1"""Simplify loading moveit config parameters.
3This module provides builder-pattern based class to simplify loading moveit related parameters found in
4robot_moveit_config package generated by moveit setup assistant.
6By default it expects the following structure for the moveit configs package
8robot_name_moveit_config/
9 .setup_assistant -> Used to retrieve information about the SRDF file and
10 the URDF file used when generating the package
12 kinematics.yaml -> IK solver's parameters
13 joint_limits.yaml -> Overriding position/velocity/acceleration limits from the URDF file
14 moveit_cpp.yaml -> MoveItCpp related parameters
15 *_planning.yaml -> planning pipelines parameters
16 pilz_cartesian_limits.yaml -> Pilz planner parameters
17 moveit_controllers.yaml -> trajectory execution manager's parameters
21 moveit_configs = MoveItConfigsBuilder("robot_name").to_moveit_configs()
23 moveit_configs.package_path
24 moveit_configs.robot_description
25 moveit_configs.robot_description_semantic
26 moveit_configs.robot_description_kinematics
27 moveit_configs.planning_pipelines
28 moveit_configs.trajectory_execution
29 moveit_configs.planning_scene_monitor
30 moveit_configs.sensors_3d
31 moveit_configs.move_group_capabilities
32 moveit_configs.joint_limits
33 moveit_configs.moveit_cpp
34 moveit_configs.pilz_cartesian_limits
35 # Or to get all the parameters as a dictionary
36 moveit_configs.to_dict()
38Each function in MoveItConfigsBuilder has a file_path as an argument which is used to override the default
42 moveit_configs = MoveItConfigsBuilder("robot_name")
43 # Relative to robot_name_moveit_configs
44 .robot_description_semantic(Path("my_config") / "my_file.srdf")
47 moveit_configs = MoveItConfigsBuilder("robot_name")
48 # Absolute path to robot_name_moveit_config
49 .robot_description_semantic(Path.home() / "my_config" / "new_file.srdf")
53from pathlib
import Path
54from typing
import Optional, List, Dict
57from dataclasses
import dataclass, field
58from ament_index_python.packages
import get_package_share_directory
60from launch_param_builder
import ParameterBuilder, load_yaml, load_xacro
61from launch_param_builder.utils
import ParameterBuilderFileNotFoundError
63from launch.some_substitutions_type
import SomeSubstitutionsType
64from launch_ros.parameter_descriptions
import ParameterValue
66moveit_configs_utils_path = Path(get_package_share_directory(
"moveit_configs_utils"))
70 """Given all the files in the folder, find those that match the pattern.
72 If there are groups defined, the groups are returned. Otherwise the path to the matches are returned.
75 if not folder.exists():
77 for child
in folder.iterdir():
78 if not child.is_file():
80 m = pattern.search(child.name)
84 matches.append(groups[0])
92 """Class containing MoveIt related parameters."""
95 package_path: Optional[str] =
None
97 robot_description: Dict = field(default_factory=dict)
99 robot_description_semantic: Dict = field(default_factory=dict)
101 robot_description_kinematics: Dict = field(default_factory=dict)
103 planning_pipelines: Dict = field(default_factory=dict)
105 trajectory_execution: Dict = field(default_factory=dict)
107 planning_scene_monitor: Dict = field(default_factory=dict)
109 sensors_3d: Dict = field(default_factory=dict)
111 move_group_capabilities: Dict = field(
112 default_factory=
lambda: {
"capabilities":
"",
"disable_capabilities":
""}
115 joint_limits: Dict = field(default_factory=dict)
117 moveit_cpp: Dict = field(default_factory=dict)
119 pilz_cartesian_limits: Dict = field(default_factory=dict)
134 parameters[
"robot_description_planning"].update(
141 __moveit_configs: MoveItConfigs
145 __urdf_file_path: Path
147 __srdf_file_path: Path
150 __robot_description: str
151 __config_dir_path = Path(
"config")
157 robot_description=
"robot_description",
158 package_name: Optional[str] =
None,
160 super().
__init__(package_name
or (robot_name +
"_moveit_config"))
163 setup_assistant_file = self._package_path /
".setup_assistant"
171 if (self._package_path / modified_urdf_path).exists():
175 if setup_assistant_file.exists():
176 setup_assistant_yaml = load_yaml(setup_assistant_file)
177 config = setup_assistant_yaml.get(
"moveit_setup_assistant_config", {})
179 if urdf_config := config.get(
"urdf", config.get(
"URDF")):
182 get_package_share_directory(urdf_config[
"package"])
186 if xacro_args := urdf_config.get(
"xacro_args"):
188 arg.split(
":=")
for arg
in xacro_args.split(
" ")
if arg
191 if srdf_config := config.get(
"srdf", config.get(
"SRDF")):
196 f
"\x1b[33;21mCannot infer URDF from `{self._package_path}`. -- using config/{robot_name}.urdf\x1b[0m"
205 f
"\x1b[33;21mCannot infer SRDF from `{self._package_path}`. -- using config/{robot_name}.srdf\x1b[0m"
215 file_path: Optional[str] =
None,
216 mappings: dict[SomeSubstitutionsType, SomeSubstitutionsType] =
None,
218 """Load robot description.
220 :param file_path: Absolute or relative path to the URDF file (w.r.t. robot_name_moveit_config).
221 :param mappings: mappings to be passed when loading the xacro file.
222 :return: Instance of MoveItConfigsBuilder with robot_description loaded.
224 if file_path
is None:
227 robot_description_file_path = self._package_path / file_path
228 if (mappings
is None)
or all(
229 (isinstance(key, str)
and isinstance(value, str))
230 for key, value
in mappings.items()
235 robot_description_file_path,
239 except ParameterBuilderFileNotFoundError
as e:
240 logging.warning(f
"\x1b[33;21m{e}\x1b[0m")
242 f
"\x1b[33;21mThe robot description will be loaded from /robot_description topic \x1b[0m"
248 Xacro(str(robot_description_file_path), mappings=mappings),
256 file_path: Optional[str] =
None,
257 mappings: dict[SomeSubstitutionsType, SomeSubstitutionsType] =
None,
259 """Load semantic robot description.
261 :param file_path: Absolute or relative path to the SRDF file (w.r.t. robot_name_moveit_config).
262 :param mappings: mappings to be passed when loading the xacro file.
263 :return: Instance of MoveItConfigsBuilder with robot_description_semantic loaded.
266 if (mappings
is None)
or all(
267 (isinstance(key, str)
and isinstance(value, str))
268 for key, value
in mappings.items()
272 +
"_semantic": load_xacro(
280 +
"_semantic": ParameterValue(
291 """Load IK solver parameters.
293 :param file_path: Absolute or relative path to the kinematics yaml file (w.r.t. robot_name_moveit_config).
294 :return: Instance of MoveItConfigsBuilder with robot_description_kinematics loaded.
298 +
"_kinematics": load_yaml(
306 """Load joint limits overrides.
308 :param file_path: Absolute or relative path to the joint limits yaml file (w.r.t. robot_name_moveit_config).
309 :return: Instance of MoveItConfigsBuilder with robot_description_planning loaded.
313 +
"_planning": load_yaml(
321 """Load MoveItCpp parameters.
323 :param file_path: Absolute or relative path to the MoveItCpp yaml file (w.r.t. robot_name_moveit_config).
324 :return: Instance of MoveItConfigsBuilder with moveit_cpp loaded.
334 file_path: Optional[str] =
None,
335 moveit_manage_controllers: bool =
True,
337 """Load trajectory execution and moveit controller managers' parameters
339 :param file_path: Absolute or relative path to the controllers yaml file (w.r.t. robot_name_moveit_config).
340 :param moveit_manage_controllers: Whether trajectory execution manager is allowed to switch controllers' states.
341 :return: Instance of MoveItConfigsBuilder with trajectory_execution loaded.
344 "moveit_manage_controllers": moveit_manage_controllers,
348 if file_path
is None:
350 controller_pattern = re.compile(
"^(.*)_controllers.yaml$")
352 if not possible_names:
355 "\x1b[33;20mtrajectory_execution: `Parameter file_path is undefined "
356 f
"and no matches for {config_folder}/*_controllers.yaml\x1b[0m"
360 if len(possible_names) == 1:
361 chosen_name = possible_names[0]
365 if name
in possible_names:
369 option_str =
"\n - ".join(
370 name +
"_controllers.yaml" for name
in possible_names
373 "trajectory_execution: "
374 f
"Unable to guess which parameter file to load. Options:\n - {option_str}"
376 file_path = config_folder / (chosen_name +
"_controllers.yaml")
379 file_path = self._package_path / file_path
387 publish_planning_scene: bool =
True,
388 publish_geometry_updates: bool =
True,
389 publish_state_updates: bool =
True,
390 publish_transforms_updates: bool =
True,
391 publish_robot_description: bool =
False,
392 publish_robot_description_semantic: bool =
False,
397 "publish_planning_scene": publish_planning_scene,
398 "publish_geometry_updates": publish_geometry_updates,
399 "publish_state_updates": publish_state_updates,
400 "publish_transforms_updates": publish_transforms_updates,
401 "publish_robot_description": publish_robot_description,
402 "publish_robot_description_semantic": publish_robot_description_semantic,
408 """Load sensors_3d parameters.
410 :param file_path: Absolute or relative path to the sensors_3d yaml file (w.r.t. robot_name_moveit_config).
411 :return: Instance of MoveItConfigsBuilder with robot_description_planning loaded.
413 sensors_path = self._package_path / (
416 if sensors_path.exists():
417 sensors_data = load_yaml(sensors_path)
420 if len(sensors_data[
"sensors"]) > 0
and sensors_data[
"sensors"][0]:
426 default_planning_pipeline: str =
None,
427 pipelines: List[str] =
None,
428 load_all: bool =
True,
430 """Load planning pipelines parameters.
432 :param default_planning_pipeline: Name of the default planning pipeline.
433 :param pipelines: List of the planning pipelines to be loaded.
434 :param load_all: Only used if pipelines is None.
435 If true, loads all pipelines defined in config package AND this package.
436 If false, only loads the pipelines defined in config package.
437 :return: Instance of MoveItConfigsBuilder with planning_pipelines loaded.
440 default_folder = moveit_configs_utils_path /
"default_configs"
443 if pipelines
is None:
444 planning_pattern = re.compile(
"^(.*)_planning.yaml$")
448 if pipeline
not in pipelines:
449 pipelines.append(pipeline)
452 if not default_planning_pipeline:
453 if "ompl" in pipelines:
454 default_planning_pipeline =
"ompl"
456 default_planning_pipeline = pipelines[0]
458 if default_planning_pipeline
not in pipelines:
460 f
"default_planning_pipeline: `{default_planning_pipeline}` doesn't name any of the input pipelines "
461 f
"`{','.join(pipelines)}`"
464 "planning_pipelines": pipelines,
465 "default_planning_pipeline": default_planning_pipeline,
467 for pipeline
in pipelines:
468 parameter_file = config_folder / (pipeline +
"_planning.yaml")
469 if not parameter_file.exists():
470 parameter_file = default_folder / (pipeline +
"_planning.yaml")
478 if "planner_configs" not in ompl_config:
479 ompl_config.update(load_yaml(default_folder /
"ompl_defaults.yaml"))
484 """Load cartesian limits.
486 :param file_path: Absolute or relative path to the cartesian limits file (w.r.t. robot_name_moveit_config).
487 :return: Instance of MoveItConfigsBuilder with pilz_cartesian_limits loaded.
489 deprecated_path = self._package_path / (
492 if deprecated_path.exists():
494 f
"\x1b[33;21mcartesian_limits.yaml is deprecated, please rename to pilz_cartesian_limits.yaml\x1b[0m"
499 +
"_planning": load_yaml(
507 """Get MoveIt configs from robot_name_moveit_config.
509 :return: An MoveItConfigs instance with all parameters loaded.
535 def to_dict(self, include_moveit_configs: bool =
True):
536 """Get loaded parameters from robot_name_moveit_config as a dictionary.
538 :param include_moveit_configs: Whether to include the MoveIt config parameters or
539 only the ones from ParameterBuilder
540 :return: Dictionary with all parameters loaded.
542 parameters = self._parameters
543 if include_moveit_configs:
robot_description_kinematics(self, Optional[str] file_path=None)
sensors_3d(self, Optional[str] file_path=None)
trajectory_execution(self, Optional[str] file_path=None, bool moveit_manage_controllers=True)
__init__(self, str robot_name, robot_description="robot_description", Optional[str] package_name=None)
to_dict(self, bool include_moveit_configs=True)
robot_description_semantic(self, Optional[str] file_path=None, dict[SomeSubstitutionsType, SomeSubstitutionsType] mappings=None)
MoveItConfigs __moveit_configs
joint_limits(self, Optional[str] file_path=None)
pilz_cartesian_limits(self, Optional[str] file_path=None)
planning_pipelines(self, str default_planning_pipeline=None, List[str] pipelines=None, bool load_all=True)
planning_scene_monitor(self, bool publish_planning_scene=True, bool publish_geometry_updates=True, bool publish_state_updates=True, bool publish_transforms_updates=True, bool publish_robot_description=False, bool publish_robot_description_semantic=False)
robot_description(self, Optional[str] file_path=None, dict[SomeSubstitutionsType, SomeSubstitutionsType] mappings=None)
robot_description_semantic
Dict robot_description_kinematics
Dict pilz_cartesian_limits
Dict planning_scene_monitor
Dict robot_description_semantic
Dict trajectory_execution
robot_description_kinematics
get_pattern_matches(folder, pattern)