Drive a Husarion ROSbot (XL or 3) from a RadioMaster TX16S over ExpressLRS, using a Holybro Pixhawk 6X Pro as RC receiver, industrial-grade IMU, and (later) GPS/position co-processor — without replacing the robot's existing motor controller.
The pipeline: TX16S sticks → ELRS 2.4 GHz → iFlight receiver → CRSF on Pixhawk TELEM2 → ArduPilot Rover → MAVLink over USB → mavros2 → rc_to_twist → twist_mux → /cmd_vel → wheels. Link-loss, e-stop, disarm, and process-death failsafes all stop the robot within ~1 s.
The full engineering write-up — every wiring decision cited, every parameter explained, and the traps we hit so you don't have to — is in docs/article.md. This README is the short operational path.
If your robot shipped from Husarion together with the TX16S and the receiver, the radios are already flashed (ExpressLRS 3.5.2, correct regulatory domain for your region) and bound to each other. You do not need any radio firmware work. Your path is:
- Wire the receiver to the Pixhawk
TELEM2port (6-pin JST-GH) — four wires, cross-over on TX/RX. Table below; photos and rationale in docs/rx-to-pixhawk-wiring.md. - Connect the Pixhawk to the robot's computer with the USB-C cable.
- Run the one-shot install (next section).
- Set up the TX16S model and do the first drive — follow FIRST-DRIVE-CHECKLIST.md top to bottom.
| iFlight RX pad | → | TELEM2 pin |
Signal |
|---|---|---|---|
| VCC (5V) | → | 1 | VCC +5 V |
| RX | → | 2 | TX5 (FC out) — cross-over |
| TX | → | 3 | RX5 (FC in) — cross-over |
| GND | → | 6 | GND |
Do not use the 3-pin RC IN header — it is SBUS/PPM only and physically cannot carry CRSF. Details in docs/rx-to-pixhawk-wiring.md.
Requires Ubuntu 24.04 + ROS 2 Jazzy (stock on current ROSbots) and just (sudo apt install just).
cd ~
git clone https://github.com/husarion/rosbot-pixhawk-teleop.git
cd rosbot-pixhawk-teleop
just teleop-bootstrapThat chains: apt deps (mavros, twist_mux) → GeographicLib datasets → udev rule (/dev/pixhawk symlink) → systemd unit → ModemManager mask → ArduPilot Rover flash → parameter push → ROS 2 build → service enable. Each step is a separate just recipe — read the justfile to see exactly what runs, or run steps individually.
Before you run it, set robot_ns at the top of the justfile to your robot's ROS 2 namespace — the prefix you see on /cmd_vel in ros2 topic list (e.g. qwerty on the ROSbot XL we tested). Pass the same value to the launch via the service if it differs from the default.
Then day-to-day:
just teleop-status # service health
just teleop-check # end-to-end sanity (TX must be on)
just teleop-log # follow the journal
just teleop-restart # after config edits| Robot | Status | Notes |
|---|---|---|
| ROSbot XL | tested | Defaults in this repo match it (namespace qwerty on our unit, TwistStamped on /cmd_vel, Ubuntu 24.04 + Jazzy). |
| ROSbot 3 | same recipe | Verify your namespace (ros2 topic list) and whether /cmd_vel takes Twist or TwistStamped (ros2 topic info -v /<ns>/cmd_vel); flip use_stamped in ros2/pixhawk_teleop/config/twist_mux.yaml if needed. |
Per the official ExpressLRS LED reference: solid (any color) = bound and linked — the color encodes the packet rate, not status. Slow blink = waiting for TX, double-blink-pause = bind mode, fast blink = WiFi mode. Full table in docs/elrs-pairing.md.
Needed only if your TX and RX are not already paired — e.g. you bring your own radios, replace one end, or change the binding phrase or regulatory domain. Use the official ExpressLRS Configurator (desktop GUI): pick the hardware target, set your binding phrase and regulatory domain (ISM2G4 for FCC regions like US/Canada/AU, LBT for the EU — both ends must match or they will never bind), build, and flash each end over its WiFi access point.
The full walk-through — targets for this exact hardware, WiFi-mode triggers, bind verification, and the RX LED reference — is in docs/elrs-pairing.md. Treat the binding phrase like a password: anyone who knows it can control your robot.
| Path | Purpose |
|---|---|
| docs/article.md | The full write-up: architecture, wiring, ArduPilot params, ROS 2 stack, TX16S setup, all the traps. |
| FIRST-DRIVE-CHECKLIST.md | Physical bring-up: TX16S model, power-up order, failsafe verification on blocks, first drive. |
| docs/rx-to-pixhawk-wiring.md | Receiver → Pixhawk wiring with every claim cited; ArduPilot + PX4 parameter sets; SBUS fallback. |
| docs/elrs-pairing.md | ELRS binding theory + TX/RX flashing with the ExpressLRS Configurator + RX LED reference. |
| docs/teleop-spec.md | Design spec: decision log, failsafe matrix, acceptance criteria. |
| docs/troubleshooting.md | Symptom → cause → fix index. Check here first when something doesn't work. |
| ros2/pixhawk_teleop/ | The ROS 2 package: rc_to_twist node, launch file, mavros + twist_mux configs. |
| justfile | Every procedure in this repo as a runnable recipe. |
| system/, tools/ | udev rule, systemd unit, ArduPilot flash/param scripts. |
Apache-2.0. Built and published by Husarion — the company behind the ROSbot line of ROS 2-native mobile robots.

