moveit2
The MoveIt Motion Planning Framework for ROS 2.
Loading...
Searching...
No Matches
moveit_cpp.cpp
Go to the documentation of this file.
1/*********************************************************************
2 * Software License Agreement (BSD License)
3 *
4 * Copyright (c) 2019, PickNik Inc.
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 PickNik Inc. 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: Henning Kayser */
36
37#include <stdexcept>
38
42#include <tf2_geometry_msgs/tf2_geometry_msgs.hpp>
43#include <geometry_msgs/msg/quaternion_stamped.hpp>
45
46namespace moveit_cpp
47{
48MoveItCpp::MoveItCpp(const rclcpp::Node::SharedPtr& node) : MoveItCpp(node, Options(node))
49{
50}
51
52MoveItCpp::MoveItCpp(const rclcpp::Node::SharedPtr& node, const Options& options)
53 : node_(node), logger_(moveit::getLogger("moveit.ros.moveit_cpp"))
54{
55 // Configure planning scene monitor
56 if (!loadPlanningSceneMonitor(options.planning_scene_monitor_options))
57 {
58 const std::string error = "Unable to configure planning scene monitor";
59 RCLCPP_FATAL_STREAM(logger_, error);
60 throw std::runtime_error(error);
61 }
62
63 if (!getRobotModel())
64 {
65 const std::string error = "Unable to construct robot model. Please make sure all needed information is on the "
66 "parameter server.";
67 RCLCPP_FATAL_STREAM(logger_, error);
68 throw std::runtime_error(error);
69 }
70
71 bool load_planning_pipelines = true;
72 if (load_planning_pipelines && !loadPlanningPipelines(options.planning_pipeline_options))
73 {
74 const std::string error = "Failed to load planning pipelines from parameter server";
75 RCLCPP_FATAL_STREAM(logger_, error);
76 throw std::runtime_error(error);
77 }
78
79 trajectory_execution_manager_ = std::make_shared<trajectory_execution_manager::TrajectoryExecutionManager>(
80 node_, getRobotModel(), planning_scene_monitor_->getStateMonitor());
81
82 RCLCPP_DEBUG(logger_, "MoveItCpp running");
83}
84
86{
87 RCLCPP_INFO(logger_, "Deleting MoveItCpp");
88}
89
90bool MoveItCpp::loadPlanningSceneMonitor(const PlanningSceneMonitorOptions& options)
91{
92 planning_scene_monitor_ =
93 std::make_shared<planning_scene_monitor::PlanningSceneMonitor>(node_, options.robot_description, options.name);
94 // Allows us to synchronize to Rviz and also publish collision objects to ourselves
95 RCLCPP_DEBUG(logger_, "Configuring Planning Scene Monitor");
96 if (planning_scene_monitor_->getPlanningScene())
97 {
98 // Start state and scene monitors
99 RCLCPP_INFO(logger_, "Listening to '%s' for joint states", options.joint_state_topic.c_str());
100 // Subscribe to JointState sensor messages
101 planning_scene_monitor_->startStateMonitor(options.joint_state_topic, options.attached_collision_object_topic);
102 // Publish planning scene updates to remote monitors like RViz
103 planning_scene_monitor_->startPublishingPlanningScene(planning_scene_monitor::PlanningSceneMonitor::UPDATE_SCENE,
104 options.monitored_planning_scene_topic);
105 // Monitor and apply planning scene updates from remote publishers like the PlanningSceneInterface
106 planning_scene_monitor_->startSceneMonitor(options.publish_planning_scene_topic);
107 // Monitor requests for changes in the collision environment
108 planning_scene_monitor_->startWorldGeometryMonitor();
109 }
110 else
111 {
112 RCLCPP_ERROR(logger_, "Planning scene not configured");
113 return false;
114 }
115
116 // Wait for complete state to be received
117 if (options.wait_for_initial_state_timeout > 0.0)
118 {
119 return planning_scene_monitor_->getStateMonitor()->waitForCurrentState(node_->now(),
120 options.wait_for_initial_state_timeout);
121 }
122
123 return true;
124}
125
126bool MoveItCpp::loadPlanningPipelines(const PlanningPipelineOptions& options)
127{
128 // TODO(henningkayser): Use parent namespace for planning pipeline config lookup
129 planning_pipelines_ =
131
132 if (planning_pipelines_.empty())
133 {
134 RCLCPP_ERROR(logger_, "Failed to load any planning pipelines.");
135 return false;
136 }
137 return true;
138}
139
140moveit::core::RobotModelConstPtr MoveItCpp::getRobotModel() const
141{
142 return planning_scene_monitor_->getRobotModel();
143}
144
145const rclcpp::Node::SharedPtr& MoveItCpp::getNode() const
146{
147 return node_;
148}
149
150bool MoveItCpp::getCurrentState(moveit::core::RobotStatePtr& current_state, double wait_seconds)
151{
152 if (wait_seconds > 0.0 && !planning_scene_monitor_->getStateMonitor()->waitForCurrentState(node_->now(), wait_seconds))
153 {
154 RCLCPP_ERROR(logger_, "Did not receive robot state");
155 return false;
156 }
157 { // Lock planning scene
158 planning_scene_monitor::LockedPlanningSceneRO scene(planning_scene_monitor_);
159 current_state = std::make_shared<moveit::core::RobotState>(scene->getCurrentState());
160 } // Unlock planning scene
161 return true;
162}
163
164moveit::core::RobotStatePtr MoveItCpp::getCurrentState(double wait)
165{
166 moveit::core::RobotStatePtr current_state;
167 getCurrentState(current_state, wait);
168 return current_state;
169}
170
171const std::unordered_map<std::string, planning_pipeline::PlanningPipelinePtr>& MoveItCpp::getPlanningPipelines() const
172{
173 return planning_pipelines_;
174}
175
176planning_scene_monitor::PlanningSceneMonitorConstPtr MoveItCpp::getPlanningSceneMonitor() const
177{
178 return planning_scene_monitor_;
179}
180
181planning_scene_monitor::PlanningSceneMonitorPtr MoveItCpp::getPlanningSceneMonitorNonConst()
182{
183 return planning_scene_monitor_;
184}
185
186trajectory_execution_manager::TrajectoryExecutionManagerConstPtr MoveItCpp::getTrajectoryExecutionManager() const
187{
188 return trajectory_execution_manager_;
189}
190
191trajectory_execution_manager::TrajectoryExecutionManagerPtr MoveItCpp::getTrajectoryExecutionManagerNonConst()
192{
193 return trajectory_execution_manager_;
194}
195
197MoveItCpp::execute(const robot_trajectory::RobotTrajectoryPtr& robot_trajectory, bool /* blocking */,
198 const std::vector<std::string>& /* controllers */)
199{
201}
202
204MoveItCpp::execute(const robot_trajectory::RobotTrajectoryPtr& robot_trajectory,
205 const std::vector<std::string>& controllers)
206{
207 if (!robot_trajectory)
208 {
209 RCLCPP_ERROR(logger_, "Robot trajectory is undefined");
211 }
212
213 const std::string group_name = robot_trajectory->getGroupName();
214
215 // Check if there are controllers that can handle the execution
216 if (!trajectory_execution_manager_->ensureActiveControllersForGroup(group_name))
217 {
218 RCLCPP_ERROR(logger_, "Execution failed! No active controllers configured for group '%s'", group_name.c_str());
220 }
221
222 // Execute trajectory
223 moveit_msgs::msg::RobotTrajectory robot_trajectory_msg;
224 robot_trajectory->getRobotTrajectoryMsg(robot_trajectory_msg);
225 trajectory_execution_manager_->push(robot_trajectory_msg, controllers);
226 trajectory_execution_manager_->execute();
227 return trajectory_execution_manager_->waitForExecution();
228}
229
230bool MoveItCpp::terminatePlanningPipeline(const std::string& pipeline_name)
231{
232 try
233 {
234 const auto& planning_pipeline = planning_pipelines_.at(pipeline_name);
235 if (planning_pipeline->isActive())
236 {
237 planning_pipeline->terminate();
238 }
239 return true;
240 }
241 catch (const std::out_of_range& oor)
242 {
243 RCLCPP_ERROR(logger_, "Cannot terminate pipeline '%s' because no pipeline with that name exists",
244 pipeline_name.c_str());
245 return false;
246 }
247}
248
249std::shared_ptr<const tf2_ros::Buffer> MoveItCpp::getTFBuffer() const
250{
251 return planning_scene_monitor_->getTFClient();
252}
253std::shared_ptr<tf2_ros::Buffer> MoveItCpp::getTFBuffer()
254{
255 return planning_scene_monitor_->getTFClient();
256}
257
258} // namespace moveit_cpp
std::shared_ptr< const tf2_ros::Buffer > getTFBuffer() const
moveit_controller_manager::ExecutionStatus execute(const robot_trajectory::RobotTrajectoryPtr &robot_trajectory, bool blocking, const std::vector< std::string > &controllers=std::vector< std::string >())
Execute a trajectory on the planning group specified by the robot's trajectory using the trajectory e...
moveit::core::RobotModelConstPtr getRobotModel() const
Get the RobotModel object.
const std::unordered_map< std::string, planning_pipeline::PlanningPipelinePtr > & getPlanningPipelines() const
Get all loaded planning pipeline instances mapped to their reference names.
~MoveItCpp()
Destructor.
planning_scene_monitor::PlanningSceneMonitorConstPtr getPlanningSceneMonitor() const
Get the stored instance of the planning scene monitor.
bool getCurrentState(moveit::core::RobotStatePtr &current_state, double wait_seconds)
Get the current state queried from the current state monitor.
planning_scene_monitor::PlanningSceneMonitorPtr getPlanningSceneMonitorNonConst()
const rclcpp::Node::SharedPtr & getNode() const
Get the ROS node this instance operates on.
MoveItCpp(const rclcpp::Node::SharedPtr &node)
Constructor.
bool terminatePlanningPipeline(const std::string &pipeline_name)
Utility to terminate the given planning pipeline.
trajectory_execution_manager::TrajectoryExecutionManagerConstPtr getTrajectoryExecutionManager() const
Get the stored instance of the trajectory execution manager.
trajectory_execution_manager::TrajectoryExecutionManagerPtr getTrajectoryExecutionManagerNonConst()
This is a convenience class for obtaining access to an instance of a locked PlanningScene.
std::unordered_map< std::string, planning_pipeline::PlanningPipelinePtr > createPlanningPipelineMap(const std::vector< std::string > &pipeline_names, const moveit::core::RobotModelConstPtr &robot_model, const rclcpp::Node::SharedPtr &node, const std::string &parameter_namespace=std::string())
Utility function to create a map of named planning pipelines.
Main namespace for MoveIt.
Definition exceptions.h:43
Parameter container for initializing MoveItCpp.
Definition moveit_cpp.h:100