ANROT Tutorial

ROS2 Serial Reading Tutorial

Minimal public workflow for publishing ANROT serial data into ROS2 IMU topics on Ubuntu 20.04 and ROS2 Foxy.

Updated Jan 1, 2025 Products 6
  • ros2
  • ubuntu
  • cplusplus
  • tutorial

ROS2 Serial Reading Example

Protocol Support

Protocol / frameSupportHow this example handles it
0x91 IMUSOLSupportedPublishes /Imu_data (sensor_msgs/msg/Imu).
0x62 GWSOLParse-only, not publishedch_serial has a 0x62 case, but the ROS2 node does not publish a topic when the frame is KItemGWSOL.
0x63 GWSOL CompactNot supportedThere is no compact gateway decoder.
0x90, 0xA0, 0xB0, 0xC0, 0xD0, 0xD1, 0xF0Partially supportedThe parser handles loose items; the main node publishes single-device /Imu_data, and pressure is not included in the standard IMU topic.

Download and unzip: demo-ros2-en.zip

This example publishes ANROT serial IMU output as ROS2 topics on Ubuntu 20.04 / ROS2 Foxy. Confirm the serial device first, then build the workspace and verify /Imu_data.

Environment:

  • Ubuntu 20.04
  • ROS2 Foxy
  • USB / USB-UART connection to Hi226, Hi229, CH100, CH104, CH108, or CH110

1. Confirm the serial device

Most Ubuntu 20.04 systems already include CP210x / CH340 USB-UART drivers. Connect the device and check the assigned port:

ls /dev/ttyUSB*

If the port exists but the ROS2 node cannot open it, grant temporary access:

sudo chmod 666 /dev/ttyUSB0

For long-term use, add the user to the dialout group and log in again.

2. Compile the serial_imu_ws workspace

  1. Open the terminal and go to the /examples/ROS2/serial_imu_ws directory
  2. Execute the colcon build command. After the compilation is successful, the following information will appear.
linux@ubuntu20:~/serial_imu_ws$ colcon build
Starting >>> serial_imu
Finished <<< serial_imu [0.24s]

Summary: 1 package finished [0.35s]
linux@ubuntu20:~/serial_imu_ws$

3. Modify serial port baud rate and device number

  1. The example supports 115200, 460800, and 921600 baud. The default baud rate is 115200, and the default device path is /dev/ttyUSB0.

  2. If you need a higher output rate, edit the macro definitions in serial_port.cpp.

#define IMU_SERIAL ("/dev/ttyUSB0")
#define BAUD (B115200)

After changing the serial settings, return to the serial_imu_ws directory and run colcon build again.

4. Display data

This example provides one standard output path:

  1. Output sensor_msgs::Imu defined by ROS.

4.1: Output ROS standard Imu.msg

  1. Configure the module in Windows to enable quaternion output.
  2. In CHCenter, connect to the COM port, open Tools -> Configuration Module -> ATCMD, send AT+SETPTL=0x91, and power-cycle the module after ok is returned. Then run ros2 launch serial_imu imu_spec_msg.launch.py to view the ROS IMU topic:
[listener-2] ---
[listener-2] header:
[listener-2] stamp:
[listener-2] secs:1639099575
[listener-2] nanosecs:538349240
[listener-2] frame_id:base_link
[listener-2] orientation:
[listener-2]x: -0.095125280320644379
[listener-2] y: -0.483648955821990967
[listener-2] z: 0.053129896521568298
[listener-2] w: 0.868453860282897949
[listener-2] orientation_covariance: [ 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0]
[listener-2] angular_velocity:
[listener-2] x: -0.000815955184543841
[listener-2] y: -0.001057390143056437
[listener-2] z: 0.001062464062371403
[listener-2] angular_velocity_covariance: [ 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0]
[listener-2] linear_acceleration:
[listener-2] x: 8.110355603694916482
[listener-2] y: -2.125157430768013000
[listener-2] z: 5.013053989410400924
[listener-2] linear_acceleration_covariance: [ 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0]
[listener-2] ---
  1. Open another terminal window and execute ros2 topic hz /Imu_data to view the frequency of topic posting.
linux@ubuntu20:~$ ros2 topic hz /Imu_data
average rate: 100.032
min: 0.008s max: 0.012s std dev: 0.00058s window: 102
average rate: 100.014
min: 0.008s max: 0.012s std dev: 0.00054s window: 202
average rate: 100.019
min: 0.007s max: 0.013s std dev: 0.00064s window: 303
^C
linux@ubuntu20:~$

5. FAQ

  1. Sometimes a lot of usb devices need to be plugged into the motherboard. In order to facilitate development, a usb port constraint file is usually written. If it is a different type of usb device, it can be distinguished by the id number of the device. If it is the same type of device, their id numbers are the same. At this time, more subdivision information is needed to distinguish different usb devices. Next, let’s learn how to distinguish between usb devices of the same model.
linux@ubuntu:~$ lsusb
Bus 001 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub
Bus 002 Device 012: ID 10c4:ea60 Cygnal Integrated Products, Inc. CP210x UART Bridge / myAVR mySmartUSB light
Bus 002 Device 011: ID 10c4:ea60 Cygnal Integrated Products, Inc. CP210x UART Bridge / myAVR mySmartUSB light
Bus 002 Device 010: ID 10c4:ea60 Cygnal Integrated Products, Inc. CP210x UART Bridge / myAVR mySmartUSB light
Bus 002 Device 008: ID 0e0f:0008 VMware, Inc.
Bus 002 Device 003: ID 0e0f:0002 VMware, Inc. Virtual USB Hub
Bus 002 Device 002: ID 0e0f:0003 VMware, Inc. Virtual Mouse
Bus 002 Device 001: ID 1d6b:0001 Linux Foundation 1.1 root hub
linux@ubuntu:~$

Observing the above content, it is found that there are three USB devices with exactly the same id numbers. It is not feasible to use a simple id number to distinguish, and more device information is required.

linux@ubuntu:~$ ls /dev
agpgart loop3 shm tty32 tty63 ttyS7
autofs loop4 snapshot tty33 tty7 ttyS8
block loop5 snd tty34 tty8 ttyS9
bsg loop6 sr0 tty35 tty9 ttyUSB0
btrfs-control loop7 stderr tty36 ttyprintk ttyUSB1
bus loop-control stdin tty37 ttyS0 ttyUSB2
......(Not all released)

At this point, three usb device files are generated in the dev file, namely: ttyUSB0, ttyUSB1, and ttyUSB2.

Now look at the details of ttyUSB0:

linux@ubuntu:~$ udevadm info --attribute-walk --name=/dev/ttyUSB0
#Through this command you can view the detailed information of the specified port
......
    ATTRS{devpath}=="2.2"
    ATTRS{idProduct}=="ea60"
    ATTRS{idVendor}=="10c4"
    ATTRS{ltm_capable}=="no"
    ATTRS{manufacturer}=="Silicon Labs"
    ATTRS{maxchild}=="0"
    ATTRS{product}=="CP2104 USB to UART Bridge Controller"
    ATTRS{quirks}=="0x0"
    ATTRS{removable}=="unknown"
    ATTRS{serial}=="01E34546"
... (There is too much information, so I won't release all of it. You can go and see the detailed information by yourself. Only the information you need to care about this time is released here)

Then there are the details of ttyUSB1:

linux@ubuntu:~$ udevadm info --attribute-walk --name=/dev/ttyUSB1
#Through this command you can view the detailed information of the specified port
......
    ATTRS{devpath}=="2.3"
    ATTRS{idProduct}=="ea60"
    ATTRS{idVendor}=="10c4"
    ATTRS{ltm_capable}=="no"
    ATTRS{manufacturer}=="Silicon Labs"
    ATTRS{maxchild}=="0"
    ATTRS{product}=="CP2102N USB to UART Bridge Controller"
    ATTRS{quirks}=="0x0"
    ATTRS{removable}=="unknown"
    ATTRS{serial}=="9c1d818b48aeeb119d082897637728c5"
... (There is too much information, so I won't release all of it. You can go and see the detailed information by yourself. Only the information you need to care about this time is released here)

Finally, the details of ttyUSB2:

linux@ubuntu:~$ udevadm info --attribute-walk --name=/dev/ttyUSB2
#Through this command you can view the detailed information of the specified port
......
    ATTRS{devnum}=="27"
    ATTRS{devpath}=="2.4"
    ATTRS{idProduct}=="ea60"
    ATTRS{idVendor}=="10c4"
    ATTRS{ltm_capable}=="no"
    ATTRS{manufacturer}=="Silicon Labs"
    ATTRS{maxchild}=="0"
    ATTRS{product}=="CP2104 USB to UART Bridge Controller"
    ATTRS{quirks}=="0x0"
    ATTRS{removable}=="unknown"
    ATTRS{serial}=="02228956"
... (There is too much information, so I won't release all of it. You can go and see the detailed information by yourself. Only the information you need to care about this time is released here)

Through the information of the three serial port devices above, I found the item ATTRS{serial}==“xxxx”, which looks very random. In fact, this is the id number of the hardware, and it is also the unique id number of the hardware. Through this number, give it an alias. In this way, as long as the hardware id number is recognized, a customized one will appear under dev. Port name device file to achieve permanent connection to the port number.

linux@ubuntu:~$ cd /etc/udev/rule.d/
linux@ubuntu:/etc/udev/rules.d$ ls
70-snap.core.rules 70-ttyusb.rules 99-vmware-scsi-udev.rules
#This step is to see what constraint files are there to avoid duplication of file names
linux@ubuntu:~$ sudo vi defined_serial.rules
#This step customizes a serial port constraint file name, suffixed with '.rules'

Then enter the following into this file:

The format is as follows:

KERNEL=="ttyUSB*", ATTRS{serial}=="xxx", ATTRS{idVendor}=="xxx", ATTRS{idProduct}=="xxx", MODE:="0777(port permission)" ,SYMLINK+="(custom name)"

Fill in the corresponding information correctly, finally save and exit the file, and execute:

linux@ubuntu:~$ service udev reload
root privileges required
linux@ubuntu:~$ service udev restart
linux@ubuntu:~$ ls /dev
agpgart loop1 sg1 tty32 tty7 ttyS9
autofs loop2 shm tty33 tty8 ttyUSB0
block loop3 snapshot tty34 tty9 ttyUSB1
BLUETOOCH loop4 snd tty35 ttyprintk ttyUSB2
....
CH110 mcelog tty0 tty40 ttyS13 vcs1
....
Hi226 rfkill tty22 tty54 ttyS27 vfio
....

Now you can see that the custom usb port name has come out. When operating, just operate the corresponding device file directly, and don’t need to pay attention to the port number.