0
$\begingroup$

I want my service node to run when Turtlebot boots up.

I have tried editing the bot's bringup files to add a call to launch file of my robot, but that didn't work and just broke the bringup completely.

Edited bringup launch file:

from ament_index_python.packages import get_package_share_directory

from launch import LaunchContext, LaunchDescription
from launch.actions import DeclareLaunchArgument, GroupAction, IncludeLaunchDescription
from launch.launch_description_sources import PythonLaunchDescriptionSource
from launch.substitutions import EnvironmentVariable, LaunchConfiguration, PathJoinSubstitution

from launch_ros.actions import PushRosNamespace

from nav2_common.launch import RewrittenYaml


def generate_launch_description():
    lc = LaunchContext()
    ld = LaunchDescription()

    diagnostics_enable = EnvironmentVariable('TURTLEBOT4_DIAGNOSTICS', default_value='1')
    namespace = EnvironmentVariable('ROBOT_NAMESPACE', default_value='')

    pkg_turtlebot4_bringup = get_package_share_directory('turtlebot4_bringup')
    pkg_turtlebot4_diagnostics = get_package_share_directory('turtlebot4_diagnostics')
    pkg_turtlebot4_description = get_package_share_directory('turtlebot4_description')
    pkg_local_navigation = get_package_share_directory('navigation_node') # MY PACKAGE

    param_file_cmd = DeclareLaunchArgument(
        'param_file',
        default_value=PathJoinSubstitution(
            [pkg_turtlebot4_bringup, 'config', 'turtlebot4.yaml']),
        description='Turtlebot4 Robot param file'
    )

    param_file = LaunchConfiguration('param_file')

    namespaced_param_file = RewrittenYaml(
        source_file=param_file,
        root_key=namespace,
        param_rewrites={},
        convert_types=True)

    # Launch files
    turtlebot4_robot_launch_file = PathJoinSubstitution(
        [pkg_turtlebot4_bringup, 'launch', 'robot.launch.py'])
    joy_teleop_launch_file = PathJoinSubstitution(
        [pkg_turtlebot4_bringup, 'launch', 'joy_teleop.launch.py'])
    diagnostics_launch_file = PathJoinSubstitution(
        [pkg_turtlebot4_diagnostics, 'launch', 'diagnostics.launch.py'])
    rplidar_launch_file = PathJoinSubstitution(
        [pkg_turtlebot4_bringup, 'launch', 'rplidar.launch.py'])
    oakd_launch_file = PathJoinSubstitution(
        [pkg_turtlebot4_bringup, 'launch', 'oakd.launch.py'])
    description_launch_file = PathJoinSubstitution(
        [pkg_turtlebot4_description, 'launch', 'robot_description.launch.py'])
    # MY LAUNCH FILE PATH
    navigation_launch_file = PathJoinSubstitution(
        [pkg_local_navigation, 'launch', 'local_navigaton.launch.py'])

    actions = [
            PushRosNamespace(namespace),

            IncludeLaunchDescription(
                PythonLaunchDescriptionSource([turtlebot4_robot_launch_file]),
                launch_arguments=[('model', 'standard'),
                                  ('param_file', namespaced_param_file)]),

            IncludeLaunchDescription(
                PythonLaunchDescriptionSource([joy_teleop_launch_file]),
                launch_arguments=[('namespace', namespace)]),

            IncludeLaunchDescription(
                PythonLaunchDescriptionSource([rplidar_launch_file])),

            IncludeLaunchDescription(
                PythonLaunchDescriptionSource([oakd_launch_file]),
                launch_arguments=[('camera', 'oakd_pro')]),

            IncludeLaunchDescription(
                PythonLaunchDescriptionSource([description_launch_file]),
                launch_arguments=[('model', 'standard')]),
           # MY LAUNCH DESCRIPTION    
           IncludeLaunchDescription(
                PythonLaunchDescriptionSource([navigation_launch_file]),
                launch_arguments=[('namespace',namespace),
                                  ('map', home/ubuntu/map_aula.yaml)]) 
        ]

    if (diagnostics_enable.perform(lc)) == '1':
        actions.append(IncludeLaunchDescription(
                PythonLaunchDescriptionSource([diagnostics_launch_file]),
                launch_arguments=[('namespace', namespace)]))

    turtlebot4_standard = GroupAction(actions)

    ld = LaunchDescription()
    ld.add_action(param_file_cmd)
    ld.add_action(turtlebot4_standard)
    return ld

Is there a proper way to do this or am I doomed to some hack?

$\endgroup$

2 Answers 2

1
$\begingroup$

There are two parts to the proper way to do this. The first is the actual changes themselves and the second is how/where you implement those changes.

Before I talk about that, I want to talk about how to see feedback about what broke in your current setup. The turtlebot4 launch is run by a systemd service (not ROS specific). If you look at the status of that service you can see if it failed and some of the log output. You can do that by running systemctl status turtlebot4.service. You can also use journalctl to view the entire log and then filter it for different words like the name of the service (journalctl -b | grep turtlebot). This can help you troubleshoot what the error is. The other option is that you can stop the service and launch it manually in the foreground. This way the output will display in your terminal, I will touch on this more below at the last part of this answer.

The changes themselves mostly look good. The one fix I can see so far is the following:

            IncludeLaunchDescription(
                PythonLaunchDescriptionSource([navigation_launch_file]),
                launch_arguments=[('namespace',namespace),
                                  ('map', '/home/ubuntu/map_aula.yaml')]) 

because you are passing a path, that path should be absolute (so that it doesn't look for this relative to where the file was launched) and the path should be in quotes.

I am assuming that your package name is correct and that the path is correct for where to find your launch file. Take note that the turtlebot4 packages explicitly copy the launch files to the share folder in the CMakeLists.txt (https://github.com/turtlebot/turtlebot4/blob/humble/turtlebot4_navigation/CMakeLists.txt#L23).

The proper process to make custom changes to the turtlebot4 software would be:

  1. Install the turtlebot4_robot repository from source (contains the turtlebot4_bringup package). Instructions can be found here: https://turtlebot.github.io/turtlebot4-user-manual/software/turtlebot4_robot.html#source-installation. If you don't already have a workspace then first make a turtlebot4_ws folder in the home directory and inside that make a src folder (can be done using this command -> mkdir -p /home/ubuntu/turtlebot4_ws/src).
  2. Run turtlebot4-setup and under ROS Setup -> Bash Setup change Workspace Setup to point at the setup.bash for your custom workspace. For the above workspace and default username it would be /home/ubuntu/turtlebot4_ws/install/setup.bash. Save and then apply settings. This will make it so that the service will automatically launch from your custom workspace. These are files that you control and will not be overwritten next time you update your debian packages.
  3. Add your custom package into this same workspace and build it. This will ensure that it is sourced at the same time and that the service will be able to find your custom package.
  4. Modify the turtlebot4 standard.launch.py file as you have but modify the local copy in your workspace (/home/ubuntu/turtlebot4_ws/src/turtlebot4_robot/turtlebot4_bringup/launch/standard.launch.py) and rebuild (colcon build --symlink-install). Note that whenever you build your workspace, you should be in the turtlebot4_ws folder, not the src folder. This will make sure that the built files are in the correct location to match up with step 2.
  5. Testing: To test your changes it is generally easiest to stop the service and run it in the foreground. That way you can see the output in your terminal. Stop the service by running sudo systemctl stop turtlebot4.service. Then run sudo turtlebot4-start. You will see the output of the launch now in your terminal instead of having to check the journalctl log. When you are ready to run the service normally you can start the service or just reboot the robot.

If you are still having issues after following this, then please share the terminal output from the launch.

$\endgroup$
4
  • $\begingroup$ Thanks for such a detailed answer. Since the network my robots are on is not connected to the internet I tried editing installed launch files first. And that seems to work for the most part. My launch file runs, localization and nav2 packages launched from here are running, as well as my node that is writing stuff in logs, but after the service that should undock the robot and start its navigation around the room robot does not move. I tried just launching my file and then it works without a problem. Do you know what might block the robot from driving? $\endgroup$
    – zdaga
    Commented Jun 8 at 15:56
  • $\begingroup$ If you are launching your launch file directly and it works then there are probably still issues with how you have added it to the turtlebot4 launch file. Despite how you have chosen to edit the files you should still go through the testing methods that I mentioned in 5. Most likely the launch is failing, if it isn't syntax then it could be that your custom package has not been sourced properly for the service to be able to find it. The terminal output should show an error about whatever is happening. If it is about sourcing your package make sure you complete step 2 that I mentioned. $\endgroup$
    – Hilary Luo
    Commented Jun 10 at 14:16
  • $\begingroup$ But my launch is not failing for sure. The node is up and running, logging things all the time. It's just that when I call its service nothing happens. And I can see the service when I call ros2 service list $\endgroup$
    – zdaga
    Commented Jun 14 at 12:52
  • $\begingroup$ If you launch the turtlebot4 service in the foreground or or review the logs you should be able to see where the errors are happening. Possibilities include that something is conflicting with the core turtlebot4 nodes or when you added your parts perhaps it caused a later part of the launch to fail. Other possibilities are that the namespacing isn't being handled the same in your node as what is expected by the turtlebot4 launch files. The default launch files propagate the namespacing throughout all other nodes that are launched. Either way the place to start is the terminal output / logs. $\endgroup$
    – Hilary Luo
    Commented Jun 22 at 3:27
0
$\begingroup$

editing the bringup should work, could you share the edit you made? Alternatively you can try writing your own launch file which launches both the bringup and the node, which would look something like this

tb_launch_dir = os.path.join( get_package_share_directory('turtlebot4_bringup'), "launch")

tb_launch = IncludeLaunchDescription(PythonLaunchDescriptionSource(os.path.join(tb_launch_dir, "standard.launch.py")),launch_arguments={'use_sim_time' : use_sim_time,}.items())

ser_node = Node(
            package='<yout_pkg_name>',
            executable='<your_exec_name>',
            name='<name>',
            output='screen',
            parameters=[{'use_sim_time': LaunchConfiguration('use_sim_time')}],
            arguments=['--ros-args', '--log-level', log_level])

ld = LaunchDescription()
ld.add_action(tb_launch)
ld.add_action(ser_node)
return ld
$\endgroup$
1
  • $\begingroup$ I have added modified bringup script to the question. I will also try your approach, but will that run automatically when the robot is booted up? $\endgroup$
    – zdaga
    Commented Jun 4 at 11:35

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.