36#include <gtest/gtest.h>
43#include <Eigen/Geometry>
44#include <kdl/frames.hpp>
45#include <kdl/path_roundedcomposite.hpp>
46#include <kdl/rotational_interpolation_sa.hpp>
47#include <kdl/trajectory.hpp>
48#include <kdl/trajectory_segment.hpp>
49#include <kdl/velocityprofile_trap.hpp>
54#include <tf2_eigen/tf2_eigen.hpp>
55#include <tf2_geometry_msgs/tf2_geometry_msgs.hpp>
63#define _USE_MATH_DEFINES
65static constexpr double EPSILON{ 1.0e-6 };
66static constexpr double IK_SEED_OFFSET{ 0.1 };
67static constexpr double L0{ 0.2604 };
68static constexpr double L1{ 0.3500 };
69static constexpr double L2{ 0.3070 };
70static constexpr double L3{ 0.0840 };
87 rclcpp::NodeOptions node_options;
88 node_options.automatically_declare_parameters_from_overrides(
true);
89 node_ = rclcpp::Node::make_shared(
"unittest_trajectory_functions", node_options);
92 rm_loader_ = std::make_unique<robot_model_loader::RobotModelLoader>(
node_);
94 ASSERT_TRUE(
bool(
robot_model_)) <<
"Failed to load robot model";
99 ASSERT_TRUE(
node_->has_parameter(
"planning_group"));
101 ASSERT_TRUE(
node_->has_parameter(
"group_tip_link"));
103 ASSERT_TRUE(
node_->has_parameter(
"tcp_link"));
105 ASSERT_TRUE(
node_->has_parameter(
"ik_fast_link"));
107 ASSERT_TRUE(
node_->has_parameter(
"random_test_number"));
133 bool tfNear(
const Eigen::Isometry3d& pose1,
const Eigen::Isometry3d& pose2,
double epsilon);
142 bool jointsNear(
const std::vector<double>& joints1,
const std::vector<double>& joints2,
double epsilon);
161 const std::string& object_name,
const Eigen::Isometry3d& object_pose,
169 std::unique_ptr<robot_model_loader::RobotModelLoader>
rm_loader_;
185 for (std::size_t i = 0; i < 3; ++i)
187 for (std::size_t j = 0; j < 4; ++j)
189 if (fabs(pose1(i, j) - pose2(i, j)) > fabs(epsilon))
199 if (joints1.size() != joints2.size())
203 for (std::size_t i = 0; i < joints1.size(); ++i)
205 if (fabs(joints1.at(i) - joints2.at(i)) > fabs(epsilon))
216 std::vector<double> joints;
225 const std::string& object_name,
const Eigen::Isometry3d& object_pose,
228 state.
attachBody(std::make_unique<moveit::core::AttachedBody>(
229 link, object_name, object_pose, std::vector<shapes::ShapeConstPtr>{}, EigenSTL::vector_Isometry3d{},
230 std::set<std::string>{}, trajectory_msgs::msg::JointTrajectory{}, subframes));
255 Eigen::Isometry3d tip_pose;
256 std::map<std::string, double> test_state = zero_state_;
258 EXPECT_NEAR(tip_pose(0, 3), 0,
EPSILON);
259 EXPECT_NEAR(tip_pose(1, 3), 0,
EPSILON);
260 EXPECT_NEAR(tip_pose(2, 3), L0 + L1 + L2 + L3,
EPSILON);
262 test_state[joint_names_.at(1)] = M_PI_2;
264 EXPECT_NEAR(tip_pose(0, 3), L1 + L2 + L3,
EPSILON);
265 EXPECT_NEAR(tip_pose(1, 3), 0,
EPSILON);
266 EXPECT_NEAR(tip_pose(2, 3), L0,
EPSILON);
268 test_state[joint_names_.at(1)] = -M_PI_2;
269 test_state[joint_names_.at(2)] = M_PI_2;
271 EXPECT_NEAR(tip_pose(0, 3), -L1,
EPSILON);
272 EXPECT_NEAR(tip_pose(1, 3), 0,
EPSILON);
273 EXPECT_NEAR(tip_pose(2, 3), L0 - L2 - L3,
EPSILON);
276 std::string link_name =
"wrong_link_name";
291 throw(
"No IK solver configured for group '" + planning_group_ +
"'");
296 while (random_test_number_ > 0)
301 geometry_msgs::msg::Pose pose_expect = tf2::toMsg(rstate.
getFrameTransform(ik_fast_link_));
304 std::vector<geometry_msgs::msg::Pose> ik_poses;
305 ik_poses.push_back(pose_expect);
306 std::vector<double> ik_seed, ik_expect, ik_actual;
320 std::vector<std::vector<double>> ik_solutions;
322 moveit_msgs::msg::MoveItErrorCodes err_code;
326 EXPECT_TRUE(solver->getPositionIK(ik_poses, ik_seed, ik_solutions, ik_result, options));
329 EXPECT_TRUE(solver->getPositionIK(pose_expect, ik_seed, ik_actual, err_code));
331 ASSERT_EQ(ik_expect.size(), ik_actual.size());
333 for (std::size_t i = 0; i < ik_expect.size(); ++i)
335 EXPECT_NEAR(ik_actual.at(i), ik_expect.at(i), 4 * IK_SEED_OFFSET);
338 --random_test_number_;
352 while (random_test_number_ > 0)
360 std::map<std::string, double> ik_seed, ik_expect;
361 for (
const auto& joint_name : joint_names_)
378 std::map<std::string, double> ik_actual;
380 EXPECT_TRUE(rstate.
setFromIK(robot_model_->getJointModelGroup(planning_group_), pose_expect, tcp_link_));
382 for (
const auto& joint_name : joint_names_)
388 for (
const auto& joint_pair : ik_actual)
390 EXPECT_NEAR(joint_pair.second, ik_expect.at(joint_pair.first), 4 * IK_SEED_OFFSET);
398 EXPECT_TRUE(tfNear(pose_expect, pose_actual,
EPSILON));
400 --random_test_number_;
411 std::vector<double> default_joints = getJoints(jmg, state);
416 Eigen::Isometry3d object_pose_in_tip = Eigen::Isometry3d::Identity();
418 attachToLink(state, tip_link,
"object", object_pose_in_tip, subframes);
421 Eigen::Isometry3d object_pose_in_base = tip_pose_in_base * object_pose_in_tip;
422 bool success = state.
setFromIK(jmg, object_pose_in_base,
"object");
423 EXPECT_TRUE(success);
426 std::vector<double> ik_joints = getJoints(jmg, state);
427 EXPECT_TRUE(jointsNear(ik_joints, default_joints, 4 * IK_SEED_OFFSET));
437 std::vector<double> default_joints = getJoints(jmg, state);
442 Eigen::Isometry3d object_pose_in_tip;
443 object_pose_in_tip = Eigen::Translation3d(1, 2, 3);
444 object_pose_in_tip *= Eigen::AngleAxis(M_PI_2, Eigen::Vector3d::UnitX());
446 attachToLink(state, tip_link,
"object", object_pose_in_tip, subframes);
449 Eigen::Isometry3d object_pose_in_base = tip_pose_in_base * object_pose_in_tip;
450 bool success = state.
setFromIK(jmg, object_pose_in_base,
"object");
451 EXPECT_TRUE(success);
454 std::vector<double> ik_joints = getJoints(jmg, state);
455 EXPECT_TRUE(jointsNear(ik_joints, default_joints, 4 * IK_SEED_OFFSET));
465 std::vector<double> default_joints = getJoints(jmg, state);
470 Eigen::Isometry3d object_pose_in_tip = Eigen::Isometry3d::Identity();
471 Eigen::Isometry3d subframe_pose_in_object = Eigen::Isometry3d::Identity();
473 attachToLink(state, tip_link,
"object", object_pose_in_tip, subframes);
476 Eigen::Isometry3d subframe_pose_in_base = tip_pose_in_base * object_pose_in_tip * subframe_pose_in_object;
477 bool success = state.
setFromIK(jmg, subframe_pose_in_base,
"object/subframe");
478 EXPECT_TRUE(success);
481 std::vector<double> ik_joints = getJoints(jmg, state);
482 EXPECT_TRUE(jointsNear(ik_joints, default_joints, 4 * IK_SEED_OFFSET));
492 std::vector<double> default_joints = getJoints(jmg, state);
497 Eigen::Isometry3d object_pose_in_tip;
498 object_pose_in_tip = Eigen::Translation3d(1, 2, 3);
499 object_pose_in_tip *= Eigen::AngleAxis(M_PI_2, Eigen::Vector3d::UnitX());
501 Eigen::Isometry3d subframe_pose_in_object;
502 subframe_pose_in_object = Eigen::Translation3d(4, 5, 6);
503 subframe_pose_in_object *= Eigen::AngleAxis(M_PI_2, Eigen::Vector3d::UnitY());
506 attachToLink(state, tip_link,
"object", object_pose_in_tip, subframes);
509 Eigen::Isometry3d subframe_pose_in_base = tip_pose_in_base * object_pose_in_tip * subframe_pose_in_object;
510 bool success = state.
setFromIK(jmg, subframe_pose_in_base,
"object/subframe");
511 EXPECT_TRUE(success);
514 std::vector<double> ik_joints = getJoints(jmg, state);
515 EXPECT_TRUE(jointsNear(ik_joints, default_joints, 4 * IK_SEED_OFFSET));
527 const std::string frame_id = robot_model_->getModelFrame();
530 while (random_test_number_ > 0)
538 std::map<std::string, double> ik_seed, ik_expect;
539 for (
const auto& joint_name : robot_model_->getJointModelGroup(planning_group_)->getActiveJointModelNames())
553 std::map<std::string, double> ik_actual;
555 frame_id, ik_seed, ik_actual,
false));
558 for (
const auto& joint_pair : ik_actual)
560 EXPECT_NEAR(joint_pair.second, ik_expect.at(joint_pair.first), 4 * IK_SEED_OFFSET);
563 --random_test_number_;
572 const std::string frame_id = robot_model_->getModelFrame();
573 Eigen::Isometry3d pose_expect;
575 std::map<std::string, double> ik_seed;
578 std::map<std::string, double> ik_actual;
580 pose_expect, frame_id, ik_seed, ik_actual,
false));
588 const std::string frame_id = robot_model_->getModelFrame();
589 Eigen::Isometry3d pose_expect;
591 std::map<std::string, double> ik_seed;
594 std::map<std::string, double> ik_actual;
596 frame_id, ik_seed, ik_actual,
false));
606 Eigen::Isometry3d pose_expect;
608 std::map<std::string, double> ik_seed;
611 std::map<std::string, double> ik_actual;
613 "InvalidFrameId", ik_seed, ik_actual,
false));
698 const std::string frame_id = robot_model_->getModelFrame();
702 std::map<std::string, double> ik_seed;
705 ik_seed[joint_name] = 0;
709 std::vector<double> ik_goal = { 0, 2.3, -2.3, 0, 0, 0 };
716 std::map<std::string, double> ik_actual;
718 frame_id, ik_seed, ik_actual,
false));
722 frame_id, ik_seed, ik_actual,
true));
737 const std::map<std::string, double> position_last, velocity_last, position_current;
738 double duration_last{ 0.0 };
741 double duration_current = 10e-7;
759 const std::string test_joint_name{
"joint" };
761 std::map<std::string, double> position_last{ { test_joint_name, 2.0 } };
762 std::map<std::string, double> position_current{ { test_joint_name, 10.0 } };
763 std::map<std::string, double> velocity_last;
764 double duration_current{ 1.0 };
765 double duration_last{ 0.0 };
772 ((position_current.at(test_joint_name) - position_last.at(test_joint_name)) / duration_current) - 1.0;
774 joint_limits.addLimit(test_joint_name, test_joint_limits);
792 const std::string test_joint_name{
"joint" };
794 double duration_current = 1.0;
795 double duration_last = 1.0;
797 std::map<std::string, double> position_last{ { test_joint_name, 2.0 } };
798 std::map<std::string, double> position_current{ { test_joint_name, 20.0 } };
799 double velocity_current =
800 ((position_current.at(test_joint_name) - position_last.at(test_joint_name)) / duration_current);
801 std::map<std::string, double> velocity_last{ { test_joint_name, 9.0 } };
807 test_joint_limits.
max_velocity = velocity_current + 1.0;
810 double acceleration_current =
811 (velocity_current - velocity_last.at(test_joint_name)) / (duration_last + duration_current) * 2;
817 joint_limits.addLimit(test_joint_name, test_joint_limits);
835 const std::string test_joint_name{
"joint" };
837 double duration_current = 1.0;
838 double duration_last = 1.0;
840 std::map<std::string, double> position_last{ { test_joint_name, 20.0 } };
841 std::map<std::string, double> position_current{ { test_joint_name, 2.0 } };
842 double velocity_current =
843 ((position_current.at(test_joint_name) - position_last.at(test_joint_name)) / duration_current);
844 std::map<std::string, double> velocity_last{ { test_joint_name, 19.0 } };
850 test_joint_limits.
max_velocity = fabs(velocity_current) + 1.0;
853 double acceleration_current =
854 (velocity_current - velocity_last.at(test_joint_name)) / (duration_last + duration_current) * 2;
860 joint_limits.addLimit(test_joint_name, test_joint_limits);
884 KDL::Path_RoundedComposite* path =
885 new KDL::Path_RoundedComposite(0.2, 0.01,
new KDL::RotationalInterpolation_SingleAxis());
886 path->Add(KDL::Frame(KDL::Rotation::RPY(0, 0, 0), KDL::Vector(-1, 0, 0)));
889 KDL::VelocityProfile* vel_prof =
new KDL::VelocityProfile_Trap(0.5, 0.1);
890 vel_prof->SetProfile(0, path->PathLength());
891 KDL::Trajectory_Segment kdl_trajectory(path, vel_prof);
894 std::string group_name{
"invalid_group_name" };
895 std::map<std::string, double> initial_joint_position;
896 double sampling_time{ 0.1 };
897 trajectory_msgs::msg::JointTrajectory joint_trajectory;
898 moveit_msgs::msg::MoveItErrorCodes error_code;
899 bool check_self_collision{
false };
902 planning_scene_,
joint_limits, kdl_trajectory, group_name, tcp_link_, initial_joint_position, sampling_time,
903 joint_trajectory, error_code, check_self_collision));
905 std::map<std::string, double> initial_joint_velocity;
911 cart_traj.
points.push_back(cart_traj_point);
914 planning_scene_,
joint_limits, cart_traj, group_name, tcp_link_, initial_joint_position, initial_joint_velocity,
915 joint_trajectory, error_code, check_self_collision));
931 robot_trajectory::RobotTrajectoryPtr first_trajectory =
932 std::make_shared<robot_trajectory::RobotTrajectory>(robot_model_, planning_group_);
933 robot_trajectory::RobotTrajectoryPtr second_trajectory =
934 std::make_shared<robot_trajectory::RobotTrajectory>(robot_model_, planning_group_);
935 double epsilon{ 0.0 };
936 double sampling_time{ 0.0 };
939 first_trajectory->insertWayPoint(0, rstate, 0.1);
940 second_trajectory->insertWayPoint(0, rstate, 0.1);
943 epsilon, sampling_time));
959 robot_trajectory::RobotTrajectoryPtr first_trajectory =
960 std::make_shared<robot_trajectory::RobotTrajectory>(robot_model_, planning_group_);
961 robot_trajectory::RobotTrajectoryPtr second_trajectory =
962 std::make_shared<robot_trajectory::RobotTrajectory>(robot_model_, planning_group_);
963 double epsilon{ 0.0001 };
964 double sampling_time{ 0.0 };
965 double expected_sampling_time{ 0.1 };
968 first_trajectory->insertWayPoint(0, rstate, expected_sampling_time);
969 first_trajectory->insertWayPoint(1, rstate, expected_sampling_time);
971 second_trajectory->insertWayPoint(0, rstate, expected_sampling_time);
972 second_trajectory->insertWayPoint(1, rstate, expected_sampling_time);
973 second_trajectory->insertWayPoint(2, rstate, expected_sampling_time);
976 epsilon, sampling_time));
977 EXPECT_EQ(expected_sampling_time, sampling_time);
993 robot_trajectory::RobotTrajectoryPtr first_trajectory =
994 std::make_shared<robot_trajectory::RobotTrajectory>(robot_model_, planning_group_);
995 robot_trajectory::RobotTrajectoryPtr second_trajectory =
996 std::make_shared<robot_trajectory::RobotTrajectory>(robot_model_, planning_group_);
997 double epsilon{ 0.0001 };
998 double sampling_time{ 0.0 };
999 double expected_sampling_time{ 0.1 };
1002 first_trajectory->insertWayPoint(0, rstate, expected_sampling_time);
1003 first_trajectory->insertWayPoint(1, rstate, expected_sampling_time);
1004 first_trajectory->insertWayPoint(2, rstate, expected_sampling_time);
1006 first_trajectory->insertWayPoint(2, rstate, expected_sampling_time + 1.0);
1007 first_trajectory->insertWayPoint(3, rstate, expected_sampling_time);
1009 second_trajectory->insertWayPoint(0, rstate, expected_sampling_time);
1010 second_trajectory->insertWayPoint(1, rstate, expected_sampling_time);
1011 second_trajectory->insertWayPoint(2, rstate, expected_sampling_time);
1012 second_trajectory->insertWayPoint(3, rstate, expected_sampling_time);
1015 epsilon, sampling_time));
1016 EXPECT_EQ(expected_sampling_time, sampling_time);
1035 double default_joint_position[6] = { 0.0, 0.0, 0.0, 0.0, 0.0, 0.0 };
1038 default_joint_position[0] = default_joint_position[0] + 70.0;
1041 double epsilon{ 0.0001 };
1062 double default_joint_position[6] = { 0.0, 0.0, 0.0, 0.0, 0.0, 0.0 };
1066 double default_joint_velocity[6] = { 0.0, 0.0, 0.0, 0.0, 0.0, 0.0 };
1069 default_joint_velocity[1] = default_joint_velocity[1] + 10.0;
1072 double epsilon{ 0.0001 };
1093 double default_joint_position[6] = { 0.0, 0.0, 0.0, 0.0, 0.0, 0.0 };
1098 double default_joint_velocity[6] = { 0.0, 0.0, 0.0, 0.0, 0.0, 0.0 };
1102 double default_joint_acceleration[6] = { 0.0, 0.0, 0.0, 0.0, 0.0, 0.0 };
1105 default_joint_acceleration[1] = default_joint_acceleration[1] + 10.0;
1108 double epsilon{ 0.0001 };
1128 double default_joint_velocity[6] = { 1.0, 0.0, 0.0, 0.0, 0.0, 0.0 };
1131 double epsilon{ 0.0001 };
1151 double default_joint_velocity[6] = { 0.0, 0.0, 0.0, 0.0, 0.0, 0.0 };
1155 double default_joint_acceleration[6] = { 1.0, 0.0, 0.0, 0.0, 0.0, 0.0 };
1158 double epsilon{ 0.0001 };
1164 rclcpp::init(argc, argv);
1165 testing::InitGoogleTest(&argc, argv);
1166 return RUN_ALL_TESTS();
std::unique_ptr< robot_model_loader::RobotModelLoader > rm_loader_
std::vector< double > getJoints(const moveit::core::JointModelGroup *jmg, const moveit::core::RobotState &state)
get the current joint values of the robot state
void SetUp() override
Create test scenario for trajectory functions.
std::string group_tip_link_
rclcpp::Node::SharedPtr node_
std::string planning_group_
random_numbers::RandomNumberGenerator rng_
void attachToLink(moveit::core::RobotState &state, const moveit::core::LinkModel *link, const std::string &object_name, const Eigen::Isometry3d &object_pose, const moveit::core::FixedTransformsMap &subframes)
attach a collision object and subframes to a link
std::string ik_fast_link_
moveit::core::RobotModelConstPtr robot_model_
std::map< std::string, double > zero_state_
planning_scene::PlanningSceneConstPtr planning_scene_
bool tfNear(const Eigen::Isometry3d &pose1, const Eigen::Isometry3d &pose2, double epsilon)
check if two transformations are close
bool jointsNear(const std::vector< double > &joints1, const std::vector< double > &joints2, double epsilon)
check if two sets of joint positions are close
std::vector< std::string > joint_names_
moveit::core::RobotStatePtr robot_state_
Parametrized class for tests with and without gripper.
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...
const kinematics::KinematicsBaseConstPtr getSolverInstance() const
A link from the robot. Contains the constant transform applied to the link and its geometry.
Representation of a robot's state. This includes position, velocity, acceleration and effort.
void setVariablePositions(const double *position)
It is assumed positions is an array containing the new positions for all variables in this state....
void attachBody(std::unique_ptr< AttachedBody > attached_body)
Add an attached body to this state.
void setJointGroupAccelerations(const std::string &joint_group_name, const double *gstate)
Given accelerations for the variables that make up a group, in the order found in the group (includin...
void setJointGroupVelocities(const std::string &joint_group_name, const double *gstate)
Given velocities for the variables that make up a group, in the order found in the group (including v...
void setJointGroupPositions(const std::string &joint_group_name, const double *gstate)
Given positions for the variables that make up a group, in the order found in the group (including va...
const Eigen::Isometry3d & getFrameTransform(const std::string &frame_id, bool *frame_found=nullptr)
Get the transformation matrix from the model frame (root of model) to the frame identified by frame_i...
void setToRandomPositions()
Set all joints to random values. Values will be within default bounds.
double getVariablePosition(const std::string &variable) const
Get the position of a particular variable. An exception is thrown if the variable is not known.
void update(bool force=false)
Update all transforms.
void setToDefaultValues()
Set all joints to their default positions. The default position is 0, or if that is not within bounds...
bool setFromIK(const JointModelGroup *group, const geometry_msgs::msg::Pose &pose, double timeout=0.0, const GroupStateValidityCallbackFn &constraint=GroupStateValidityCallbackFn(), const kinematics::KinematicsQueryOptions &options=kinematics::KinematicsQueryOptions(), const kinematics::KinematicsBase::IKCostFn &cost_function=kinematics::KinematicsBase::IKCostFn())
If the group this state corresponds to is a chain and a solver is available, then the joint values ca...
Container for JointLimits, essentially a map with convenience functions. Adds the ability to as for l...
std::map< std::string, Eigen::Isometry3d, std::less< std::string >, Eigen::aligned_allocator< std::pair< const std::string, Eigen::Isometry3d > > > FixedTransformsMap
Map frame names to the transformation matrix that can transform objects from the frame name to the pl...
bool computeLinkFK(moveit::core::RobotState &robot_state, const std::string &link_name, const std::map< std::string, double > &joint_state, Eigen::Isometry3d &pose)
compute the pose of a link at a given robot state
joint_limits_interface::JointLimits JointLimit
bool isRobotStateStationary(const moveit::core::RobotState &state, const std::string &group, double EPSILON)
check if the robot state have zero velocity/acceleration
bool determineAndCheckSamplingTime(const robot_trajectory::RobotTrajectoryPtr &first_trajectory, const robot_trajectory::RobotTrajectoryPtr &second_trajectory, double EPSILON, double &sampling_time)
Determines the sampling time and checks that both trajectroies use the same sampling time.
bool verifySampleJointLimits(const std::map< std::string, double > &position_last, const std::map< std::string, double > &velocity_last, const std::map< std::string, double > &position_current, double duration_last, double duration_current, const JointLimitsContainer &joint_limits)
verify the velocity/acceleration limits of current sample (based on backward difference computation) ...
bool generateJointTrajectory(const planning_scene::PlanningSceneConstPtr &scene, const JointLimitsContainer &joint_limits, const KDL::Trajectory &trajectory, const std::string &group_name, const std::string &link_name, const std::map< std::string, double > &initial_joint_position, double sampling_time, trajectory_msgs::msg::JointTrajectory &joint_trajectory, moveit_msgs::msg::MoveItErrorCodes &error_code, bool check_self_collision=false)
Generate joint trajectory from a KDL Cartesian trajectory.
bool computePoseIK(const planning_scene::PlanningSceneConstPtr &scene, const std::string &group_name, const std::string &link_name, const Eigen::Isometry3d &pose, const std::string &frame_id, const std::map< std::string, double > &seed, std::map< std::string, double > &solution, bool check_self_collision=true, const double timeout=0.0)
compute the inverse kinematics of a given pose, also check robot self collision
bool isRobotStateEqual(const moveit::core::RobotState &state1, const moveit::core::RobotState &state2, const std::string &joint_group_name, double epsilon)
Check if the two robot states have the same joint position/velocity/acceleration.
void checkRobotModel(const moveit::core::RobotModelConstPtr &robot_model, const std::string &group_name, const std::string &link_name)
bool has_acceleration_limits
A set of options for the kinematics solver.
std::vector< CartesianTrajectoryPoint > points
bool has_deceleration_limits
double max_deceleration
maximum deceleration MUST(!) be negative
const std::string RANDOM_TEST_NUMBER("random_test_number")
int main(int argc, char **argv)
TEST_F(TrajectoryFunctionsTestFlangeAndGripper, TipLinkFK)
Parametrized class for tests, that only run with a gripper.