Skip to main content

Overview

https://github.com/user-attachments/assets/5769819d-2a6d-4df5-94b2-a1d8380427e4

An self-charging routine for Stretch 4 that docks the robot in under 20 seconds, while avoiding obstacles, during daytime or night, and functions on a variety of floorings and room layouts. I describe how it works in this blog post. We welcome feedback in Github Issues or on the forum.

Quickstart

  1. pip3 install hello-robot-stretch4-docking

  2. Setup the Jetson Coming soon

  3. Put a docking station near the robot

    Robot near dock
  4. Use the CLI

    stretch_autodock
    
  5. Use the ROS2 docking servers

    Create a map and ensure Nav2 is working. Then:

    Coming Soon
    # ros2 launch stretch_nav2 autodocking_cpu.launch.py
    # # In a separate terminal:
    # cd stretch_nav2
    # rviz2 -d rviz/autodocking_panel.rviz
    

Assumptions

  1. Robot and dock is on flat level ground
  2. Dock is flat against a single wall, with free space to the left and right of the dock
  3. Robot should not see 2 docks at the same time (they can be in different rooms)
  4. Robot's arm must be stowed (retracted and lowered)

Edge cases (!)

These edge cases are not supported currently. The robot may exhibit bad behavior under these conditions!

  1. Object on dock Object on dock
  2. Object below dock
  3. Multiple docks in scene

Developing

Single vs. Dual Return

Each LiDAR's "return mode" can configured using the pyhesai wrapper. Typically, a LiDAR either returns its strongest reading (single return) or last & strongest (dual return). This means the LiDARs report double the data in dual return mode, typ. ~230400 points.

Profiling stretch_autodock CLI, we found total latency (cloud in -> control out) dropped from an average of 49.95 ms (Dual) to 34.76 ms (Single), resulting in a ~30% computation overhead reduction.

  • Average dock ID-ing processing step decreased from 10.52 ms to 6.57 ms (~38% decrease).
  • Average ring filtering processing step decreased from 21.90 ms to 16.28 ms (~26% decrease).
  • Average costmap building processing step decreased from 15.10 ms to 10.07 ms (~33% decrease).

Rate Stability increased. Both configurations successfully maintain 10.0 Hz control, but the single return mode exhibits much higher frame rate stability (standard deviation of 0.02 Hz versus 0.15 Hz).

Rate stability and total latency directly affect the quality of motion during docking. If it's too high (>100ms), you'll see weird behavior from the routine. So if your LiDARS are configured for dual-return mode, stretch_autodock temporarily switches them to single-return for the duration of the routine. The ROS2 docking servers do not do this since developers may have concurrently running nodes that need the second set of returns. You can see which return mode your LiDARs are in using REx_hesai_show_config. To change it programmatically:

from stretch4_pyhesai_wrapper.ptc_client import (
    LEFT_LIDAR_IP,
    RIGHT_LIDAR_IP,
    get_return_mode,
    set_return_mode,
    RETURN_MODE_NAMES,
)

# Set LiDARs to single-return if needed
lmode = get_return_mode(LEFT_LIDAR_IP)
rmode = get_return_mode(RIGHT_LIDAR_IP)
modes_before = None
if RETURN_MODE_NAMES.get(lmode, 'unknown') != 'strongest' or \
    RETURN_MODE_NAMES.get(rmode, 'unknown') != 'strongest':
    modes_before = (lmode, rmode)
    set_return_mode(LEFT_LIDAR_IP, 1) # 1 -> strongest
    set_return_mode(RIGHT_LIDAR_IP, 1)

# Change it back if needed
if modes_before is not None:
    lmode, rmode = modes_before
    set_return_mode(LEFT_LIDAR_IP, lmode)
    set_return_mode(RIGHT_LIDAR_IP, rmode)

ROS2

Coming Soon

Building your own docking pipeline (Advanced)

You can identify a dock and track it using:

from stretch4_docking.trackers import DockTracker, DockAmbiguityError

tracker = DockTracker()
tracker.warm_start()  # compiles on first run, loads from cache afterwards

try:
    tracker.identify(points) # Nx4 (x,y,z,intensity)
except DockAmbiguityError as e:
    print('Only 1 dock allowed per room')

if tracker.is_tracking():
    print(tracker.get_pose()) # SE(3) pose as (x, y, z, qx, qy, qz, qw)

You can build a egocentric costmap using:

from stretch4_docking.costmap import Costmap, RingFilter, LIDAR_LEFT_ORIGIN, LIDAR_RIGHT_ORIGIN

ring_filter = RingFilter()
ring_filter.warm_start()

costmapper = Costmap()
costmapper.warm_start()

left = ring_filter.process(left_frame.points, sensor_origin=LIDAR_LEFT_ORIGIN)
right = ring_filter.process(right_frame.points, sensor_origin=LIDAR_RIGHT_ORIGIN)
filtered_xyz = np.vstack([left[:, :3], right[:, :3]])
costmap = costmapper.process(filtered_xyz, dock_pose=tracker.get_pose())

You can servo (with collision awareness) using:

from stretch4_docking.costmap import filter_clearance_velocity
from stretch4_docking.servo import XYThetaServo

servo_law = XYThetaServo()

errx, erry, errt = error
vx, vy, wz = servo_law.step(errx, erry, errt)
filtered = filter_clearance_velocity(vx, vy, wz, costmap.obstacle_xy, costmap.cliff_xy)
robot.set_velocity(filtered.vx, filtered.vy, filtered.wz)
robot.push_command()

Metadata

Release files for hello-robot-stretch4-docking 2026.9.3

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for hello-robot-stretch4-docking 2026.9.3
File Size Uploaded
hello_robot_stretch4_docking-2026.9.3.tar.gz 24.9 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for hello-robot-stretch4-docking 2026.9.3
File Interpreter ABI Platform
hello_robot_stretch4_docking-2026.9.3-py3-none-any.whl Python 3 none any Details

Total release size: 59.1 kB

Release files / hello_robot_stretch4_docking-2026.9.3.tar.gz

Download URL hello_robot_stretch4_docking-2026.9.3.tar.gz
Size 24.9 kB
Tags Source
SHA-256 checksum
How to use checksums
7153127c5b8c99beca39c299229a94d7f93b4aa5e97ea10b8c686990603a872b
BLAKE2b-256 checksum
How to use checksums
0e2ec80499de687e2af30bad5c6c2941f7b05d6dd20d8f396f450030cdc7c7dd
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via uv/0.10.7 {"installer":{"name":"uv","version":"0.10.7","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}

Release files / hello_robot_stretch4_docking-2026.9.3-py3-none-any.whl

Download URL hello_robot_stretch4_docking-2026.9.3-py3-none-any.whl
Size 34.1 kB
Tags Python 3
SHA-256 checksum
How to use checksums
d3dace54f114101924c35a53717f3ee90aea1c75e11f98d317e4a284e729993e
BLAKE2b-256 checksum
How to use checksums
651b2b94b55cf70d72f848df399e7e6f2e50bccbd05625449312fa35d5216375
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via uv/0.10.7 {"installer":{"name":"uv","version":"0.10.7","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}

Release history Release notifications | RSS feed

This release

2026.9.3 This release

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page