benchmark_ik.cpp
Go to the documentation of this file.
1 /*********************************************************************
2  * Software License Agreement (BSD License)
3  *
4  * Copyright (c) 2017, Rice University
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
9  * are met:
10  *
11  * * Redistributions of source code must retain the above copyright
12  * notice, this list of conditions and the following disclaimer.
13  * * Redistributions in binary form must reproduce the above
14  * copyright notice, this list of conditions and the following
15  * disclaimer in the documentation and/or other materials provided
16  * with the distribution.
17  * * Neither the name of the Rice University nor the names of its
18  * contributors may be used to endorse or promote products derived
19  * from this software without specific prior written permission.
20  *
21  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
24  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
25  * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
26  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
27  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
28  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
29  * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
31  * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
32  * POSSIBILITY OF SUCH DAMAGE.
33  *********************************************************************/
34 
35 /* Author: Mark Moll */
36 
37 #include <chrono>
38 #include <ros/ros.h>
39 #include <boost/program_options.hpp>
40 #include <moveit/robot_model_loader/robot_model_loader.h>
42 
43 namespace po = boost::program_options;
44 
46 int main(int argc, char* argv[])
47 {
48  std::string group;
49  std::string tip;
50  unsigned int num;
51  bool reset_to_default;
52  po::options_description desc("Options");
53  // clang-format off
54  desc.add_options()
55  ("help", "show help message")
56  ("group", po::value<std::string>(&group)->default_value("all"), "name of planning group")
57  ("tip", po::value<std::string>(&tip)->default_value("default"), "name of the end effector in the planning group")
58  ("num", po::value<unsigned int>(&num)->default_value(100000), "number of IK solutions to compute")
59  ("reset_to_default", po::value<bool>(&reset_to_default)->default_value(true),
60  "whether to reset IK seed to default state. If set to false, the seed is the "
61  "correct IK solution (to accelerate filling the cache).");
62  // clang-format on
63 
64  po::variables_map vm;
65  po::store(po::parse_command_line(argc, argv, desc), vm);
66  po::notify(vm);
67 
68  if (vm.count("help") != 0u)
69  {
70  std::cout << desc << "\n";
71  return 1;
72  }
73 
74  ros::init(argc, argv, "benchmark_ik");
76  spinner.start();
77 
78  robot_model_loader::RobotModelLoader robot_model_loader;
79  const moveit::core::RobotModelPtr& kinematic_model = robot_model_loader.getModel();
81  moveit::core::RobotState& kinematic_state = planning_scene.getCurrentStateNonConst();
82  collision_detection::CollisionRequest collision_request;
83  collision_detection::CollisionResult collision_result;
84  std::chrono::duration<double> ik_time(0);
85  std::chrono::time_point<std::chrono::system_clock> start;
86  std::vector<moveit::core::JointModelGroup*> groups;
87  std::vector<std::string> end_effectors;
88 
89  if (group == "all")
90  groups = kinematic_model->getJointModelGroups();
91  else
92  groups.push_back(kinematic_model->getJointModelGroup(group));
93 
94  for (const auto& group : groups)
95  {
96  // skip group if there's no IK solver
97  if (group->getSolverInstance() == nullptr)
98  continue;
99 
100  if (tip == "default")
101  group->getEndEffectorTips(end_effectors);
102  else
103  end_effectors = std::vector<std::string>(1, tip);
104 
105  // perform first IK call to load the cache, so that the time for loading is not included in
106  // average IK call time
107  kinematic_state.setToDefaultValues();
108  EigenSTL::vector_Isometry3d default_eef_states;
109  for (const auto& end_effector : end_effectors)
110  default_eef_states.push_back(kinematic_state.getGlobalLinkTransform(end_effector));
111  if (end_effectors.size() == 1)
112  kinematic_state.setFromIK(group, default_eef_states[0], end_effectors[0], 0.1);
113  else
114  kinematic_state.setFromIK(group, default_eef_states, end_effectors, 0.1);
115 
116  bool found_ik;
117  unsigned int num_failed_calls = 0, num_self_collisions = 0;
118  EigenSTL::vector_Isometry3d end_effector_states(end_effectors.size());
119  unsigned int i = 0;
120  while (i < num)
121  {
122  kinematic_state.setToRandomPositions(group);
123  collision_result.clear();
124  planning_scene.checkSelfCollision(collision_request, collision_result);
125  if (collision_result.collision)
126  {
127  ++num_self_collisions;
128  continue;
129  }
130  for (unsigned j = 0; j < end_effectors.size(); ++j)
131  end_effector_states[j] = kinematic_state.getGlobalLinkTransform(end_effectors[j]);
132  if (reset_to_default)
133  kinematic_state.setToDefaultValues();
134  start = std::chrono::system_clock::now();
135  if (end_effectors.size() == 1)
136  found_ik = kinematic_state.setFromIK(group, end_effector_states[0], end_effectors[0], 0.1);
137  else
138  found_ik = kinematic_state.setFromIK(group, end_effector_states, end_effectors, 0.1);
139  ik_time += std::chrono::system_clock::now() - start;
140  if (!found_ik)
141  num_failed_calls++;
142  ++i;
143  if (i % 100 == 0)
144  ROS_INFO_NAMED("cached_ik.measure_ik_call_cost",
145  "Avg. time per IK solver call is %g after %d calls. %g%% of calls failed to return a solution. "
146  "%g%% of random joint configurations were ignored due to self-collisions.",
147  ik_time.count() / (double)i, i, 100. * num_failed_calls / i,
148  100. * num_self_collisions / (num_self_collisions + i));
149  }
150  ROS_INFO_NAMED("cached_ik.measure_ik_call_cost", "Summary for group %s: %g %g %g", group->getName().c_str(),
151  ik_time.count() / (double)i, 100. * num_failed_calls / i,
152  100. * num_self_collisions / (num_self_collisions + i));
153  }
154 
155  ros::shutdown();
156  return 0;
157 }
EigenSTL::vector_Isometry3d
std::vector< Eigen::Isometry3d, Eigen::aligned_allocator< Eigen::Isometry3d > > vector_Isometry3d
ros::init
ROSCPP_DECL void init(const M_string &remappings, const std::string &name, uint32_t options=0)
ros.h
planning_scene::PlanningScene
ros::AsyncSpinner
ros::shutdown
ROSCPP_DECL void shutdown()
moveit::core::RobotState
moveit::core::RobotState::getGlobalLinkTransform
const Eigen::Isometry3d & getGlobalLinkTransform(const std::string &link_name)
moveit::core::RobotState::setFromIK
bool setFromIK(const JointModelGroup *group, const geometry_msgs::Pose &pose, double timeout=0.0, const GroupStateValidityCallbackFn &constraint=GroupStateValidityCallbackFn(), const kinematics::KinematicsQueryOptions &options=kinematics::KinematicsQueryOptions())
moveit::core::RobotState::setToRandomPositions
void setToRandomPositions()
collision_detection::CollisionRequest
spinner
void spinner()
ROS_INFO_NAMED
#define ROS_INFO_NAMED(name,...)
collision_detection::CollisionResult
moveit::core::RobotState::setToDefaultValues
void setToDefaultValues()
start
ROSCPP_DECL void start()
main
int main(int argc, char *argv[])
Definition: benchmark_ik.cpp:46
planning_scene.h
collision_detection::CollisionResult::collision
bool collision
planning_scene
collision_detection::CollisionResult::clear
EIGEN_MAKE_ALIGNED_OPERATOR_NEW void clear()


moveit_kinematics
Author(s): Dave Coleman , Ioan Sucan , Sachin Chitta
autogenerated on Fri May 3 2024 02:29:32