moveit2
The MoveIt Motion Planning Framework for ROS 2.
Loading...
Searching...
No Matches
common.cpp
Go to the documentation of this file.
1/*******************************************************************************
2 * BSD 3-Clause License
3 *
4 * Copyright (c) 2019, Los Alamos National Security, 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 are met:
9 *
10 * * Redistributions of source code must retain the above copyright notice, this
11 * list of conditions and the following disclaimer.
12 *
13 * * Redistributions in binary form must reproduce the above copyright notice,
14 * this list of conditions and the following disclaimer in the documentation
15 * and/or other materials provided with the distribution.
16 *
17 * * Neither the name of the copyright holder nor the names of its
18 * contributors may be used to endorse or promote products derived from
19 * this software without specific prior written permission.
20 *
21 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
22 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24 * ARE
25 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
26 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
27 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
28 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
29 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
30 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
31 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32 *******************************************************************************/
33
34/* Title : utils.cpp
35 * Project : moveit_servo
36 * Created : 05/17/2023
37 * Author : Andy Zelenak, V Mohammed Ibrahim
38 */
39
41
42namespace
43{
44// The threshold above which `override_velocity_scaling_factor` will be used instead of computing the scaling from joint bounds.
45constexpr double SCALING_OVERRIDE_THRESHOLD = 0.01;
46
47// The angle threshold in radians below which a rotation will be considered the identity.
48constexpr double MIN_ANGLE_THRESHOLD = 1E-16;
49
50// The publishing frequency for the planning scene monitor, in Hz.
51constexpr double PLANNING_SCENE_PUBLISHING_FREQUENCY = 25.0;
52} // namespace
53
54namespace moveit_servo
55{
56
57std::optional<std::string> getIKSolverBaseFrame(const moveit::core::RobotStatePtr& robot_state,
58 const std::string& group_name)
59{
60 const auto ik_solver = robot_state->getJointModelGroup(group_name)->getSolverInstance();
61
62 if (ik_solver)
63 {
64 return ik_solver->getBaseFrame();
65 }
66 else
67 {
68 return std::nullopt;
69 }
70}
71
72std::optional<std::string> getIKSolverTipFrame(const moveit::core::RobotStatePtr& robot_state,
73 const std::string& group_name)
74{
75 const auto ik_solver = robot_state->getJointModelGroup(group_name)->getSolverInstance();
76
77 if (ik_solver)
78 {
79 return ik_solver->getTipFrame();
80 }
81 else
82 {
83 return std::nullopt;
84 }
85}
86
87bool isValidCommand(const Eigen::VectorXd& command)
88{
89 // returns true only if there are no nan values.
90 return command.allFinite();
91}
92
93bool isValidCommand(const Eigen::Isometry3d& command)
94{
95 Eigen::Matrix3d identity, rotation;
96 identity.setIdentity();
97 rotation = command.linear();
98 // checks rotation, will fail if there is nan
99 const bool is_valid_rotation = rotation.allFinite() && identity.isApprox(rotation.inverse() * rotation);
100 // Command is not vald if there is Nan
101 const bool is_valid_translation = isValidCommand(command.translation());
102 return is_valid_rotation && is_valid_translation;
103}
104
105bool isValidCommand(const TwistCommand& command)
106{
107 return !command.frame_id.empty() && isValidCommand(command.velocities);
108}
109
110bool isValidCommand(const PoseCommand& command)
111{
112 return !command.frame_id.empty() && isValidCommand(command.pose);
113}
114
115geometry_msgs::msg::Pose poseFromCartesianDelta(const Eigen::VectorXd& delta_x,
116 const Eigen::Isometry3d& base_to_tip_frame_transform)
117{
118 // Get a transformation matrix with the desired position change
119 Eigen::Isometry3d tf_pos_delta(Eigen::Isometry3d::Identity());
120 tf_pos_delta.translate(Eigen::Vector3d(delta_x[0], delta_x[1], delta_x[2]));
121
122 // Get a transformation matrix with desired orientation change
123 Eigen::Isometry3d tf_rot_delta(Eigen::Isometry3d::Identity());
124 const Eigen::Vector3d rot_vec = delta_x.block<3, 1>(3, 0, 3, 1);
125 double angle = rot_vec.norm();
126 if (angle > MIN_ANGLE_THRESHOLD)
127 {
128 const Eigen::Quaterniond q(Eigen::AngleAxisd(angle, rot_vec / angle).toRotationMatrix());
129 tf_rot_delta.rotate(q);
130 }
131
132 // Find the new tip link position without newly applied rotation
133 const Eigen::Isometry3d tf_no_new_rot = tf_pos_delta * base_to_tip_frame_transform;
134
135 // we want the rotation to be applied in the requested reference frame,
136 // but we want the rotation to be about the EE point in space, not the origin.
137 // So, we need to translate to origin, rotate, then translate back
138 // Given T = transformation matrix from origin -> EE point in space (translation component of tf_no_new_rot)
139 // and T' as the opposite transformation, EE point in space -> origin (translation only)
140 // apply final transformation as T * R * T' * tf_no_new_rot
141 Eigen::Isometry3d tf_neg_translation = Eigen::Isometry3d::Identity(); // T'
142 tf_neg_translation.translation() = -1 * tf_no_new_rot.translation();
143 Eigen::Isometry3d tf_pos_translation = Eigen::Isometry3d::Identity(); // T
144 tf_pos_translation.translation() = tf_no_new_rot.translation();
145
146 // T * R * T' * tf_no_new_rot
147 return tf2::toMsg(tf_pos_translation * tf_rot_delta * tf_neg_translation * tf_no_new_rot);
148}
149
150std::optional<trajectory_msgs::msg::JointTrajectory>
151composeTrajectoryMessage(const servo::Params& servo_params, const std::deque<KinematicState>& joint_cmd_rolling_window)
152{
153 if (joint_cmd_rolling_window.size() < MIN_POINTS_FOR_TRAJ_MSG)
154 {
155 return {};
156 }
157
158 trajectory_msgs::msg::JointTrajectory joint_trajectory;
159
160 joint_trajectory.joint_names = joint_cmd_rolling_window.front().joint_names;
161 joint_trajectory.points.reserve(joint_cmd_rolling_window.size() + 1);
162 joint_trajectory.header.stamp = joint_cmd_rolling_window.front().time_stamp;
163
164 auto add_point = [servo_params](trajectory_msgs::msg::JointTrajectory& joint_trajectory, const KinematicState& state) {
165 trajectory_msgs::msg::JointTrajectoryPoint point;
166 size_t num_joints = state.positions.size();
167 point.positions.reserve(num_joints);
168 point.velocities.reserve(num_joints);
169 point.accelerations.reserve(num_joints);
170 if (servo_params.publish_joint_positions)
171 {
172 for (const auto& pos : state.positions)
173 {
174 point.positions.emplace_back(pos);
175 }
176 }
177 if (servo_params.publish_joint_velocities)
178 {
179 for (const auto& vel : state.velocities)
180 {
181 point.velocities.emplace_back(vel);
182 }
183 }
184 if (servo_params.publish_joint_accelerations)
185 {
186 for (const auto& acc : state.accelerations)
187 {
188 point.accelerations.emplace_back(acc);
189 }
190 }
191 point.time_from_start = state.time_stamp - joint_trajectory.header.stamp;
192 joint_trajectory.points.emplace_back(point);
193 };
194
195 for (size_t i = 0; i < joint_cmd_rolling_window.size() - 1; ++i)
196 {
197 add_point(joint_trajectory, joint_cmd_rolling_window[i]);
198 }
199
200 return joint_trajectory;
201}
202
203void updateSlidingWindow(KinematicState& next_joint_state, std::deque<KinematicState>& joint_cmd_rolling_window,
204 double max_expected_latency, const rclcpp::Time& cur_time)
205{
206 // remove commands older than current time minus the length of the sliding window
207 next_joint_state.time_stamp = cur_time + rclcpp::Duration::from_seconds(max_expected_latency);
208 const auto active_time_window = rclcpp::Duration::from_seconds(max_expected_latency);
209 while (!joint_cmd_rolling_window.empty() &&
210 joint_cmd_rolling_window.front().time_stamp < (cur_time - active_time_window))
211 {
212 joint_cmd_rolling_window.pop_front();
213 }
214
215 // remove commands at end of window if timestamp is the same as current command
216 while (!joint_cmd_rolling_window.empty() && next_joint_state.time_stamp == joint_cmd_rolling_window.back().time_stamp)
217 {
218 joint_cmd_rolling_window.pop_back();
219 }
220
221 // update velocity: the velocity has the potential to dramatically influence interpolation of splines and causes large
222 // overshooting. To alleviate this effect, the target velocity will be set to zero if the motion changes direction,
223 // otherwise, it will calculate the forward and backward finite difference velocities and choose the minimum.
224 if (joint_cmd_rolling_window.size() >= 2)
225 {
226 size_t num_points = joint_cmd_rolling_window.size();
227 auto& last_state = joint_cmd_rolling_window[num_points - 1];
228 auto& second_last_state = joint_cmd_rolling_window[num_points - 2];
229
230 Eigen::VectorXd direction_1 = second_last_state.positions - last_state.positions;
231 Eigen::VectorXd direction_2 = next_joint_state.positions - last_state.positions;
232 Eigen::VectorXd signs = (direction_1.array().sign() - direction_2.array().sign()).round();
233 for (long i = 0; i < last_state.velocities.size(); ++i)
234 {
235 // check if the direction have changed. `signs` will either have -2, +2 meaning a flat line, -1, 1 meaning a
236 // rotated L shape, or 0 meaning a v-shape.
237 if (signs[i] == 0.0)
238 {
239 // direction changed
240 last_state.velocities[i] = 0;
241 }
242 else
243 {
244 const double delta_time_1 = (next_joint_state.time_stamp - last_state.time_stamp).seconds();
245 const double delta_time_2 = (last_state.time_stamp - second_last_state.time_stamp).seconds();
246 const auto velocity_1 = (next_joint_state.positions[i] - last_state.positions[i]) / delta_time_1;
247 const auto velocity_2 = (last_state.positions[i] - second_last_state.positions[i]) / delta_time_2;
248 last_state.velocities[i] = (std::abs(velocity_1) < std::abs(velocity_2)) ? velocity_1 : velocity_2;
249 }
250 next_joint_state.velocities[i] = last_state.velocities[i];
251 }
252 }
253
254 // add next command
255 joint_cmd_rolling_window.push_back(next_joint_state);
256}
257
258std_msgs::msg::Float64MultiArray composeMultiArrayMessage(const servo::Params& servo_params,
259 const KinematicState& joint_state)
260{
261 std_msgs::msg::Float64MultiArray multi_array;
262 const size_t num_joints = joint_state.joint_names.size();
263 multi_array.data.resize(num_joints);
264 if (servo_params.publish_joint_positions)
265 {
266 for (size_t i = 0; i < num_joints; ++i)
267 {
268 multi_array.data[i] = joint_state.positions[i];
269 }
270 }
271 else if (servo_params.publish_joint_velocities)
272 {
273 for (size_t i = 0; i < num_joints; ++i)
274 {
275 multi_array.data[i] = joint_state.velocities[i];
276 }
277 }
278
279 return multi_array;
280}
281
282std::pair<double, StatusCode> velocityScalingFactorForSingularity(const moveit::core::RobotStatePtr& robot_state,
283 const Eigen::VectorXd& target_delta_x,
284 const servo::Params& servo_params)
285{
286 // We need to send information back about if we are halting, moving away or towards the singularity.
287 StatusCode servo_status = StatusCode::NO_WARNING;
288
289 const moveit::core::JointModelGroup* joint_model_group =
290 robot_state->getJointModelGroup(servo_params.move_group_name);
291
292 // Get the thresholds.
293 const double lower_singularity_threshold = servo_params.lower_singularity_threshold;
294 const double hard_stop_singularity_threshold = servo_params.hard_stop_singularity_threshold;
295 const double leaving_singularity_threshold_multiplier = servo_params.leaving_singularity_threshold_multiplier;
296
297 // Get size of total controllable dimensions.
298 const size_t dims = target_delta_x.size();
299
300 // Get the current Jacobian and compute SVD
301 const Eigen::JacobiSVD<Eigen::MatrixXd> current_svd = Eigen::JacobiSVD<Eigen::MatrixXd>(
302 robot_state->getJacobian(joint_model_group), Eigen::ComputeThinU | Eigen::ComputeThinV);
303 const Eigen::MatrixXd matrix_s = current_svd.singularValues().asDiagonal();
304
305 // Compute pseudo inverse
306 const Eigen::MatrixXd pseudo_inverse = current_svd.matrixV() * matrix_s.inverse() * current_svd.matrixU().transpose();
307
308 // Get the singular vector corresponding to least singular value.
309 // This vector represents the least responsive dimension. By convention this is the last column of the matrix U.
310 // The sign of the singular vector from result of SVD is not reliable, so we need to do extra checking to make sure of
311 // the sign. See R. Bro, "Resolving the Sign Ambiguity in the Singular Value Decomposition".
312 Eigen::VectorXd vector_towards_singularity = current_svd.matrixU().col(dims - 1);
313
314 // Compute the current condition number. The ratio of max and min singular values.
315 // By convention these are the first and last element of the diagonal.
316 const double current_condition_number = current_svd.singularValues()(0) / current_svd.singularValues()(dims - 1);
317
318 // Take a small step in the direction of vector_towards_singularity
319 const Eigen::VectorXd delta_x = vector_towards_singularity * servo_params.singularity_step_scale;
320
321 // Compute the new joint angles if we take the small step delta_x
322 Eigen::VectorXd next_joint_angles;
323 robot_state->copyJointGroupPositions(joint_model_group, next_joint_angles);
324 next_joint_angles += pseudo_inverse * delta_x;
325
326 // Compute the Jacobian SVD for the new robot state.
327 robot_state->setJointGroupPositions(joint_model_group, next_joint_angles);
328 const Eigen::JacobiSVD<Eigen::MatrixXd> next_svd = Eigen::JacobiSVD<Eigen::MatrixXd>(
329 robot_state->getJacobian(joint_model_group), Eigen::ComputeThinU | Eigen::ComputeThinV);
330
331 // Compute condition number for the new Jacobian.
332 const double next_condition_number = next_svd.singularValues()(0) / next_svd.singularValues()(dims - 1);
333
334 // If the condition number has increased, we are moving towards singularity and the direction of the
335 // vector_towards_singularity is correct. If the condition number has decreased, it means the sign of
336 // vector_towards_singularity needs to be flipped.
337 if (next_condition_number <= current_condition_number)
338 {
339 vector_towards_singularity *= -1;
340 }
341
342 // Double check the direction using dot product.
343 const bool moving_towards_singularity = vector_towards_singularity.dot(target_delta_x) > 0;
344
345 // Compute upper condition variable threshold based on if we are moving towards or away from singularity.
346 // See https://github.com/moveit/moveit2/pull/620#issuecomment-1201418258 for visual explanation.
347 double upper_threshold;
348 if (moving_towards_singularity)
349 {
350 upper_threshold = hard_stop_singularity_threshold;
351 }
352 else
353 {
354 const double threshold_size = (hard_stop_singularity_threshold - lower_singularity_threshold);
355 upper_threshold = lower_singularity_threshold + (threshold_size * leaving_singularity_threshold_multiplier);
356 }
357
358 // Compute the scale based on the current condition number.
359 double velocity_scale = 1.0;
360 const bool is_above_lower_limit = current_condition_number > lower_singularity_threshold;
361 const bool is_below_hard_stop_limit = current_condition_number < hard_stop_singularity_threshold;
362 if (is_above_lower_limit && is_below_hard_stop_limit)
363 {
364 velocity_scale -=
365 (current_condition_number - lower_singularity_threshold) / (upper_threshold - lower_singularity_threshold);
366
367 servo_status = moving_towards_singularity ? StatusCode::DECELERATE_FOR_APPROACHING_SINGULARITY :
369 }
370 // If condition number has crossed hard stop limit, halt the robot.
371 else if (!is_below_hard_stop_limit)
372 {
374 velocity_scale = 0.0;
375 }
376
377 return std::make_pair(velocity_scale, servo_status);
378}
379
380double jointLimitVelocityScalingFactor(const Eigen::VectorXd& velocities,
381 const moveit::core::JointBoundsVector& joint_bounds, double scaling_override)
382{
383 // If override value is close to zero, user is not overriding the scaling
384 double min_scaling_factor = scaling_override;
385 if (scaling_override < SCALING_OVERRIDE_THRESHOLD)
386 {
387 min_scaling_factor = 1.0; // Set to no scaling override.
388 }
389
390 // Now get the scaling factor from joint velocity limits.
391 size_t idx = 0;
392 for (const auto& joint_bound : joint_bounds)
393 {
394 for (const auto& variable_bound : *joint_bound)
395 {
396 const auto& target_vel = velocities(idx);
397 if (variable_bound.velocity_bounded_ && target_vel != 0.0)
398 {
399 // Find the ratio of clamped velocity to original velocity
400 const auto bounded_vel = std::clamp(target_vel, variable_bound.min_velocity_, variable_bound.max_velocity_);
401 const auto joint_scaling_factor = bounded_vel / target_vel;
402 min_scaling_factor = std::min(min_scaling_factor, joint_scaling_factor);
403 }
404 ++idx;
405 }
406 }
407
408 return min_scaling_factor;
409}
410
411std::vector<size_t> jointVariablesToHalt(const Eigen::VectorXd& positions, const Eigen::VectorXd& velocities,
412 const moveit::core::JointBoundsVector& joint_bounds,
413 const std::vector<double>& margins)
414{
415 std::vector<size_t> variable_indices_to_halt;
416
417 // Now get the scaling factor from joint velocity limits.
418 size_t variable_idx = 0;
419 for (const auto& joint_bound : joint_bounds)
420 {
421 bool halt_joint = false;
422 for (const auto& variable_bound : *joint_bound)
423 {
424 // First, loop through all the joint variables to see if the entire joint should be halted.
425 if (variable_bound.position_bounded_)
426 {
427 const bool approaching_negative_bound =
428 velocities[variable_idx] < 0 &&
429 positions[variable_idx] < (variable_bound.min_position_ + margins[variable_idx]);
430 const bool approaching_positive_bound =
431 velocities[variable_idx] > 0 &&
432 positions[variable_idx] > (variable_bound.max_position_ - margins[variable_idx]);
433 if (approaching_negative_bound || approaching_positive_bound)
434 {
435 halt_joint |= true;
436 }
437 }
438 ++variable_idx;
439
440 // If the joint needs to be halted, add all variable indices corresponding to that joint.
441 if (halt_joint)
442 {
443 for (size_t k = variable_idx - joint_bound->size(); k < variable_idx; ++k)
444 {
445 variable_indices_to_halt.push_back(k);
446 }
447 }
448 }
449 }
450 return variable_indices_to_halt;
451}
452
454geometry_msgs::msg::TransformStamped convertIsometryToTransform(const Eigen::Isometry3d& eigen_tf,
455 const std::string& parent_frame,
456 const std::string& child_frame)
457{
458 geometry_msgs::msg::TransformStamped output = tf2::eigenToTransform(eigen_tf);
459 output.header.frame_id = parent_frame;
460 output.child_frame_id = child_frame;
461 return output;
462}
463
464PoseCommand poseFromPoseStamped(const geometry_msgs::msg::PoseStamped& msg)
465{
466 PoseCommand command;
467 command.frame_id = msg.header.frame_id;
468
469 const Eigen::Vector3d translation(msg.pose.position.x, msg.pose.position.y, msg.pose.position.z);
470 const Eigen::Quaterniond rotation(msg.pose.orientation.w, msg.pose.orientation.x, msg.pose.orientation.y,
471 msg.pose.orientation.z);
472
473 command.pose = Eigen::Isometry3d::Identity();
474 command.pose.translate(translation);
475 command.pose.linear() = rotation.normalized().toRotationMatrix();
476
477 return command;
478}
479
480planning_scene_monitor::PlanningSceneMonitorPtr createPlanningSceneMonitor(const rclcpp::Node::SharedPtr& node,
481 const servo::Params& servo_params)
482{
483 // Can set robot_description name from parameters
484 std::string robot_description_name = "robot_description";
485 node->get_parameter_or("robot_description_name", robot_description_name, robot_description_name);
486
487 // Set up planning_scene_monitor
488 auto planning_scene_monitor = std::make_shared<planning_scene_monitor::PlanningSceneMonitor>(
489 node, robot_description_name, "planning_scene_monitor");
490
491 planning_scene_monitor->startStateMonitor(servo_params.joint_topic);
492 planning_scene_monitor->startSceneMonitor(servo_params.monitored_planning_scene_topic);
493 planning_scene_monitor->startWorldGeometryMonitor(
496 servo_params.check_octomap_collisions);
497
498 if (servo_params.is_primary_planning_scene_monitor)
499 {
500 planning_scene_monitor->providePlanningSceneService();
501 }
502 else
503 {
504 planning_scene_monitor->requestPlanningSceneState();
505 }
506
507 planning_scene_monitor->setPlanningScenePublishingFrequency(PLANNING_SCENE_PUBLISHING_FREQUENCY);
508 planning_scene_monitor->getStateMonitor()->enableCopyDynamics(true);
510 std::string(node->get_fully_qualified_name()) +
511 "/publish_planning_scene");
512
514}
515
516KinematicState extractRobotState(const moveit::core::RobotStatePtr& robot_state, const std::string& move_group_name)
517{
518 const moveit::core::JointModelGroup* joint_model_group = robot_state->getJointModelGroup(move_group_name);
519 const auto joint_names = joint_model_group->getActiveJointModelNames();
520 KinematicState current_state(joint_names.size());
521 current_state.joint_names = joint_names;
522 robot_state->copyJointGroupPositions(joint_model_group, current_state.positions);
523 robot_state->copyJointGroupVelocities(joint_model_group, current_state.velocities);
524
525 robot_state->copyJointGroupAccelerations(joint_model_group, current_state.accelerations);
526 // If any acceleration is nan, set all accelerations to zero
527 // TODO: fix the root cause so this isn't necessary (#2958)
528 if (std::any_of(current_state.accelerations.begin(), current_state.accelerations.end(),
529 [](double v) { return isnan(v); }))
530 {
531 robot_state->zeroAccelerations();
532 robot_state->copyJointGroupAccelerations(joint_model_group, current_state.accelerations);
533 }
534
535 return current_state;
536}
537
538} // namespace moveit_servo
const std::vector< std::string > & getActiveJointModelNames() const
Get the names of the active joints in this group. These are the names of the joints returned by getJo...
static const std::string DEFAULT_COLLISION_OBJECT_TOPIC
The name of the topic used by default for receiving collision objects in the world.
std::vector< const JointModel::Bounds * > JointBoundsVector
std::optional< std::string > getIKSolverTipFrame(const moveit::core::RobotStatePtr &robot_state, const std::string &group_name)
Get the tip (end-effector) frame of the current active joint group or subgroup's IK solver.
Definition common.cpp:72
std::optional< trajectory_msgs::msg::JointTrajectory > composeTrajectoryMessage(const servo::Params &servo_params, const std::deque< KinematicState > &joint_cmd_rolling_window)
Create a trajectory message from a rolling window queue of joint state commands. Method optionally re...
Definition common.cpp:151
geometry_msgs::msg::Pose poseFromCartesianDelta(const Eigen::VectorXd &delta_x, const Eigen::Isometry3d &base_to_tip_frame_transform)
Create a pose message for the provided change in Cartesian position.
Definition common.cpp:115
std::pair< double, StatusCode > velocityScalingFactorForSingularity(const moveit::core::RobotStatePtr &robot_state, const Eigen::VectorXd &target_delta_x, const servo::Params &servo_params)
Computes scaling factor for velocity when the robot is near a singularity.
Definition common.cpp:282
std::optional< std::string > getIKSolverBaseFrame(const moveit::core::RobotStatePtr &robot_state, const std::string &group_name)
Get the base frame of the current active joint group or subgroup's IK solver.
Definition common.cpp:57
double jointLimitVelocityScalingFactor(const Eigen::VectorXd &velocities, const moveit::core::JointBoundsVector &joint_bounds, double scaling_override)
Apply velocity scaling based on joint limits. If the robot model does not have velocity limits define...
Definition common.cpp:380
std_msgs::msg::Float64MultiArray composeMultiArrayMessage(const servo::Params &servo_params, const KinematicState &joint_state)
Create a Float64MultiArray message from given joint state.
Definition common.cpp:258
bool isValidCommand(const Eigen::VectorXd &command)
Checks if a given VectorXd is a valid command.
Definition common.cpp:87
geometry_msgs::msg::TransformStamped convertIsometryToTransform(const Eigen::Isometry3d &eigen_tf, const std::string &parent_frame, const std::string &child_frame)
Helper function for converting Eigen::Isometry3d to geometry_msgs/TransformStamped.
Definition common.cpp:454
void updateSlidingWindow(KinematicState &next_joint_state, std::deque< KinematicState > &joint_cmd_rolling_window, double max_expected_latency, const rclcpp::Time &cur_time)
Adds a new joint state command to a queue containing commands over a time window. Also modifies the v...
Definition common.cpp:203
constexpr int MIN_POINTS_FOR_TRAJ_MSG
Definition common.hpp:58
std::vector< size_t > jointVariablesToHalt(const Eigen::VectorXd &positions, const Eigen::VectorXd &velocities, const moveit::core::JointBoundsVector &joint_bounds, const std::vector< double > &margins)
Finds the joint variable indices corresponding to joints exceeding allowable position limits.
Definition common.cpp:411
KinematicState extractRobotState(const moveit::core::RobotStatePtr &robot_state, const std::string &move_group_name)
Extract the state from a RobotStatePtr instance.
Definition common.cpp:516
PoseCommand poseFromPoseStamped(const geometry_msgs::msg::PoseStamped &msg)
Convert a PoseStamped message to a Servo Pose.
Definition common.cpp:464
planning_scene_monitor::PlanningSceneMonitorPtr createPlanningSceneMonitor(const rclcpp::Node::SharedPtr &node, const servo::Params &servo_params)
Creates the planning scene monitor used by servo.
Definition common.cpp:480
std::vector< std::string > joint_names
Eigen::VectorXd accelerations
Eigen::Isometry3d pose
Eigen::Vector< double, 6 > velocities
Definition datatypes.hpp:99