import os import subprocess import yaml from launch import LaunchDescription from launch_ros.actions import Node, SetParameter from launch.actions import IncludeLaunchDescription, RegisterEventHandler, LogInfo, ExecuteProcess, ExecuteLocal, TimerAction from launch_ros.substitutions import FindPackageShare from launch.substitutions import PathJoinSubstitution from launch.launch_description_sources import PythonLaunchDescriptionSource from ament_index_python.packages import get_package_share_directory from launch.event_handlers import OnProcessExit from launch.launch_description_entity import LaunchDescriptionEntity from pathlib import Path def load_file(package_name, file_path): package_path = get_package_share_directory(package_name) absolute_file_path = os.path.join(package_path, file_path) try: with open(absolute_file_path, 'r') as file: print("Opened file") return file.read() except EnvironmentError: # parent of IOError, OSError *and* WindowsError where available print("ERROR: load_file " + package_name + " | " + file_path + " -> " + absolute_file_path) return None def load_xacro(package_name, file_path): package_path = get_package_share_directory(package_name) absolute_file_path = os.path.join(package_path, file_path) process = subprocess.run(["xacro", absolute_file_path], capture_output=True) if process.returncode != 0: print(process.stderr) return process.stdout.decode("UTF-8") def load_yaml(package_name, file_path): package_path = get_package_share_directory(package_name) absolute_file_path = os.path.join(package_path, file_path) try: with open(absolute_file_path, 'r') as file: print("Opened file") return yaml.safe_load(file) except EnvironmentError: # parent of IOError, OSError *and* WindowsError where available print("ERROR: load_yaml " + package_name + " | " + file_path + " -> " + absolute_file_path) return None def launch_chain(nodes: list[ExecuteLocal]): generatedNodes: list[LaunchDescriptionEntity] = [] for index in range(1, len(nodes)): generatedNodes.append(RegisterEventHandler( OnProcessExit( target_action=nodes[index-1], on_exit=nodes[index] ) )) generatedNodes.append(nodes[0]) return generatedNodes def generate_launch_description(): robot_description_config = load_xacro('iisy_config', 'urdf/iisy.urdf') robot_description = {'robot_description': robot_description_config} robot_description_semantic_config = load_file('iisy_config', 'srdf/iisy.srdf') robot_description_semantic = {'robot_description_semantic': robot_description_semantic_config} kinematics_yaml = load_yaml('iisy_config', 'config/kinematics.yml') robot_description_kinematics = {'robot_description_kinematics': kinematics_yaml} controllers = { "moveit_simple_controller_manager": load_yaml("iisy_config", "config/iisy_controllers.yml"), "moveit_controller_manager": "moveit_ros_control_interface/Ros2ControlMultiManager", } ompl_planning_pipeline_config = { 'move_group': { 'planning_plugin': 'ompl_interface/OMPLPlanner', 'request_adapters': """default_planner_request_adapters/AddTimeOptimalParameterization default_planner_request_adapters/FixWorkspaceBounds default_planner_request_adapters/FixStartStateBounds default_planner_request_adapters/FixStartStateCollision default_planner_request_adapters/FixStartStatePathConstraints""", 'start_state_max_bounds_error': 0.1 } } ompl_planning_yaml = load_yaml('iisy_config', 'config/ompl_planning.yml') ompl_planning_pipeline_config['move_group'].update(ompl_planning_yaml) robot_description_planning = { "robot_description_planning": PathJoinSubstitution( [ FindPackageShare("iisy_config"), "config/joint_limits.yml" ] ) } trajectory_execution = { 'moveit_manage_controllers': False, 'trajectory_execution.allowed_execution_duration_scaling': 1.2, 'trajectory_execution.allowed_goal_duration_margin': 0.5, 'trajectory_execution.allowed_start_tolerance': 0.01 } planning_scene_monitor_parameters = { "publish_planning_scene": True, "publish_geometry_updates": True, "publish_state_updates": True, "publish_transforms_updates": True } planning = { "move_group": { "planning_plugin": "ompl_interface/OMPLPlanner", "request_adapters": "default_planner_request_adapters/AddTimeParameterization default_planner_request_adapters/FixWorkspaceBounds default_planner_request_adapters/FixStartStateBounds default_planner_request_adapters/FixStartStateCollision default_planner_request_adapters/FixStartStatePathConstraints", "start_state_max_bounds_error": 0.1 } } spawn_robot = Node( package='ros_gz_sim', executable='create', arguments=['-world', 'default', '-string', robot_description_config], output='screen' ) rviz = Node( package='rviz2', executable='rviz2', arguments=['-d', os.path.join(get_package_share_directory("ign_world"), 'rviz', 'iisy.rviz')], parameters=[ robot_description, robot_description_semantic, robot_description_planning, ompl_planning_pipeline_config, robot_description_kinematics, planning, trajectory_execution, controllers, planning_scene_monitor_parameters, ], ) controller_manager = Node( package="controller_manager", executable="ros2_control_node", parameters=[ robot_description, str(Path(get_package_share_directory("iisy_config")+"/config/iisy_controllers.yaml")), ], ) load_joint_state_broadcaster = ExecuteProcess( cmd=['ros2', 'control', 'load_controller', '--set-state', 'active', 'joint_state_broadcaster'], output='both' ) load_joint_trajectory_controller = ExecuteProcess( cmd=['ros2', 'control', 'load_controller', '--set-state', 'active', 'joint_trajectory_controller'], output='both' ) move_group = Node( package='moveit_ros_move_group', executable='move_group', # prefix='xterm -fs 10 -e gdb --ex run --args', output='both', parameters=[ robot_description, robot_description_semantic, robot_description_planning, ompl_planning_pipeline_config, robot_description_kinematics, planning, trajectory_execution, controllers, planning_scene_monitor_parameters, # octomap_config, # octomap_updater_config ] ) test = Node( package='moveit_test', executable='move', output='both', parameters=[ robot_description, robot_description_semantic, robot_description_planning, ompl_planning_pipeline_config, robot_description_kinematics, planning, trajectory_execution, controllers, planning_scene_monitor_parameters, # octomap_config, # octomap_updater_config ], ) # octomap_config = {'octomap_frame': 'camera_rgb_optical_frame', # 'octomap_resolution': 0.05, # 'max_range': 5.0} # octomap_updater_config = load_yaml('moveit_tutorials', 'config/sensors_3d.yaml') pkg_ros_gz_sim = get_package_share_directory('ros_gz_sim') return LaunchDescription([ #IncludeLaunchDescription( # PythonLaunchDescriptionSource(os.path.join(pkg_ros_gz_sim, 'launch', 'gz_sim.launch.py')), # launch_arguments={'gz_args': '-r '+get_package_share_directory('ign_world')+'/world/gaz_new_test.sdf'}.items(), #), Node( package='ros_gz_bridge', executable='parameter_bridge', arguments=["/clock[rosgraph_msgs/msg/Clock@ignition.msgs.Clock"], output='both', ), SetParameter(name="use_sim_time", value=True), move_group, #RegisterEventHandler( # OnProcessExit( # target_action=spawn_robot, # on_exit=[load_joint_state_broadcaster] # ) #), controller_manager, RegisterEventHandler( OnProcessExit( target_action=load_joint_state_broadcaster, on_exit=[load_joint_trajectory_controller] ) ), RegisterEventHandler( OnProcessExit( target_action=load_joint_trajectory_controller, on_exit=TimerAction(period=10.0,actions=[test]) ) ), #spawn_robot, load_joint_state_broadcaster, #load_joint_trajectory_controller, rviz, Node( package='ros_actor_action_server', executable='ros_actor_action_server'), Node( package='tf2_ros', executable='static_transform_publisher', name='lidar_1_broadcaster', arguments=[ "--x", "1", "--y", "-1.9", "--z", "1", "--roll", "1.5707963267949", "--pitch", "0", "--yaw", "0", "--frame-id", "world", "--child-frame-id", "lidar_1_link"] ), Node( package='tf2_ros', executable='static_transform_publisher', name='lidar_2_broadcaster', arguments=[ "--x", "-1.9", "--y", "1", "--z", "1", "--roll", "0", "--pitch", "0", "--yaw", "0", "--frame-id", "world", "--child-frame-id", "lidar_2_link"] ), #Node( # package='ros_gz_bridge', # executable='parameter_bridge', # arguments=["/world/default/model/iisy/joint_state[sensor_msgs/msg/JointState@ignition.msgs.Model"], # output='both', # remappings=[ # ('/world/default/model/iisy/joint_state', '/joint_states'), # ] #), Node( package='robot_state_publisher', executable='robot_state_publisher', output='both', parameters=[robot_description] ), ])