moveit2
The MoveIt Motion Planning Framework for ROS 2.
trajectory_test.cpp
Go to the documentation of this file.
1 /*********************************************************************
2  * Software License Agreement
3  *
4  * Copyright (c) 2019, PickNik Inc.
5  * All rights reserved.
6  *
7  *********************************************************************/
8 
9 /* Author: Omid Heidari
10  Desc: Test the trajectory planned by trajopt
11  */
12 
13 // C++
14 #include <iostream>
15 #include <string>
16 #include <cmath>
17 
18 // ROS
19 #include <ros/ros.h>
20 
21 // Testing
22 #include <gtest/gtest.h>
23 
24 #include <trajopt/common.hpp>
25 
31 
34 
39 #include <moveit_msgs/MotionPlanResponse.h>
40 
41 class TrajectoryTest : public ::testing::Test
42 {
43 public:
45  {
46  }
47 
48 protected:
49  void SetUp() override
50  {
51  node_handle_ = ros::NodeHandle("~");
53  bool robot_model_ok_ = static_cast<bool>(robot_model_);
54  if (!robot_model_ok_)
55  ROS_ERROR_STREAM_NAMED("trajectory_test", "robot model is not loaded correctly");
56  }
57 
58 protected:
59  moveit::core::RobotModelPtr robot_model_;
60  std::vector<std::string> group_joint_names_;
61  const std::string PLANNING_GROUP = "panda_arm";
62  const double GOAL_TOLERANCE = 0.1;
63  ros::NodeHandle node_handle_;
64 }; // class TrajectoryTest
65 
66 TEST_F(TrajectoryTest, concatVectorValidation)
67 {
68  std::vector<double> vec_a = { 1, 2, 3, 4, 5 };
69  std::vector<double> vec_b = { 6, 7, 8, 9, 10 };
70  std::vector<double> vec_c = trajopt_interface::concatVector(vec_a, vec_b);
71  EXPECT_EQ(vec_c.size(), vec_a.size() + vec_b.size());
72 
73  // Check if the output of concatVector is correct.
74  // Loop over the output and the input vectors to see if they match
75  std::size_t length_ab = vec_a.size() + vec_b.size();
76  for (std::size_t index = 0; index < length_ab; ++index)
77  {
78  if (index < vec_a.size())
79  {
80  EXPECT_EQ(vec_c[index], vec_a[index]);
81  }
82  else
83  {
84  EXPECT_EQ(vec_c[index], vec_b[index - vec_a.size()]);
85  }
86  }
87 }
88 
89 TEST_F(TrajectoryTest, goalTolerance)
90 {
91  const std::string NODE_NAME = "trajectory_test";
92 
93  // Create a RobotState and JointModelGroup to keep track of the current robot pose and planning group
94  auto current_state = std::make_shared<moveit::core::RobotState>(robot_model_);
95  current_state->setToDefaultValues();
96 
97  const moveit::core::JointModelGroup* joint_model_group = current_state->getJointModelGroup(PLANNING_GROUP);
98  EXPECT_NE(joint_model_group, nullptr);
99  const std::vector<std::string>& joint_names = joint_model_group->getActiveJointModelNames();
100  EXPECT_EQ(joint_names.size(), 7);
101 
102  auto planning_scene = std::make_shared<planning_scene::PlanningScene>(robot_model_);
103 
104  // Create response and request
107 
108  // Set start state
109  // ======================================================================================
110  std::vector<double> start_joint_values = { 0.4, 0.3, 0.5, -0.55, 0.88, 1.0, -0.075 };
111  auto start_state = std::make_shared<moveit::core::RobotState>(robot_model_);
112  start_state->setJointGroupPositions(joint_model_group, start_joint_values);
113  start_state->update();
114 
115  req.start_state.joint_state.name = joint_names;
116  req.start_state.joint_state.position = start_joint_values;
117  req.goal_constraints.clear();
118  req.group_name = PLANNING_GROUP;
119 
120  // Set the goal state and joints tolerance
121  // ========================================================================================
122  auto goal_state = std::make_shared<moveit::core::RobotState>(robot_model_);
123  std::vector<double> goal_joint_values = { 0.8, 0.7, 1, -1.3, 1.9, 2.2, -0.1 };
124  goal_state->setJointGroupPositions(joint_model_group, goal_joint_values);
125  goal_state->update();
126  moveit_msgs::Constraints joint_goal = kinematic_constraints::constructGoalConstraints(*goal_state, joint_model_group);
127  req.goal_constraints.push_back(joint_goal);
128  req.goal_constraints[0].name = "goal_pos";
129  // Set joint tolerance
130  std::vector<moveit_msgs::JointConstraint> goal_joint_constraint = req.goal_constraints[0].joint_constraints;
131  for (std::size_t x = 0; x < goal_joint_constraint.size(); ++x)
132  {
133  req.goal_constraints[0].joint_constraints[x].tolerance_above = 0.001;
134  req.goal_constraints[0].joint_constraints[x].tolerance_below = 0.001;
135  }
136 
137  // Load planner
138  // ======================================================================================
139  // We will now construct a loader to load a planner, by name.
140  // Note that we are using the ROS pluginlib library here.
141  std::unique_ptr<pluginlib::ClassLoader<planning_interface::PlannerManager>> planner_plugin_loader;
142  planning_interface::PlannerManagerPtr planner_instance;
143 
144  std::string planner_plugin_name = "trajopt_interface/TrajOptPlanner";
145  node_handle_.setParam("planning_plugin", planner_plugin_name);
146 
147  // Make sure the planner plugin is loaded
148  EXPECT_TRUE(node_handle_.getParam("planning_plugin", planner_plugin_name));
149  try
150  {
151  planner_plugin_loader = std::make_shared<pluginlib::ClassLoader<planning_interface::PlannerManager>>(
152  "moveit_core", "planning_interface::PlannerManager");
153  }
154  catch (pluginlib::PluginlibException& ex)
155  {
156  ROS_FATAL_STREAM_NAMED(NODE_NAME, "Exception while creating planning plugin loader " << ex.what());
157  }
158  try
159  {
160  planner_instance.reset(planner_plugin_loader->createUnmanagedInstance(planner_plugin_name));
161  if (!planner_instance->initialize(robot_model_, node_handle_.getNamespace()))
162  ROS_FATAL_STREAM_NAMED(NODE_NAME, "Could not initialize planner instance");
163  ROS_INFO_STREAM_NAMED(NODE_NAME, "Using planning interface '" << planner_instance->getDescription() << "'");
164  }
165  catch (pluginlib::PluginlibException& ex)
166  {
167  const std::vector<std::string>& classes = planner_plugin_loader->getDeclaredClasses();
168  std::stringstream ss;
169  for (std::size_t i = 0; i < classes.size(); ++i)
170  ss << classes[i] << " ";
171  ROS_ERROR_STREAM_NAMED(NODE_NAME, "Exception while loading planner '" << planner_plugin_name << "': " << ex.what()
172  << '\n'
173  << "Available plugins: " << ss.str());
174  }
175 
176  // Create planning context
177  // ========================================================================================
178  planning_interface::PlanningContextPtr context =
179  planner_instance->getPlanningContext(planning_scene, req, res.error_code_);
180 
181  context->solve(res);
182  EXPECT_EQ(res.error_code_.val, res.error_code_.SUCCESS);
183 
184  moveit_msgs::MotionPlanResponse response;
185  res.getMessage(response);
186 
187  // Check the difference between the last step in the solution and the goal
188  // ========================================================================================
189  std::vector<double> joints_values_last_step = response.trajectory.joint_trajectory.points.back().positions;
190 
191  for (std::size_t joint_index = 0; joint_index < joints_values_last_step.size(); ++joint_index)
192  {
193  double goal_error =
194  abs(joints_values_last_step[joint_index] - req.goal_constraints[0].joint_constraints[joint_index].position);
195  std::cerr << "goal_error: " << goal_error << '\n';
196  EXPECT_LT(goal_error, GOAL_TOLERANCE);
197  }
198 }
199 
200 int main(int argc, char** argv)
201 {
202  testing::InitGoogleTest(&argc, argv);
203  ros::init(argc, argv, "trajectory_test");
204 
205  ros::AsyncSpinner spinner(1);
206  spinner.start();
207 
208  int result = RUN_ALL_TESTS();
209  ros::shutdown();
210 
211  return result;
212 }
const std::string PLANNING_GROUP
const double GOAL_TOLERANCE
ros::NodeHandle node_handle_
moveit::core::RobotModelPtr robot_model_
std::vector< std::string > group_joint_names_
void SetUp() override
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...
constexpr double GOAL_TOLERANCE
moveit_msgs::msg::Constraints constructGoalConstraints(const moveit::core::RobotState &state, const moveit::core::JointModelGroup *jmg, double tolerance_below, double tolerance_above)
Generates a constraint message intended to be used as a goal constraint for a joint group....
Definition: utils.cpp:144
moveit::core::RobotModelPtr loadTestingRobotModel(const std::string &robot_name)
Loads a robot from moveit_resources.
x
Definition: pick.py:64
moveit_msgs::msg::MotionPlanRequest MotionPlanRequest
This namespace includes the central class for representing planning contexts.
Eigen::VectorXd concatVector(const Eigen::VectorXd &vector_a, const Eigen::VectorXd &vector_b)
Appends b to a of type VectorXd.
void getMessage(moveit_msgs::msg::MotionPlanResponse &msg) const
moveit_msgs::msg::MoveItErrorCodes error_code_
int main(int argc, char **argv)
TEST_F(TrajectoryTest, concatVectorValidation)