Ricbot ROS2: Difference between revisions

From Rsewiki
(Created page with "Back to Ricbot == ROS2 ==")
 
 
Line 2: Line 2:


== ROS2 ==
== ROS2 ==
From https://docs.ros.org/en/jazzy/Installation/Ubuntu-Install-Debs.html
Install
export ROS_APT_SOURCE_VERSION=$(curl -s https://api.github.com/repos/ros-infrastructure/ros-apt-source/releases/latest | grep -F "tag_name" | awk -F\" '{print $4}')
curl -L -o /tmp/ros2-apt-source.deb "https://github.com/ros-infrastructure/ros-apt-source/releases/download/${ROS_APT_SOURCE_VERSION}/ros2-apt-source_${ROS_APT_SOURCE_VERSION}.$(. /etc/os-release && echo ${UBUNTU_CODENAME:-${VERSION_CODENAME}})_all.deb"
sudo dpkg -i /tmp/ros2-apt-source.deb
sudo apt update && sudo apt install ros-dev-tools
Install full ROS2 Jazzy
sudo apt install ros-jazzy-desktop
Start in this ROS2 environment, now and in new terminals:
source /opt/ros/jazzy/setup.bash
echo "source /opt/ros/jazzy/setup.bash" >> ~/.bashrc
export ROS_DOMAIN_ID=0
echo "export ROS_DOMAIN_ID=0" >> ~/.bashrc
Install ROS QT GUI stuff
sudo apt install '~nros-jazzy-rqt*'
=== Create workspace ===
From https://docs.ros.org/en/jazzy/Tutorials/Beginner-Client-Libraries/Colcon-Tutorial.html
Install colcon
sudo apt install python3-colcon-common-extensions
Create workspace directory
mkdir -p ~/ros2_ws/src
cd ~/ros2_ws
From within this directory clone (any) standard package
e.g. tutorial examples
git clone https://github.com/ros2/examples src/examples -b jazzy
Build the examples; this is memory and CPU-hungry, so the option ''--executor sequential'' may come in handy, especially on a Raspberry Pi, but it will take significantly longer.
colcon build --symlink-install --executor sequential
Allow use of colcon_cd
echo "source /usr/share/colcon_cd/function/colcon_cd.sh" >> ~/.bashrc
echo "export _colcon_cd_root=/opt/ros/jazzy/" >> ~/.bashrc
To use the ''mixin'' shortcut for some colcon options, add:
colcon mixin add default https://raw.githubusercontent.com/colcon/colcon-mixin-repository/master/index.yaml
colcon mixin update default
=== MQTT client ===
The un-modified ''mqtt_client'' package can act as a bridge between the ''teensy_interface'' and the ROS domain.
From MQTT to ROS, the translation is using the primitive ROS type ''string'' for the parameters of the ''teensy_interface'' messages.
The MQTT topic name is translated to ROS topic names as specified in the parameter file below.
From ROS to Teensy, the message should be published on a topic that matches the desired destination.
Topics for command messages to the ''teensy_interface'':
* MQTT topic ricbot/cmd/T0 for the Teensy, the message is the string to send to the Teensy.
* MQTT topic ricbot/cmd/shutdown to schedule a shutdown of the RICBOT (power off), something like 20 seconds after the message.
* MQTT topic ricbot/cmd/ti for messages to the teensy_interface, the message is a string.
==== Install ====
The robot's interface is via MQTT. Install the MQTT ROS client
sudo apt install ros-jazzy-mqtt-client
Or directly as source
cd src
git clone https://github.com/ika-rwth-aachen/mqtt_client
Compile:
cd ~/ros2_ws
colcon build
==== Run MQTT_client ====
To start the ''mqtt_client'':
cd ros2_ws/src/mqtt_client/mqtt_client/config
ros2 launch mqtt_client standalone.launch.xml params_file:="params.teensy.yaml"
The parameter file should be extended with more ''mqtt2ros'' topics as needed.
This will launch the un-modified ''mqtt_client'' node with specific bridge parameters as specified in ''params.teensy.yaml'':
/**/*:
  ros__parameters:
    broker:
      host: localhost
      port: 1883
      tls:
        enabled: false
    client:
      id: ros
      clean_session: true
      keep_alive_interval: 20.0
    bridge:
      ros2mqtt:
        ros_topics:
          - /teensy/cmd/T0
          - /teensy/cmd/shutdown
          - /teensy/cmd/ti
        /teensy/cmd/T0:
          mqtt_topic: ricbot/cmd/T0
          primitive: true
          inject_timestamp: false
        /teensy/cmd/shutdown:
          mqtt_topic: ricbot/cmd/shutdown
          primitive: true
          inject_timestamp: false
        /teensy/cmd/ti:
          mqtt_topic: ricbot/cmd/ti
          primitive: true
          inject_timestamp: false
      mqtt2ros:
        # Needs to be expanded to relevant topics
        mqtt_topics:
          - ricbot/data/T0/info
          - ricbot/data/T0/hbt
        ricbot/data/T0/info:
          ros_topic: /teensy/T0/info
          primitive: true
        ricbot/data/T0/hbt:
          ros_topic: /teensy/T0/hbt
          primitive: true
=== Test interface ===
Start the ''teensy_interface'' with the right ini-file:
cd ~/svn/robobot/teensy_interface/build
./teensy_interface -z ricbot.ini
This should respond with something like:
$ ./teensy_interface -z ricbot.ini
# UService:: created directory log_20260118_083120.745/
# UMqtt:: connection to MQTT broker on tcp://localhost:1883 established
# UMqttIn:: connection to MQTT broker on tcp://localhost:1883 established
# STeensy:: opening to USB /dev/ttyACM0
# SRobot:: (t0) found IP 0: eno1 192.168.2.157
# STeensy:: just connected
# UService:: setup of Teensy 0 modules finished OK.
# Type quit to stop, or 'h' for help
Start the ''mqtt_client'' in ROS
cd ~/svn/ricbot/ros_config
ros2 launch mqtt_client standalone.launch.xml params_file:="params.teensy.yaml"
==== From MQTT to ROS ====
There should now be ''hbt'' (heartbeat) message on the ROS side:
ros2 topic echo /teensy/T0/hbt
This should give something like:
data: '1768722645.7425 1738.4885 93 1748 4.85 0 9 18.1 0 0
  '
---
data: '1768722646.2426 1738.9885 93 1748 4.85 0 9 18.0 0 0
  '
---
data: '1768722646.7431 1739.4885 93 1748 4.85 0 9 18.0 0 0
  '
---
The data is: timestamp (host), timestamp Teensy, Teensy ID, version, battery voltage, ... (the rest depend on the platform).
==== From ROS to MQTT ====
e.g. make the robot drive with velocity 0.25m/s and turn 0.1 rad/s CCV, followed by stop:
ros2 topic pub /ricbot/cmd/ti std_msgs/String 'data: rc 0.25 0.1'
ros2 topic pub /ricbot/cmd/ti std_msgs/String 'data: rc 0 0'
Or send a request to publish gyro data every 12ms:
ros2 topic pub /ricbot/cmd/T0 std_msgs/String 'data: sub gyro 12'
== (RIC_pkg) HW sensor translate package ==
Create the package in the workspace.
cd ~/ros2_ws/src
ros2 pkg create --build-type ament_cmake --license MIT --node-name ric_node ric_pkg
Add dependencies to other packages to CMakeLists.txt.
Add to the list of ''find_package''
find_package(rclcpp REQUIRED)
find_package(std_msgs REQUIRED)
find_package(nav_msgs REQUIRED)
find_package(sensor_msgs REQUIRED)
find_package(geometry_msgs REQUIRED)
Make target dependencies available in the include path (and elsewhere as needed).
Add this after the ''add_executable''
ament_target_dependencies(talker rclcpp std_msgs nav_msgs sensor_msgs geometry_msgs)
To the package description ''package.xml'' add dependencies:
Add just after the ''buildtool_depend'' section:
<depend>rclcpp</depend>
<depend>std_msgs</depend>
<depend>nav_msgs</depend>
<depend>sensor_msgs</depend>
<depend>geometry_msgs</depend>
=== RIC_node code ===
The code in ''ris_node.cpp'' is pt this (not functional yet):
#include <cstdio>
#include <chrono>
#include <memory>
#include <string>
#include "rclcpp/rclcpp.hpp"
#include "std_msgs/msg/string.hpp"
#include "std_msgs/msg/int32.hpp"
#include <nav_msgs/msg/odometry.hpp>
#include "geometry_msgs/msg/twist.hpp"
class RIC_translator : public rclcpp::Node
{
public:
  RIC_translator()
  : Node("minimal_publisher"), count(0)
  {
    publisher_ = this->create_publisher<std_msgs::msg::String>("/ric/hbt", 10);
    //
    // Heartbeat
    auto topic_callback =
    [this](std_msgs::msg::String::UniquePtr msg) -> void {
      // RCLCPP_INFO(this->get_logger(), "I heard: hbt '%s'", msg->data.c_str());
      // strncpy(hbtParams, msg->data.c_str(), 100);
      printHbt(msg->data.c_str());
    };
    subsHbt =
    this->create_subscription<std_msgs::msg::String>("/teensy/T0/hbt", 10, topic_callback);
  }
private:
  rclcpp::TimerBase::SharedPtr timer_;
  rclcpp::Publisher<std_msgs::msg::String>::SharedPtr publisher_;
  rclcpp::Publisher<std_msgs::msg::Int32>::SharedPtr odo_;
  size_t count;
  //
  char hbtParams[100] = "";
  rclcpp::Subscription<std_msgs::msg::String>::SharedPtr subsHbt;
  void printHbt(const char * msg)
  {
    printf("# %lu got hbt %s", count, msg);
    snprintf(hbtParams, 100, "Hello RIC %lu %s", count++, msg);
    auto message = std_msgs::msg::String();
    message.set__data(hbtParams);
    this->publisher_->publish(message);
  }
};
int main(int argc, char ** argv)
{
  rclcpp::init(argc, argv);
  rclcpp::spin(std::make_shared<RIC_translator>());
  rclcpp::shutdown();
  return 0;
}
=== Run RIC_node ===
Compile (from workspace)
colcon build --packages-select ric_pkg
Then add it to the path
source install/setup.bash
and run
ros2 run ric_pkg ric_node
If the ''teensy_interface'' and the ''mqtt-client'' are also running, then (with the code above), it should print something like this on the console.
# 0 got hbt 1769340959.8623 13504.9463 105 1033 15.65 4 8 8.9 0.27 0
# 1 got hbt 1769340960.3625 13505.4463 105 1033 15.65 4 8 8.8 0.28 0
# 2 got hbt 1769340960.8626 13505.9453 105 1033 15.65 4 8 8.8 0.27 0
# 3 got hbt 1769340961.3622 13506.4463 105 1033 15.65 4 8 8.9 0.28 0
# 4 got hbt 1769340961.8625 13506.9463 105 1033 15.65 4 8 8.9 0.25 0
# 5 got hbt 1769340962.3631 13507.4453 105 1033 15.66 4 8 8.9 0.26 0
# 6 got hbt 1769340962.8624 13507.9463 105 1033 15.63 4 8 8.8 0.26 0
=== Ros2 relevant messages ===
One of the messages are probably ''twist'':
ros2 interface show geometry_msgs/msg/Twist
# This expresses velocity in free space broken into its linear and angular parts.
Vector3  linear
        float64 x
        float64 y
        float64 z
Vector3  angular
        float64 x
        float64 y
        float64 z
=== Where from here ===
Search for tutorials in https://docs.ros.org/en/jazzy/

Latest revision as of 12:26, 20 April 2026

Back to Ricbot

ROS2

From https://docs.ros.org/en/jazzy/Installation/Ubuntu-Install-Debs.html

Install

export ROS_APT_SOURCE_VERSION=$(curl -s https://api.github.com/repos/ros-infrastructure/ros-apt-source/releases/latest | grep -F "tag_name" | awk -F\" '{print $4}')
curl -L -o /tmp/ros2-apt-source.deb "https://github.com/ros-infrastructure/ros-apt-source/releases/download/${ROS_APT_SOURCE_VERSION}/ros2-apt-source_${ROS_APT_SOURCE_VERSION}.$(. /etc/os-release && echo ${UBUNTU_CODENAME:-${VERSION_CODENAME}})_all.deb"
sudo dpkg -i /tmp/ros2-apt-source.deb
sudo apt update && sudo apt install ros-dev-tools

Install full ROS2 Jazzy

sudo apt install ros-jazzy-desktop

Start in this ROS2 environment, now and in new terminals:

source /opt/ros/jazzy/setup.bash
echo "source /opt/ros/jazzy/setup.bash" >> ~/.bashrc
export ROS_DOMAIN_ID=0
echo "export ROS_DOMAIN_ID=0" >> ~/.bashrc

Install ROS QT GUI stuff

sudo apt install '~nros-jazzy-rqt*'

Create workspace

From https://docs.ros.org/en/jazzy/Tutorials/Beginner-Client-Libraries/Colcon-Tutorial.html

Install colcon

sudo apt install python3-colcon-common-extensions

Create workspace directory

mkdir -p ~/ros2_ws/src
cd ~/ros2_ws

From within this directory clone (any) standard package

e.g. tutorial examples

git clone https://github.com/ros2/examples src/examples -b jazzy

Build the examples; this is memory and CPU-hungry, so the option --executor sequential may come in handy, especially on a Raspberry Pi, but it will take significantly longer.

colcon build --symlink-install --executor sequential

Allow use of colcon_cd

echo "source /usr/share/colcon_cd/function/colcon_cd.sh" >> ~/.bashrc
echo "export _colcon_cd_root=/opt/ros/jazzy/" >> ~/.bashrc

To use the mixin shortcut for some colcon options, add:

colcon mixin add default https://raw.githubusercontent.com/colcon/colcon-mixin-repository/master/index.yaml
colcon mixin update default

MQTT client

The un-modified mqtt_client package can act as a bridge between the teensy_interface and the ROS domain.

From MQTT to ROS, the translation is using the primitive ROS type string for the parameters of the teensy_interface messages. The MQTT topic name is translated to ROS topic names as specified in the parameter file below.

From ROS to Teensy, the message should be published on a topic that matches the desired destination. Topics for command messages to the teensy_interface:

  • MQTT topic ricbot/cmd/T0 for the Teensy, the message is the string to send to the Teensy.
  • MQTT topic ricbot/cmd/shutdown to schedule a shutdown of the RICBOT (power off), something like 20 seconds after the message.
  • MQTT topic ricbot/cmd/ti for messages to the teensy_interface, the message is a string.

Install

The robot's interface is via MQTT. Install the MQTT ROS client

sudo apt install ros-jazzy-mqtt-client

Or directly as source

cd src
git clone https://github.com/ika-rwth-aachen/mqtt_client

Compile:

cd ~/ros2_ws
colcon build

Run MQTT_client

To start the mqtt_client:

cd ros2_ws/src/mqtt_client/mqtt_client/config
ros2 launch mqtt_client standalone.launch.xml params_file:="params.teensy.yaml"

The parameter file should be extended with more mqtt2ros topics as needed.

This will launch the un-modified mqtt_client node with specific bridge parameters as specified in params.teensy.yaml:

/**/*:
 ros__parameters:
   broker:
     host: localhost
     port: 1883
     tls:
       enabled: false
   client:
     id: ros
     clean_session: true
     keep_alive_interval: 20.0
   bridge:
     ros2mqtt:
       ros_topics: 
         - /teensy/cmd/T0
         - /teensy/cmd/shutdown
         - /teensy/cmd/ti
       /teensy/cmd/T0:
         mqtt_topic: ricbot/cmd/T0
         primitive: true
         inject_timestamp: false
       /teensy/cmd/shutdown:
         mqtt_topic: ricbot/cmd/shutdown
         primitive: true
         inject_timestamp: false
       /teensy/cmd/ti:
         mqtt_topic: ricbot/cmd/ti
         primitive: true
         inject_timestamp: false
     mqtt2ros:
       # Needs to be expanded to relevant topics
       mqtt_topics: 
         - ricbot/data/T0/info
         - ricbot/data/T0/hbt
       ricbot/data/T0/info:
         ros_topic: /teensy/T0/info
         primitive: true
       ricbot/data/T0/hbt:
         ros_topic: /teensy/T0/hbt
         primitive: true

Test interface

Start the teensy_interface with the right ini-file:

cd ~/svn/robobot/teensy_interface/build
./teensy_interface -z ricbot.ini

This should respond with something like:

$ ./teensy_interface -z ricbot.ini
# UService:: created directory log_20260118_083120.745/
# UMqtt:: connection to MQTT broker on tcp://localhost:1883 established
# UMqttIn:: connection to MQTT broker on tcp://localhost:1883 established
# STeensy:: opening to USB /dev/ttyACM0
# SRobot:: (t0) found IP 0: eno1 192.168.2.157
# STeensy:: just connected 
# UService:: setup of Teensy 0 modules finished OK.
# Type quit to stop, or 'h' for help

Start the mqtt_client in ROS

cd ~/svn/ricbot/ros_config
ros2 launch mqtt_client standalone.launch.xml params_file:="params.teensy.yaml"

From MQTT to ROS

There should now be hbt (heartbeat) message on the ROS side:

ros2 topic echo /teensy/T0/hbt

This should give something like:

data: '1768722645.7425 1738.4885 93 1748 4.85 0 9 18.1 0 0
  '
---
data: '1768722646.2426 1738.9885 93 1748 4.85 0 9 18.0 0 0
  '
---
data: '1768722646.7431 1739.4885 93 1748 4.85 0 9 18.0 0 0
  '
---

The data is: timestamp (host), timestamp Teensy, Teensy ID, version, battery voltage, ... (the rest depend on the platform).

From ROS to MQTT

e.g. make the robot drive with velocity 0.25m/s and turn 0.1 rad/s CCV, followed by stop:

ros2 topic pub /ricbot/cmd/ti std_msgs/String 'data: rc 0.25 0.1'
ros2 topic pub /ricbot/cmd/ti std_msgs/String 'data: rc 0 0'

Or send a request to publish gyro data every 12ms:

ros2 topic pub /ricbot/cmd/T0 std_msgs/String 'data: sub gyro 12'

(RIC_pkg) HW sensor translate package

Create the package in the workspace.

cd ~/ros2_ws/src
ros2 pkg create --build-type ament_cmake --license MIT --node-name ric_node ric_pkg

Add dependencies to other packages to CMakeLists.txt. Add to the list of find_package

find_package(rclcpp REQUIRED)
find_package(std_msgs REQUIRED)
find_package(nav_msgs REQUIRED)
find_package(sensor_msgs REQUIRED)
find_package(geometry_msgs REQUIRED)

Make target dependencies available in the include path (and elsewhere as needed).

Add this after the add_executable

ament_target_dependencies(talker rclcpp std_msgs nav_msgs sensor_msgs geometry_msgs)

To the package description package.xml add dependencies:

Add just after the buildtool_depend section:

<depend>rclcpp</depend>
<depend>std_msgs</depend>
<depend>nav_msgs</depend>
<depend>sensor_msgs</depend>
<depend>geometry_msgs</depend>

RIC_node code

The code in ris_node.cpp is pt this (not functional yet):

#include <cstdio>
#include <chrono>
#include <memory>
#include <string> 

#include "rclcpp/rclcpp.hpp"
#include "std_msgs/msg/string.hpp"
#include "std_msgs/msg/int32.hpp"
#include <nav_msgs/msg/odometry.hpp>
#include "geometry_msgs/msg/twist.hpp"

class RIC_translator : public rclcpp::Node
{
public:
 RIC_translator()
 : Node("minimal_publisher"), count(0)
 {
   publisher_ = this->create_publisher<std_msgs::msg::String>("/ric/hbt", 10);
   //
   // Heartbeat
   auto topic_callback =
   [this](std_msgs::msg::String::UniquePtr msg) -> void {
     // RCLCPP_INFO(this->get_logger(), "I heard: hbt '%s'", msg->data.c_str());
     // strncpy(hbtParams, msg->data.c_str(), 100);
     printHbt(msg->data.c_str());
   };
   subsHbt =
   this->create_subscription<std_msgs::msg::String>("/teensy/T0/hbt", 10, topic_callback);
 }
private:
 rclcpp::TimerBase::SharedPtr timer_;
 rclcpp::Publisher<std_msgs::msg::String>::SharedPtr publisher_;
 rclcpp::Publisher<std_msgs::msg::Int32>::SharedPtr odo_;
 size_t count;
 //
 char hbtParams[100] = "";
 rclcpp::Subscription<std_msgs::msg::String>::SharedPtr subsHbt;
 void printHbt(const char * msg)
 {
   printf("# %lu got hbt %s", count, msg);
   snprintf(hbtParams, 100, "Hello RIC %lu %s", count++, msg);
   auto message = std_msgs::msg::String();
   message.set__data(hbtParams);
   this->publisher_->publish(message);
 }
};

int main(int argc, char ** argv)
{
 rclcpp::init(argc, argv);
 rclcpp::spin(std::make_shared<RIC_translator>());
 rclcpp::shutdown();
 return 0;
}

Run RIC_node

Compile (from workspace)

colcon build --packages-select ric_pkg

Then add it to the path

source install/setup.bash

and run

ros2 run ric_pkg ric_node

If the teensy_interface and the mqtt-client are also running, then (with the code above), it should print something like this on the console.

# 0 got hbt 1769340959.8623 13504.9463 105 1033 15.65 4 8 8.9 0.27 0
# 1 got hbt 1769340960.3625 13505.4463 105 1033 15.65 4 8 8.8 0.28 0
# 2 got hbt 1769340960.8626 13505.9453 105 1033 15.65 4 8 8.8 0.27 0
# 3 got hbt 1769340961.3622 13506.4463 105 1033 15.65 4 8 8.9 0.28 0
# 4 got hbt 1769340961.8625 13506.9463 105 1033 15.65 4 8 8.9 0.25 0
# 5 got hbt 1769340962.3631 13507.4453 105 1033 15.66 4 8 8.9 0.26 0
# 6 got hbt 1769340962.8624 13507.9463 105 1033 15.63 4 8 8.8 0.26 0

Ros2 relevant messages

One of the messages are probably twist:

ros2 interface show geometry_msgs/msg/Twist
# This expresses velocity in free space broken into its linear and angular parts.
Vector3  linear
       float64 x
       float64 y
       float64 z
Vector3  angular
       float64 x
       float64 y
       float64 z

Where from here

Search for tutorials in https://docs.ros.org/en/jazzy/