Skip to content
Thomas Chou edited this page Jul 14, 2024 · 6 revisions

Welcome to the micro-ROS-demos-platformio wiki

This repository ports the upstream micro_ros_demos packages to platformio to run on a real micro-controller, such as esp32 teensy and pico.

Install software tools

Follow this guide to install software tools.

Clone demos repository

git clone https://github.com/hippo5329/micro-ROS-demos-platformio.git

The demonstrations packages are located in the rclc subdirectory.

Serial transport

Take int32_publisher as an example, build and upload to esp32.

cd micro-ros-demos-platformio/rclc/int32_publisher
pio run -e esp32 -t upload

Then connect to micro-ROS serial agent.

ros2 run micro_ros_agent micro_ros_agent serial --dev /dev/ttyUSB0 --baudrate 921600

Screen output after connect.

[1718994292.702493] info     | TermiosAgentLinux.cpp | init                     | running...             | fd: 14
[1718994292.702712] info     | Root.cpp           | set_verbose_level        | logger setup           | verbose_level: 4
[1718994293.013253] info     | Root.cpp           | create_client            | create                 | client_key: 0x64E60CB5, session_id: 0x81
[1718994293.013293] info     | SessionManager.hpp | establish_session        | session established    | client_key: 0x64E60CB5, address: 0
[1718994293.033488] info     | ProxyClient.cpp    | create_participant       | participant created    | client_key: 0x64E60CB5, participant_id: 0x000(1)
[1718994293.049832] info     | ProxyClient.cpp    | create_topic             | topic created          | client_key: 0x64E60CB5, topic_id: 0x000(2), participant_id: 0x000(1)
[1718994293.060696] info     | ProxyClient.cpp    | create_publisher         | publisher created      | client_key: 0x64E60CB5, publisher_id: 0x000(3), participant_id: 0x000(1)
[1718994293.072949] info     | ProxyClient.cpp    | create_datawriter        | datawriter created     | client_key: 0x64E60CB5, datawriter_id: 0x000(5), publisher_id: 0x000(3)

Check topic

Open another terminal to check the publisher node and topic.

ubuntu@better-snipe:~/bin$ ros2 node list
/int32_publisher_rclc

ubuntu@better-snipe:~/bin$ ros2 node info /int32_publisher_rclc
/int32_publisher_rclc
Subscribers:
Publishers:
    /std_msgs_msg_Int32: std_msgs/msg/Int32
Service Servers:
Service Clients:
Action Servers:
Action Clients:

ubuntu@better-snipe:~/bin$ ros2 topic list -t
/parameter_events [rcl_interfaces/msg/ParameterEvent]
/rosout [rcl_interfaces/msg/Log]
/std_msgs_msg_Int32 [std_msgs/msg/Int32]

ubuntu@better-snipe:~/bin$ ros2 topic hz /std_msgs_msg_Int32
average rate: 1.125
    min: 0.666s max: 1.000s std dev: 0.15738s window: 3
average rate: 1.091
    min: 0.666s max: 1.000s std dev: 0.14460s window: 4

ubuntu@better-snipe:~/bin$ ros2 topic echo /std_msgs_msg_Int32
data: 74
---
data: 75
---

Wifi transport

Update rclc/platformio/platformio.ini with agent ip (ie. your computer's ip) and wifi keys.

[env]
...
build_flags =
    ...
    '-D AGENT_IP={ 192, 168, 1, 100 }'
    '-D AGENT_PORT=8888'
    '-D WIFI_SSID="wifi_ssid"'
    '-D WIFI_PSK="wifi_password"'

Take int32_publisher as an example, build and upload to esp32.

cd micro-ros-demos-platformio/rclc/int32_publisher
pio run -e esp32_wifi -t upload

Run device monitor to view the serial output.

pio run device monitor -e esp32_wifi -p /dev/ttyUSB0 -b 921600

Then open another terminal to run micro-ROS wifi agent.

ros2 run micro_ros_agent micro_ros_agent udp4 --port 8888

Screen output of agent after connected.

[1719004509.846308] info     | UDPv4AgentLinux.cpp | init                     | running...             | port: 8888
[1719004509.846534] info     | Root.cpp           | set_verbose_level        | logger setup           | verbose_level: 4
[1719004511.136599] info     | Root.cpp           | create_client            | create                 | client_key: 0x6CFC0C00, session_id: 0x81
[1719004511.136763] info     | SessionManager.hpp | establish_session        | session established    | client_key: 0x6CFC0C00, address: 192.168.1.101:47138
[1719004511.348916] info     | ProxyClient.cpp    | create_participant       | participant created    | client_key: 0x6CFC0C00, participant_id: 0x000(1)
[1719004511.399397] info     | ProxyClient.cpp    | create_topic             | topic created          | client_key: 0x6CFC0C00, topic_id: 0x000(2), participant_id: 0x000(1)
[1719004511.416526] info     | ProxyClient.cpp    | create_publisher         | publisher created      | client_key: 0x6CFC0C00, publisher_id: 0x000(3), participant_id: 0x000(1)
[1719004511.461559] info     | ProxyClient.cpp    | create_datawriter        | datawriter created     | client_key: 0x6CFC0C00, datawriter_id: 0x000(5), publisher_id: 0x000(3)

Screen output from device monitor after connected to agent.

Sent: 0
Sent: 1
Sent: 2

Open another terminal to check the publisher node and topic as it was in serial transport.

Implementation

The rclc/platformio/platformio.ini file, copied from micro_ros_platformio/ci, contains common platformio project configuration for various platforms. The rclc/platformio/src/setup.cpp file contains common arduino setup() and loop(). The micro-ROS transport initialization is handled in setup(). Every project in the demonstrations sources this project setup. The original main() in the project is renamed to rmain() as main() is used by most arduino core libraries. Then platformio/arduino related stuff is added. Modification to original source is minimized to keep the changes clean.

Both serial and wifi transport are supported on esp32. On the other platforms, only serial transport is supported. With serial transport, the serial port is occupied by micro-ROS and the printf() output is not available. For best result, use wifi transport on esp32.

Limitations: Reconnection is not supported as in upstream.

Increase middleware memory allocation

Do not use cyclonedds. It does not support micro-ROS service and action.

The default micro-ROS middleware configuration memory allocation is very limited because most micro-controllers have limited memory.

            "-DRMW_UXRCE_MAX_NODES=1",
            "-DRMW_UXRCE_MAX_PUBLISHERS=10",
            "-DRMW_UXRCE_MAX_SUBSCRIPTIONS=5",
            "-DRMW_UXRCE_MAX_SERVICES=1",
            "-DRMW_UXRCE_MAX_CLIENTS=1",
            "-DRMW_UXRCE_MAX_HISTORY=4",

Each ros2 action server needs three services. To run ros2 action servers, you will need to increase middle ware configuration with custom meta. There is a sample meta at micro-ros-demos-platformio/rclc/platformio/action.meta. You may add this with "board_microros_user_meta = action.meta" to board configuration in micro-ros-demos-platformio/rclc/platformio/platformio.ini. Then clean and build the micro-ROS lib with "pio run -e <your_board> -t clean_microros" "pio run -e <your_board> -t upload". esp32 and esp32_wifi have this meta enabled already.

{
    "names": {
        "rmw_microxrcedds": {
            "cmake-args": [
                "-DRMW_UXRCE_MAX_NODES=2",
                "-DRMW_UXRCE_MAX_PUBLISHERS=10",
                "-DRMW_UXRCE_MAX_SUBSCRIPTIONS=10",
                "-DRMW_UXRCE_MAX_SERVICES=6",
                "-DRMW_UXRCE_MAX_CLIENTS=2",
                "-DRMW_UXRCE_MAX_HISTORY=2",
            ]
        }
    }
}

paramter server The parameter server uses five services and an optional publisher.

Add two int service demo

cd micro-ros-demos-platformio/rclc/addtwoints_server

Build, upload and connect to micro-ROS agent as before. Open another terminal to call the service.

ros2 service call <service_name> <service_type> <arguments>
ros2 interface show <type_name>

ros2 service call /addtwoints example_interfaces/srv/AddTwoInts "{ a: 12, b: 13 }"

ubuntu@better-snipe:~$ ros2 node list
/add_twoints_client_rclc

ubuntu@better-snipe:~$ ros2 node info /add_twoints_client_rclc
/add_twoints_client_rclc
Subscribers:
Publishers:
Service Servers:
    /addtwoints: example_interfaces/srv/AddTwoInts
Service Clients:
Action Servers:
Action Clients:

ubuntu@better-snipe:~$ ros2 service list -t
/addtwoints [example_interfaces/srv/AddTwoInts]

ubuntu@better-snipe:~$ ros2 service call /addtwoints example_interfaces/srv/AddTwoInts "{ a: 12, b: 23 }"
requester: making request: example_interfaces.srv.AddTwoInts_Request(a=12, b=23)

response:
example_interfaces.srv.AddTwoInts_Response(sum=35)

Fibonacci action server demo

cd micro-ros-demos-platformio/rclc/fibonacci_action_server

Build, upload and connect to micro-ROS agent as before. Open another terminal to call the service.

ros2 action send_goal <action_name> <action_type> <values>

ros2 action send_goal /fibonacci example_interfaces/action/Fibonacci "{ order: 3}"

ubuntu@cc187:~$ ros2 node info /esp32
/esp32
Subscribers:
    /cmd_vel: geometry_msgs/msg/Twist
Publishers:
    /battery: sensor_msgs/msg/BatteryState
    /imu/data: sensor_msgs/msg/Imu
    /odom/unfiltered: nav_msgs/msg/Odometry
Service Servers:

Service Clients:

Action Servers:
    /fibonacci: example_interfaces/action/Fibonacci
Action Clients:

ubuntu@cc187:~$ ros2 action list -t
/fibonacci [example_interfaces/action/Fibonacci]

ubuntu@cc187:~$ ros2 interface show example_interfaces/action/Fibonacci
# Goal
int32 order
---
# Result
int32[] sequence
---
# Feedback
int32[] sequence

ubuntu@cc187:~$ ros2 action send_goal /fibonacci example_interfaces/action/Fibonacci "{ order: 3}"
Waiting for an action server to become available...
Sending goal:
    order: 3

Goal accepted with ID: 9b8e5cc5668e45508fdbb21b6458bbda

Result:
    sequence:
- 0
- 1
- 1
- 2

Goal finished with status: SUCCEEDED