39#include <urdf_parser/urdf_parser.h>
40#include <tf2_geometry_msgs/tf2_geometry_msgs.hpp>
41#include <gtest/gtest.h>
42#include <gmock/gmock-matchers.h>
49constexpr double EPSILON{ 1.e-9 };
53Eigen::VectorXd makeVector(
const std::vector<double>& values)
55 Eigen::VectorXd vector = Eigen::VectorXd::Zero(values.size());
56 for (std::size_t i = 0; i < values.size(); i++)
58 vector[i] = values[i];
65 const Eigen::VectorXd& joint_values,
const Eigen::VectorXd& joint_velocities,
83 Eigen::MatrixXd jacobian;
84 state.
getJacobian(&joint_model_group, reference_link, Eigen::Vector3d::Zero(), jacobian);
87 const std::vector<const moveit::core::JointModel*>& joint_models = joint_model_group.
getJointModels();
89 return jm->getParentLinkModel() == reference_link;
91 if (it != joint_models.end())
93 std::size_t index = 0;
94 for (
auto jt = joint_models.begin(); jt != it; ++jt)
96 index += (*jt)->getVariableCount();
99 EXPECT_TRUE(jacobian.block(0, index, jacobian.rows(), jacobian.cols() - index).isZero())
100 <<
"Jacobian contains non-zero values for joints that are not used based on the reference link "
101 << reference_link->getName() <<
". This is the faulty Jacobian: " <<
'\n'
103 <<
"The columns " << index <<
" to " << jacobian.cols() <<
" should be zero. Instead the values are: " <<
'\n'
104 << jacobian.block(0, index, jacobian.rows(), jacobian.cols() - index);
108 const Eigen::VectorXd cartesian_velocity = jacobian * joint_velocities;
112 constexpr double time_step = 1e-5;
113 const Eigen::VectorXd delta_joint_angles = time_step * joint_velocities;
116 const Eigen::Isometry3d tip_pose_after_delta = root_pose_world * state.
getGlobalLinkTransform(reference_link);
117 const Eigen::Vector3d displacement = tip_pose_after_delta.translation() - tip_pose_initial.translation();
121 double angle = std::acos(displacement.dot(cartesian_velocity.head<3>()) /
122 (displacement.norm() * cartesian_velocity.head<3>().norm()));
123 EXPECT_NEAR(angle, 0.0, 1e-05) <<
"Angle between Cartesian velocity and Cartesian displacement larger than expected. "
125 << angle <<
". displacement: " << displacement.transpose()
126 <<
". Cartesian velocity: " << cartesian_velocity.head<3>().transpose() <<
'\n';
130static void expect_near(
const Eigen::MatrixXd& x,
const Eigen::MatrixXd& y,
131 double eps = std::numeric_limits<double>::epsilon())
133 ASSERT_EQ(x.rows(), y.rows());
134 ASSERT_EQ(x.cols(), y.cols());
135 for (
int r = 0; r < x.rows(); ++r)
137 for (
int c = 0; c < x.cols(); ++c)
138 EXPECT_NEAR(x(r, c), y(r, c), eps) <<
"(r,c) = (" << r <<
',' << c <<
')';
143#define EXPECT_NEAR_TRACED(...) { \
144 SCOPED_TRACE("expect_near(" #__VA_ARGS__ ")"); \
145 expect_near(__VA_ARGS__); \
152 builder.
addVirtualJoint(
"odom_combined",
"base_link",
"floating",
"base_joint");
153 ASSERT_TRUE(builder.
isValid());
154 moveit::core::RobotModelPtr model = builder.
build();
164 EXPECT_EQ(std::string(
"myrobot"), model->getName());
167 const std::vector<moveit::core::LinkModel*>& links = model->getLinkModels();
168 EXPECT_EQ(1u, links.size());
170 const std::vector<moveit::core::JointModel*>& joints = model->getJointModels();
171 EXPECT_EQ(1u, joints.size());
173 const std::vector<std::string>& pgroups = model->getJointModelGroupNames();
174 EXPECT_EQ(0u, pgroups.size());
180 geometry_msgs::msg::Pose pose;
181 pose.position.x = -0.1;
187 pose.orientation = tf2::toMsg(q);
193 pose.orientation = tf2::toMsg(q);
196 pose.position.y = 0.099;
199 pose.orientation = tf2::toMsg(q);
200 builder.
addInertial(
"base_link", 2.81, pose, 0.1, -0.2, 0.5, -0.09, 1, 0.101);
201 builder.
addVirtualJoint(
"odom_combined",
"base_link",
"planar",
"base_joint");
202 builder.
addGroup({}, {
"base_joint" },
"base");
204 ASSERT_TRUE(builder.
isValid());
205 moveit::core::RobotModelPtr model = builder.
build();
212 EXPECT_EQ(1u,
static_cast<unsigned int>(model->getJointModelCount()));
213 EXPECT_EQ(3u,
static_cast<unsigned int>(model->getJointModels()[0]->getLocalVariableNames().size()));
215 std::map<std::string, double> joint_values;
216 joint_values[
"base_joint/x"] = 10.0;
217 joint_values[
"base_joint/y"] = 8.0;
220 std::vector<std::string> missing_states;
222 ASSERT_EQ(missing_states.size(), 1u);
223 EXPECT_EQ(missing_states[0], std::string(
"base_joint/theta"));
224 joint_values[
"base_joint/theta"] = 0.1;
227 ASSERT_EQ(missing_states.size(), 0u);
233 const auto new_state = std::make_unique<moveit::core::RobotState>(state);
237 jv[state.
getRobotModel()->getVariableIndex(
"base_joint/x")] = 5.0;
238 jv[state.
getRobotModel()->getVariableIndex(
"base_joint/y")] = 4.0;
239 jv[state.
getRobotModel()->getVariableIndex(
"base_joint/theta")] = 0.0;
250 static const std::string MODEL2 = R
"(
251<?xml version="1.0" ?>
252<robot name="one_robot">
253<link name="base_link">
256 <origin rpy="0 0 0" xyz="0.0 0.0 .0"/>
257 <inertia ixx="0.1" ixy="-0.2" ixz="0.5" iyy="-.09" iyz="1" izz="0.101"/>
259 <collision name="my_collision">
260 <origin rpy="0 0 0" xyz="0 0 0"/>
266 <origin rpy="0 0 0" xyz="0.0 0 0"/>
272<joint name="joint_a" type="continuous">
274 <parent link="base_link"/>
275 <child link="link_a"/>
276 <origin rpy=" 0.0 0 0 " xyz="0.0 0 0 "/>
281 <origin rpy="0 0 0" xyz="0.0 0.0 .0"/>
282 <inertia ixx="0.1" ixy="-0.2" ixz="0.5" iyy="-.09" iyz="1" izz="0.101"/>
285 <origin rpy="0 0 0" xyz="0 0 0"/>
291 <origin rpy="0 0 0" xyz="0.0 0 0"/>
297<joint name="joint_b" type="fixed">
298 <parent link="link_a"/>
299 <child link="link_b"/>
300 <origin rpy=" 0.0 -0.42 0 " xyz="0.0 0.5 0 "/>
305 <origin rpy="0 0 0" xyz="0.0 0.0 .0"/>
306 <inertia ixx="0.1" ixy="-0.2" ixz="0.5" iyy="-.09" iyz="1" izz="0.101"/>
309 <origin rpy="0 0 0" xyz="0 0 0"/>
315 <origin rpy="0 0 0" xyz="0.0 0 0"/>
321 <joint name="joint_c" type="prismatic">
323 <limit effort="100.0" lower="0.0" upper="0.09" velocity="0.2"/>
324 <safety_controller k_position="20.0" k_velocity="500.0" soft_lower_limit="0.0"
325soft_upper_limit="0.089"/>
326 <parent link="link_b"/>
327 <child link="link_c"/>
328 <origin rpy=" 0.0 0.42 0.0 " xyz="0.0 -0.1 0 "/>
333 <origin rpy="0 0 0" xyz="0.0 0 .0"/>
334 <inertia ixx="0.1" ixy="-0.2" ixz="0.5" iyy="-.09" iyz="1" izz="0.101"/>
337 <origin rpy="0 0 0" xyz="0 0 0"/>
343 <origin rpy="0 0 0" xyz="0.0 0 0"/>
349 <joint name="mim_f" type="prismatic">
351 <limit effort="100.0" lower="0.0" upper="0.19" velocity="0.2"/>
352 <parent link="link_c"/>
353 <child link="link_d"/>
354 <origin rpy=" 0.0 0.0 0.0 " xyz="0.1 0.1 0 "/>
355 <mimic joint="joint_f" multiplier="1.5" offset="0.1"/>
357 <joint name="joint_f" type="prismatic">
359 <limit effort="100.0" lower="0.0" upper="0.19" velocity="0.2"/>
360 <parent link="link_d"/>
361 <child link="link_e"/>
362 <origin rpy=" 0.0 0.0 0.0 " xyz="0.1 0.1 0 "/>
366 <origin rpy="0 0 0" xyz="0 0 0"/>
372 <origin rpy="0 1 0" xyz="0 0.1 0"/>
380 <origin rpy="0 0 0" xyz="0 0 0"/>
386 <origin rpy="0 1 0" xyz="0 0.1 0"/>
392<link name="link/with/slash" />
393<joint name="joint_link_with_slash" type="fixed">
394 <parent link="base_link"/>
395 <child link="link/with/slash"/>
396 <origin rpy="0 0 0" xyz="0 0 0"/>
400 static const std::string SMODEL2 = R
"(
401<?xml version="1.0" ?>
402<robot name="one_robot">
403<virtual_joint name="base_joint" child_link="base_link" parent_frame="odom_combined" type="planar"/>
404<group name="base_from_joints">
405<joint name="base_joint"/>
406<joint name="joint_a"/>
407<joint name="joint_c"/>
409<group name="mim_joints">
410<joint name="joint_f"/>
413<group name="base_with_subgroups">
414<group name="base_from_base_to_tip"/>
415<joint name="joint_c"/>
417<group name="base_from_base_to_tip">
418<chain base_link="base_link" tip_link="link_b"/>
419<joint name="base_joint"/>
421<group name="base_from_base_to_e">
422<chain base_link="base_link" tip_link="link_e"/>
423<joint name="base_joint"/>
425<group name="base_with_bad_subgroups">
431 urdf::ModelInterfaceSharedPtr urdf_model = urdf::parseURDF(MODEL2);
432 auto srdf_model = std::make_shared<srdf::Model>();
433 srdf_model->initString(*urdf_model, SMODEL2);
434 robot_model_ = std::make_shared<moveit::core::RobotModel>(urdf_model, srdf_model);
475 moveit::core::RobotModelConstPtr model = robot_model_;
484 ASSERT_TRUE(g_one !=
nullptr);
485 ASSERT_TRUE(g_two !=
nullptr);
486 ASSERT_TRUE(g_three !=
nullptr);
487 ASSERT_TRUE(g_four ==
nullptr);
489 EXPECT_THAT(g_one->
getJointModelNames(), ::testing::ElementsAreArray({
"base_joint",
"joint_a",
"joint_c" }));
490 EXPECT_THAT(g_two->
getJointModelNames(), ::testing::ElementsAreArray({
"base_joint",
"joint_a",
"joint_b" }));
492 ::testing::ElementsAreArray({
"base_joint",
"joint_a",
"joint_b",
"joint_c" }));
493 EXPECT_THAT(g_mim->
getJointModelNames(), ::testing::ElementsAreArray({
"mim_f",
"joint_f" }));
495 EXPECT_THAT(g_one->
getLinkModelNames(), ::testing::ElementsAreArray({
"base_link",
"link_a",
"link_c" }));
496 EXPECT_THAT(g_two->
getLinkModelNames(), ::testing::ElementsAreArray({
"base_link",
"link_a",
"link_b" }));
497 EXPECT_THAT(g_three->
getLinkModelNames(), ::testing::ElementsAreArray({
"base_link",
"link_a",
"link_b",
"link_c" }));
500 auto updated_link_model_names = {
"base_link",
"link_a",
"link_b",
"link_c",
"link_d",
"link_e",
"link/with/slash" };
511 std::map<std::string, double> joint_values;
512 joint_values[
"base_joint/x"] = 1.0;
513 joint_values[
"base_joint/y"] = 1.0;
514 joint_values[
"base_joint/theta"] = 0.5;
515 joint_values[
"joint_a"] = -0.5;
516 joint_values[
"joint_c"] = 0.08;
545 std::map<std::string, double> upd_a;
546 upd_a[
"joint_a"] = 0.2;
553 upd_a[
"joint_a"] = 3.2;
585 EXPECT_NEAR(mim_f, 1.5 * joint_f + 0.1, 1e-8);
590 Eigen::Vector3d(0.1 + mim_f + joint_f + 0.1, 0.6, 0));
606 ASSERT_TRUE(joint_model_group);
610 std::cout <<
"\nVisual inspection should show NO joints out of bounds:\n";
613 std::cout <<
"\nVisual inspection should show ONE joint out of bounds:\n";
614 std::vector<double> single_joint(1);
615 single_joint[0] = -1.0;
619 std::cout <<
"\nVisual inspection should show TWO joint out of bounds:\n";
620 single_joint[0] = 1.0;
624 std::cout <<
"\nVisual inspection should show ONE joint out of bounds:\n";
625 single_joint[0] = 0.19;
638 for (
size_t i = 0; i <= 10; ++i)
640 state_a.
interpolate(state_b,
static_cast<double>(i) / 10., interpolated_state,
642 EXPECT_NEAR(state_a.
distance(state_b), 0,
EPSILON) <<
"Interpolation between identical states yielded a different "
645 for (
const auto& link_name : robot_model_->getLinkModelNames())
655 std::map<std::string, double> joint_values;
656 joint_values[
"base_joint/x"] = 1.0;
657 joint_values[
"base_joint/y"] = 1.0;
659 joint_values[
"base_joint/x"] = 0.0;
660 joint_values[
"base_joint/y"] = 2.0;
662 EXPECT_NEAR(3 * std::sqrt(2), state_a.
distance(state_b),
EPSILON) <<
"Simple interpolation of base_joint failed.";
665 EXPECT_NEAR(0., state_a.
distance(interpolated_state) - state_b.
distance(interpolated_state),
EPSILON) <<
"Simple "
671 "base_joint failed.";
673 "base_joint failed.";
676 "base_joint failed.";
678 "base_joint failed.";
681 joint_values[
"base_joint/x"] = 0.0;
682 joint_values[
"base_joint/y"] = 20.0;
683 joint_values[
"base_joint/theta"] = 3 * M_PI / 4;
684 joint_values[
"joint_a"] = -4 * M_PI / 5;
685 joint_values[
"joint_c"] = 0.0;
686 joint_values[
"joint_f"] = 1.0;
689 joint_values[
"base_joint/x"] = 10.0;
690 joint_values[
"base_joint/y"] = 0.0;
691 joint_values[
"base_joint/theta"] = -3 * M_PI / 4;
692 joint_values[
"joint_a"] = 4 * M_PI / 5;
693 joint_values[
"joint_c"] = 0.07;
694 joint_values[
"joint_f"] = 0.0;
697 for (
size_t i = 0; i <= 5; ++i)
699 double t =
static_cast<double>(i) / 5.;
702 "interpolation failed.";
709 <<
"Base joint theta interpolation failed.";
711 <<
"Continuous joint interpolation failed.";
715 EXPECT_NEAR(-3 * M_PI / 4 - (M_PI / 2) * (1 - t), interpolated_state.
getVariablePosition(
"base_joint/theta"),
717 <<
"Base joint theta interpolation failed.";
719 <<
"Continuous joint interpolation failed.";
730 bool nan_exception =
false;
735 catch (std::exception& e)
737 std::cout <<
"Caught expected exception: " << e.what() <<
'\n';
738 nan_exception =
true;
740 EXPECT_TRUE(nan_exception) <<
"NaN interpolation parameter did not create expected exception.";
747 EXPECT_EQ(robot_model_->getRigidlyConnectedParentLinkModel(link_e), link_e);
752 EXPECT_EQ(robot_model_->getRigidlyConnectedParentLinkModel(link_b), link_a);
757 Eigen::Isometry3d a_to_b;
761 state.
attachBody(std::make_unique<moveit::core::AttachedBody>(
762 link_b,
"object", Eigen::Isometry3d(Eigen::Translation3d(1, 0, 0)), std::vector<shapes::ShapeConstPtr>{},
763 EigenSTL::vector_Isometry3d{}, std::set<std::string>{}, trajectory_msgs::msg::JointTrajectory{},
767 Eigen::Isometry3d transform;
780 EXPECT_TRUE(link_with_slash);
783 ASSERT_TRUE(rigid_parent_of_link_with_slash);
784 EXPECT_EQ(
"base_link", rigid_parent_of_link_with_slash->
getName());
787 state.
attachBody(std::make_unique<moveit::core::AttachedBody>(
788 link_with_slash,
"object/with/slash", Eigen::Isometry3d(Eigen::Translation3d(1, 0, 0)),
789 std::vector<shapes::ShapeConstPtr>{}, EigenSTL::vector_Isometry3d{}, std::set<std::string>{},
790 trajectory_msgs::msg::JointTrajectory{},
794 ASSERT_TRUE(rigid_parent_of_object);
795 EXPECT_EQ(rigid_parent_of_link_with_slash, rigid_parent_of_object);
798TEST(getJacobian, RevoluteJoints)
801 constexpr char robot_urdf[] = R
"(
802 <?xml version="1.0" ?>
803 <robot name="one_robot">
804 <link name="base_link"/>
805 <joint name="joint_a_revolute" type="revolute">
807 <parent link="base_link"/>
808 <child link="link_a"/>
809 <origin rpy="0 0 0" xyz="0 0 0"/>
810 <limit effort="100.0" lower="-3.14" upper="3.14" velocity="0.2"/>
812 <link name="link_a"/>
813 <joint name="joint_b_revolute" type="revolute">
815 <parent link="link_a"/>
816 <child link="link_b"/>
817 <origin rpy="0 0 0" xyz="0.0 0.5 0"/>
818 <limit effort="100.0" lower="-3.14" upper="3.14" velocity="0.2"/>
820 <link name="link_b"/>
821 <joint name="joint_c_revolute" type="revolute">
823 <parent link="link_b"/>
824 <child link="link_c"/>
825 <origin rpy="0 0 0" xyz="0.2 0.2 0"/>
826 <limit effort="100.0" lower="-3.14" upper="3.14" velocity="0.2"/>
828 <link name="link_c"/>
829 <joint name="joint_d_revolute" type="revolute">
831 <parent link="link_c"/>
832 <child link="link_d"/>
833 <origin rpy="0 0 0" xyz="0.0 0.2 0.4"/>
834 <limit effort="100.0" lower="-3.14" upper="3.14" velocity="0.2"/>
836 <link name="link_d"/>
840 constexpr char robot_srdf[] = R
"xml(
841 <?xml version="1.0" ?>
842 <robot name="one_robot">
843 <group name="base_to_tip">
844 <joint name="joint_a_revolute"/>
845 <joint name="joint_b_revolute"/>
846 <joint name="joint_c_revolute"/>
847 <joint name="joint_d_revolute"/>
852 const urdf::ModelInterfaceSharedPtr urdf_model = urdf::parseURDF(robot_urdf);
853 ASSERT_TRUE(urdf_model);
854 const auto srdf_model = std::make_shared<srdf::Model>();
855 ASSERT_TRUE(srdf_model->initString(*urdf_model, robot_srdf));
856 const auto robot_model = std::make_shared<moveit::core::RobotModel>(urdf_model, srdf_model);
862 checkJacobian(state, *jmg, makeVector({ 0.0, 0.0, 0.0, 0.0 }), makeVector({ 0.1, 0.2, 0.3, 0.4 }));
863 checkJacobian(state, *jmg, makeVector({ 0.1, 0.2, 0.3, 0.4 }), makeVector({ 0.5, 0.3, 0.2, 0.1 }));
866TEST(getJacobian, RevoluteJointsButDifferentLink)
869 constexpr char robot_urdf[] = R
"(
870 <?xml version="1.0" ?>
871 <robot name="one_robot">
872 <link name="base_link"/>
873 <joint name="joint_a_revolute" type="revolute">
875 <parent link="base_link"/>
876 <child link="link_a"/>
877 <origin rpy="0 0 0" xyz="0 0 0"/>
878 <limit effort="100.0" lower="-3.14" upper="3.14" velocity="0.2"/>
880 <link name="link_a"/>
881 <joint name="joint_b_revolute" type="revolute">
883 <parent link="link_a"/>
884 <child link="link_b"/>
885 <origin rpy="0 0 0" xyz="0.0 0.5 0"/>
886 <limit effort="100.0" lower="-3.14" upper="3.14" velocity="0.2"/>
888 <link name="link_b"/>
889 <joint name="joint_c_revolute" type="revolute">
891 <parent link="link_b"/>
892 <child link="link_c"/>
893 <origin rpy="0 0 0" xyz="0.2 0.2 0"/>
894 <limit effort="100.0" lower="-3.14" upper="3.14" velocity="0.2"/>
896 <link name="link_c"/>
897 <joint name="joint_d_revolute" type="revolute">
899 <parent link="link_c"/>
900 <child link="link_d"/>
901 <origin rpy="0 0 0" xyz="0.0 0.2 0.4"/>
902 <limit effort="100.0" lower="-3.14" upper="3.14" velocity="0.2"/>
904 <link name="link_d"/>
908 constexpr char robot_srdf[] = R
"xml(
909 <?xml version="1.0" ?>
910 <robot name="one_robot">
911 <group name="base_to_tip">
912 <joint name="joint_a_revolute"/>
913 <joint name="joint_b_revolute"/>
914 <joint name="joint_c_revolute"/>
915 <joint name="joint_d_revolute"/>
920 const urdf::ModelInterfaceSharedPtr urdf_model = urdf::parseURDF(robot_urdf);
921 ASSERT_TRUE(urdf_model);
922 const auto srdf_model = std::make_shared<srdf::Model>();
923 ASSERT_TRUE(srdf_model->initString(*urdf_model, robot_srdf));
924 const auto robot_model = std::make_shared<moveit::core::RobotModel>(urdf_model, srdf_model);
930 checkJacobian(state, *jmg, makeVector({ 0.0, 0.0, 0.0, 0.0 }), makeVector({ 0.1, 0.2, 0.3, 0.4 }),
932 checkJacobian(state, *jmg, makeVector({ 0.1, 0.2, 0.3, 0.4 }), makeVector({ 0.5, 0.3, 0.2, 0.1 }),
936TEST(getJacobian, RevoluteAndPrismaticJoints)
939 constexpr char robot_urdf[] = R
"(
940 <?xml version="1.0" ?>
941 <robot name="one_robot">
942 <link name="base_link"/>
943 <joint name="joint_a_revolute" type="revolute">
945 <parent link="base_link"/>
946 <child link="link_a"/>
947 <origin rpy="0 0 0" xyz="0 0 0"/>
948 <limit effort="100.0" lower="-3.14" upper="3.14" velocity="0.2"/>
950 <link name="link_a"/>
951 <joint name="joint_b_revolute" type="revolute">
953 <parent link="link_a"/>
954 <child link="link_b"/>
955 <origin rpy="0 0 0" xyz="0.0 0.5 0"/>
956 <limit effort="100.0" lower="-3.14" upper="3.14" velocity="0.2"/>
958 <link name="link_b"/>
959 <joint name="joint_c_prismatic" type="prismatic">
961 <parent link="link_b"/>
962 <child link="link_c"/>
963 <origin rpy="0 0 0" xyz="0.2 0.2 0"/>
964 <limit effort="100.0" lower="-1.0" upper="1.0" velocity="0.2"/>
966 <link name="link_c"/>
967 <joint name="joint_d_revolute" type="revolute">
969 <parent link="link_c"/>
970 <child link="link_d"/>
971 <origin rpy="0 0 0" xyz="0.0 0.2 0.4"/>
972 <limit effort="100.0" lower="-3.14" upper="3.14" velocity="0.2"/>
974 <link name="link_d"/>
978 constexpr char robot_srdf[] = R
"xml(
979 <?xml version="1.0" ?>
980 <robot name="one_robot">
981 <group name="base_to_tip">
982 <joint name="joint_a_revolute"/>
983 <joint name="joint_b_revolute"/>
984 <joint name="joint_c_prismatic"/>
985 <joint name="joint_d_revolute"/>
990 const urdf::ModelInterfaceSharedPtr urdf_model = urdf::parseURDF(robot_urdf);
991 ASSERT_TRUE(urdf_model);
992 const auto srdf_model = std::make_shared<srdf::Model>();
993 ASSERT_TRUE(srdf_model->initString(*urdf_model, robot_srdf));
994 const auto robot_model = std::make_shared<moveit::core::RobotModel>(urdf_model, srdf_model);
1000 checkJacobian(state, *jmg, makeVector({ 0.0, 0.0, 0.0, 0.0 }), makeVector({ 0.1, 0.2, 0.3, 0.4 }));
1001 checkJacobian(state, *jmg, makeVector({ 0.1, 0.2, 0.3, 0.4 }), makeVector({ 0.5, 0.3, 0.2, 0.1 }));
1004TEST(getJacobian, RevoluteAndFixedJoints)
1007 constexpr char robot_urdf[] = R
"(
1008 <?xml version="1.0" ?>
1009 <robot name="one_robot">
1010 <link name="base_link"/>
1011 <joint name="joint_a_revolute" type="revolute">
1013 <parent link="base_link"/>
1014 <child link="link_a"/>
1015 <origin rpy="0 0 0" xyz="0 0 0"/>
1016 <limit effort="100.0" lower="-3.14" upper="3.14" velocity="0.2"/>
1018 <link name="link_a"/>
1019 <joint name="joint_b_fixed" type="fixed">
1020 <parent link="link_a"/>
1021 <child link="link_b"/>
1023 <link name="link_b"/>
1024 <joint name="joint_c_fixed" type="fixed">
1025 <parent link="link_b"/>
1026 <child link="link_c"/>
1028 <link name="link_c"/>
1029 <joint name="joint_d_revolute" type="revolute">
1031 <parent link="link_c"/>
1032 <child link="link_d"/>
1033 <origin rpy="0 0 0" xyz="0.0 0.2 0.4"/>
1034 <limit effort="100.0" lower="-3.14" upper="3.14" velocity="0.2"/>
1036 <link name="link_d"/>
1040 constexpr char robot_srdf[] = R
"xml(
1041 <?xml version="1.0" ?>
1042 <robot name="one_robot">
1043 <group name="base_to_tip">
1044 <joint name="joint_a_revolute"/>
1045 <joint name="joint_b_fixed"/>
1046 <joint name="joint_c_fixed"/>
1047 <joint name="joint_d_revolute"/>
1052 const urdf::ModelInterfaceSharedPtr urdf_model = urdf::parseURDF(robot_urdf);
1053 ASSERT_TRUE(urdf_model);
1054 const auto srdf_model = std::make_shared<srdf::Model>();
1055 ASSERT_TRUE(srdf_model->initString(*urdf_model, robot_srdf));
1056 const auto robot_model = std::make_shared<moveit::core::RobotModel>(urdf_model, srdf_model);
1062 checkJacobian(state, *jmg, makeVector({ 0.0, 0.0 }), makeVector({ 0.1, 0.4 }));
1063 checkJacobian(state, *jmg, makeVector({ 0.1, 0.4 }), makeVector({ 0.5, 0.1 }));
1066TEST(getJacobian, RevolutePlanarAndPrismaticJoints)
1069 constexpr char robot_urdf[] = R
"(
1070 <?xml version="1.0" ?>
1071 <robot name="one_robot">
1072 <link name="base_link"/>
1073 <joint name="joint_a_planar" type="planar">
1075 <parent link="base_link"/>
1076 <child link="link_a"/>
1077 <origin rpy="0 0 0" xyz="0 0 0"/>
1078 <limit effort="100.0" lower="-1.0" upper="1.0" velocity="0.2"/>
1080 <link name="link_a"/>
1081 <joint name="joint_b_revolute" type="revolute">
1083 <parent link="link_a"/>
1084 <child link="link_b"/>
1085 <origin rpy="0 0 0" xyz="0.0 0.5 0"/>
1086 <limit effort="100.0" lower="-3.14" upper="3.14" velocity="0.2"/>
1088 <link name="link_b"/>
1089 <joint name="joint_c_prismatic" type="prismatic">
1091 <parent link="link_b"/>
1092 <child link="link_c"/>
1093 <origin rpy="0 0 0" xyz="0.2 0.2 0"/>
1094 <limit effort="100.0" lower="-1.0" upper="1.0" velocity="0.2"/>
1096 <link name="link_c"/>
1097 <joint name="joint_d_revolute" type="revolute">
1099 <parent link="link_c"/>
1100 <child link="link_d"/>
1101 <origin rpy="0 0 0" xyz="0.0 0.2 0.4"/>
1102 <limit effort="100.0" lower="-3.14" upper="3.14" velocity="0.2"/>
1104 <link name="link_d"/>
1108 constexpr char robot_srdf[] = R
"xml(
1109 <?xml version="1.0" ?>
1110 <robot name="one_robot">
1111 <group name="base_to_tip">
1112 <joint name="joint_a_planar"/>
1113 <joint name="joint_b_revolute"/>
1114 <joint name="joint_c_prismatic"/>
1115 <joint name="joint_d_revolute"/>
1120 const urdf::ModelInterfaceSharedPtr urdf_model = urdf::parseURDF(robot_urdf);
1121 ASSERT_TRUE(urdf_model);
1122 const auto srdf_model = std::make_shared<srdf::Model>();
1123 ASSERT_TRUE(srdf_model->initString(*urdf_model, robot_srdf));
1124 const auto robot_model = std::make_shared<moveit::core::RobotModel>(urdf_model, srdf_model);
1129 checkJacobian(state, *jmg, makeVector({ 0.0, 0.0, 0.0, 0.0, 0.0, 0.0 }),
1130 makeVector({ 0.2, 0.05, 0.1, 0.2, 0.3, 0.4 }));
1136 constexpr char robot_urdf[] = R
"(
1137 <?xml version="1.0" ?>
1138 <robot name="one_robot">
1139 <link name="origin"/>
1140 <joint name="fixed_offset" type="fixed">
1141 <parent link="origin"/>
1142 <child link="link_a"/>
1143 <origin rpy="0 0 1.5707" xyz="0.0 0.0 0.0"/>
1145 <link name="link_a"/>
1146 <joint name="joint_a_revolute" type="revolute">
1148 <parent link="link_a"/>
1149 <child link="link_b"/>
1150 <origin rpy="0 0 0" xyz="0.0 0.2 0.4"/>
1151 <limit effort="100.0" lower="-3.14" upper="3.14" velocity="0.2"/>
1153 <link name="link_b"/>
1154 <joint name="joint_b_revolute" type="revolute">
1156 <parent link="link_b"/>
1157 <child link="link_c"/>
1158 <origin rpy="0 0 0" xyz="0.0 0.2 0.4"/>
1159 <limit effort="100.0" lower="-3.14" upper="3.14" velocity="0.2"/>
1161 <link name="link_c"/>
1162 <joint name="joint_c_revolute" type="revolute">
1164 <parent link="link_c"/>
1165 <child link="link_d"/>
1166 <origin rpy="0 0 0" xyz="0.0 0.2 0.4"/>
1167 <limit effort="100.0" lower="-3.14" upper="3.14" velocity="0.2"/>
1169 <link name="link_d"/>
1173 constexpr char robot_srdf[] = R
"xml(
1174 <?xml version="1.0" ?>
1175 <robot name="one_robot">
1176 <group name="base_to_tip">
1177 <joint name="joint_a_revolute"/>
1178 <joint name="joint_b_revolute"/>
1179 <joint name="joint_c_revolute"/>
1184 const urdf::ModelInterfaceSharedPtr urdf_model = urdf::parseURDF(robot_urdf);
1185 ASSERT_TRUE(urdf_model);
1186 const auto srdf_model = std::make_shared<srdf::Model>();
1187 ASSERT_TRUE(srdf_model->initString(*urdf_model, robot_srdf));
1188 const auto robot_model = std::make_shared<moveit::core::RobotModel>(urdf_model, srdf_model);
1194 checkJacobian(state, *jmg, makeVector({ 0.0, 0.0, 0.0 }), makeVector({ 0.1, 0.4, 0.2 }));
1195 checkJacobian(state, *jmg, makeVector({ 0.1, 0.4, 0.3 }), makeVector({ 0.5, 0.1, 0.2 }));
1198TEST(getJointPositions, getFixedJointValue)
1202 constexpr char robot_urdf[] = R
"(
1203 <?xml version="1.0" ?>
1204 <robot name="one_robot">
1205 <link name="base_link"/>
1206 <joint name="joint_a_revolute" type="revolute">
1208 <parent link="base_link"/>
1209 <child link="link_a"/>
1210 <origin rpy="0 0 0" xyz="0 0 0"/>
1211 <limit effort="100.0" lower="-3.14" upper="3.14" velocity="0.2"/>
1213 <link name="link_a"/>
1214 <joint name="joint_b_revolute" type="revolute">
1216 <parent link="link_a"/>
1217 <child link="link_b"/>
1218 <origin rpy="0 0 0" xyz="0 0 0"/>
1219 <limit effort="100.0" lower="-3.14" upper="3.14" velocity="0.2"/>
1221 <link name="link_b"/>
1222 <joint name="joint_c_fixed" type="fixed">
1223 <parent link="link_b"/>
1224 <child link="link_c"/>
1226 <link name="link_c"/>
1230 constexpr char robot_srdf[] = R
"xml(
1231 <?xml version="1.0" ?>
1232 <robot name="one_robot">
1233 <group name="base_to_tip">
1234 <joint name="joint_a_revolute"/>
1235 <joint name="joint_b_revolute"/>
1236 <joint name="joint_c_fixed"/>
1241 const urdf::ModelInterfaceSharedPtr urdf_model = urdf::parseURDF(robot_urdf);
1242 ASSERT_TRUE(urdf_model);
1243 const auto srdf_model = std::make_shared<srdf::Model>();
1244 ASSERT_TRUE(srdf_model->initString(*urdf_model, robot_srdf));
1245 const auto robot_model = std::make_shared<moveit::core::RobotModel>(urdf_model, srdf_model);
1251 ASSERT_EQ(joint_value,
nullptr);
1256 testing::InitGoogleTest(&argc, argv);
1257 return RUN_ALL_TESTS();
moveit::core::RobotModelConstPtr robot_model_
const std::vector< std::string > & getJointModelNames() const
Get the names of the joints in this group. These are the names of the joints returned by getJointMode...
const std::vector< const LinkModel * > & getLinkModels() const
Get the links that are part of this joint group.
const std::vector< std::string > & getUpdatedLinkModelNames() const
Get the names of the links returned by getUpdatedLinkModels()
unsigned int getVariableCount() const
Get the number of variables that describe this joint group. This includes variables necessary for mim...
const std::vector< std::string > & getLinkModelNames() const
Get the names of the links that are part of this joint group.
const std::vector< const JointModel * > & getJointModels() const
Get all the joints in this group (including fixed and mimic joints).
A joint from the robot. Models the transform that this joint applies in the kinematic chain....
const LinkModel * getParentLinkModel() const
Get the link that this joint connects to. The robot is assumed to start with a joint,...
A link from the robot. Contains the constant transform applied to the link and its geometry.
const std::string & getName() const
The name of this link.
Easily build different robot models for testing. Essentially a programmer-friendly light wrapper arou...
void addInertial(const std::string &link_name, double mass, geometry_msgs::msg::Pose origin, double ixx, double ixy, double ixz, double iyy, double iyz, double izz)
void addCollisionBox(const std::string &link_name, const std::vector< double > &dims, geometry_msgs::msg::Pose origin)
Adds a collision box to a specific link.
bool isValid()
Returns true if the building process so far has been valid.
void addGroup(const std::vector< std::string > &links, const std::vector< std::string > &joints, const std::string &name)
Adds a new group using a list of links and a list of joints.
moveit::core::RobotModelPtr build()
Builds and returns the robot model added to the builder.
void addVirtualJoint(const std::string &parent_frame, const std::string &child_link, const std::string &type, const std::string &name="")
Adds a virtual joint to the SRDF.
void addVisualBox(const std::string &link_name, const std::vector< double > &size, geometry_msgs::msg::Pose origin)
Adds a visual box to a specific link.
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 setVariableAcceleration(const std::string &variable, double value)
Set the acceleration of a variable. If an unknown variable name is specified, an exception is thrown.
double getVariableAcceleration(const std::string &variable) const
Get the acceleration of a particular variable. An exception is thrown if the variable is not known.
void attachBody(std::unique_ptr< AttachedBody > attached_body)
Add an attached body to this state.
bool getJacobian(const JointModelGroup *group, const LinkModel *link, const Eigen::Vector3d &reference_point_position, Eigen::MatrixXd &jacobian, bool use_quaternion_representation=false) const
Compute the Jacobian with reference to a particular point on a given link, for a specified group.
const double * getJointPositions(const std::string &joint_name) const
void setVariableVelocity(const std::string &variable, double value)
Set the velocity of a variable. If an unknown variable name is specified, an exception is thrown.
double getVariableVelocity(const std::string &variable) const
Get the velocity of a particular variable. An exception is thrown if the variable is not known.
void setVariablePosition(const std::string &variable, double value)
Set the position of a single variable. An exception is thrown if the variable name is not known.
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...
void copyJointGroupPositions(const std::string &joint_group_name, std::vector< double > &gstate) const
For a given group, copy the position values of the variables that make up the group into another loca...
const JointModelGroup * getJointModelGroup(const std::string &group) const
Get the model of a particular joint group.
void printStatePositionsWithJointLimits(const moveit::core::JointModelGroup *jmg, std::ostream &out=std::cout) const
Output to console the current state of the robot's joint limits.
const LinkModel * getLinkModel(const std::string &link) const
Get the model of a particular link.
const RobotModelConstPtr & getRobotModel() const
Get the robot model this state is constructed for.
void updateLinkTransforms()
Update the reference frame transforms for links. This call is needed before using the transforms of l...
void interpolate(const RobotState &to, double t, RobotState &state) const
const Eigen::Isometry3d & getCollisionBodyTransform(const std::string &link_name, std::size_t index)
Get the link transform w.r.t. the root link (model frame) of the RobotModel. This is typically the ro...
double distance(const RobotState &other) const
Return the sum of joint distances to "other" state. An L1 norm. Only considers active joints.
void setToRandomPositions()
Set all joints to random values. Values will be within default bounds.
bool satisfiesBounds(double margin=0.0) const
bool dirtyLinkTransforms() const
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 setToDefaultValues()
Set all joints to their default positions. The default position is 0, or if that is not within bounds...
std::size_t getVariableCount() const
Get the number of variables that make up this state.
const Eigen::Isometry3d & getGlobalLinkTransform(const std::string &link_name)
Get the link transform w.r.t. the root link (model frame) of the RobotModel. This is typically the ro...
const moveit::core::LinkModel * getRigidlyConnectedParentLinkModel(const std::string &frame, const moveit::core::JointModelGroup *jmg=nullptr) const
Get the latest link upwards the kinematic tree which is only connected via fixed joints.
void setJointPositions(const std::string &joint_name, const double *position)
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...
int main(int argc, char **argv)
TEST(Loading, SimpleRobot)
#define EXPECT_NEAR_TRACED(...)
TEST_F(OneRobot, setToDefaultValues)