moveit2
The MoveIt Motion Planning Framework for ROS 2.
srdf_config.cpp
Go to the documentation of this file.
1 /*********************************************************************
2  * Software License Agreement (BSD License)
3  *
4  * Copyright (c) 2021, PickNik Robotics, 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 Robotics 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  *********************************************************************/
38 
39 namespace moveit_setup
40 {
42 {
43  parent_node_->declare_parameter("robot_description_semantic", rclcpp::ParameterType::PARAMETER_STRING);
44  changes_ = 0L;
45 }
46 
47 void SRDFConfig::loadPrevious(const std::filesystem::path& package_path, const YAML::Node& node)
48 {
49  if (!getYamlProperty(node, "relative_path", srdf_pkg_relative_path_))
50  {
51  throw std::runtime_error("cannot find relative_path property in SRDF");
52  }
54 }
55 
56 YAML::Node SRDFConfig::saveToYaml() const
57 {
58  YAML::Node node;
59  node["relative_path"] = srdf_pkg_relative_path_.string();
60  return node;
61 }
62 
64 {
65  if (urdf_model_ != nullptr)
66  {
67  return;
68  }
69 
70  auto urdf_config = config_data_->get<URDFConfig>("urdf");
71  urdf_model_ = urdf_config->getModelPtr();
72  srdf_.robot_name_ = urdf_model_->getName();
73  parent_node_->set_parameter(rclcpp::Parameter("robot_description_semantic", srdf_.getSRDFString()));
74 }
75 
76 void SRDFConfig::loadSRDFFile(const std::filesystem::path& package_path, const std::filesystem::path& relative_path)
77 {
78  srdf_pkg_relative_path_ = relative_path;
79  loadSRDFFile(std::filesystem::path(package_path) / relative_path);
80 }
81 // ******************************************************************************************
82 // Load SRDF File to Parameter Server
83 // ******************************************************************************************
84 void SRDFConfig::loadSRDFFile(const std::filesystem::path& srdf_file_path, const std::vector<std::string>& xacro_args)
85 {
86  srdf_path_ = srdf_file_path;
87 
88  loadURDFModel();
89 
90  std::string srdf_string;
91  if (!rdf_loader::RDFLoader::loadXmlFileToString(srdf_string, srdf_path_, xacro_args))
92  {
93  throw std::runtime_error("SRDF file not found: " + srdf_path_.string());
94  }
95 
96  // Verify that file is in correct format / not an XACRO by loading into robot model
97  if (!srdf_.initString(*urdf_model_, srdf_string))
98  {
99  throw std::runtime_error("SRDF file not a valid semantic robot description model.");
100  }
101 
102  // Set parameter
103  parent_node_->set_parameter(rclcpp::Parameter("robot_description_semantic", srdf_string));
104 
106 
107  RCLCPP_INFO_STREAM(*logger_, "Robot semantic model successfully loaded.");
108 }
109 
111 {
112  if (!srdf_pkg_relative_path_.empty())
113  {
114  return;
115  }
116  srdf_pkg_relative_path_ = std::filesystem::path("config") / (urdf_model_->getName() + ".srdf");
117 }
118 
119 void SRDFConfig::updateRobotModel(long changed_information)
120 {
121  // Initialize with a URDF Model Interface and a SRDF Model
122  loadURDFModel();
123  if (changed_information > 0)
124  {
125  srdf_.updateSRDFModel(*urdf_model_);
126  }
127 
128  robot_model_ = std::make_shared<moveit::core::RobotModel>(urdf_model_, srdf_.srdf_model_);
129 
130  if (srdf_pkg_relative_path_.empty())
131  {
132  srdf_pkg_relative_path_ = std::filesystem::path("config") / (urdf_model_->getName() + ".srdf");
133  srdf_.robot_name_ = urdf_model_->getName();
134  changes_ |= OTHER;
135  }
136  changes_ |= changed_information;
137 
138  // Reset the planning scene
139  planning_scene_.reset();
140 }
141 
142 // ******************************************************************************************
143 // Provide a shared planning scene
144 // ******************************************************************************************
145 planning_scene::PlanningScenePtr SRDFConfig::getPlanningScene()
146 {
147  if (!planning_scene_)
148  {
149  // make sure kinematic model exists
150  getRobotModel();
151 
152  // Allocate an empty planning scene
153  planning_scene_ = std::make_shared<planning_scene::PlanningScene>(robot_model_);
154  }
155  return planning_scene_;
156 }
157 
158 std::vector<std::string> SRDFConfig::getLinkNames() const
159 {
160  std::vector<std::string> names;
161  for (const moveit::core::LinkModel* link_model : robot_model_->getLinkModels())
162  {
163  names.push_back(link_model->getName());
164  }
165  return names;
166 }
167 
168 std::string SRDFConfig::getChildOfJoint(const std::string& joint_name) const
169 {
170  const moveit::core::JointModel* joint_model = getRobotModel()->getJointModel(joint_name);
171  // Check that a joint model was found
172  if (!joint_model)
173  {
174  return "";
175  }
176  return joint_model->getChildLinkModel()->getName();
177 }
178 
179 void SRDFConfig::removePoseByName(const std::string& pose_name, const std::string& group_name)
180 {
181  for (std::vector<srdf::Model::GroupState>::iterator pose_it = srdf_.group_states_.begin();
182  pose_it != srdf_.group_states_.end(); ++pose_it)
183  {
184  if (pose_it->name_ == pose_name && pose_it->group_ == group_name)
185  {
186  srdf_.group_states_.erase(pose_it);
188  return;
189  }
190  }
191 }
192 
193 std::vector<std::string> SRDFConfig::getJointNames(const std::string& group_name, bool include_multi_dof,
194  bool include_passive)
195 {
196  std::vector<std::string> names;
197  const moveit::core::JointModelGroup* joint_model_group = robot_model_->getJointModelGroup(group_name);
198 
199  // Iterate through the joints
200  for (const moveit::core::JointModel* joint : joint_model_group->getActiveJointModels())
201  {
202  if (!include_multi_dof && joint->getVariableCount() > 1)
203  {
204  continue;
205  }
206  else if (!include_passive && joint->isPassive())
207  {
208  continue;
209  }
210  names.push_back(joint->getName());
211  }
212  return names;
213 }
214 
215 void SRDFConfig::collectVariables(std::vector<TemplateVariable>& variables)
216 {
217  variables.push_back(TemplateVariable("ROBOT_NAME", srdf_.robot_name_));
218  variables.push_back(TemplateVariable("ROBOT_ROOT_LINK", robot_model_->getRootLinkName()));
219  variables.push_back(TemplateVariable("PLANNING_FRAME", robot_model_->getModelFrame()));
220 }
221 
229 {
231  {
232  return jm1->getName() < jm2->getName();
233  }
234 };
235 
237 {
238  emitter << YAML::Comment("joint_limits.yaml allows the dynamics properties specified in the URDF "
239  "to be overwritten or augmented as needed");
240  emitter << YAML::Newline;
241 
242  emitter << YAML::BeginMap;
243 
244  emitter << YAML::Comment("For beginners, we downscale velocity and acceleration limits.") << YAML::Newline;
245  emitter << YAML::Comment("You can always specify higher scaling factors (<= 1.0) in your motion requests.");
246  emitter << YAML::Comment("Increase the values below to 1.0 to always move at maximum speed.");
247  emitter << YAML::Key << "default_velocity_scaling_factor";
248  emitter << YAML::Value << "0.1";
249 
250  emitter << YAML::Key << "default_acceleration_scaling_factor";
251  emitter << YAML::Value << "0.1";
252 
253  emitter << YAML::Newline << YAML::Newline;
254  emitter << YAML::Comment("Specific joint properties can be changed with the keys "
255  "[max_position, min_position, max_velocity, max_acceleration]")
256  << YAML::Newline;
257  emitter << YAML::Comment("Joint limits can be turned off with [has_velocity_limits, has_acceleration_limits]");
258 
259  emitter << YAML::Key << "joint_limits";
260  emitter << YAML::Value << YAML::BeginMap;
261 
262  // Union all the joints in groups. Uses a custom comparator to allow the joints to be sorted by name
263  std::set<const moveit::core::JointModel*, JointModelCompare> joints;
264 
265  // Loop through groups
266  for (srdf::Model::Group& group : parent_.srdf_.groups_)
267  {
268  // Get list of associated joints
269  const moveit::core::JointModelGroup* joint_model_group = parent_.getRobotModel()->getJointModelGroup(group.name_);
270 
271  const std::vector<const moveit::core::JointModel*>& joint_models = joint_model_group->getJointModels();
272 
273  // Iterate through the joints
274  for (const moveit::core::JointModel* joint_model : joint_models)
275  {
276  // Check that this joint only represents 1 variable.
277  if (joint_model->getVariableCount() == 1)
278  joints.insert(joint_model);
279  }
280  }
281 
282  // Add joints to yaml file, if no more than 1 dof
283  for (const moveit::core::JointModel* joint : joints)
284  {
285  emitter << YAML::Key << joint->getName();
286  emitter << YAML::Value << YAML::BeginMap;
287 
288  const moveit::core::VariableBounds& b = joint->getVariableBounds()[0];
289 
290  // Output property
291  emitter << YAML::Key << "has_velocity_limits";
292  if (b.velocity_bounded_)
293  {
294  emitter << YAML::Value << "true";
295  }
296  else
297  {
298  emitter << YAML::Value << "false";
299  }
300 
301  // Output property
302  emitter << YAML::Key << "max_velocity";
303  emitter << YAML::Value << std::min(fabs(b.max_velocity_), fabs(b.min_velocity_));
304 
305  // Output property
306  emitter << YAML::Key << "has_acceleration_limits";
307  if (b.acceleration_bounded_)
308  {
309  emitter << YAML::Value << "true";
310  }
311  else
312  {
313  emitter << YAML::Value << "false";
314  }
315 
316  // Output property
317  emitter << YAML::Key << "max_acceleration";
318  emitter << YAML::Value << std::min(fabs(b.max_acceleration_), fabs(b.min_acceleration_));
319 
320  emitter << YAML::EndMap;
321  }
322 
323  emitter << YAML::EndMap;
324  return true; // file created successfully
325 }
326 
327 } // namespace moveit_setup
328 
329 #include <pluginlib/class_list_macros.hpp> // NOLINT
PLUGINLIB_EXPORT_CLASS(cached_ik_kinematics_plugin::CachedIKKinematicsPlugin< kdl_kinematics_plugin::KDLKinematicsPlugin >, kinematics::KinematicsBase)
const std::vector< const JointModel * > & getActiveJointModels() const
Get the active joints in this group (that have controllable DOF). This does not include mimic joints.
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....
Definition: joint_model.h:117
const LinkModel * getChildLinkModel() const
Get the link that this joint connects to. There will always be such a link.
Definition: joint_model.h:168
const std::string & getName() const
Get the name of the joint.
Definition: joint_model.h:145
A link from the robot. Contains the constant transform applied to the link and its geometry.
Definition: link_model.h:72
const std::string & getName() const
The name of this link.
Definition: link_model.h:86
bool writeYaml(YAML::Emitter &emitter) override
void updateRobotModel(long changed_information=0L)
srdf::SRDFWriter srdf_
SRDF Data and Writer.
planning_scene::PlanningScenePtr planning_scene_
Shared planning scene.
void removePoseByName(const std::string &pose_name, const std::string &group_name)
std::shared_ptr< urdf::Model > urdf_model_
planning_scene::PlanningScenePtr getPlanningScene()
Provide a shared planning scene.
std::filesystem::path srdf_pkg_relative_path_
Path relative to loaded configuration package.
std::string getChildOfJoint(const std::string &joint_name) const
Return the name of the child link of a joint.
moveit::core::RobotModelPtr getRobotModel() const
Definition: srdf_config.hpp:82
moveit::core::RobotModelPtr robot_model_
std::vector< std::string > getJointNames(const std::string &group_name, bool include_multi_dof=true, bool include_passive=true)
std::filesystem::path srdf_path_
Full file-system path to srdf.
void loadSRDFFile(const std::filesystem::path &package_path, const std::filesystem::path &relative_path)
Load SRDF File.
Definition: srdf_config.cpp:76
YAML::Node saveToYaml() const override
Optionally save "meta" information for saving in the .setup_assistant yaml file.
Definition: srdf_config.cpp:56
void onInit() override
Overridable initialization method.
Definition: srdf_config.cpp:41
std::vector< std::string > getLinkNames() const
void collectVariables(std::vector< TemplateVariable > &variables) override
Collect key/value pairs for use in templates.
void loadPrevious(const std::filesystem::path &package_path, const YAML::Node &node) override
Loads the configuration from an existing MoveIt configuration.
Definition: srdf_config.cpp:47
where all the data for each part of the configuration is stored.
Definition: config.hpp:58
rclcpp::Node::SharedPtr parent_node_
Definition: config.hpp:162
std::shared_ptr< DataWarehouse > config_data_
Definition: config.hpp:161
std::shared_ptr< rclcpp::Logger > logger_
Definition: config.hpp:164
static bool loadXmlFileToString(std::string &buffer, const std::string &path, const std::vector< std::string > &xacro_args)
helper that branches between loadFileToString() and loadXacroFileToString() based on result of isXacr...
Definition: rdf_loader.cpp:206
bool getYamlProperty(const YAML::Node &node, const std::string &key, T &storage, const T &default_value=T())
Definition: utilities.hpp:118
Custom std::set comparator, used for sorting the joint_limits.yaml file into alphabetical order.
bool operator()(const moveit::core::JointModel *jm1, const moveit::core::JointModel *jm2) const
Simple Key/value pair for templates.
Definition: templates.hpp:47