Skip to content

Viser Manipulation Module#2413

Open
TomCC7 wants to merge 8 commits into
mainfrom
cc/viser-vis
Open

Viser Manipulation Module#2413
TomCC7 wants to merge 8 commits into
mainfrom
cc/viser-vis

Conversation

@TomCC7
Copy link
Copy Markdown
Member

@TomCC7 TomCC7 commented Jun 6, 2026

Problem

Going to replace the drake meshcat and provide a moveit style console.

Closes #2412

Solution

  1. Viser as a dimos module
  2. most of communication through rpc
  3. moveit style dragging and plan-review-execute
  4. small issue: ik kind of slow (currently through rpc to manipulation module), not sure it's rpc or ik impl issue
image

How to Test

uv run --extra manipulation-viser dimos run xarm7-viser-panel-mock

Contributor License Agreement

  • I have read and approved the CLA.

@greptile-apps
Copy link
Copy Markdown
Contributor

greptile-apps Bot commented Jun 6, 2026

Greptile Summary

This PR introduces ViserManipulationPanelModule, a new Viser-based operator panel for robot manipulation that replaces the Drake/Meshcat visualizer. Communication flows through RPC to the existing ManipulationModule, implementing a MoveIt-style drag-IK → plan → review → execute workflow.

  • Adds the full viser_panel package (module, backend, gui, scene, state, animation, controller) with session state management, debounced preview requests, and a poll loop that drives GUI updates.
  • Extends ManipulationModule with read-only RPC endpoints (evaluate_pose_target, evaluate_joint_target, get_planned_path_poses, list_robots) and adds a xarm7_viser_panel_mock blueprint wiring ManipulationModule + ControlCoordinator + ViserManipulationPanelModule together.

Confidence Score: 4/5

Safe to merge for initial use; one restart scenario leaves the preview worker permanently silent but normal single-lifecycle operation is unaffected.

The new PreviewWorker has start() and stop() methods but stop() does not clear _thread or _stop_event, so a module stop-then-restart leaves the worker inert with no error. All interactive features (drag-IK, plan, execute) depend on the worker and would silently do nothing after a restart. Every other concern from prior reviews (action_status mutation race, thread accumulation, wrong path coordinates, dead callback registration) appears to have been addressed in this version.

dimos/manipulation/viser_panel/state.py — PreviewWorker.stop() needs to reset _thread and _stop_event before the worker can be safely restarted.

Important Files Changed

Filename Overview
dimos/manipulation/viser_panel/module.py Core panel module: 700-line orchestrator wiring backend RPC, GUI, scene, and controller. Well-structured locking strategy with self._lock (RLock) guarding session state in the poll thread; operation threads run RPC calls outside the lock (intentional). Potential silent preview breakage on restart due to PreviewWorker restart bug.
dimos/manipulation/viser_panel/state.py Defines all state enums, dataclasses, and PreviewWorker. PreviewWorker.stop() leaves _thread and _stop_event dirty, preventing restart. can_execute() now correctly accepts an explicit action_status parameter instead of mutating shared state (addressing a previous review concern).
dimos/manipulation/viser_panel/backend.py PanelBackend wraps RPC-client lifecycle with a preview-busy guard that prevents stacking concurrent IK calls — directly addresses the thread-accumulation concern from a prior review. close() assigns self.client = None outside _preview_lock, but this is only called after the poll and preview threads are already joined.
dimos/manipulation/viser_panel/scene.py Scene management for URDF rendering and path visualization. render_plan_path now correctly uses Cartesian end-effector poses from FK (fixing the wrong-coordinate path visualization flagged in a previous review).
dimos/manipulation/viser_panel/gui.py GUI builder and state-updater. Uses sync_source sentinel to suppress re-entrant callbacks when programmatically updating sliders or the EE transform control; the try/finally pattern correctly resets sync_source even on exception.
dimos/manipulation/viser_panel/animation.py Joint-path interpolation and PreviewAnimator. Clean implementation; appends the exact final waypoint to guard against floating-point drift at path_t=1.0.
dimos/manipulation/manipulation_module.py Adds evaluate_pose_target, evaluate_joint_target, get_planned_path_poses, and list_robots RPC endpoints to support the Viser panel without mutating any planner state.
dimos/manipulation/blueprints.py Adds xarm7_viser_panel_mock blueprint (ManipulationModule + ControlCoordinator + ViserManipulationPanelModule) and updates all to include it — the omission raised in a prior review has been resolved.

Sequence Diagram

sequenceDiagram
    participant User as Operator (Browser)
    participant ViserPanel as ViserManipulationPanelModule
    participant PreviewWorker as PreviewWorker thread
    participant PollThread as Poll thread
    participant Backend as PanelBackend
    participant Manip as ManipulationModule (RPC)

    User->>ViserPanel: drag EE control
    ViserPanel->>PreviewWorker: submit(PreviewRequest, sequence_id)
    PreviewWorker->>Backend: call_preview_with_timeout(evaluate_pose_target)
    Backend->>Manip: evaluate_pose_target(pose, robot)
    Manip-->>Backend: "{success, joint_state, collision_free}"
    Backend-->>PreviewWorker: result dict
    PreviewWorker->>ViserPanel: _apply_preview_result (acquires _lock)
    ViserPanel->>ViserPanel: update ghost URDF joints + feasibility

    User->>ViserPanel: click Plan
    ViserPanel->>ViserPanel: _run_operation(Plan) new thread
    ViserPanel->>Manip: plan_to_joints / plan_to_pose
    Manip-->>ViserPanel: True/False
    ViserPanel->>Manip: get_planned_path + get_planned_path_poses
    Manip-->>ViserPanel: JointPath + [Pose]
    ViserPanel->>ViserPanel: render_plan_path (line segments in scene)

    User->>ViserPanel: click Execute
    ViserPanel->>ViserPanel: _can_execute_for_operation() check
    ViserPanel->>Manip: execute(robot)
    Manip-->>ViserPanel: accepted

    PollThread->>ViserPanel: _refresh_panel_state_impl (every 1/poll_hz s)
    ViserPanel->>Manip: list_robots, get_current_joints, get_ee_pose, get_state
    Manip-->>ViserPanel: current state
    ViserPanel->>ViserPanel: update GUI labels + enable/disable buttons
Loading

Reviews (3): Last reviewed commit: "fix: avoid execute gate action status ra..." | Re-trigger Greptile

Comment thread dimos/manipulation/viser_panel/module.py Outdated
Comment thread dimos/manipulation/viser_panel/scene.py Outdated
Comment thread dimos/manipulation/viser_panel/backend.py
Comment thread dimos/manipulation/viser_panel/module.py Outdated
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.

Viser Manipulation Control Panel

1 participant