-
Notifications
You must be signed in to change notification settings - Fork 0
Home
This is a port of examples from micro_ros_arduino to PlatfromIO.
Pico2/pico are cheap and have more resources for robotic than most other MCUs. They have 4M/2M flash, 512K/256K RAM, 24/16 PWM for motors and 12/8 PIO state-machines for wheel encoders. The USB CDC /dev/ttyACM0 on pico2/pico works better than USB serial /dev/ttyUSB0 on esp32. Pico2 and pico share the same pinout. Because their prices are very close, you should choose pico2.
Esp32 supports micro-ROS wifi transport and can be used if you do not have a robot computer such as RPI4/5. It has 4M flash, 512K RAM, 16 PWM for motors and 8 pulse counters for wheel encoders.
Teensy41 is fast but more expensive. It has 8M flash, 1M RAM, 31 PWM pins. It uses interrupt-driven encoders.
Most Arduino boards have very limited flash and RAM for micro-ROS. Some have only 32K RAM. They should be avoided.
The latest ROS2 LTS release is Jazzy and the latest Ubuntu LTS release is 24.04. This combination is recommended for beginners and new designs. The micro_ros_platformio is based on Arduino framework. Most Arduino drivers should work. The following guide assumes you are building pico micro-ROS firmware for ROS2 Jazzy on Ubuntu 24.04.
If you develop on Windows, you may install vscode with platformio extension and use docker to run ROS2.
Install Ubuntu 24.04 Desktop. Or, if you use Rpi4/5 as robot computer, you may use vscode/ssh for remote development on your Windows or Linux desktop.
Install low latency kernel and reboot to use new kernel. Default linux kernel is optimized for computation. Switch to low latency kernel will improve realtime response for robot control.
sudo apt update
sudo apt upgrade -y
sudo apt-get install -y --install-recommends linux-lowlatency
sudo reboot
Install essential build tools. Remove brltty package which interferes with CH340 USB serial bridge on some esp32 boards.
sudo apt remove -y brltty
sudo apt install -y python3-venv build-essential cmake git curl
curl -fsSL -o get-platformio.py https://raw.githubusercontent.com/platformio/platformio-core-installer/master/get-platformio.py
python3 get-platformio.py
rm get-platformio.py
echo "PATH=\"\$PATH:\$HOME/.platformio/penv/bin\"" >> $HOME/.bashrc
source ~/.bashrc
curl -fsSL https://raw.githubusercontent.com/platformio/platformio-core/develop/platformio/assets/system/99-platformio-udev.rules | sudo tee /etc/udev/rules.d/99-platformio-udev.rules
sudo service udev restart
sudo usermod -a -G dialout $USER
sudo usermod -a -G plugdev $USER
Skip the udev step or ignore the udev error if you are running on docker.
Blink is the "hello world" for micro-controller. It should be run when we get a new board as the very first test. Clone the example source into your working directory. Change the env "pico" to the board you use, eg "esp32" or "teensy41" etc. Build and upload. The on-board LED should blink every two seconds.
git clone https://github.com/hippo5329/Blink-platformio.git
cd Blink-platformio
pio run -e pico -t upload
Platformio does not require ROS2 installation to build micro-ROS firmware. If you want to build the micro-ROS firmware without ROS2 installed, you may set the ROS_DISTRO env to yours, eg, jazzy or humble. Then proceed to build with platformio.
export ROS_DISTRO=jazzy
Or, set it in platformio/platformio.ini
board_microros_distro = jazzy
(PS. If you still want to use Humble and Ubuntu 22.04, you will need to replace all commands here from "jazzy" to "humble".)
export ROS_DISTRO=jazzy
sudo curl -sSL https://raw.githubusercontent.com/ros/rosdistro/master/ros.key -o /usr/share/keyrings/ros-archive-keyring.gpg
echo "deb [arch=$(dpkg --print-architecture) signed-by=/usr/share/keyrings/ros-archive-keyring.gpg] http://packages.ros.org/ros2/ubuntu $(. /etc/os-release && echo $UBUNTU_CODENAME) main" | sudo tee /etc/apt/sources.list.d/ros2.list > /dev/null
sudo apt update
sudo apt install -y ros-$ROS_DISTRO-desktop ros-dev-tools python3-colcon-common-extensions python3-pip
sudo rosdep init
rosdep update
echo "source /opt/ros/$ROS_DISTRO/setup.bash" >> ~/.bashrc
source ~/.bashrc
mkdir ~/uros_ws/src -p
cd ~/uros_ws/src
git clone -b $ROS_DISTRO https://github.com/micro-ROS/micro-ROS-Agent.git
git clone -b $ROS_DISTRO https://github.com/micro-ROS/micro_ros_msgs.git
cd ..
rosdep install --from-paths src --ignore-src -r -y
colcon build
cd ~
echo "source \$HOME/uros_ws/install/setup.bash" >> ~/.bashrc
source ~/.bashrc
Clone the examples source into your working directory.
git clone https://github.com/hippo5329/micro_ros_arduino_examples_platformio.git
All the examples use a shared configuration file platformio/platformioio.ini.
Micro-ROS supports serial, mutli-serial, udp/wifi and custom transports.
-
If you have a robot computer such as rpi4/5, jetson, laptop or mini PC on your robot. You will connect your micro-ROS controller with USB serial port and use serial transport. This is the most popular use case.
-
If you have several micro-ROS controllers connected to USB ports, you will use multi-serial transport.
-
If you do not have a robot computer on your robot, you can use wifi transport to connect the micro-controller to ROS2 on a remote PC or server.
Take micro-ros_reconnection_example as an example, build and upload to pico.
cd micro_ros_arduino_examples_platformio/micro-ros_reconnection_example
pio run -e pico -t upload
Then connect to micro-ROS serial agent.
ros2 run micro_ros_agent micro_ros_agent serial --dev /dev/ttyACM0 --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)
You may use Ctrl-C to kill the agent. Then run the agent again. It will reconnect to the agent.
Both the pico programmer and micro-ROS agent use the same serial port. They can not run at the same time. You will need to kill the micro-ROS agent to program pico. And you cannot use serial port to print messages when micro-ROS serial transport is running.
Micro-ROS wifi transport does have such limitation.
pio run -e pico2 -t upload
ros2 run micro_ros_agent micro_ros_agent serial --dev /dev/ttyACM0
pio run -e esp32 -t upload
ros2 run micro_ros_agent micro_ros_agent serial --dev /dev/ttyUSB0
pio run -e teensy41 -t upload
ros2 run micro_ros_agent micro_ros_agent serial --dev /dev/ttyACM0
Open another terminal to check the publisher node and topic.
ubuntu@better-snipe:~$ ros2 node list
/int32_publisher_rclc
ubuntu@better-snipe:~$ 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:~$ ros2 topic list -t
/std_msgs_msg_Int32 [std_msgs/msg/Int32]
/parameter_events [rcl_interfaces/msg/ParameterEvent]
/rosout [rcl_interfaces/msg/Log]
ubuntu@better-snipe:~$ ros2 topic echo /std_msgs_msg_Int32
data: 162
---
data: 163
---
data: 164
---
Update micro_ros_arduino_examples_platformio/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_PASSWORD="wifi_password"'
Take micro-ros_reconnection_example as an example, build and upload to esp32.
cd micro_ros_arduino_examples_platformio/micro-ros_reconnection_example
pio run -e esp32_wifi -t upload
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)
Open another terminal to check the publisher node and topic as it was in serial transport.
Follow the ethernet kit guide to build the hardware. Test it with Arduino examples - native ethernet - web server. You should make sure the hardware works before proceeding.
Update micro_ros_arduino_examples_platformio/platformio/platformio.ini with your network settings.
[env]
...
build_flags =
'-D LOCAL_MAC={ 0xAA, 0xBB, 0xCC, 0xEE, 0xDD, 0xFF }'
'-D LOCAL_IP={ 192, 168, 1, 101 }'
'-D AGENT_IP={ 192, 168, 1, 100 }'
'-D AGENT_PORT=8888'
Take micro-ros_reconnection_example as an example, build and upload to teensy41.
cd micro_ros_arduino_examples_platformio/micro-ros_reconnection_example
pio run -e teensy41_eth -t upload
The native ethernet transport uses the same udp4 protocol as wifi transport. Follow the wifi transport guide to bring up the agent and check topic.
- rolling -- ubuntu 24.04
- jazzy -- ubuntu 24.04 -- recommended
- iron -- ubuntu 22.04
- humble -- ubuntu 22.04
- (foxy EOL) -- (ubuntu 20.04 EOL)
portenta_h7_m7, teensy41, teensy40, teensy36, teensy35, teensy31, due, zero, olimex_e407, esp32, esp32s3, esp32c3, nanorp2040connect, pico, pico2.
Supported examples:
- micro-ros_subscriber
- micro-ros_subscriber_twist
- micro-ros_addtwoints_service
- micro-ros_time_sync
- micro-ros_publisher
- micro-ros_types_handling
- micro-ros_reconnection_example
Unsupported examples due to specific boards/sensors requirement:
- micro-ros_IMU_ML
- micro-ros_tf_publisher
- micro-ros_decibels
Removed examples:
- micro-ros_publisher_ethernet = micro-ros_publisher
- micro-ros_publisher_wifi = micro-ros_publisher
If you run Windows or Linux desktop and want to develop on Rpi4/5, you can use remote development SSH feature of VSCode. Though the setup may take some time, it will save a lot of time in the future.
Overview
- Install VSCode on Windows or Linux desktop
- Install Remote development extension on VSCode
- Generate SSH key pair on Windows or Linux desktop
- Upload SSH public key to your github account
- Import SSH key from github to Rpi
- Connect to Rpi from VSCode on Windows or Linux desktop
- Edit and build your application on Rpi through VSCode on Windows or Linux desktop
In details
Open browser on Windows. Download and install VSCode. https://code.visualstudio.com/download
Run VSCode and add the "Remote Development" extension from microsoft.com.
Run PowerShell on Windows or open a terminal on Linux desktop. Run ssh-keygen and press Enter to the questions.
ssh-keygen -t ed25519
cat .ssh/id_ed25519.pub
XXXXXX
The long string XXXXXX is your SSH public key. Copy it to clipboard.
Open browser. Sign-in to your github. In Profile - Settings - SSH and GPG keys - New SSH Key, paste the key from your clipboard and save.
You may create your Rpi SD card using RPI Imager, select "Ubuntu 24.04 LTS Server" to run ROS2 Jazzy. Then setup your WIFI keys, username, password and ssh key XXXXXX. Or, after you login the Rpi on screen or ssh, import the ssk key from github.
sudo apt install -y ssh-import-id
ssh-import-id-gh <your github account name>
It should install and list your public keys on github.
From VSCode, press F1, search SSH, Remote SSH: Add New SSH Host, enter the command below, change ubuntu to your username on Rpi, change 192.168.1.100 to your Rpi IP address.
ssh ubuntu@192.168.1.100
Save it to .ssh/config on your Windows account. Press F1 again, search SSH, Remote SSH: Connect to Host.. or Connect current Windows to Host..
Now the VSCode is connected to the remote Rpi. Open a terminal in vscode to run command on Rpi. Run "ssh-keygen -t ed25519" for Rpi and add the public key to your github.
You will install VSCode extensions, such as PlatfromIO, GitLens etc, to your Rpi. And clone repository from github, edit, build and develop to Rpi from your Windows or Linux desktop. The code will be built on the Rpi. This way, you develop remotely on your VSCode on Windows or Linux desktop. You do not need a monitor connected to your Rpi.
You may start with the Blink example. It is the "hello world" for micro-controller. It should be run when we get a new board as the first test.
https://github.com/hippo5329/Blink-platformio
You may fork the Blink example, use vscode on Windows to clone build and upload on Rpi4/5 to pico. You will use use "SSH" url to clone your forks instead of "HTTPS" when you clone the other people's repos.
VSCode on Windows --> Rpi4/5 --> pico
VSCode on Windows or Linux desktop is your command center. You can open terminals in VSCode on Windows to run and launch ros2 on Rpi4. A browser (mostly to github.com) and VSCode will server your development work. Once you get familiar with this github/vscode/platformio workflow, you will work better then ever. enjoy.
Tip: enable trailing whitespace trimming.
If you use variable size message, such as string, array or multiarray, you have to handle the allocation of the message.
https://micro.ros.org/docs/tutorials/advanced/handling_type_memory/
If you use service, action or parameters, you will need to increase RMW allocation with a user meta file. An action requires 3 services and 2 topics. A parameters server requires 5 services.
platformio.ini board_microros_user_meta = action.meta
https://micro.ros.org/docs/tutorials/advanced/microxrcedds_rmw_configuration/
micro-ROS tutorials includes important usage information.
PlatfromIO IDE for VSCode - a bit outdated
ROS2 and VSCode - 2024 very new
linorobot2_hardware firmware for mobile robots
VNC server Install VNC server on Rpi, and view RVIZ etc on Windows with VNC viewer.
An Updated Guide to Docker and ROS 2
Setup ROS 2 with VSCode and Docker
Develop on a remote Docker host
Connect to remote Docker over SSH
Docker nodes must be on the same host. Only the platformio programmer and micro-ros agent dockers need " -v /dev:/dev --privileged" to use the USB serial port.
# Open terminal, run docker to install platformio, build and upload the micro-ros firmware to pico
$ docker run -it -v /dev:/dev --privileged ros:humble
...
# In another terminal, run micro-ros agent
$ docker run -it -v /dev:/dev --privileged microros/micro-ros-agent:humble serial --dev /dev/ttyACM0 --baudrate 921600
[1730936457.655211] info | TermiosAgentLinux.cpp | init | running... | fd: 3
[1730936457.656602] info | Root.cpp | set_verbose_level | logger setup | verbose_level: 4
[1730936461.765455] info | Root.cpp | create_client | create | client_key: 0x7426150A, session_id: 0x81
[1730936461.765664] info | SessionManager.hpp | establish_session | session established | client_key: 0x7426150A, address: 0
[1730936461.836409] info | ProxyClient.cpp | create_participant | participant created | client_key: 0x7426150A, participant_id: 0x000(1)
[1730936461.886272] info | ProxyClient.cpp | create_topic | topic created | client_key: 0x7426150A, topic_id: 0x000(2), participant_id: 0x000(1)
[1730936461.931648] info | ProxyClient.cpp | create_publisher | publisher created | client_key: 0x7426150A, publisher_id: 0x000(3), participant_id: 0x000(1)
[1730936461.977454] info | ProxyClient.cpp | create_datawriter | datawriter created | client_key: 0x7426150A, datawriter_id: 0x000(5), publisher_id: 0x000(3)
In another terminal, check the published messages
$ docker run -it ros:humble ros2 topic echo /micro_ros_arduino_node_publisher
data: 44
---
data: 45
---
data: 46
---
cd micro_ros_arduino_examples_platformio/micro-ros_addtwoints_service
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)