1+ /* ********************************************************************
2+ * Software License Agreement (BSD License)
3+ *
4+ * Copyright (c) 2015, PickNik LLC
5+ * All rights reserved.
6+ *
7+ * Redistribution and use in source and binary forms, with or without
8+ * modification, are permitted provided that the following conditions
9+ * are met:
10+ *
11+ * * Redistributions of source code must retain the above copyright
12+ * notice, this list of conditions and the following disclaimer.
13+ * * Redistributions in binary form must reproduce the above
14+ * copyright notice, this list of conditions and the following
15+ * disclaimer in the documentation and/or other materials provided
16+ * with the distribution.
17+ * * Neither the name of PickNik LLC nor the names of its
18+ * contributors may be used to endorse or promote products derived
19+ * from this software without specific prior written permission.
20+ *
21+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
24+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
25+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
26+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
27+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
28+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
29+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
31+ * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
32+ * POSSIBILITY OF SUCH DAMAGE.
33+ *********************************************************************/
34+
35+ /* Author: Dave Coleman
36+ Desc: Helper ros_control hardware interface that loads configurations
37+ */
38+
39+ #include " ur_robot_driver/ros/hardware_interface.h"
40+
41+ namespace ur_driver
42+ {
43+ void HardwareInterface::registerJointLimits (ros::NodeHandle& robot_hw_nh,
44+ const hardware_interface::JointHandle& joint_handle_position,
45+ const hardware_interface::JointHandle& joint_handle_velocity,
46+ std::size_t joint_id)
47+ {
48+ // Default values
49+ joint_position_lower_limits_[joint_id] = -std::numeric_limits<double >::max ();
50+ joint_position_upper_limits_[joint_id] = std::numeric_limits<double >::max ();
51+ joint_velocity_limits_[joint_id] = std::numeric_limits<double >::max ();
52+
53+ // Limits datastructures
54+ joint_limits_interface::JointLimits joint_limits; // Position
55+ joint_limits_interface::SoftJointLimits soft_limits; // Soft Position
56+ bool has_joint_limits = false ;
57+ bool has_soft_limits = false ;
58+
59+ // Get limits from URDF
60+ if (urdf_model_ == nullptr )
61+ {
62+ ROS_WARN_STREAM (" No URDF model loaded, unable to get joint limits" );
63+ return ;
64+ }
65+
66+ // Get limits from URDF
67+ urdf::JointConstSharedPtr urdf_joint = urdf_model_->getJoint (joint_names_[joint_id]);
68+
69+ // Get main joint limits
70+ if (urdf_joint == nullptr )
71+ {
72+ ROS_ERROR_STREAM (" URDF joint not found " << joint_names_[joint_id]);
73+ return ;
74+ }
75+
76+ // Get limits from URDF
77+ if (joint_limits_interface::getJointLimits (urdf_joint, joint_limits))
78+ {
79+ has_joint_limits = true ;
80+ ROS_DEBUG_STREAM (" Joint " << joint_names_[joint_id] << " has URDF position limits [" << joint_limits.min_position
81+ << " , " << joint_limits.max_position << " ]" );
82+ if (joint_limits.has_velocity_limits )
83+ ROS_DEBUG_STREAM (" Joint " << joint_names_[joint_id] << " has URDF velocity limit [" << joint_limits.max_velocity
84+ << " ]" );
85+ }
86+ else
87+ {
88+ if (urdf_joint->type != urdf::Joint::CONTINUOUS)
89+ ROS_WARN_STREAM (" No URDF limits are configured for joint " << joint_names_[joint_id]);
90+ }
91+
92+ // Get limits from ROS param
93+ if (joint_limits_interface::getJointLimits (joint_names_[joint_id], robot_hw_nh, joint_limits))
94+ {
95+ has_joint_limits = true ;
96+ ROS_DEBUG_STREAM (" Joint " << joint_names_[joint_id] << " has rosparam position limits ["
97+ << joint_limits.min_position << " , " << joint_limits.max_position << " ]" );
98+ if (joint_limits.has_velocity_limits )
99+ ROS_DEBUG_STREAM (" Joint " << joint_names_[joint_id] << " has rosparam velocity limit ["
100+ << joint_limits.max_velocity << " ]" );
101+ } // the else debug message provided internally by joint_limits_interface
102+
103+ // Get soft limits from URDF
104+ if (joint_limits_interface::getSoftJointLimits (urdf_joint, soft_limits))
105+ {
106+ has_soft_limits = true ;
107+ ROS_DEBUG_STREAM (" Joint " << joint_names_[joint_id] << " has soft joint limits." );
108+ }
109+ else
110+ {
111+ ROS_DEBUG_STREAM (" Joint " << joint_names_[joint_id]
112+ << " does not have soft joint "
113+ " limits" );
114+ }
115+
116+ // Quit we we haven't found any limits in URDF or rosparam server
117+ if (!has_joint_limits)
118+ {
119+ return ;
120+ }
121+
122+ // Copy position limits if available
123+ if (joint_limits.has_position_limits )
124+ {
125+ // Slighly reduce the joint limits to prevent floating point errors
126+ joint_limits.min_position += std::numeric_limits<double >::epsilon ();
127+ joint_limits.max_position -= std::numeric_limits<double >::epsilon ();
128+
129+ joint_position_lower_limits_[joint_id] = joint_limits.min_position ;
130+ joint_position_upper_limits_[joint_id] = joint_limits.max_position ;
131+ }
132+
133+ // Copy velocity limits if available
134+ if (joint_limits.has_velocity_limits )
135+ {
136+ joint_velocity_limits_[joint_id] = joint_limits.max_velocity ;
137+ }
138+
139+ if (has_soft_limits) // Use soft limits
140+ {
141+ ROS_DEBUG_STREAM (" Using soft saturation limits" );
142+ const joint_limits_interface::PositionJointSoftLimitsHandle soft_handle_position (joint_handle_position,
143+ joint_limits, soft_limits);
144+ pos_jnt_soft_interface_.registerHandle (soft_handle_position);
145+ const joint_limits_interface::VelocityJointSoftLimitsHandle soft_handle_velocity (joint_handle_velocity,
146+ joint_limits, soft_limits);
147+ vel_jnt_soft_interface_.registerHandle (soft_handle_velocity);
148+ }
149+ else // Use saturation limits
150+ {
151+ ROS_DEBUG_STREAM (" Using saturation limits (not soft limits)" );
152+
153+ const joint_limits_interface::PositionJointSaturationHandle sat_handle_position (joint_handle_position,
154+ joint_limits);
155+ pos_jnt_sat_interface_.registerHandle (sat_handle_position);
156+
157+ const joint_limits_interface::VelocityJointSaturationHandle sat_handle_velocity (joint_handle_velocity,
158+ joint_limits);
159+ vel_jnt_sat_interface_.registerHandle (sat_handle_velocity);
160+ }
161+ }
162+
163+ void HardwareInterface::loadURDF (ros::NodeHandle& nh, std::string param_name)
164+ {
165+ std::string urdf_string;
166+ urdf_model_ = new urdf::Model ();
167+
168+ // search and wait for robot_description on param server
169+ while (urdf_string.empty () && ros::ok ())
170+ {
171+ std::string search_param_name;
172+ if (nh.searchParam (param_name, search_param_name))
173+ {
174+ ROS_INFO_STREAM (" Waiting for model URDF on the ROS param server at location: " << nh.getNamespace ()
175+ << search_param_name);
176+ nh.getParam (search_param_name, urdf_string);
177+ }
178+
179+ usleep (100000 );
180+ }
181+
182+ if (!urdf_model_->initString (urdf_string))
183+ ROS_ERROR_STREAM (" Unable to load URDF model" );
184+ else
185+ ROS_DEBUG_STREAM (" Received URDF from param server" );
186+ }
187+ }
0 commit comments