Skip to content

Blog

Sending Commands from ROS 2 to RoboClaw in ROS 1 with a ROS Bridge

Introduction

With ROS 1 Noetic and ROS 2 Foxy running on the same system, it’s possible to bridge topics between them. This allows controlling a RoboClaw motor controller (running on ROS 1) using ROS 2 commands. This guide walks you through setting up the ros1_bridge and sending commands to the RoboClaw-controlled robot from ROS 2.


Key Topics Covered

  • Running the RoboClaw node in ROS 1
  • Setting up the ROS 1-ROS 2 bridge
  • Sending velocity commands from ROS 2
  • Debugging issues

1. Launching the RoboClaw Node in ROS 1

Make sure ROS 1 Noetic is sourced and start the RoboClaw node:

source /opt/ros/noetic/setup.bash
roslaunch roboclaw_node roboclaw.launch

Check if the /cmd_vel topic is available in ROS 1:

rostopic list

You should see /cmd_vel in the list.

To verify if the node is working, try publishing a command directly from ROS 1:

rostopic pub /cmd_vel geometry_msgs/Twist '{linear: {x: 0.5}, angular: {z: 0.1}}'

If the robot moves, the RoboClaw node is working correctly.


2. Setting Up the ROS 1-ROS 2 Bridge

Since ROS 1 and ROS 2 use different communication protocols, we need to bridge them.

Step 1: Install the Bridge

Ensure both ROS 1 and ROS 2 are sourced:

source /opt/ros/noetic/setup.bash
source /opt/ros/foxy/setup.bash

Install ros1_bridge:

sudo apt install ros-foxy-ros1-bridge

Step 2: Run the Bridge

ros2 run ros1_bridge dynamic_bridge

This will automatically bridge compatible topics between ROS 1 and ROS 2.


3. Sending Commands from ROS 2 to RoboClaw

Now that the bridge is running, switch to a new terminal and source ROS 2:

source /opt/ros/foxy/setup.bash

Check if the /cmd_vel topic is being bridged in ROS 2:

ros2 topic list

If /cmd_vel appears, you can publish a movement command from ROS 2:

ros2 topic pub /cmd_vel geometry_msgs/msg/Twist "{linear: {x: 0.5}, angular: {z: 0.1}}"

This should move the robot as if the command came from ROS 1.


4. Debugging Common Issues

Issue 1: ROS 1 and ROS 2 Variables Overlapping

Solution: Open separate terminals for ROS 1 and ROS 2, and source them separately.

Issue 2: The Bridge Doesn’t Forward /cmd_vel

Solution: Restart the bridge and verify that both ROS versions are sourced properly.

Issue 3: RoboClaw Doesn’t Respond to Commands

Solution: Ensure the RoboClaw node is running, and check /cmd_vel in ROS 1 using:

rostopic echo /cmd_vel

Conclusion

By following this guide, you can successfully control your RoboClaw-powered robot from ROS 2 while it runs on ROS 1 Noetic. The ros1_bridge ensures seamless communication, allowing hybrid ROS applications.

With this setup, you can integrate ROS 2-based navigation stacks with older ROS 1 hardware.

Automating the ROS 1-ROS 2 Bridge for RoboClaw

Introduction

Setting up the ROS 1-ROS 2 bridge manually every time can be frustrating. This guide provides a Python script that automates the process, making it easier to run your RoboClaw motor controller in ROS 1 while sending commands from ROS 2.


Why Use a Bridge?

Since ROS 1 Noetic and ROS 2 Foxy use different middleware, we need the ros1_bridge to communicate between them. With this setup, you can control RoboClaw from ROS 2 while it runs on ROS 1.


Steps Automated by the Script

  1. Detect ROS 1 and ROS 2 installations
  2. Start roscore (if not running)
  3. Launch the RoboClaw node in ROS 1
  4. Start the ROS 1-ROS 2 bridge
  5. Verify if /cmd_vel is bridged between ROS versions
  6. Send a velocity command from ROS 2

The Python Script

Here is the script that automates the process:

import os
import subprocess
import time

def run_command(command):
    """ Runs a shell command and returns the output """
    try:
        output = subprocess.run(command, shell=True, check=True, text=True, capture_output=True)
        return output.stdout.strip()
    except subprocess.CalledProcessError as e:
        print(f"Error: {e}")
        return None

def source_ros(version):
    """ Sources the correct ROS environment """
    if version == "ros1":
        os.system("source /opt/ros/noetic/setup.bash")
    elif version == "ros2":
        os.system("source /opt/ros/foxy/setup.bash")
    else:
        print("Invalid ROS version specified")

def check_ros_version():
    """ Checks if ROS 1 and ROS 2 are installed """
    ros1_check = run_command("rosversion -d")
    ros2_check = run_command("ros2 --version")

    if "noetic" in str(ros1_check):
        print("[✔] ROS 1 Noetic detected")
    else:
        print("[X] ROS 1 Noetic not found!")

    if ros2_check:
        print(f"[✔] ROS 2 detected (Version: {ros2_check})")
    else:
        print("[X] ROS 2 not found!")

def start_roscore():
    """ Starts roscore if not already running """
    output = run_command("pgrep -x roscore")
    if output:
        print("[✔] roscore is already running")
    else:
        print("[✔] Starting roscore...")
        os.system("roscore &")
        time.sleep(3)

def start_roboclaw_node():
    """ Launches the RoboClaw node """
    print("[✔] Launching RoboClaw node...")
    os.system("roslaunch roboclaw_node roboclaw.launch &")
    time.sleep(3)

def start_ros1_bridge():
    """ Starts the ROS 1-ROS 2 bridge """
    print("[✔] Launching ROS 1-ROS 2 bridge...")
    os.system("ros2 run ros1_bridge dynamic_bridge &")
    time.sleep(3)

def check_cmd_vel_topic():
    """ Checks if /cmd_vel is available in both ROS 1 and ROS 2 """
    ros1_topics = run_command("rostopic list")
    ros2_topics = run_command("ros2 topic list")

    if "/cmd_vel" in str(ros1_topics):
        print("[✔] /cmd_vel is available in ROS 1")
    else:
        print("[X] /cmd_vel not found in ROS 1")

    if "/cmd_vel" in str(ros2_topics):
        print("[✔] /cmd_vel is available in ROS 2")
    else:
        print("[X] /cmd_vel not found in ROS 2")

if __name__ == "__main__":
    print("\n[✔] Setting up ROS 1-ROS 2 Bridge for RoboClaw...")
    check_ros_version()

    source_ros("ros1")
    start_roscore()
    start_roboclaw_node()

    source_ros("ros2")
    start_ros1_bridge()

    check_cmd_vel_topic()

    print("\n[✔] Setup complete! You can now control RoboClaw from ROS 2.")

Conclusion

This script automates the ROS bridge setup so you can focus on developing your robot. Just run:

python3 setup_ros_bridge.py

🚀 Now you can control your RoboClaw motor from ROS 2 effortlessly!

Running ROS 1 Noetic and ROS 2 Foxy From Source on Ubuntu 20.04

Introduction

Running both ROS 1 (Noetic) and ROS 2 (Foxy) on the same system can be challenging due to differences in dependencies, environment variables, and communication mechanisms. However, Ubuntu 20.04 remains the best option for managing both distributions, as Noetic is the last ROS 1 release and Foxy is a long-term support (LTS) release of ROS 2.

This guide will walk you through the process of installing, sourcing, and managing both ROS versions from source while minimizing conflicts.


Key Topics Covered

  • Installing ROS 1 Noetic from source
  • Installing ROS 2 Foxy from source
  • Managing environment variables to switch between Noetic and Foxy
  • Running a ROS 1-ROS 2 bridge for interoperability

1. Installing ROS 1 Noetic From Source

Since Ubuntu 20.04 is the preferred OS for ROS Noetic, you can follow these steps to build it from source.

Step 1: Install Dependencies

sudo apt update && sudo apt upgrade -y
sudo apt install -y python3-rosdep python3-rosinstall-generator \
  python3-vcstool build-essential

Initialize rosdep:

sudo rosdep init
rosdep update

Step 2: Create a Workspace and Clone ROS 1

mkdir -p ~/ros1_noetic/src
cd ~/ros1_noetic
rosinstall_generator desktop --rosdistro noetic --deps --tar > noetic.rosinstall
vcs import --input noetic.rosinstall src
rosdep install --from-paths src --ignore-src -r -y

Step 3: Build ROS 1

cd ~/ros1_noetic
colcon build --symlink-install

Step 4: Source ROS 1

echo 'source ~/ros1_noetic/install/setup.bash' >> ~/.bashrc
source ~/.bashrc

Verify installation:

echo $ROS_DISTRO  # Should output 'noetic'


2. Installing ROS 2 Foxy From Source

Since Noetic and Foxy have different architectures, we will install ROS 2 Foxy in a separate workspace.

Step 1: Install Dependencies

sudo apt install -y python3-colcon-common-extensions \
  python3-vcstool git wget

Step 2: Create a Workspace and Clone ROS 2

mkdir -p ~/ros2_foxy/src
cd ~/ros2_foxy
vcs import src < https://raw.githubusercontent.com/ros2/ros2/foxy/ros2.repos
rosdep install --from-paths src --ignore-src -r -y

Step 3: Build ROS 2

cd ~/ros2_foxy
colcon build --symlink-install

Step 4: Source ROS 2

echo 'source ~/ros2_foxy/install/setup.bash' >> ~/.bashrc
source ~/.bashrc

Verify installation:

echo $ROS_DISTRO  # Should output 'foxy'


3. Managing ROS 1 and ROS 2 Environments

By default, sourcing both ROS 1 and ROS 2 together will cause conflicts. To manage this, create separate aliases:

Option 1: Use Aliases to Switch Between ROS Versions

Add these lines to your ~/.bashrc:

alias source_ros1="source ~/ros1_noetic/install/setup.bash"
alias source_ros2="source ~/ros2_foxy/install/setup.bash"

Now, you can quickly switch between them:

source_ros1  # Switch to ROS Noetic
source_ros2  # Switch to ROS 2 Foxy

Option 2: Use Separate Terminals

For seamless operation, open two terminals:

  • Terminal 1 (ROS 1 Noetic)

    source ~/ros1_noetic/install/setup.bash
    roscore
    

  • Terminal 2 (ROS 2 Foxy)

    source ~/ros2_foxy/install/setup.bash
    ros2 run demo_nodes_cpp talker
    


4. Running the ROS 1-ROS 2 Bridge

To communicate between ROS 1 and ROS 2, use ros1_bridge.

Step 1: Install ros1_bridge

source_ros1
source_ros2
sudo apt install -y ros-foxy-ros1-bridge

Step 2: Run the Bridge

ros2 run ros1_bridge dynamic_bridge

Now, any topic published in ROS 1 will be available in ROS 2, and vice versa.


5. Debugging Common Issues

Problem: ROS 1 and ROS 2 Variables Overlapping

Solution: Always source only one ROS version at a time or use separate terminals.

Problem: colcon Build Fails

Solution: Ensure all dependencies are installed using rosdep update && rosdep install --from-paths src --ignore-src -r -y.

Problem: ROS 1-ROS 2 Bridge Fails to Start

Solution:
- Ensure both source_ros1 and source_ros2 are sourced.
- Try restarting the bridge with ros2 run ros1_bridge dynamic_bridge.


Conclusion

By following this guide, you can successfully install, source, and run both ROS 1 Noetic and ROS 2 Foxy on Ubuntu 20.04 without conflicts. Using environment management strategies such as aliases and separate terminals ensures smooth switching between versions.

The addition of ros1_bridge further enables seamless communication, making hybrid ROS 1/2 projects possible.

Happy Coding! 🚀

Efficient Docker Management for Robotics

Introduction

Docker is an essential tool for robotics development, offering quick prototyping, environment isolation, and streamlined deployment. However, managing containers effectively—especially with ROS (Robot Operating System)—can be complex. This guide highlights best practices for saving Docker images, removing unused resources, enabling GUI and Bluetooth in containers, and ensuring seamless ROS integration for robotics projects.


Key Topics Covered

  • Saving and tagging Docker images for reproducibility
  • Cleaning up unused images and resources
  • Running Docker containers with GUI and peripheral support
  • Setting up ROS workspaces inside containers
  • Debugging common integration issues

1. Saving Docker Containers as Images

Why Save Docker Containers?

  • Preserve your work after container modifications.
  • Quickly replicate development environments for prototyping or deployment.

Steps to Save an Image:

  1. Stop the container:

    sudo docker stop <container_name>
    

  2. Commit the container to an image:

    sudo docker commit <container_id> <new_image_name>
    

  3. Verify the saved image:

    sudo docker images
    

Example:

sudo docker commit 96a9ad78d1e6 roboclaw_v02


2. Removing Unused Images and Containers

Why Clean Up?

  • Free up disk space.
  • Reduce clutter from unused or dangling images.

Commands:

  1. List dangling images:

    sudo docker images -f dangling=true
    

  2. Remove dangling images:

    sudo docker image prune -f
    

  3. Remove specific images:

    sudo docker rmi <image_id>
    

  4. Remove stopped containers:

    sudo docker container prune
    


3. Running Containers with GUI and Peripheral Support

Why Enable GUI and Peripherals?

Robotics projects often require visualization tools like RViz and peripheral support for devices such as Xbox controllers or Bluetooth sensors. Docker flags ensure seamless integration.

Command Example:

sudo docker run -it --name roboclaw_v02 \
    --net=host \
    --privileged \
    --device=/dev/input/js0:/dev/input/js0 \
    --device=/dev/input/event0:/dev/input/event0 \
    -v /var/run/dbus:/var/run/dbus \
    -v /tmp/.X11-unix:/tmp/.X11-unix \
    -e DISPLAY=$DISPLAY \
    roboclaw_v02

Explanation of Flags:

  • --net=host: Enables network communication between container and host.
  • --privileged: Grants access to host devices (e.g., Bluetooth).
  • --device: Maps input devices for peripherals like controllers.
  • -v: Mounts directories for GUI and device access.

4. Setting Up a ROS Workspace in Docker

Why Use a Mounted Workspace?

  • Edit code on the host machine while executing it inside the container.
  • Persist changes across container restarts.

Steps:

  1. Run the container with a mounted workspace:

    sudo docker run -it --name <container_name> \
        -v ~/ros_ws:/root/ros_ws \
        <base_image>
    

  2. Inside the container, initialize the ROS workspace:

    cd ~/ros_ws
    catkin_make
    source devel/setup.bash
    


5. Running ROS Nodes and Debugging

Starting roscore:

  1. Attach to the container:

    sudo docker exec -it <container_name> /bin/bash
    

  2. Start roscore:

    roscore
    

Running ROS Nodes:

  1. Source the workspace:

    source ~/ros_ws/devel/setup.bash
    

  2. Run the node:

    rosrun roboclaw_node xbox_teleop_odom.py
    


6. Debugging Common Issues

Issue: "Master Not Found"

  • Ensure roscore is running in the same container.

Issue: "Device Not Found"

  • Verify input device mapping:
    ls /dev/input/js0
    

Issue: "ROS_PACKAGE_PATH Missing"

  • Set the workspace path:
    export ROS_PACKAGE_PATH=/root/ros_ws/src:$ROS_PACKAGE_PATH
    

Conclusion

By mastering these Docker and ROS workflows, you can create efficient and portable robotics development environments. Whether it’s saving images, enabling peripherals, or debugging nodes, these practices ensure a robust foundation for prototyping and deployment.

Stay innovative, and build the future of robotics with confidence! 🚀

Mastering Docker and ROS for Roboclaw With Key Tips and Workflows

Introduction

Integrating Docker and ROS for robotics projects, especially with RoboClaw motor controllers, can seem daunting. This post streamlines critical steps, from saving Docker images to running ROS nodes with Xbox controller support, ensuring a smooth and efficient workflow.


Key Topics Covered

  • Saving Docker containers for future use
  • Opening new terminals in containers
  • Running containers with Bluetooth and port access
  • Setting up and using a ROS workspace in Docker
  • Debugging common integration issues

1. Saving Docker Containers

Why Save Containers?

  • Prevents loss of your setup if the container is stopped or deleted.
  • Allows easy re-creation of environments.

Steps:

  1. Stop the container:
    sudo docker stop <container_name>
    
  2. Commit the container as an image:
    sudo docker commit <container_id> <new_image_name>
    
  3. Verify the image:
    sudo docker images
    

Example:

sudo docker commit 96a9ad78d1e6 ros_noetic_with_rviz


2. Opening a New Terminal in a Running Container

Why Do This?

  • Manage multiple ROS nodes or debug processes.

Steps:

  1. List running containers:
    sudo docker ps
    
  2. Attach a terminal to the container:
    sudo docker exec -it <container_name> /bin/bash
    

Example:

sudo docker exec -it ros_rviz_container /bin/bash


3. Running Containers with Bluetooth and Port Access

Why Use These Flags?

  • --net=host: Enables seamless network communication.
  • --privileged: Grants full access to host devices.
  • --device: Connects peripherals like an Xbox controller.
  • -v: Mounts necessary directories for GUI and Bluetooth.

Command Example:

sudo docker run -it --name roboclaw_v02 \
    --net=host \
    --privileged \
    --device=/dev/input/js0:/dev/input/js0 \
    --device=/dev/input/event0:/dev/input/event0 \
    -v /var/run/dbus:/var/run/dbus \
    -v /tmp/.X11-unix:/tmp/.X11-unix \
    -e DISPLAY=$DISPLAY \
    roboclaw_v02


4. Setting Up a ROS Workspace in Docker

Steps:

  1. Mount the workspace:
    sudo docker run -it --name <container_name> \
        -v ~/ros_noetic_ws:/root/ros_noetic_ws \
        <base_image>
    
  2. Inside the container:
    cd ~/ros_noetic_ws
    catkin_make
    source devel/setup.bash
    

5. Running ROS Nodes and Debugging

Starting roscore:

  1. Attach a terminal to the container:
    sudo docker exec -it <container_name> /bin/bash
    
  2. Run roscore:
    roscore
    

Running a ROS Node:

  1. Source the workspace:
    source ~/ros_noetic_ws/devel/setup.bash
    
  2. Run the node:
    rosrun roboclaw_node xbox_teleop_odom.py
    

6. Debugging Common Issues

Problem: "Master Not Found"

  • Ensure roscore is running in the same container.

Problem: Device Not Found

  • Check device mapping:
    ls /dev/input/js0
    

Problem: Missing ROS_PACKAGE_PATH

  • Add the workspace to ROS_PACKAGE_PATH:
    export ROS_PACKAGE_PATH=/root/ros_noetic_ws/src:$ROS_PACKAGE_PATH
    

Conclusion

By following these practices, you can efficiently develop robotics applications using Docker and ROS. This workflow allows for robust integration of peripherals, such as Xbox controllers, and ensures smooth communication between ROS nodes.

Stay innovative and focus on building your robotics vision without being bogged down by setup hurdles!

Happy Robotics! 🚀

Setting Up and Running D500 LiDAR Kit's STL-19P on ROS 2 Jazzy

This guide walks you through setting up the D500 LiDAR Kit's STL-19P sensor for ROS 2 Jazzy, using the ldrobotSensorTeam/ldlidar_ros2 repository. By the end of this article, you'll be able to configure, launch, and visualize LIDAR data in ROS 2.


Prerequisites

Before proceeding, ensure you have the following set up:

  1. ROS 2 Jazzy Installed: Follow the official instructions to install ROS 2 Jazzy.

  2. Set Up Your ROS 2 Workspace: Create a workspace if you don't already have one:

    mkdir -p ~/Desktop/frata_workspace/src
    cd ~/Desktop/frata_workspace
    colcon build
    source install/setup.bash
    


Cloning and Building the LDLiDAR Package

  1. Clone the Repository:

    cd ~/Desktop/frata_workspace/src
    git clone https://github.com/ldrobotSensorTeam/ldlidar_ros2.git
    

  2. Install Dependencies: Use rosdep to install any missing dependencies:

    cd ~/Desktop/frata_workspace
    rosdep install --from-paths src --ignore-src -r -y
    

  3. Build the Workspace: Compile the package:

    colcon build --symlink-install --cmake-args=-DCMAKE_BUILD_TYPE=Release
    

  4. Source the Workspace: Add the following to your ~/.bashrc and source it:

    echo "source ~/Desktop/frata_workspace/install/local_setup.bash" >> ~/.bashrc
    source ~/.bashrc
    


Running the LDLiDAR Node

  1. Connect the LIDAR to a USB Port:
  2. Ensure the LIDAR is connected to your machine. If the device isn't detected, try using a USB extension cable.

  3. Identify the Serial Port: Check for the device's serial port:

    ls /dev/ttyUSB*
    
    Example output: /dev/ttyUSB0.

  4. Launch the Node: Start the LDLiDAR node with the appropriate launch file:

    ros2 launch ldlidar_ros2 ld19.launch.py
    
    If required, modify the port_name in the ld19.launch.py file to match your detected port (e.g., /dev/ttyUSB0).

  5. View LIDAR Data:

  6. Open Rviz2 to visualize the LIDAR data:
    rviz2
    
  7. Add a "LaserScan" display and set the topic to /scan.

Troubleshooting Common Errors

1. "Communication Abnormal" Error

If you encounter this error:

[ERROR] [ldlidar_publisher_ld19]: ldlidar communication is abnormal.

  • Check Serial Port: Ensure the correct serial port (/dev/ttyUSB0) is specified in the launch file.

  • Verify Baud Rate: Confirm that the baud rate in the launch file matches the LIDAR's configuration (default is 230400).

  • Reconnect the Device: Use a USB extension cable if the device isn't recognized properly.

2. Device Not Found

  • Run:
    ls /dev/ttyUSB*
    
  • If no device appears, ensure the LIDAR is securely connected and powered.

3. No Data in Rviz2

  • Verify the /scan topic is being published:
    ros2 topic list
    ros2 topic echo /scan
    

4. "Failed init_port fastrtps_port7000" Error

This is a common shared memory transport error in ROS 2. - Solution: Add the following to your .bashrc to disable shared memory transport:

export RMW_IMPLEMENTATION=rmw_cyclonedds_cpp


Example Launch Output

Once everything is set up correctly, you should see the following output:

[INFO] [ldlidar_publisher_ld19]: LDLiDAR SDK Pack Version is:3.3.1
[INFO] [ldlidar_publisher_ld19]: ROS2 param input:
[INFO] [ldlidar_publisher_ld19]: ldlidar serial connect is success
[INFO] [ldlidar_publisher_ld19]: ldlidar communication is normal.
[INFO] [ldlidar_publisher_ld19]: ldlidar driver start is success.
[INFO] [ldlidar_publisher_ld19]: start normal, pub lidar data


Conclusion

With this guide, you can successfully set up and run the D500 LiDAR Kit's STL-19P on ROS 2 Jazzy. If you encounter the "communication abnormal" or other errors, refer to the troubleshooting section to resolve them quickly. This setup enables seamless LIDAR integration for your autonomous robotics projects.

For more information, visit the ldrobotSensorTeam GitHub repository.


Setting Up the roboclaw_ros Node with ROS Noetic in Docker

Introduction

In this guide, we’ll walk through setting up the roboclaw_ros node in ROS Noetic using Docker. This approach ensures a clean, consistent environment for development and deployment while leveraging Docker's flexibility. We'll cover everything from creating the Docker image to running the node with the correct configurations.


Prerequisites

Before proceeding, ensure you have:

  1. Docker Installed: Docker must be installed and operational on your system.
  2. Hardware Setup:
  3. A Roboclaw motor controller connected to /dev/ttyACM0.
  4. Encoders configured for your robot’s specific dimensions.
  5. Dependencies Installed:
  6. The roboclaw_driver library for ROS.
  7. Python libraries like pyserial for communication.

Setup Steps

1. Pull the Base Docker Image

Start by pulling the base Docker image for ROS Noetic:

sudo docker pull arm64v8/ros:noetic-ros-base

2. Run a Container and Install ROS Noetic Components

Launch a container from the base image:

sudo docker run -it --name ros_noetic_container --rm arm64v8/ros:noetic-ros-base

Inside the container, update and install required packages:

apt update
apt install -y ros-noetic-rosbridge-server ros-noetic-tf python3-serial python3-pip
pip3 install diagnostic-updater

3. Create and Mount a Workspace

To persist your workspace across sessions, create a workspace on your host machine and mount it in the container:

mkdir -p ~/ros_noetic_ws/src
sudo docker run -it --name ros_noetic_container --rm -v ~/ros_noetic_ws:/root/ros_noetic_ws arm64v8/ros:noetic-ros-base

Inside the container, initialize the workspace:

cd /root/ros_noetic_ws
catkin_make

4. Clone the roboclaw_ros Repository

Clone the repository into the workspace:

cd /root/ros_noetic_ws/src
git clone https://github.com/DoanNguyenTrong/roboclaw_ros.git

5. Build the Workspace

Return to the root of the workspace and build it:

cd /root/ros_noetic_ws
catkin_make
source devel/setup.bash

6. Save the Docker Image

To save your container for future use, commit it as a new image:

sudo docker commit ros_noetic_container ros_noetic_saved

Run this saved image with automatic restart enabled:

sudo docker run -it --name ros_noetic_container --restart always ros_noetic_saved

Running the roboclaw_ros Node

To run the roboclaw_ros node, use the following steps:

1. Start the Container

Start the container with the saved image:

sudo docker start -ai ros_noetic_container

2. Launch the Node

Inside the container, run the launch file:

roslaunch roboclaw_node roboclaw.launch

Testing the Node

To verify the node's functionality:

  1. Publish Commands to /cmd_vel:
rostopic pub /cmd_vel geometry_msgs/Twist '{linear: {x: 0.5}, angular: {z: 0.1}}'
  1. Monitor Output:

Check odometry data on /odom:

rostopic echo /odom

Viewing Docker Folder Structure

To view the folder structure inside the container, use:

sudo docker exec -it ros_noetic_container bash
cd /root/ros_noetic_ws
tree

Conclusion

This guide provides a straightforward approach to setting up and running the roboclaw_ros node in a ROS Noetic Docker environment. Docker ensures consistency and portability, making it an ideal choice for robotics development. By following these steps, you can integrate Roboclaw into your robotic system efficiently.

Setting Up and Running a Roboclaw-Based ROS Node with Obstacle Avoidance

Setting Up and Running a Roboclaw-Based ROS Node with Obstacle Avoidance

This guide walks you through setting up and running a Roboclaw-based ROS node with obstacle avoidance functionality using LIDAR sensors. Follow these steps to configure and launch your robotics system efficiently.


Prerequisites

Before starting, ensure the following are set up on your system:

  1. ROS Installed: Ensure you have ROS Melodic or a compatible version installed on your system.
  2. Workspace Prepared: Your ROS workspace (e.g., ~/armpi_pro) is built and sourced.
  3. Packages Installed:
  4. roboclaw_ros for motor control.
  5. ldlidar_stl_ros for LIDAR sensor integration.
  6. Hardware Connections:
  7. Roboclaw is connected via /dev/ttyACM0.
  8. LIDAR sensor is operational and connected (e.g., /dev/ttyUSB0).

Launching the Required Nodes

To operate the system, you need to launch three components in sequence:

1. Start the ROS Core

Open a terminal and launch the ROS core:

roscore

Keep this terminal open as it provides the foundation for all ROS nodes.


2. Launch the Roboclaw Node

In a new terminal, navigate to your workspace and launch the Roboclaw node:

roslaunch roboclaw_node roboclaw.launch

This node handles motor control, publishing odometry, and subscribing to velocity commands (/cmd_vel).


3. Launch the LIDAR Node

In another terminal, launch the LIDAR node:

roslaunch ldlidar_stl_ros ld19.launch

This node processes LIDAR data and publishes it to the /scan topic.


Running the Obstacle Avoidance Node

Once the Roboclaw and LIDAR nodes are running, you can start the obstacle avoidance script. This script subscribes to /scan for LIDAR data and publishes velocity commands to /cmd_vel.

  1. Ensure the script is located at:

    ~/armpi_pro/src/roboclaw_ros/roboclaw_node/scripts/obstacle_avoidance.py
    

  2. Make the script executable:

    chmod +x ~/armpi_pro/src/roboclaw_ros/roboclaw_node/scripts/obstacle_avoidance.py
    

  3. Run the script using rosrun:

    rosrun roboclaw_node obstacle_avoidance.py
    


How It Works

  1. LIDAR Data Processing: The obstacle avoidance node processes data from /scan. It checks for obstacles within 6 inches (0.15 meters) in front of the robot.

  2. Motor Commands:

  3. If an obstacle is detected, the script sends a stop command to /cmd_vel.
  4. If the path is clear, the script commands the robot to move forward.

Example Workflow

Here’s how you would set up and run the entire system step-by-step:

  1. Open a terminal and start the ROS core:

    roscore
    

  2. In a second terminal, launch the Roboclaw node:

    roslaunch roboclaw_node roboclaw.launch
    

  3. In a third terminal, launch the LIDAR node:

    roslaunch ldlidar_stl_ros ld19.launch
    

  4. Finally, in a fourth terminal, run the obstacle avoidance script:

    rosrun roboclaw_node obstacle_avoidance.py
    


Troubleshooting

  1. Package Not Found: If you encounter errors like package 'roboclaw_node' not found, rebuild your workspace:

    cd ~/armpi_pro
    catkin_make
    source devel/setup.bash
    

  2. LIDAR or Roboclaw Not Responding:

  3. Verify device connections using ls /dev/tty* for correct port names.
  4. Update the respective .launch files to reflect the correct ports.

  5. Script Permissions: Ensure all scripts are executable using:

    chmod +x ~/armpi_pro/src/roboclaw_ros/roboclaw_node/scripts/*.py
    


Conclusion

With this setup, your robot is capable of autonomously navigating forward and stopping when obstacles are detected. The modular structure allows for easy debugging and future enhancements, such as adding new sensors or navigation strategies.

Mastering these steps ensures a reliable and robust robotic system ready for real-world applications.

Setting Up Hector SLAM with ROS 1 for a Roboclaw-Based Rover

Setting Up Hector SLAM with ROS 1 for a Roboclaw-Based Rover

This guide details the steps to configure and use Hector SLAM with a Roboclaw-based ROS 1 robot. We’ll cover LIDAR integration, transform configuration, and how to set RViz for successful mapping and navigation.


Prerequisites

Ensure the following are set up on your system:

  1. ROS Installed: ROS Melodic or a compatible version is installed.
  2. Workspace Prepared: A catkin workspace (e.g., ~/armpi_pro) is created, built, and sourced.
  3. Hector SLAM Package:
  4. Installed and located in your workspace under src/hector_slam.
  5. Ensure hector_mapping and hector_slam_launch are available.
  6. LIDAR Sensor:
  7. Configured and publishing scan data to /scan.
  8. Roboclaw Node:
  9. Operational, publishing odometry to /odom.

Steps to Set Up Hector SLAM

1. Launch ROS Core

Open a terminal and start the ROS core:

roscore

This is required for all other nodes to communicate.


2. Launch the LIDAR and RoboClaw Nodes

To enable LIDAR data for mapping, launch the LIDAR node in a new terminal:

roslaunch ldlidar_stl_ros ld19.launch

This ensures the LIDAR sensor is active and publishing data to the /scan topic, which is necessary for Hector SLAM to create a map.


3. Configure and Launch Hector Mapping

In your workspace, navigate to the Hector SLAM launch folder:

cd ~/armpi_pro/src/hector_slam/hector_slam_launch/launch

Use the tutorial.launch file as a base for running Hector SLAM. Modify the following parameters in the launch file to match your setup:

<launch>
    <!-- Hector Mapping Node -->
    <node pkg="hector_mapping" type="hector_mapping" name="hector_mapping" output="screen">
        <param name="pub_map_odom_transform" value="true"/>
        <param name="map_frame" value="map"/>
        <param name="base_frame" value="base_link"/>
        <param name="odom_frame" value="odom"/>
        <remap from="scan" to="/scan"/>  <!-- Your LIDAR topic -->
        <remap from="odom" to="/odom"/>  <!-- Your odometry topic -->
    </node>

    <!-- Static Transform Publisher -->
    <node pkg="tf2_ros" type="static_transform_publisher" name="laser_to_base_link"
          args="0 0 0.2 0 0 0 base_link laser_link"/>

    <!-- RViz for Visualization -->
    <node pkg="rviz" type="rviz" name="rviz" args="-d $(find hector_slam_launch)/rviz_cfg/mapping.rviz" />
</launch>

Run the newly created launch file above using:

roslaunch hector_slam_launch mapping_with_odom.launch

4. Adjust RViz Configuration

To visualize the mapping process:

  1. Start RViz:

    rosrun rviz rviz
    

  2. Set the Fixed Frame to scanmatcher_frame:

  3. Navigate to Global Options in RViz.
  4. Set Fixed Frame to scanmatcher_frame.

  5. Add relevant displays:

  6. Map: Subscribe to /map for live updates.
  7. LaserScan: Subscribe to /scan to visualize LIDAR data.
  8. TF: Check the frame hierarchy and transformations.

5. Launch the Roboclaw Node

Start the Roboclaw node to handle motor control and odometry:

roslaunch roboclaw_node roboclaw.launch

This node should publish odometry data to the /odom topic, which Hector SLAM uses.


6. Run the rover

Now that the mapping and motor control nodes are active:

  • Drive the rover manually or programmatically using the following script:
        #!/usr/bin/env python2
    # -*- coding: utf-8 -*-
    """
    Example: Use Pygame to read an Xbox controller and RoboClaw on ROS Melodic (Python 2).
    No f-strings; uses .format().
    
    Make sure:
      1) roscore is running (for rospy logs).
      2) SDL_VIDEODRIVER=dummy is set if headless: export SDL_VIDEODRIVER=dummy
      3) RoboClaw is on /dev/ttyACM0 (or change param).
    """
    
    import sys
    import rospy
    import pygame
    import time
    
    # For TF in Melodic (Python 2)
    import tf
    import tf.transformations as tft
    
    # RoboClaw library (python2-compatible)
    from roboclaw import Roboclaw
    
    class XboxRoboclawDebugPy2(object):
        def __init__(self):
            # 1) ROS init
            rospy.init_node("xbox_teleop_debug_py2", anonymous=True)
            rospy.loginfo("Starting xbox_teleop_debug_py2 node...")
    
            # 2) RoboClaw Setup
            self.port_name = rospy.get_param("~port", "/dev/ttyACM0")
            self.baud_rate = rospy.get_param("~baud", 115200)
            self.address   = rospy.get_param("~address", 0x80)  # decimal 128
    
            rospy.loginfo("Attempting to open RoboClaw on {0} at {1} baud, address=0x{2:X}".format(
                self.port_name, self.baud_rate, self.address))
            self.rc = Roboclaw(self.port_name, self.baud_rate)
            if not self.rc.Open():
                rospy.logerr("Failed to open RoboClaw on {0}. Exiting.".format(self.port_name))
                sys.exit(1)
            rospy.loginfo("RoboClaw opened successfully on {0}.".format(self.port_name))
    
            # 3) Initialize Pygame
            pygame.init()
            pygame.joystick.init()
    
            joystick_count = pygame.joystick.get_count()
            rospy.loginfo("Detected {0} joystick(s).".format(joystick_count))
            if joystick_count == 0:
                rospy.logerr("No joystick detected. Exiting.")
                sys.exit(1)
    
            self.joystick = pygame.joystick.Joystick(0)
            self.joystick.init()
            rospy.loginfo("Joystick: {0}".format(self.joystick.get_name()))
    
            # 4) Speed config
            self.max_speed_cmd = 15.0  # if 127 is full speed, 20 is slower
            self.deadzone = 0.1
            rospy.loginfo("max_speed_cmd={0}, deadzone={1}".format(self.max_speed_cmd, self.deadzone))
    
            # Rate
            self.loop_rate = rospy.Rate(20)  # 20 Hz
    
            # On shutdown => stop motors
            rospy.on_shutdown(self.stop_motors)
    
            rospy.loginfo("Initialization complete. Ready to run...")
    
        def stop_motors(self):
            rospy.loginfo("Stopping motors.")
            self.rc.ForwardM1(self.address, 0)
            self.rc.ForwardM2(self.address, 0)
    
        def run(self):
            loop_counter = 0
            while not rospy.is_shutdown():
                loop_counter += 1
                # Just for debugging
                rospy.logdebug("Main loop iteration={0}".format(loop_counter))
    
                pygame.event.pump()
    
                # Example: left stick vertical = axis 1, right stick horizontal = axis 3
                forward_axis = -self.joystick.get_axis(1)
                turn_axis    =  self.joystick.get_axis(3)
    
                # Debug prints
                rospy.logdebug("Raw axes => forward_axis={0:.2f}, turn_axis={1:.2f}".format(
                    forward_axis, turn_axis))
    
                # Deadzone
                if abs(forward_axis) < self.deadzone:
                    forward_axis = 0.0
                if abs(turn_axis) < self.deadzone:
                    turn_axis = 0.0
    
                # Skid-steer mixing
                left_val  = forward_axis - turn_axis
                right_val = forward_axis + turn_axis
    
                # clamp [-1..+1]
                left_val  = max(-1.0, min(1.0, left_val))
                right_val = max(-1.0, min(1.0, right_val))
    
                # Convert to RoboClaw speed
                left_speed, left_dir   = self.convert_speed(left_val)
                right_speed, right_dir = self.convert_speed(right_val)
    
                rospy.logdebug("Mixed => L={0:.2f}, R={1:.2f} => speeds {2} ({3}), {4} ({5})".format(
                    left_val, right_val, left_speed, left_dir, right_speed, right_dir))
    
                # Send to motors
                if left_dir == "forward":
                    self.rc.ForwardM1(self.address, left_speed)
                else:
                    self.rc.BackwardM1(self.address, left_speed)
    
                if right_dir == "forward":
                    self.rc.ForwardM2(self.address, right_speed)
                else:
                    self.rc.BackwardM2(self.address, right_speed)
    
                self.loop_rate.sleep()
    
            self.stop_motors()
            pygame.quit()
    
        def convert_speed(self, val):
            """
            Convert [-1..+1] => (0..max_speed_cmd, direction).
            """
            if val >= 0:
                return (int(val * self.max_speed_cmd), "forward")
            else:
                return (int(abs(val) * self.max_speed_cmd), "backward")
    
    def main():
        try:
            node = XboxRoboclawDebugPy2()
            node.run()
        except rospy.ROSInterruptException:
            pass
        finally:
            rospy.loginfo("Exiting python2 xbox teleop script.")
    
    if __name__ == "__main__":
        main()
    
  • Watch the map being built in RViz.
  • Ensure the rover avoids obstacles and updates the map in real-time.

Key Adjustments Made

Here’s a summary of the adjustments we made to configure Hector SLAM:

  1. Set Fixed Frame in RViz to scanmatcher_frame.
  2. Modified the Hector SLAM launch file to include:
  3. pub_map_odom_transform set to true.
  4. Correct frame names (map, odom, base_link).
  5. Verified LIDAR publishing to /scan using ld19.launch.
  6. Ensured odometry data was published to /odom by the Roboclaw node.

Troubleshooting

Error: Transform Lookup Failed

If you see errors like "Lookup would require extrapolation into the future," check the following: - Ensure the system clocks are synchronized using ntp or chrony. - Verify all topics (/scan, /odom) have valid and synchronized timestamps.

LIDAR Not Publishing

Run:

rostopic echo /scan
If no data appears, ensure the LIDAR launch file is correctly configured and the sensor is operational.


Conclusion

By following these steps, you’ve successfully set up Hector SLAM on a Roboclaw-based ROS 1 rover. With LIDAR and odometry data, your rover can build a 2D map of its environment, enabling autonomous navigation and enhanced spatial awareness.

Feel free to experiment with SLAM parameters and refine your rover’s capabilities for your specific use case.

Bypassing Cloudflare with Selenium and Undetected-Chromedriver

Bypassing Cloudflare with Selenium and Undetected-Chromedriver

By combining Selenium with undetected-chromedriver (UC), you can overcome common automation challenges like Cloudflare's browser verification. This guide explores practical workflows and techniques to enhance your web automation projects.


Why Use Selenium with Undetected-Chromedriver?

Cloudflare protections are designed to block bots, posing challenges for developers. By using undetected-chromedriver with Selenium, you can:

  • Bypass Browser Fingerprinting: UC modifies ChromeDriver to avoid detection.
  • Handle Cloudflare Challenges: Seamlessly bypass "wait while your browser is verified" messages.
  • Mitigate CAPTCHA Issues: Reduce interruptions caused by automated bot checks.

Detection Challenges in Web Automation

Websites employ multiple strategies to detect and prevent automated interactions:

  • CAPTCHA Challenges: Validating user authenticity.
  • Cloudflare Browser Verification: Infinite loading screens or token-based checks.
  • Bot Detection Mechanisms: Browser fingerprinting, behavioral analytics, and cookie validation.

These barriers often require advanced techniques to maintain automation workflows.


The Solution: Selenium and Undetected-Chromedriver

The undetected-chromedriver library modifies the default ChromeDriver to emulate human-like behavior and evade detection. When integrated with Selenium, it allows:

  1. Seamless CAPTCHA Bypass: Minimize interruptions by automating responses or avoiding challenges.
  2. Cloudflare Token Handling: Automatically manage verification processes.
  3. Cookie Reuse for Session Preservation: Skip repetitive verifications by reusing authenticated cookies.

Implementation Guide: Setting Up Selenium with Undetected-Chromedriver

Step 1: Install Required Libraries

Install Selenium and undetected-chromedriver:

pip install selenium undetected-chromedriver

Step 2: Initialize the Browser Driver

Set up a Selenium session with UC:

import undetected_chromedriver as uc

# Initialize the driver
driver = uc.Chrome()

# Navigate to a website
driver.get("https://example.com")
print("Page Title:", driver.title)

# Quit the driver
driver.quit()

Step 3: Handle CAPTCHA and Cloudflare Challenges

  • Use UC to bypass passive bot checks.
  • Extract and reuse cookies to maintain session continuity:
    cookies = driver.get_cookies()
    driver.add_cookie(cookies)
    

Advanced Automation Workflow with Cookies

Step 1: Attempt Standard Automation

Use Selenium with UC to navigate and interact with the website.

Step 2: Use Cookies for Session Continuity

Manually authenticate once, extract cookies, and reuse them for automated sessions:

# Save cookies after manual login
cookies = driver.get_cookies()

# Use cookies in future sessions
for cookie in cookies:
    driver.add_cookie(cookie)
driver.refresh()

Step 3: Fall Back to Manual Assistance

Prompt users to resolve CAPTCHA or login challenges in a separate session and capture the cookies for automation.


Proposed Workflow for Automation

  1. Initial Attempt: Start with Selenium and UC for automation.
  2. Fallback to Cookies: Reuse cookies for continuity if CAPTCHA or Cloudflare challenges arise.
  3. Manual Assistance: Open a browser session for user input, capture cookies, and resume automation.

This iterative process ensures maximum efficiency and minimizes disruptions.


Conclusion

Selenium and undetected-chromedriver provide a powerful toolkit for overcoming automation barriers like CAPTCHA and Cloudflare protections. By leveraging cookies and manual fallbacks, you can create robust workflows that streamline automation processes.

Ready to enhance your web automation? Start integrating Selenium with UC today and unlock new possibilities!


References