Spawn 5dof lss-arm in gazebo with turtlebot4 robot

Hi! I have been trying to launch the 5dof lss-arm in gazebo in a specified location. I’ve managed to launch rviz, but the arm doesn’t appear.

I’ve added the x, y, z and yaw launch arguments for the the robot_lss_arm.launch.py file that comes with the lss_sim_moveit_example package from the official repository.

The new launch file:

#!/usr/bin/env -S ros2 launch
"""Launch script for spawning LSS 4DoF/5DoF Arm into Gazebo world"""

from typing import List

from launch_ros.actions import Node

from launch import LaunchDescription
from launch.actions import DeclareLaunchArgument
from launch.substitutions import LaunchConfiguration, PythonExpression


def generate_launch_description() -> LaunchDescription:

    # Declare all launch arguments
    declared_arguments = generate_declared_arguments()

    # Get substitution for all arguments
    dof = LaunchConfiguration("dof")
    use_sim_time = LaunchConfiguration("use_sim_time")
    log_level = LaunchConfiguration("log_level")
    x = LaunchConfiguration("x")
    y = LaunchConfiguration("y")
    z = LaunchConfiguration("z")
    yaw = LaunchConfiguration("yaw")

    model = PythonExpression(["'lss_arm_", dof, "dof'"])

    # List of nodes to be launched
    nodes = [
        Node(
            package="ros_ign_gazebo",
            executable="create",
            output="log",
            arguments=["-file", model, "--ros-args", "--log-level", log_level],
            parameters=[{"use_sim_time": use_sim_time}],
        ),
    ]


    # Declare namespace


    return LaunchDescription(declared_arguments + nodes)


def generate_declared_arguments() -> List[DeclareLaunchArgument]:
    """
    Generate list of all launch arguments that are declared for this launch script.
    """

    return [
        # Gripper
        DeclareLaunchArgument(
            "dof",
            default_value='5',
            choices=['4','5'],
            description="Parameter to select gripper model."
        ),
        # Miscellaneous
        DeclareLaunchArgument(
            "use_sim_time",
            default_value="true",
            description="If true, use simulated clock.",
        ),
        DeclareLaunchArgument(
            "log_level",
            default_value="warn",
            description="The level of logging that is applied to all ROS 2 nodes launched by this script.",
        ),

        # position
        DeclareLaunchArgument(
            "x",
            default_value='0.0',
            description='X coordinate for the robot\'s initial position.' 
        ),
        DeclareLaunchArgument(
            "y",
            default_value='0.0',
            description='Y coordinate for the robot\'s initial position.' 
        ),
        DeclareLaunchArgument(
            "z",
            default_value='0.0',
            description='Z coordinate for the robot\'s initial position.' 
        ),
        DeclareLaunchArgument(
            "yaw",
            default_value='0.0',
            description='Yaw angle for the robot\'s initial position.' 
        ),
    ]

The launch file with turtlebot4 and the arm:

# Adopted from https://github.com/turtlebot/turtlebot4_simulator/blob/humble/turtlebot4_ignition_bringup/launch/turtlebot4_ignition.launch.py
from ament_index_python.packages import get_package_share_directory

from os import path

from launch import LaunchDescription
from launch.actions import DeclareLaunchArgument
from launch.actions import IncludeLaunchDescription
from launch.launch_description_sources import PythonLaunchDescriptionSource
from launch.substitutions import LaunchConfiguration, PathJoinSubstitution
from launch_ros.substitutions import FindPackageShare


ARGUMENTS = [
    DeclareLaunchArgument('namespace', default_value='',
                          description='Robot namespace'),
    DeclareLaunchArgument('rviz', default_value='true',
                          choices=['true', 'false'], description='Start rviz.'),
    DeclareLaunchArgument('autostart', default_value='true',
                          choices=['true', 'false'], description='Auto start the nav2 stack.'),
    DeclareLaunchArgument('description', default_value='true',
                          choices=['true', 'false'], description='Launch tb3 description server'),
    DeclareLaunchArgument('use_respawn', default_value='true',
                          choices=['true', 'false'], description='Launch tb3 description server'),
    DeclareLaunchArgument('world', default_value='warehouse',
                          description='Ignition World'),
    DeclareLaunchArgument('model', default_value='lite',
                          choices=['standard', 'lite'],
                          description='Turtlebot4 Model'),
    DeclareLaunchArgument('localization', default_value='true',
                          choices=['true', 'false'], description='Start localization.'),
    DeclareLaunchArgument('nav2', default_value='true',
                          choices=['true', 'false'], description='Start nav2.'),
    DeclareLaunchArgument('params_file', default_value=f'{get_package_share_directory("rome_sim")}/params/nav2_params.yaml',
                          description='Full path to Nav2 params file.'),
    DeclareLaunchArgument('map',
                          default_value=f'{get_package_share_directory("rome_sim")}/maps/warehouse.yaml',
                          description='Full path to map yaml.'),
    # Gripper
    DeclareLaunchArgument(
        "dof",
        default_value='5',
        choices=['4','5'],
        description="Parameter to select gripper model."
    ),

    # miscellaneous
    DeclareLaunchArgument(
        "rviz_config",
        default_value=path.join(
            get_package_share_directory("lss_sim_moveit_example"),
            "rviz",
            "lss_sim_moveit.rviz",
        ),
        description="Path to configuration for RViz2.",
    ),
    DeclareLaunchArgument(
        "use_sim_time",
        default_value="true",
        description="If true, use simulated clock.",
    ),
    DeclareLaunchArgument(
        "ign_verbosity",
        default_value="2",
        description="Verbosity level for Gazebo (0~4).",
    ),
    DeclareLaunchArgument(
        "log_level",
        default_value="warn",
        description="The level of logging that is applied to all ROS 2 nodes launched by this script.",
    ),
]

for pose_element in ['x', 'y', 'z', 'yaw']:
    ARGUMENTS.append(DeclareLaunchArgument(pose_element, default_value='0.0',
                     description=f'{pose_element} component of the robot pose.'))


def generate_launch_description():
    # Directories
    pkg_turtlebot4_ignition_bringup = get_package_share_directory(
        'turtlebot4_ignition_bringup')

    # Paths
    ignition_launch = PathJoinSubstitution(
        [pkg_turtlebot4_ignition_bringup, 'launch', 'ignition.launch.py'])
    robot_spawn_launch = PathJoinSubstitution(
        [pkg_turtlebot4_ignition_bringup, 'launch', 'turtlebot4_spawn.launch.py'])

    ignition = IncludeLaunchDescription(
        PythonLaunchDescriptionSource([ignition_launch]),
        launch_arguments=[
            ('world', LaunchConfiguration('world'))
        ]
    )

    robot_spawn = IncludeLaunchDescription(
        PythonLaunchDescriptionSource([robot_spawn_launch]),
        launch_arguments=[
            ('namespace', LaunchConfiguration('namespace')),
            ('rviz', LaunchConfiguration('rviz')),
            ('autostart', LaunchConfiguration('autostart')),
            ('description', LaunchConfiguration('description')),
            ('use_respawn', LaunchConfiguration('use_respawn')),
            ('x', LaunchConfiguration('x')),
            ('y', LaunchConfiguration('y')),
            ('z', LaunchConfiguration('z')),
            ('yaw', LaunchConfiguration('yaw')),
            ('map', LaunchConfiguration('map')),
            ('nav2', LaunchConfiguration('nav2')),
            ('localization', LaunchConfiguration('localization')),
            ('params_file', LaunchConfiguration('params_file')),]
    )

    # Spawn arm
    lss_arm_spawn = IncludeLaunchDescription(
        PythonLaunchDescriptionSource(
            PathJoinSubstitution(
                [
                    FindPackageShare("lss_sim_moveit_example"),
                    "launch",
                    "robots",
                    "robot_lss_arm.launch.py",
                ]
            )
        ),
        launch_arguments=[
            ("dof", LaunchConfiguration("dof")),
            ("use_sim_time", LaunchConfiguration("use_sim_time")),
            ("ign_verbosity", LaunchConfiguration("ign_verbosity")),
            ("log_level", LaunchConfiguration("log_level")),
            ("x", LaunchConfiguration('x')),
            ("y", '1.0'),
            ("z", LaunchConfiguration('z')),
            ("yaw", LaunchConfiguration('yaw')),
        ]
    )
    
    # Launch move_group of MoveIt 2
    moveit2 = IncludeLaunchDescription(
        PythonLaunchDescriptionSource(
            PathJoinSubstitution(
                [
                    FindPackageShare(["lss_arm_moveit"]),
                    "launch",
                    "move_arm.launch.py",
                ]
            )
        ),
        launch_arguments=[
            ("dof", LaunchConfiguration("dof")),
            ("ros2_control_plugin", "sim"),
            ("collision", "true"),
            ("rviz_config", LaunchConfiguration("rviz_config")),
            ("use_sim_time", LaunchConfiguration("use_sim_time")),
            ("log_level", LaunchConfiguration("log_level")),
        ]
    )

    # Create launch description and add actions
    ld = LaunchDescription(ARGUMENTS)
    ld.add_action(ignition)
    ld.add_action(robot_spawn)
    ld.add_action(lss_arm_spawn)
    ld.add_action(moveit2)
    return ld

Is this the right way to specify the coordinates of the arm?

Hello @luricl

The base of the arm is fixed to the world so just declaring those arguments won’t move the robot to that position. You could use those arguments in “lss_arm.urdf.xacro” origin_xyz and origin_rpy.

2 Likes