Free worldwide shiping on $150+

Tutorial: Connect Robot Vacuum Cleaner to ROS 2 – Proscenic M6 Pro
Turn a Proscenic M6 Pro robot vacuum into a ROS 2 robot: root it over ADB, flash the open-source SangamIO firmware, and bridge its LiDAR, odometry and motors into ROS 2 Jazzy as /scan, /odom and /cmd_vel.
A robot vacuum is one of the cheapest ways to get a real mobile robot: differential-drive motors with wheel encoders, a spinning 360° LiDAR, an IMU, bumpers, cliff sensors and a battery — all for the price of an appliance. In this tutorial we turn a Proscenic M6 Pro into a ROS 2 robot. By the end, the vacuum’s LiDAR, odometry, IMU and motors show up as standard ROS 2 topics like /scan, /odom and /cmd_vel that you can drive, visualize in RViz, and run SLAM or Nav2 on.

Heads up — this is an advanced, experimental project. Rooting the vacuum and replacing its firmware voids the warranty, can brick the device, and relies on community reverse-engineering. Do it only on a unit you’re happy to tinker with, and at your own risk.
Huge credit to codetiger’s VacuumTiger project, which reverse-engineered the Proscenic / 3irobotix CRL-200S hardware and wrote the open-source on-device firmware (SangamIO, DhruvaSLAM, Drishti) we deploy here. The ROS 2 bridge is remake.ai’s vacuum_ros2_bridge.
What you’ll need
- A Proscenic M6 Pro (built on the 3irobotix CRL-200S platform — Allwinner SoC running TinaLinux). Other CRL-200S-based vacuums are similar.
- A micro-USB cable — the M6 Pro exposes ADB on its USB port, so no soldering or teardown is required.
- A PC with Ubuntu 24.04 (native install recommended for the ROS 2 side). Windows 10/11 users can do the rooting and firmware build under WSL2.
- ROS 2 Jazzy on the Ubuntu side.
- ADB (Android platform-tools) and the Rust toolchain with an ARM cross-compiler (to build the firmware).
How the pieces fit together
Two small programs do all the work:
- On the vacuum — SangamIO: a tiny daemon (part of VacuumTiger) that talks to the GD32 motor controller and the LiDAR over the robot’s internal serial ports, and exposes everything over TCP port 5555.
- On your PC — vacuum_ros2_bridge: a ROS 2 Jazzy node that connects to SangamIO over your network and republishes the data as ROS 2 topics, services and TF.
Proscenic M6 Pro (SangamIO, TCP 5555) <--> Wi-Fi / LAN <--> PC (vacuum_ros2_bridge) <--> ROS 2Step 1 — Get a root ADB shell
The M6 Pro conveniently exposes an Android Debug Bridge (ADB) interface on its micro-USB port, with root access out of the box. Plug the vacuum into your PC with a micro-USB cable and pick your OS below.
Windows
Download the Android platform-tools, unzip them to a folder such as C:\Users\you\adb, then in PowerShell:
cd C:\Users\you\adb
.\adb.exe devicesYou should see your vacuum listed with a serial number:
List of devices attached
20080411 deviceOpen a shell on the vacuum (you’ll land on its TinaLinux system as root):
.\adb.exe shellUbuntu
sudo apt update
sudo apt install adb # or: android-tools-adb android-tools-fastboot
adb version
adb kill-server
sudo adb start-server
adb devices
adb shellMake the root shell stick
By default the ADB shell can drop into a bare-bones environment. Install a proper root login profile so every adb shell gives you a full root shell. On your PC, create a file named adb_shell containing:
#!/bin/sh
export ENV='/etc/adb_profile'
exec /bin/sh "$@"Then make it executable and push it onto the vacuum:
chmod +x adb_shell
adb push ./adb_shell /bin/adb_shellIf your unit has a root password set, clear it from inside the vacuum’s shell so SSH and console login work without prompting:
passwd -d rootStep 2 — Put the vacuum on Wi-Fi and enable SSH
So the robot can roam without a USB tether, get it onto your Wi-Fi and turn on its SSH server. Run these inside the vacuum’s shell (via adb shell):
cat > /etc/wifi/wpa_supplicant.conf << 'EOF'
update_config=1
ctrl_interface=/etc/wifi/sockets
network={
ssid="YOUR_WIFI_SSID"
psk="YOUR_WIFI_PASSWORD"
key_mgmt=WPA-PSK
}
EOF
rm -f /etc/wifi/sockets/wlan0
killall wpa_supplicant
wpa_supplicant -B -i wlan0 -c /etc/wifi/wpa_supplicant.conf
udhcpc -i wlan0
# Note the vacuum's IP address:
ip addr show wlan0Enable the Dropbear SSH server so you can reach the vacuum wirelessly:
/etc/init.d/dropbear start
/etc/init.d/dropbear enable
pidof dropbearDropbear uses legacy algorithms, so connect from your PC with a few extra options (replace <VACUUM_IP> with the address from above):
ssh -o HostKeyAlgorithms=+ssh-rsa -o PubkeyAcceptedAlgorithms=+ssh-rsa -o MACs=+hmac-sha1 root@<VACUUM_IP>You can now unplug the USB cable — the rest of the work happens over the network.
Get new tutorials by email
Step 3 — Build and deploy the SangamIO firmware
SangamIO is cross-compiled for the vacuum’s ARM CPU. Building needs a Linux toolchain — do this on Ubuntu, or in a WSL2 Ubuntu shell on Windows. First, install Rust and the ARM target:
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh
source ~/.cargo/env
rustup target add armv7-unknown-linux-musleabihfInstall a musl ARM cross-compiler:
cd /opt
sudo wget https://musl.cc/armv7l-linux-musleabihf-cross.tgz
sudo tar xzf armv7l-linux-musleabihf-cross.tgz
echo 'export PATH="/opt/armv7l-linux-musleabihf-cross/bin:$PATH"' >> ~/.bashrc
source ~/.bashrc
cd /opt/armv7l-linux-musleabihf-cross/bin
sudo ln -s armv7l-linux-musleabihf-gcc armv7-unknown-linux-musleabihf-gccClone VacuumTiger and build SangamIO:
sudo apt install protobuf-compiler
git clone https://github.com/codetiger/VacuumTiger.git
cd VacuumTiger/sangam-io
cargo build --release --target armv7-unknown-linux-musleabihfPush the binary and its config onto the vacuum, and make it executable:
adb push target/armv7-unknown-linux-musleabihf/release/sangam-io /usr/sbin/sangamio
adb push sangamio.toml /etc/sangamio.toml
adb shell chmod +x /usr/sbin/sangamioThe default sangamio.toml is set up for the CRL-200S (serial ports /dev/ttyS3 for the motor controller and /dev/ttyS1 for the LiDAR, listening on 0.0.0.0:5555). You shouldn’t need to change it for an M6 Pro.
Step 4 — Start SangamIO on the vacuum
The stock firmware holds the serial ports open, so stop it first, then launch SangamIO (inside the vacuum’s shell):
killall robotManager AuxCtrl Monitor everest-server 2>/dev/null
RUST_LOG=info /usr/sbin/sangamioYou should see it initialize the motor controller and LiDAR and open its TCP server:
[INFO sangam_io] Device: CRL-200S Vacuum Robot
[INFO sangam_io::devices::crl200s] Opening GD32 port /dev/ttyS3
[INFO sangam_io::devices::crl200s] Opening lidar port /dev/ttyS1
[INFO sangam_io::devices::crl200s::gd32] GD32 responded - initialization successful
[INFO sangam_io::devices::crl200s::lidar] Lidar motor started
[INFO sangam_io::streaming] TCP server listening on 0.0.0.0:5555Leave it running. (To run it in the background, append > /tmp/sangamio.log 2>&1 &; to start it automatically on boot, the VacuumTiger deployment guide includes an /etc/init.d/sangamio service script.) Your vacuum is now a robot server on TCP port 5555.
Step 5 — Install ROS 2 Jazzy and the bridge
Switch to your PC. Install ROS 2 Jazzy on Ubuntu 24.04 by following the official install guide, then clone and build the bridge in a colcon workspace:
mkdir -p ~/ros2_ws/src
cd ~/ros2_ws/src
git clone https://github.com/remakeai/vacuum_ros2_bridge
cd ~/ros2_ws
colcon build --packages-select vacuum_ros2_bridge
source install/setup.bashWSL2 note: ADB and the firmware build work fine under WSL2, but ROS 2 networking to the vacuum is smoothest on a native Ubuntu install or a dedicated Linux PC.
Step 6 — Configure and launch the bridge
Point the bridge at your vacuum’s IP address (the one from Step 2). You can pass it on the command line:
ros2 launch vacuum_ros2_bridge bridge.launch.py robot_ip:=192.168.1.143…or edit config/bridge_params.yaml and set robot_ip permanently. The default port (5555) matches SangamIO. If it connects, the bridge starts streaming topics immediately.
How LiDARs are used in self-driving robots?
Build a real LiDAR self-driving Arduino/ROS2 robot using our kit - with complete step-by-step instructions. No robotics experience necessary.
See the full robot kit →Step 7 — See your vacuum in ROS 2
In another sourced terminal, confirm the topics are live:
ros2 topic list
ros2 topic echo /scan
ros2 topic echo /odomIf /scan is empty, make sure the LiDAR motor is spinning:
ros2 service call /set_lidar vacuum_ros2_bridge/srv/SetLidar "{enable: true}"Drive it around with the keyboard:
sudo apt install ros-jazzy-teleop-twist-keyboard
ros2 run teleop_twist_keyboard teleop_twist_keyboard…and even run the actual vacuum motor and brushes through ROS 2 services:
ros2 service call /set_actuator vacuum_ros2_bridge/srv/SetActuator "{component: 'vacuum', speed: 50}"
ros2 service call /set_actuator vacuum_ros2_bridge/srv/SetActuator "{component: 'main_brush', speed: 80}"Here’s what the bridge exposes:
- Published:
/scan(LaserScan),/imu,/odom,/battery,/bumper,/cliff,/vacuum_status - Subscribed:
/cmd_vel(drive),/actuator_cmd,/led_cmd - Services:
/set_actuator,/set_led,/set_lidar - TF:
odom→base_link→laser
Step 8 — Where to go next
- Visualize in RViz: set the fixed frame to
odomand add a LaserScan display on/scanto watch the room appear. - Build a map (SLAM): the bridge publishes standard
/scanand/odom, soslam_toolboxworks out of the box:sudo apt install ros-jazzy-slam-toolbox. - Autonomous navigation: feed the map into Nav2. Fuse the IMU with
robot_localizationto tame wheel-odometry drift. - On-device SLAM: VacuumTiger also ships DhruvaSLAM and the Drishti visualizer that run on the vacuum itself — a fun alternative to the ROS 2 stack.
Troubleshooting
- ADB device offline / not listed:
adb kill-serverthensudo adb start-serverand reconnect the cable. - SangamIO can’t open
/dev/ttyS3: the stock firmware is still running —killall AuxCtrl(androbotManager Monitor everest-server) to free the serial ports. - No
/scandata: enable the LiDAR motor with the/set_lidarservice and listen for it spinning up. - Bridge can’t connect:
ping <VACUUM_IP>, confirm SangamIO is still running, and make sure the PC and vacuum are on the same subnet with TCP 5555 unblocked. - Odometry drifts: it’s wheel-encoder-only — fuse with the IMU via
robot_localizationfor better localization.
Source code and credits
- VacuumTiger by codetiger — on-device firmware (SangamIO, DhruvaSLAM, Drishti) and the CRL-200S reverse engineering this tutorial stands on.
- VacuumRobot by codetiger — the underlying hardware/protocol research.
- vacuum_ros2_bridge by remake.ai — the ROS 2 Jazzy bridge.
New to ROS 2 and robotics? Our build-a-robot crash course is a gentler place to start — no rooting required.