Skip to content

feat: hosted teleop over Cloudflare RT#2411

Draft
ruthwikdasyam wants to merge 57 commits into
mainfrom
ruthwik/hosted-teleop
Draft

feat: hosted teleop over Cloudflare RT#2411
ruthwikdasyam wants to merge 57 commits into
mainfrom
ruthwik/hosted-teleop

Conversation

@ruthwikdasyam
Copy link
Copy Markdown
Contributor

@ruthwikdasyam ruthwikdasyam commented Jun 6, 2026

Detailed in #2372

Problem

Hosted Teleop setup for DimOS

Closes DIM-XXX

Solution

Add hosted teleop over WebRTC via a Cloudflare Realtime SFU broker: a HostedTeleopModule with cmd/state datachannels + a camera video track that drops into existing blueprints, plus a shared teleop/utils recording &
transport-stats stack (recorder, latency/jitter/loss report, VideoStats).

How to Test

dimos run teleop-hosted-go2 teleop-recorder

Contributor License Agreement

  • I have read and approved the CLA.

@ruthwikdasyam ruthwikdasyam changed the title Ruthwik/hosted teleop feat: hosted teleop over Cloudflare RT Jun 6, 2026
@codecov
Copy link
Copy Markdown

codecov Bot commented Jun 6, 2026

❌ 1 Tests Failed:

Tests completed Failed Passed Skipped
2121 1 2120 81
View the top 1 failed test(s) by shortest run time
dimos.e2e_tests.test_dimsim_path_replaning::test_path_replanning
Stack Traces | 240s run time
lcm_spy = <dimos.e2e_tests.lcm_spy.LcmSpy object at 0x7269281d4bc0>
start_blueprint = <function start_blueprint.<locals>.set_name_and_start at 0x726927721260>
dim_sim = <dimos.e2e_tests.dim_sim_client.DimSimClient object at 0x72692802d640>
direct_cmd_vel_explorer = <dimos.simulation.mujoco.direct_cmd_vel_explorer.DirectCmdVelExplorer object at 0x7269299a6840>
spawn_wall_on_pose = <function spawn_wall_on_pose.<locals>.spawn at 0x7269277220c0>

    @pytest.mark.self_hosted_large
    def test_path_replanning(
        lcm_spy, start_blueprint, dim_sim, direct_cmd_vel_explorer, spawn_wall_on_pose
    ) -> None:
        start_blueprint(
            "--dimsim-scene=empty",
            "run",
            "unitree-go2-agentic",
            simulator="dimsim",
        )
        lcm_spy.save_topic(".../McpClient/on_system_modules/res")
        lcm_spy.wait_for_saved_topic(".../McpClient/on_system_modules/res", timeout=1200.0)
    
        # robot spawns at (3, 2)
    
        # side wall
        dim_sim.add_wall(2, -2.5, 12, -2.5)
        # other side wall
        dim_sim.add_wall(2, 3.5, 12, 3.5)
        # back wall (behind robot)
        dim_sim.add_wall(2, -2.5, 2, 3.5)
        # forward wall (far end)
        dim_sim.add_wall(12, -2.5, 12, 3.5)
        # dividing wall at x=7 with doors at y=[-1.5,-0.5] and y=[1.5,2.5]
        dim_sim.add_wall(7, -2.5, 7, -1.5)
        dim_sim.add_wall(7, -0.5, 7, 1.5)
        dim_sim.add_wall(7, 2.5, 7, 3.5)
    
        direct_cmd_vel_explorer.linear_speed = 0.8
        direct_cmd_vel_explorer.follow_points([(10, 2), (2.5, 2), (3, 2)])
    
        # When the robot comes within 1.5 m of the left door's centre, drop a wall
        # in the opening so the planner has to bail out and route through the
        # right door at y=-1 instead.
        spawn_wall_on_pose(
            point=(7, 2),
            threshold=1.5,
            wall=(7, 1.5, 7, 2.5),
        )
    
        dim_sim.publish_goal(10.913, 0.588)
    
>       lcm_spy.wait_until_odom_position(10.913, 0.588, threshold=1, timeout=120)

dim_sim    = <dimos.e2e_tests.dim_sim_client.DimSimClient object at 0x72692802d640>
direct_cmd_vel_explorer = <dimos.simulation.mujoco.direct_cmd_vel_explorer.DirectCmdVelExplorer object at 0x7269299a6840>
lcm_spy    = <dimos.e2e_tests.lcm_spy.LcmSpy object at 0x7269281d4bc0>
spawn_wall_on_pose = <function spawn_wall_on_pose.<locals>.spawn at 0x7269277220c0>
start_blueprint = <function start_blueprint.<locals>.set_name_and_start at 0x726927721260>

dimos/e2e_tests/test_dimsim_path_replaning.py:60: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 
dimos/e2e_tests/lcm_spy.py:182: in wait_until_odom_position
    self.wait_for_message_result(
        predicate  = <function LcmSpy.wait_until_odom_position.<locals>.predicate at 0x726927722ac0>
        self       = <dimos.e2e_tests.lcm_spy.LcmSpy object at 0x7269281d4bc0>
        threshold  = 1
        timeout    = 120
        x          = 10.913
        y          = 0.588
dimos/e2e_tests/lcm_spy.py:168: in wait_for_message_result
    self.wait_until(
        event      = <threading.Event at 0x726927604560: unset>
        fail_message = 'Failed to get to position x=10.913, y=0.588'
        listener   = <function LcmSpy.wait_for_message_result.<locals>.listener at 0x726927722b60>
        predicate  = <function LcmSpy.wait_until_odom_position.<locals>.predicate at 0x726927722ac0>
        self       = <dimos.e2e_tests.lcm_spy.LcmSpy object at 0x7269281d4bc0>
        timeout    = 120
        topic      = '/odom#geometry_msgs.PoseStamped'
        type       = <class 'dimos.msgs.geometry_msgs.PoseStamped.PoseStamped'>
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

self = <dimos.e2e_tests.lcm_spy.LcmSpy object at 0x7269281d4bc0>

    def wait_until(
        self,
        *,
        condition: Callable[[], bool],
        timeout: float,
        error_message: str,
        poll_interval: float = 0.1,
    ) -> None:
        start_time = time.time()
        while time.time() - start_time < timeout:
            if condition():
                return
            time.sleep(poll_interval)
>       raise TimeoutError(error_message)
E       TimeoutError: Failed to get to position x=10.913, y=0.588

condition  = <bound method Event.is_set of <threading.Event at 0x726927604560: unset>>
error_message = 'Failed to get to position x=10.913, y=0.588'
poll_interval = 0.1
self       = <dimos.e2e_tests.lcm_spy.LcmSpy object at 0x7269281d4bc0>
start_time = 1780782505.6478946
timeout    = 120

dimos/e2e_tests/lcm_spy.py:105: TimeoutError

To view more test analytics, go to the Test Analytics Dashboard
📋 Got 3 mins? Take this short survey to help us improve Test Analytics.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant