Centring and Increasing the Size of your Global Costmap – ROS2, RVIZ2 and NAV2

Hi everyone,

I’ve been following the Articulated Robots tutorial series which has helped me to create a self navigating diff drive robot.

One issue I ran into after implementing Nav2 was that my Global Costmap was offset from the robot.

This ended up being a pretty easy fix. In your Nav2 configuration you can simply set rolling_window to true. This will centre the costmap on the robot as it moves around.

A second issue was the size of the costmap. I was only able to set navigation waypoints that were within 5m (note the size of the grey shading). To get around this you can use nav2 parameters again to increase the width and height. In my case I doubled the default (from 5m to 10m).

This is the config I ended up with:

global_costmap:
  global_costmap:
    ros__parameters:
      rolling_window: true
      width: 10
      height: 10

Thanks to these links for putting me on the right track:

Nav2 Localisation not Loading a Default Map

Hi everyone,

I finally have my diffdrive robot navigating with waypoints using Nav2 and this great tutorial. However, while trying to use a saved map for localization I ran into the following error:

ros2 launch my_bot localization_launch.py use_sim_time:=false
....
ocalization]: Configuring map_server
[map_server-1] [INFO] [1673064055.126698671] [map_server]: Configuring
[map_server-1] [ERROR] [map_io]: Failed processing YAML file /home/chris/Desktop/dev_ws/install/my_bot/share/my_bot/maps/chris_room_07012023/chris_room_save.yaml at position (-1:-1) for reason: bad file
[map_server-1] [ERROR] [1673064055.126801797] []: Caught exception in callback for transition 10
[map_server-1] [ERROR] [1673064055.126805589] []: Original error: Failed to load map yaml file: /home/chris/Desktop/dev_ws/install/my_bot/share/my_bot/maps/chris_room_07012023/chris_room_save.yaml
[map_server-1] [WARN] [1673064055.126811964] []: Error occurred while doing error handling.
[map_server-1] [FATAL] [1673064055.126815339] [map_server]: Lifecycle node map_server does not have error state implemented
[map_server-1] [INFO] [map_io]: Loading yaml file: /home/chris/Desktop/dev_ws/install/my_bot/share/my_bot/maps/chris_room_07012023/chris_room_save.yaml
[lifecycle_manager-3] [ERROR] [1673064055.127951438] [lifecycle_manager_localization]: Failed to change state for node: map_server
[lifecycle_manager-3] [ERROR] [1673064055.128136607] [lifecycle_manager_localization]: Failed to bring up all requested nodes. Aborting bringup.
^C[WARNING] [launch]: user interrupted with ctrl-c (SIGINT)

I had the following entry in my launch file:

        DeclareLaunchArgument(
            'map',
            default_value=os.path.join(bringup_dir, 'maps', 'chris_room_07012023/chris_room_save.yaml'),
            description='Full path to map yaml file to load'),

My map was also in the correct folder and valid output from the slam_toolbox plugin in rviz2. I had also run `colcon build –symlink-install`.

Initially I thought that I’d used the wrong settings in rviz but eventually I realised that the file was missing from the install directory. Despite running colcon build it was not building my new map files.

Luckily, this ended up being a fairly easy fix. I’d simply missed adding the directory to CMakeLists.txt.

# Add maps to the end of the DIRECTORY line.
install(
  DIRECTORY config description launch worlds maps
  DESTINATION share/${PROJECT_NAME}
)

After updating CMakeLists.txt and re-running colcon build --symlink-install I was finally able to start localization with a default map.

Lidar Failing to Start – ROS2 and RaspberryPi

Hi everyone,

I’m messing around with a diff-drive robot and have been hitting an intermittent issue with my Lidar:

[INFO] [rplidar_composition-1]: process started with pid [5959]
[rplidar_composition-1] [INFO] [1672456772.854599418] [rplidar_node]: RPLIDAR running on ROS 2 package rplidar_ros. SDK Version: '1.12.0'
[rplidar_composition-1] [INFO] [1672456775.375585284] [rplidar_node]: RPLIDAR S/N: CD8EED93C0EA98C7A0E69BF55D504560
[rplidar_composition-1] [INFO] [1672456775.375837134] [rplidar_node]: Firmware Ver: 1.29
[rplidar_composition-1] [INFO] [1672456775.375932041] [rplidar_node]: Hardware Rev: 7
[rplidar_composition-1] [INFO] [1672456775.377533563] [rplidar_node]: RPLidar health status : '0'
[rplidar_composition-1] [ERROR] [1672456777.925797978] [rplidar_node]: Cannot start scan: '80008000'

This turned out to be a low power issue. The Pi’s voltage had been dropping to about 4.5v as my 12v battery grew a little flat. Recharging the battery immediately fixed the issue.

For a more permanent fix I will switch to a larger battery. Alternatively, using a USB hub with its own power supply would also work.

Thanks to this github thread for the help.

Wheel Going in the Wrong Direction – RVIZ2 and FoxGlove

Hi everyone,

I hope you’re having a good break! I’m currently following this tutorial and messing around with a diffdrive robot. After making a few changes I noticed that my simulations were playing up. Strangely, the robot itself was still working perfectly fine.

The problem I was having was that even though my robot was driving forward the simulations seemed to think that the left wheel was going backwards. Initially I suspected this was an issue with my robot’s definition but even when returning to a known working state the issue persisted.

Eventually, I realised that this meant it had to be a hardware issue. I am using an Arduino and two L298N motor controllers for the motors that run my wheels. The arduino then publishes my encoding counts over serial.

To debug this setup, I used miniterm to communicate with the arduino and view the serial output. To get this going I had to track down which serial port had the arduino connected:

ubuntu@ubuntu:~/robot_ws$ lsusb
Bus 003 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub
Bus 002 Device 001: ID 1d6b:0003 Linux Foundation 3.0 root hub
Bus 001 Device 006: ID 1a86:7523 QinHeng Electronics HL-340 USB-Serial adapter

Alternatively, ls /dev/ttyUSB* would also work. I also needed the baud rate which is set to 57600. This allowed me to connect, move the motors forward and also see the encoding counts:

ubuntu@ubuntu:~/robot_ws$ miniterm -e /dev/ttyUSB0 57600
--- Miniterm on /dev/ttyUSB0 57600,8,N,1 ---
--- Quit: Ctrl+] | Menu: Ctrl+T | Help: Ctrl+T followed by Ctrl+H ---
e
0 0
o 255 255
OK
e
-5531 5572
e
-8120 8222
e
-8120 8222

The issue became obvious with the left wheel outputting a negative value. The fix for this was pretty simple. Reversing the pins outputting the encoding count for the left wheel reverses the counter. Re-running the miniterm test showed both wheels with a positive count:

ubuntu@ubuntu:~/robot_ws$ miniterm -e /dev/ttyUSB0 57600
--- Miniterm on /dev/ttyUSB0 57600,8,N,1 ---
--- Quit: Ctrl+] | Menu: Ctrl+T | Help: Ctrl+T followed by Ctrl+H ---
e
0 0
o 255 255
OK
e
8146 8211

ros2 controller manager not available – articubot tutorials

Hey everyone,
I’m currently working through a great tutorial series on youtube for ROS2. Unfortunately, I ran into a bit of an issue with a race condition in a launch file. The controller managers were timing out before Gazebo was able to launch.

Controller manager not available

The author offers a suggestion to try using OnProcessExit to work around this but unfortunately it did not work for me. The comments on the video seem to suggest that a few others also hit this problem.

I did a bit of Googling and found an alternative way to add a delay on startup using TimerAction. Using the following code as a replacement for the original launch actions seems to work:

import os

from ament_index_python.packages import get_package_share_directory


from launch import LaunchDescription
from launch.actions import IncludeLaunchDescription
from launch.actions import TimerAction
from launch.launch_description_sources import PythonLaunchDescriptionSource
from launch.actions import RegisterEventHandler
from launch.event_handlers import OnProcessExit

from launch_ros.actions import Node



def generate_launch_description():


    # Include the robot_state_publisher launch file, provided by our own package. Force sim time to be enabled
    # !!! MAKE SURE YOU SET THE PACKAGE NAME CORRECTLY !!!

    package_name='my_bot' #<--- CHANGE ME

    rsp = IncludeLaunchDescription(
                PythonLaunchDescriptionSource([os.path.join(
                    get_package_share_directory(package_name),'launch','rsp.launch.py'
                )]), launch_arguments={'use_sim_time': 'true'}.items()
    )

    # Include the Gazebo launch file, provided by the gazebo_ros package
    gazebo = IncludeLaunchDescription(
                PythonLaunchDescriptionSource([os.path.join(
                    get_package_share_directory('gazebo_ros'), 'launch', 'gazebo.launch.py')]),
             )

    # Run the spawner node from the gazebo_ros package. The entity name doesn't really matter if you only have a single robot.
    spawn_entity = Node(package='gazebo_ros', executable='spawn_entity.py',
                        arguments=['-topic', 'robot_description',
                                   '-entity', 'my_bot'],
                        output='screen')    

    # This helps to address race conditions on startup for the 
    # controller managers. Note that we are exporting delayed_controller_manager_spawner
    # instead of just diff_drive_spawner.
    delayed_controller_manager_spawner = TimerAction(
        period=10.0,
        actions=[
            Node(
                package="controller_manager",
                executable="spawner.py",
                arguments=["diff_cont"],
            ),
            Node(
                package="controller_manager",
                executable="spawner.py",
                arguments=["joint_broad"],
            )
        ],
    )


    # Launch them all!
    return LaunchDescription([
        rsp,
        gazebo,
        spawn_entity,
        delayed_controller_manager_spawner,
    ])

This Github link has a good example of how to do this for another similar project: https://github.com/ros2/launch_ros/blob/b84b72748e22d8fd648151d96478d19305c96c82/launch_testing_ros/test/examples/check_node_launch_test.py#L36-L45.

RaspberryPi Camera not detected – Ubuntu 20.04.5 LTS

Hi everyone,

I ran into a bit of an issue with a RaspberryPi 4 running Ubuntu 20.04.5 this morning. Running vcgencmd get_camera should have returned supported=1 detected=1 but instead I was getting supported=0 detected=0.

This was a bit of a hard one to track down with Google but I eventually came across a stackoverflow post suggesting the following:

  • Run sudo nano /boot/firmware/config.txt
  • Add start_x=1 at the end
  • Reboot

Check out this post for more info: https://askubuntu.com/a/1244259/770194.

If you’re using a new camera you may also run into this error:

mmal: Cannot read camera info, keeping the defaults for OV5647
mmal: mmal_vc_component_create: failed to create component 'vc.ril.camera' (1:ENOMEM)
mmal: mmal_component_create_core: could not create component 'vc.ril.camera' (1)
mmal: Failed to create camera component
mmal: main: Failed to create camera component
mmal: Only 76M of gpu_mem is configured. Try running "sudo raspi-config" and ensure that "memory_split" has a value of 128 or greater

The fix for this one is to simply append another line to /boot/firmware/config.txt. All you’ll need is gpu_mem=128.

Another issue you might run into is VHCI initialization failed. Generally, that just means you need to add your current user to the video group.

# Check your current user's groups.
groups

# Add your user to the video group.
sudo usermod -aG video <username>

Once you’ve added the group, rebooting should be enough to get past that error.

ROS2 on Parallels unable to be reached by other nodes

Hi everyone,

I’ve been messing around with ROS2 on a RaspberryPi and a Mac using Parallels to run Ubuntu. I hit a small snag when trying to get the nodes to communicate. The nodes on the RaspberryPi could not reach the ones being hosted on Ubuntu (Parallels).

While I initially assumed that I had messed up my ROS workspaces, it turned out to be a problem with my Parallels config. I was using a shared network. Switching to bridged immediately resolved the issue.

Gazebo classic material colors not working in Gazebo Ignition

Hi everyone,

I’m doing a few tutorials to simulate a lidar based navigation system and I’ve hit a few issues when trying to use Gazebo classic features in Gazebo Ignition.

A recent one is that Gazebo Ignition was ignoring the material colours that I’d specified in my urdf. This is an example of what was working in Gazebo classic:

    <gazebo reference="left_wheel">
        <material>Gazebo/Blue</material>
    </gazebo> 

This Github issue revealed the following format that can be used instead:

     <gazebo reference="chassis">
        <visual>
            <material>
                <ambient>0 0 1 1</ambient>
                <diffuse>0 0 1 1</diffuse>
                <specular>0 0 1 1</specular>
            </material>
        </visual>
    </gazebo>

Once updated, Gazebo ignition finally started rendering my material colors:

Gazebo Classic to Gazebo Ignition Diff Drive Conversion

Hi everyone,

I’m currently following some ros2 tutorials for simulating a diff drive robot in Gazebo Classic. I’m using Gazebo Ignition and unfortunately the definitions aren’t interchangeable.

Just in case anyone else hits the same issue, this is the definition I ended up using instead:

        <plugin
            filename="libignition-gazebo-diff-drive-system.so"
            name="ignition::gazebo::systems::DiffDrive"
        >
            <!-- Wheel info: https://youtu.be/IjFcr5r0nMs?t=876 -->
            <left_joint>left_wheel_joint</left_joint>
            <right_joint>right_wheel_joint</right_joint>
            <wheel_separation>0.35</wheel_separation>
            <wheel_diameter>0.1</wheel_diameter>

            <!-- Limits -->
            <max_wheel_torque>200</max_wheel_torque>
            <max_wheel_acceleration>10.0</max_wheel_acceleration>

            <!-- Output -->
            <odometry_frame>odom</odometry_frame>
            <robot_base_frame>base_link</robot_base_frame>

            <publish_odom>true</publish_odom>
            <publish_odom_tf>true</publish_odom_tf>
            <publish_wheel_tf>true</publish_wheel_tf>

        </plugin>

The following links were pretty helpful when it came to tracking down the differences:
https://github.com/chapulina/dolly/issues/28
https://github.com/gazebosim/gz-sim/blob/main/examples/worlds/visualize_lidar.sd

Spawn entity timeout in Gazebo from Ros2

Hi everyone,

I’m currently following a tutorial to simulate a fairly basic lidar robot with ROS2 and Gazebo: https://www.youtube.com/watch?v=laWn7_cj434. Unfortunately, there have been a few updates since the tutorial was created and a number of the commands don’t map 1:1 (no copy and paste).

While trying to create a launch file I ran into the following error:

[create-3] [ERROR] [1668289712.483268807] [ros_gz_sim]: Request to create entity from service [/world/deafult/create] timed out.

This was the relevant line in the launch file:

# Run the spawner node from the gazebo_ros package. The entity name doesn't really matter if you only have a single robot.
spawn_entity = Node(package='ros_ign_gazebo', executable='create',
arguments=[
'-world', 'deafult',
'-topic', 'robot_description',
'-entity', 'my_bot'],
output='screen')

The issue causing it to hang is that the world doesn’t exist. In my case, it’s because of a typo. However, if you’ve defined a world that you haven’t created yet it will result in the same error.