45 #include <rclcpp/logger.hpp>
46 #include <rclcpp/logging.hpp>
47 #include <rclcpp/parameter.hpp>
48 #include <rclcpp/parameter_value.hpp>
49 #include <type_traits>
55 const rclcpp::Logger
LOGGER = rclcpp::get_logger(
"moveit_servo.servo_parameters");
58 rcl_interfaces::msg::SetParametersResult
59 ServoParameters::CallbackHandler::setParametersCallback(
const std::vector<rclcpp::Parameter>& parameters)
61 const std::lock_guard<std::mutex> guard(
mutex_);
62 auto result = rcl_interfaces::msg::SetParametersResult();
63 result.successful =
true;
65 for (
const auto& parameter : parameters)
67 auto search = set_parameter_callbacks_.find(parameter.get_name());
68 if (search != set_parameter_callbacks_.end())
70 RCLCPP_INFO_STREAM(LOGGER,
"setParametersCallback - "
71 << parameter.get_name() <<
"<" << parameter.get_type_name()
72 <<
">: " << rclcpp::to_string(parameter.get_parameter_value()));
73 for (
const auto& callback : search->second)
75 result = callback(parameter);
77 if (!result.successful)
89 void ServoParameters::declare(
const std::string& ns,
90 const rclcpp::node_interfaces::NodeParametersInterface::SharedPtr& node_parameters)
92 using rclcpp::ParameterValue;
93 using rclcpp::ParameterType::PARAMETER_BOOL;
94 using rclcpp::ParameterType::PARAMETER_DOUBLE;
95 using rclcpp::ParameterType::PARAMETER_INTEGER;
96 using rclcpp::ParameterType::PARAMETER_STRING;
97 auto parameters = ServoParameters{};
100 node_parameters->declare_parameter(
101 ns +
".use_gazebo", ParameterValue{ parameters.use_gazebo },
102 ParameterDescriptorBuilder{}
103 .type(PARAMETER_BOOL)
104 .
description(
"Whether the robot is started in a Gazebo simulation environment"));
105 node_parameters->declare_parameter(
106 ns +
".status_topic", ParameterValue{ parameters.status_topic },
107 ParameterDescriptorBuilder{}.type(PARAMETER_STRING).
description(
"Publish status to this topic"));
109 node_parameters->declare_parameter(
110 ns +
".cartesian_command_in_topic", ParameterValue{ parameters.cartesian_command_in_topic },
111 ParameterDescriptorBuilder{}.type(PARAMETER_STRING).
description(
"Topic for incoming Cartesian twist commands"));
112 node_parameters->declare_parameter(
113 ns +
".joint_command_in_topic", ParameterValue{ parameters.joint_command_in_topic },
114 ParameterDescriptorBuilder{}.type(PARAMETER_STRING).
description(
"Topic for incoming joint angle commands"));
115 node_parameters->declare_parameter(
116 ns +
".robot_link_command_frame", ParameterValue{ parameters.robot_link_command_frame },
117 ParameterDescriptorBuilder{}
118 .type(PARAMETER_STRING)
119 .
description(
"Commands must be given in the frame of a robot link. Usually either the base or end effector"));
120 node_parameters->declare_parameter(
ns +
".command_in_type", ParameterValue{ parameters.command_in_type },
121 ParameterDescriptorBuilder{}
122 .type(PARAMETER_STRING)
123 .
description(
"\"unitless\"> in the range [-1:1], as if from joystick. "
124 "\"speed_units\"> cmds are in m/s and rad/s"));
125 node_parameters->declare_parameter(
ns +
".scale.linear", ParameterValue{ parameters.linear_scale },
126 ParameterDescriptorBuilder{}
127 .type(PARAMETER_DOUBLE)
128 .
description(
"Max linear velocity. Unit is [m/s]. "
129 "Only used for Cartesian commands."));
130 node_parameters->declare_parameter(
ns +
".scale.rotational", ParameterValue{ parameters.rotational_scale },
131 ParameterDescriptorBuilder{}
132 .type(PARAMETER_DOUBLE)
133 .
description(
"Max angular velocity. Unit is [rad/s]. "
134 "Only used for Cartesian commands."));
135 node_parameters->declare_parameter(
ns +
".scale.joint", ParameterValue{ parameters.joint_scale },
136 ParameterDescriptorBuilder{}
137 .type(PARAMETER_DOUBLE)
138 .
description(
"Max joint angular/linear velocity. Only used for joint "
139 "commands on joint_command_in_topic."));
142 node_parameters->declare_parameter(
ns +
".override_velocity_scaling_factor",
143 ParameterValue{ parameters.override_velocity_scaling_factor },
144 ParameterDescriptorBuilder{}
145 .type(PARAMETER_DOUBLE)
146 .
description(
"Override constant scalar of how fast the robot should jog."
147 "Valid values are between 0-1.0"));
150 node_parameters->declare_parameter(
151 ns +
".command_out_topic", ParameterValue{ parameters.command_out_topic },
152 ParameterDescriptorBuilder{}.type(PARAMETER_STRING).
description(
"Publish outgoing commands here"));
153 node_parameters->declare_parameter(
154 ns +
".publish_period", ParameterValue{ parameters.publish_period },
155 ParameterDescriptorBuilder{}.type(PARAMETER_DOUBLE).
description(
"1/Nominal publish rate [seconds]"));
156 node_parameters->declare_parameter(
157 ns +
".command_out_type", ParameterValue{ parameters.command_out_type },
158 ParameterDescriptorBuilder{}
159 .type(PARAMETER_STRING)
160 .
description(
"What type of topic does your robot driver expect? Currently supported are "
161 "std_msgs/Float64MultiArray or trajectory_msgs/JointTrajectory"));
162 node_parameters->declare_parameter(
163 ns +
".publish_joint_positions", ParameterValue{ parameters.publish_joint_positions },
164 ParameterDescriptorBuilder{}
165 .type(PARAMETER_BOOL)
166 .
description(
"What to publish? Can save some bandwidth as most robots only require positions or velocities"));
167 node_parameters->declare_parameter(
168 ns +
".publish_joint_velocities", ParameterValue{ parameters.publish_joint_velocities },
169 ParameterDescriptorBuilder{}
170 .type(PARAMETER_BOOL)
171 .
description(
"What to publish? Can save some bandwidth as most robots only require positions or velocities"));
172 node_parameters->declare_parameter(
173 ns +
".publish_joint_accelerations", ParameterValue{ parameters.publish_joint_accelerations },
174 ParameterDescriptorBuilder{}
175 .type(PARAMETER_BOOL)
176 .
description(
"What to publish? Can save some bandwidth as most robots only require positions or velocities"));
177 node_parameters->declare_parameter(
ns +
".low_latency_mode", ParameterValue{ parameters.low_latency_mode },
178 ParameterDescriptorBuilder{}.type(PARAMETER_BOOL).
description(
"Low latency mode"));
181 node_parameters->declare_parameter(
ns +
".joint_topic", ParameterValue{ parameters.joint_topic },
182 ParameterDescriptorBuilder{}.type(PARAMETER_STRING).
description(
"Joint topic"));
183 node_parameters->declare_parameter(
184 ns +
".smoothing_filter_plugin_name", ParameterValue{ parameters.smoothing_filter_plugin_name },
185 ParameterDescriptorBuilder{}.type(PARAMETER_STRING).
description(
"Plugins for smoothing outgoing commands"));
188 node_parameters->declare_parameter(
189 ns +
".move_group_name", ParameterValue{ parameters.move_group_name },
190 ParameterDescriptorBuilder{}.type(PARAMETER_STRING).
description(
"Often 'manipulator' or 'arm'"));
191 node_parameters->declare_parameter(
ns +
".planning_frame", ParameterValue{ parameters.planning_frame },
192 ParameterDescriptorBuilder{}
193 .type(PARAMETER_STRING)
194 .
description(
"The MoveIt planning frame. Often 'base_link' or 'world'"));
195 node_parameters->declare_parameter(
ns +
".ee_frame_name", ParameterValue{ parameters.ee_frame_name },
196 ParameterDescriptorBuilder{}
197 .type(PARAMETER_STRING)
198 .
description(
"The name of the end effector link, used to return the EE pose"));
199 node_parameters->declare_parameter(
200 ns +
".is_primary_planning_scene_monitor", ParameterValue{ parameters.is_primary_planning_scene_monitor },
201 ParameterDescriptorBuilder{}.type(PARAMETER_BOOL).
description(
"Is primary planning scene monitor"));
202 node_parameters->declare_parameter(
203 ns +
".monitored_planning_scene_topic", ParameterValue{ parameters.monitored_planning_scene_topic },
204 ParameterDescriptorBuilder{}.type(PARAMETER_STRING).
description(
"Monitored planning scene topic"));
207 node_parameters->declare_parameter(
208 ns +
".incoming_command_timeout", ParameterValue{ parameters.incoming_command_timeout },
209 ParameterDescriptorBuilder{}
210 .type(PARAMETER_DOUBLE)
211 .
description(
"Stop servoing if X seconds elapse without a new command. If 0, republish commands forever even "
212 "if the robot is stationary.Otherwise, specify num.to publish. Important because ROS may drop "
213 "some messages and we need the robot to halt reliably."));
214 node_parameters->declare_parameter(
215 ns +
".num_outgoing_halt_msgs_to_publish", ParameterValue{ parameters.num_outgoing_halt_msgs_to_publish },
216 ParameterDescriptorBuilder{}.type(PARAMETER_INTEGER).
description(
"Num outgoing halt msgs to publish"));
217 node_parameters->declare_parameter(
218 ns +
".halt_all_joints_in_joint_mode", ParameterValue{ parameters.halt_all_joints_in_joint_mode },
219 ParameterDescriptorBuilder{}.type(PARAMETER_BOOL).
description(
"Halt all joints in joint mode"));
220 node_parameters->declare_parameter(
221 ns +
".halt_all_joints_in_cartesian_mode", ParameterValue{ parameters.halt_all_joints_in_cartesian_mode },
222 ParameterDescriptorBuilder{}.type(PARAMETER_BOOL).
description(
"Halt all joints in cartesian mode"));
225 node_parameters->declare_parameter(
226 ns +
".lower_singularity_threshold", ParameterValue{ parameters.lower_singularity_threshold },
227 ParameterDescriptorBuilder{}
228 .type(PARAMETER_DOUBLE)
229 .
description(
"Start decelerating when the condition number hits this (close to singularity)"));
230 node_parameters->declare_parameter(
231 ns +
".hard_stop_singularity_threshold", ParameterValue{ parameters.hard_stop_singularity_threshold },
232 ParameterDescriptorBuilder{}.type(PARAMETER_DOUBLE).
description(
"Stop when the condition number hits this"));
233 node_parameters->declare_parameter(
234 ns +
".joint_limit_margin", ParameterValue{ parameters.joint_limit_margin },
235 ParameterDescriptorBuilder{}
236 .type(PARAMETER_DOUBLE)
237 .
description(
"Added as a buffer to joint limits [radians]. If moving quickly, make this larger."));
238 node_parameters->declare_parameter(
239 ns +
".leaving_singularity_threshold_multiplier",
240 ParameterValue{ parameters.leaving_singularity_threshold_multiplier },
241 ParameterDescriptorBuilder{}
242 .type(PARAMETER_DOUBLE)
243 .
description(
"When 'lower_singularity_threshold' is triggered, but we are moving away from singularity, move "
244 "this many times faster than if we were moving further into singularity"));
247 node_parameters->declare_parameter(
ns +
".check_collisions", ParameterValue{ parameters.check_collisions },
248 ParameterDescriptorBuilder{}.type(PARAMETER_BOOL).
description(
"Check collisions?"));
249 node_parameters->declare_parameter(
250 ns +
".collision_check_rate", ParameterValue(parameters.collision_check_rate),
251 ParameterDescriptorBuilder{}
252 .type(PARAMETER_DOUBLE)
253 .description(
"[Hz] Collision-checking can easily bog down a CPU if done too often. Collision checking begins "
254 "slowing down when nearer than a specified distance."));
255 node_parameters->declare_parameter(
ns +
".self_collision_proximity_threshold",
256 ParameterValue{ parameters.self_collision_proximity_threshold },
257 ParameterDescriptorBuilder{}
258 .type(PARAMETER_DOUBLE)
259 .
description(
"Start decelerating when a self-collision is this far [m]"));
260 node_parameters->declare_parameter(
ns +
".scene_collision_proximity_threshold",
261 ParameterValue{ parameters.scene_collision_proximity_threshold },
262 ParameterDescriptorBuilder{}
263 .type(PARAMETER_DOUBLE)
264 .
description(
"Start decelerating when a scene collision is this far [m]"));
268 const rclcpp::node_interfaces::NodeParametersInterface::SharedPtr& node_parameters)
273 parameters.
use_gazebo = node_parameters->get_parameter(
ns +
".use_gazebo").as_bool();
274 parameters.status_topic = node_parameters->get_parameter(
ns +
".status_topic").as_string();
277 parameters.cartesian_command_in_topic =
278 node_parameters->get_parameter(
ns +
".cartesian_command_in_topic").as_string();
279 parameters.joint_command_in_topic = node_parameters->get_parameter(
ns +
".joint_command_in_topic").as_string();
280 parameters.robot_link_command_frame = node_parameters->get_parameter(
ns +
".robot_link_command_frame").as_string();
281 parameters.command_in_type = node_parameters->get_parameter(
ns +
".command_in_type").as_string();
282 parameters.linear_scale = node_parameters->get_parameter(
ns +
".scale.linear").as_double();
283 parameters.rotational_scale = node_parameters->get_parameter(
ns +
".scale.rotational").as_double();
284 parameters.joint_scale = node_parameters->get_parameter(
ns +
".scale.joint").as_double();
287 parameters.override_velocity_scaling_factor =
288 node_parameters->get_parameter(
ns +
".override_velocity_scaling_factor").as_double();
291 parameters.command_out_topic = node_parameters->get_parameter(
ns +
".command_out_topic").as_string();
292 parameters.publish_period = node_parameters->get_parameter(
ns +
".publish_period").as_double();
293 parameters.command_out_type = node_parameters->get_parameter(
ns +
".command_out_type").as_string();
294 parameters.publish_joint_positions = node_parameters->get_parameter(
ns +
".publish_joint_positions").as_bool();
295 parameters.publish_joint_velocities = node_parameters->get_parameter(
ns +
".publish_joint_velocities").as_bool();
296 parameters.publish_joint_accelerations =
297 node_parameters->get_parameter(
ns +
".publish_joint_accelerations").as_bool();
298 parameters.low_latency_mode = node_parameters->get_parameter(
ns +
".low_latency_mode").as_bool();
301 parameters.joint_topic = node_parameters->get_parameter(
ns +
".joint_topic").as_string();
302 parameters.smoothing_filter_plugin_name =
303 node_parameters->get_parameter(
ns +
".smoothing_filter_plugin_name").as_string();
306 parameters.move_group_name = node_parameters->get_parameter(
ns +
".move_group_name").as_string();
307 parameters.planning_frame = node_parameters->get_parameter(
ns +
".planning_frame").as_string();
308 parameters.ee_frame_name = node_parameters->get_parameter(
ns +
".ee_frame_name").as_string();
309 parameters.is_primary_planning_scene_monitor =
310 node_parameters->get_parameter(
ns +
".is_primary_planning_scene_monitor").as_bool();
311 parameters.monitored_planning_scene_topic =
312 node_parameters->get_parameter(
ns +
".monitored_planning_scene_topic").as_string();
315 parameters.incoming_command_timeout = node_parameters->get_parameter(
ns +
".incoming_command_timeout").as_double();
316 parameters.num_outgoing_halt_msgs_to_publish =
317 node_parameters->get_parameter(
ns +
".num_outgoing_halt_msgs_to_publish").as_int();
318 parameters.halt_all_joints_in_joint_mode =
319 node_parameters->get_parameter(
ns +
".halt_all_joints_in_joint_mode").as_bool();
320 parameters.halt_all_joints_in_cartesian_mode =
321 node_parameters->get_parameter(
ns +
".halt_all_joints_in_cartesian_mode").as_bool();
324 parameters.lower_singularity_threshold =
325 node_parameters->get_parameter(
ns +
".lower_singularity_threshold").as_double();
326 parameters.hard_stop_singularity_threshold =
327 node_parameters->get_parameter(
ns +
".hard_stop_singularity_threshold").as_double();
328 parameters.joint_limit_margin = node_parameters->get_parameter(
ns +
".joint_limit_margin").as_double();
330 if (node_parameters->has_parameter(
ns +
".leaving_singularity_threshold_multiplier"))
332 parameters.leaving_singularity_threshold_multiplier =
333 node_parameters->get_parameter(
ns +
".leaving_singularity_threshold_multiplier").as_double();
337 parameters.leaving_singularity_threshold_multiplier = 1.0;
338 RCLCPP_WARN(LOGGER,
"Using the deprecated type of servo singularity handling; add parameter "
339 "'leaving_singularity_threshold_multiplier' to define leaving singularity threshold. See "
340 "https://github.com/ros-planning/moveit2/pull/620 for more information.");
344 parameters.check_collisions = node_parameters->get_parameter(
ns +
".check_collisions").as_bool();
345 parameters.collision_check_rate = node_parameters->get_parameter(
ns +
".collision_check_rate").as_double();
346 parameters.self_collision_proximity_threshold =
347 node_parameters->get_parameter(
ns +
".self_collision_proximity_threshold").as_double();
348 parameters.scene_collision_proximity_threshold =
349 node_parameters->get_parameter(
ns +
".scene_collision_proximity_threshold").as_double();
359 RCLCPP_WARN(LOGGER,
"Parameter 'publish_period' should be "
360 "greater than zero. Check yaml file.");
365 RCLCPP_WARN(LOGGER,
"Parameter 'num_outgoing_halt_msgs_to_publish' should be greater than zero. Check yaml file.");
371 "Parameter 'leaving_singularity_threshold_multiplier' should be greater than zero. Check yaml file.");
376 RCLCPP_WARN(LOGGER,
"Parameter 'hard_stop_singularity_threshold' "
377 "should be greater than 'lower_singularity_threshold.' "
383 RCLCPP_WARN(LOGGER,
"Parameters 'hard_stop_singularity_threshold' "
384 "and 'lower_singularity_threshold' should be "
385 "greater than zero. Check yaml file.");
390 RCLCPP_WARN(LOGGER,
"A smoothing plugin is required.");
395 RCLCPP_WARN(LOGGER,
"Parameter 'joint_limit_margin' should usually be greater than or equal to zero, "
396 "although negative values can be used if the specified joint limits are actually soft. "
401 RCLCPP_WARN(LOGGER,
"command_in_type should be 'unitless' or "
402 "'speed_units'. Check yaml file.");
408 RCLCPP_WARN(LOGGER,
"Parameter command_out_type should be "
409 "'trajectory_msgs/JointTrajectory' or "
410 "'std_msgs/Float64MultiArray'. Check yaml file.");
416 RCLCPP_WARN(LOGGER,
"At least one of publish_joint_positions / "
417 "publish_joint_velocities / "
418 "publish_joint_accelerations must be true. Check "
425 RCLCPP_WARN(LOGGER,
"When publishing a std_msgs/Float64MultiArray, "
426 "you must select positions OR velocities.");
432 RCLCPP_WARN(LOGGER,
"Parameter 'self_collision_proximity_threshold' should be "
433 "greater than zero. Check yaml file.");
438 RCLCPP_WARN(LOGGER,
"Parameter 'scene_collision_proximity_threshold' should be "
439 "greater than zero. Check yaml file.");
444 RCLCPP_WARN(LOGGER,
"Parameter 'self_collision_proximity_threshold' should probably be less "
445 "than or equal to 'scene_collision_proximity_threshold'. Check yaml file.");
449 RCLCPP_WARN(LOGGER,
"Parameter 'collision_check_rate' should be "
450 "greater than zero. Check yaml file.");
457 const std::string& ns,
458 bool dynamic_parameters )
460 auto node_parameters = node->get_node_parameters_interface();
463 declare(
ns, node_parameters);
468 auto parameters_ptr = std::make_shared<ServoParameters>(parameters.value());
469 parameters_ptr->callback_handler_ = std::make_shared<ServoParameters::CallbackHandler>();
472 if (dynamic_parameters)
474 parameters_ptr->callback_handler_->on_set_parameters_callback_handler_ = node->add_on_set_parameters_callback(
475 [ptr = parameters_ptr->callback_handler_.get()](
const std::vector<rclcpp::Parameter>& parameters) {
476 return ptr->setParametersCallback(parameters);
480 return parameters_ptr;
const rclcpp::Logger LOGGER
double hard_stop_singularity_threshold
double joint_limit_margin
int num_outgoing_halt_msgs_to_publish
std::shared_ptr< const ServoParameters > SharedConstPtr
std::string smoothing_filter_plugin_name
double self_collision_proximity_threshold
bool publish_joint_velocities
double scene_collision_proximity_threshold
double leaving_singularity_threshold_multiplier
double lower_singularity_threshold
static ServoParameters get(const std::string &ns, const rclcpp::node_interfaces::NodeParametersInterface::SharedPtr &node_parameters)
bool publish_joint_positions
static SharedConstPtr makeServoParameters(const rclcpp::Node::SharedPtr &node, const std::string &ns="moveit_servo", bool dynamic_parameters=true)
std::string command_out_type
bool publish_joint_accelerations
std::string command_in_type
static std::optional< ServoParameters > validate(ServoParameters parameters)
double collision_check_rate