A ROS 2 Humble human-following stack built for dual UWB PDOA anchors and a wearable tag.
UWB Follower is a pure-UWB following project for differential-drive robots. It uses:
2 x ULM3-PDOAanchors mounted on the robot front and rear1 x ULM3-SHwearable tag carried by the target person0extra sensors for following control
The system reads vendor PDOA serial frames, estimates the target pose in the robot base_link frame, and publishes a standard /cmd_vel command for downstream motor control.
- Pure UWB following without relying on camera, lidar, or GPS
- Dual-anchor layout for forward/rear target awareness
- ROS 2 native interfaces:
/uwb/target_pose_raw/uwb/target_pose/cmd_vel
- Clean package split:
- localization package for serial parsing and target pose estimation
- controller package for following logic and velocity generation
- Works on regular Ubuntu PCs and Jetson devices running ROS 2 Humble
flowchart LR
A0[Front ULM3-PDOA] --> L[uwb_follower_localization]
A1[Rear ULM3-PDOA] --> L
T[ULM3-SH Tag] -. measured by .-> A0
T -. measured by .-> A1
L -->|PoseStamped| P1[/uwb/target_pose_raw/]
L -->|PoseStamped| P2[/uwb/target_pose/]
P2 --> C[uwb_follower_controller]
C -->|Twist| CMD[/cmd_vel/]
UWB_Follower/
├── src/
│ ├── uwb_follower_localization/
│ │ ├── config/localization.yaml
│ │ ├── launch/uwb_localization.launch.py
│ │ └── src/
│ └── uwb_follower_controller/
│ ├── config/controller.yaml
│ ├── launch/uwb_follower_controller.launch.py
│ ├── launch/uwb_follow_bringup.launch.py
│ └── src/
└── README.md
The target pose is published in the robot base_link frame:
x > 0: target is in front of the robotx < 0: target is behind the roboty > 0: target is on the robot left sidey < 0: target is on the robot right side
This convention is important when installing anchors and tuning aoa_sign.
Recommended physical layout:
- front anchor mounted at the robot front center, facing forward
- rear anchor mounted at the robot rear center, facing backward
- wearable tag carried on the person being followed
- anchors connected to the host through USB serial or TTL UART
Recommended first-test conditions:
- open indoor area
- clear line of sight between anchors and tag
- low robot speed
- no nearby metal obstruction if possible
- Ubuntu 22.04
- ROS 2 Humble
colcon- standard ROS 2 C++ build environment
Tested target environments:
- x86_64 Ubuntu with ROS 2 Humble
- Jetson AGX Orin with ROS 2 Humble
From the repository root:
source /opt/ros/humble/setup.bash
colcon build --symlink-install
source install/setup.bashEdit these two files:
- src/uwb_follower_localization/config/localization.yaml
- src/uwb_follower_controller/config/controller.yaml
At minimum, verify:
- serial port names for front and rear anchors
- anchor mounting positions relative to
base_link - anchor mounting yaw angles
- desired following distance
- speed limits suitable for your robot
source /opt/ros/humble/setup.bash
source install/setup.bash
ros2 launch uwb_follower_controller uwb_follow_bringup.launch.py| Topic | Type | Description |
|---|---|---|
/uwb/target_pose_raw |
geometry_msgs/msg/PoseStamped |
Raw target pose estimated from UWB observations |
/uwb/target_pose |
geometry_msgs/msg/PoseStamped |
Filtered target pose used by the controller |
/cmd_vel |
geometry_msgs/msg/Twist |
Robot velocity command generated by the follow controller |
| Launch File | Purpose |
|---|---|
uwb_localization.launch.py |
Run localization only |
uwb_follower_controller.launch.py |
Run controller only |
uwb_follow_bringup.launch.py |
Run localization and controller together |
Responsibilities:
- open front and rear serial ports
- parse vendor
MPxxxx,...PDOA frames - convert range and AOA into target points in
base_link - fuse front and rear observations
- publish raw and filtered
PoseStamped
Package README:
Responsibilities:
- subscribe to
/uwb/target_pose - compute
linear.xandangular.z - support front-following and behind-target turn-around behavior
- ramp output back to zero when target data becomes stale
Package README:
Recommended bringup order:
- Connect only the front anchor first
- Verify the serial device exists:
ls -l /dev/ttyUSB* /dev/ttyACM* 2>/dev/null- Verify raw pose output:
ros2 topic echo /uwb/target_pose_raw-
Check left/right correctness:
- target on the left should give
y > 0 - target on the right should give
y < 0
- target on the left should give
-
Connect the rear anchor and repeat verification
-
Finally inspect:
ros2 topic echo /uwb/target_pose
ros2 topic echo /cmd_velRecommended low-risk first values:
max_linear_speed_mps: 0.25max_reverse_speed_mps: 0.10max_angular_speed_rps: 0.80desired_distance_m: 1.20position_lowpass_alpha: 0.30
Typical tuning order:
- Fix serial ports and confirm data is flowing
- Fix left/right sign using
front.aoa_signandrear.aoa_sign - Fix anchor positions and yaw angles
- Tune target smoothing with
position_lowpass_alpha - Tune angular response with
angular_kpandbehind_angular_kp - Tune distance response with
linear_kp - Raise speed limits gradually
This means the OS did not create the expected serial device. Check:
- USB cable is a data cable, not charge-only
lsusbdmesg -wlsmod | grep -E 'ch34|usbserial|cp210x|ftdi'- whether
brlttyis occupying CH340/CH341 devices
On Jetson and Ubuntu systems, this is often caused by:
- wrong serial device name
- CH340 driver not bound
brltty-udev.servicegrabbing the USB serial device
Check:
- the tag is powered on and actively transmitting
- the anchor is facing the tag
target_tag_idis not filtering out the real tagmin_range_mis not too large- serial data is actually coming from the device
Check:
/uwb/target_poseis updating- target is not stale
- target is not already inside distance and heading deadbands
- the controller is subscribed to the correct pose topic
This repository is focused on following behavior, not full autonomous navigation.
Please note:
- there is no obstacle avoidance in this stack
- pure UWB following can be affected by multipath and occlusion
- low speed is strongly recommended for first tests
- use open space and keep a hardware emergency stop available
If you plan to publish this repository on GitHub, it is recommended to:
- remove
build/,install/, andlog/before pushing - add a project-level
LICENSEfile - add real photos, demo GIFs, or test videos
- document your exact robot base and wiring setup
- License: MIT
- Contribution guide: CONTRIBUTING.md
This project was developed with guidance from:
- vendor ULM3-PDOA / follow-auto manuals and example ROS drivers
eth-ait/uwb_tracker_roscliansang/uwb-tracking-rosnooploop-dev/nlink_parserTIERS/ros-dwm1001-uwb-localizationfcaponetto/robot-follow-path-uwbjiaying001/AGV-UWB-localizatoin-and-navigation
This implementation is tailored to the ULM3-PDOA + ULM3-SH hardware combination and ROS 2 Humble workflow used in this project.