Skip to content

feat: g1 quest teleop on shared dual-arm IK - #3436

Draft
TomCC7 wants to merge 10 commits into
cc/g1-smooth-bringupfrom
pim/feat/g1-quest-teleop-stacked
Draft

feat: g1 quest teleop on shared dual-arm IK#3436
TomCC7 wants to merge 10 commits into
cc/g1-smooth-bringupfrom
pim/feat/g1-quest-teleop-stacked

Conversation

@TomCC7

@TomCC7 TomCC7 commented Aug 11, 2026

Copy link
Copy Markdown
Member

Contribution path

Problem

The G1 Quest teleop branch duplicated the dual-arm IK task, relative-pose handling, and web UI that are now provided by the shared dual-arm teleop work. Keeping both implementations would leave two competing control paths and two UI protocols.

Solution

  • Replace the G1-only IK task with the shared teleop_ik task and Pink pose-target solver.
  • Keep only G1-specific model selection, controlled arm joints, task weights, posture weights, velocity limits, and frame names.
  • Reduce full-body Pinocchio models to their configured controlled joints so the G1 solver cannot satisfy hand targets through the waist or legs.
  • Extend the shared video arm teleop module with locomotion output and route it through MovementManager.
  • Preserve G1 camera streaming and episode recording, including controller Cartesian targets.
  • Remove the obsolete G1 Quest module, custom IK task, tests, and UI protocol. The shared UI now owns reference-pose capture and controller input semantics.

How to Test

dimos --simulation mujoco --scene-package office run unitree-g1-teleop

Validation:

  • 4,073 full-suite tests passed; 33 skipped; 282 deselected.
  • Pre-commit hooks passed.
  • Actual G1 URDF solver-reduction test passed under the self-hosted marker.

AI assistance

Codex with GPT-5 implemented the refactor and tests under human direction.

Checklist

  • I have read and approved the CLA.

@codecov

codecov Bot commented Aug 11, 2026

Copy link
Copy Markdown

❌ 1 Tests Failed:

Tests completed Failed Passed Skipped
4421 1 4420 177
View the top 1 failed test(s) by shortest run time
dimos.robot.unitree.g1.test_g1_teleop::test_g1_upper_body_model_keeps_waist_and_arms_but_removes_legs
Stack Traces | 3.15s run time
def test_g1_upper_body_model_keeps_waist_and_arms_but_removes_legs() -> None:
        config = g1_upper_body_model_config()
>       loaded = config.model.load()

config     = <[RuntimeError("Failed to pull LFS file .../dimos/data/.lfs/g1_urdf.tar.gz after 3 attempts: Comma...tar.gz', '--exclude=']' returned non-zero exit status 1.") raised in repr()] RobotModelConfig object at 0xffc60be833e0>

.../unitree/g1/test_g1_teleop.py:141: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 
.../robot/assets/model.py:191: in load
    return self._loaded
        self       = <[RuntimeError("Failed to pull LFS file .../dimos/data/.lfs/g1_urdf.tar.gz after 3 attempts: Comma..._urdf.tar.gz', '--exclude=']' returned non-zero exit status 1.") raised in repr()] RobotModel object at 0xffc647db54f0>
.../usr/lib/python3.12/functools.py:995: in __get__
    val = self.func(instance)
        cache      = {'_fixed_frames': (), '_fixed_joints': (), '_joint_position_limits': (), '_package_paths': (('g1_description', <[Runti...tar.gz', '--exclude=']' returned non-zero exit status 1.") raised in repr()] LfsPath object at 0xffc647e18850>),), ...}
        instance   = <[RuntimeError("Failed to pull LFS file .../dimos/data/.lfs/g1_urdf.tar.gz after 3 attempts: Comma..._urdf.tar.gz', '--exclude=']' returned non-zero exit status 1.") raised in repr()] RobotModel object at 0xffc647db54f0>
        owner      = <class 'dimos.robot.assets.model.RobotModel'>
        self       = <functools.cached_property object at 0xffc647dd77a0>
        val        = <object object at 0xffc6a3178290>
.../robot/assets/model.py:200: in _loaded
    package_paths = _normalize_package_paths(dict(self._package_paths))
        self       = <[RuntimeError("Failed to pull LFS file .../dimos/data/.lfs/g1_urdf.tar.gz after 3 attempts: Comma..._urdf.tar.gz', '--exclude=']' returned non-zero exit status 1.") raised in repr()] RobotModel object at 0xffc647db54f0>
        source_path = PosixPath('.../unitree/g1/g1.urdf')
.../robot/assets/model.py:489: in _normalize_package_paths
    package_name: Path(os.fspath(package_path)).resolve()
        package_paths = {'g1_description': <[RuntimeError("Failed to pull LFS file .../dimos/data/.lfs/g1_urdf.tar.gz afte...g1_urdf.tar.gz', '--exclude=']' returned non-zero exit status 1.") raised in repr()] LfsPath object at 0xffc647e18850>}
dimos/utils/data.py:379: in __fspath__
    return str(self._ensure_downloaded())
        self       = <[RuntimeError("Failed to pull LFS file .../dimos/data/.lfs/g1_urdf.tar.gz after 3 attempts: Comma.../g1_urdf.tar.gz', '--exclude=']' returned non-zero exit status 1.") raised in repr()] LfsPath object at 0xffc647e18850>
dimos/utils/data.py:353: in _ensure_downloaded
    cache = get_data(filename)
        cache      = None
        filename   = 'g1_urdf'
        self       = <[RuntimeError("Failed to pull LFS file .../dimos/data/.lfs/g1_urdf.tar.gz after 3 attempts: Comma.../g1_urdf.tar.gz', '--exclude=']' returned non-zero exit status 1.") raised in repr()] LfsPath object at 0xffc647e18850>
dimos/utils/data.py:310: in get_data
    archive_path = _decompress_archive(_pull_lfs_archive(archive_name))
        archive_name = 'g1_urdf'
        data_dir   = PosixPath('.../dimos/dimos/data')
        file_path  = PosixPath('.../dimos/dimos/data/g1_urdf')
        name       = 'g1_urdf'
        nested_path = None
        path_parts = ('g1_urdf',)
dimos/utils/data.py:254: in _pull_lfs_archive
    _lfs_pull(file_path, repo_root)
        file_path  = PosixPath('.../dimos/data/.lfs/g1_urdf.tar.gz')
        filename   = 'g1_urdf'
        repo_root  = PosixPath('.../work/dimos/dimos')
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

file_path = PosixPath('.../dimos/data/.lfs/g1_urdf.tar.gz')
repo_root = PosixPath('.../work/dimos/dimos')

    def _lfs_pull(file_path: Path, repo_root: Path, *, retries: int = 2) -> None:
        relative_path = file_path.relative_to(repo_root)
    
        env = os.environ.copy()
        env["GIT_LFS_FORCE_PROGRESS"] = "1"
    
        last_err: subprocess.CalledProcessError | None = None
        for attempt in range(1, retries + 2):  # retries + 1 total attempts
            try:
                subprocess.run(
                    # --exclude= overrides lfs.fetchexclude from .lfsconfig, which
                    # otherwise silently skips data/.lfs/* even when --include matches.
                    ["git", "lfs", "pull", "--include", str(relative_path), "--exclude="],
                    cwd=repo_root,
                    check=True,
                    env=env,
                )
                return
            except subprocess.CalledProcessError as e:
                last_err = e
                if attempt <= retries:
                    time.sleep(attempt)  # 1s, 2s backoff
    
>       raise RuntimeError(
            f"Failed to pull LFS file {file_path} after {retries + 1} attempts: {last_err}"
        )
E       RuntimeError: Failed to pull LFS file .../dimos/data/.lfs/g1_urdf.tar.gz after 3 attempts: Command '['git', 'lfs', 'pull', '--include', 'data/.lfs/g1_urdf.tar.gz', '--exclude=']' returned non-zero exit status 1.

attempt    = 3
env        = {'ACCEPT_EULA': 'Y', 'ACTIONS_ID_TOKEN_REQUEST_TOKEN': 'eyJhbGciOiJSUzI1NiIsImtpZCI6IjM4ODI2YjE3LTZhMzAtNWY5Yi1iMTY5LT...-version=2.0', 'ACTIONS_ORCHESTRATION_ID': '5a68b270-cc24-439d-882e-efa85575f488.tests.ubuntu-24_04-arm_3_14_fal', ...}
file_path  = PosixPath('.../dimos/data/.lfs/g1_urdf.tar.gz')
last_err   = CalledProcessError(1, ['git', 'lfs', 'pull', '--include', 'data/.lfs/g1_urdf.tar.gz', '--exclude='])
relative_path = PosixPath('data/.lfs/g1_urdf.tar.gz')
repo_root  = PosixPath('.../work/dimos/dimos')
retries    = 2

dimos/utils/data.py:224: RuntimeError

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

@TomCC7
TomCC7 force-pushed the pim/feat/g1-quest-teleop-stacked branch 2 times, most recently from 1b1e9dc to 82c7e51 Compare August 11, 2026 03:07
@TomCC7 TomCC7 changed the title feat(g1): stack Quest teleop on shared dual-arm IK feat(g1): Quest teleop on shared dual-arm IK Aug 14, 2026
@TomCC7
TomCC7 force-pushed the pim/feat/g1-quest-teleop-stacked branch from 82c7e51 to f813b09 Compare August 14, 2026 21:37
@TomCC7
TomCC7 force-pushed the pim/feat/g1-quest-teleop-stacked branch from de06b06 to a620d64 Compare August 14, 2026 21:40
@TomCC7
TomCC7 force-pushed the pim/feat/g1-quest-teleop-stacked branch from a620d64 to 6983ee5 Compare August 14, 2026 21:56
@TomCC7 TomCC7 changed the title feat(g1): Quest teleop on shared dual-arm IK feat: g1 quest teleop on shared dual-arm IK Aug 18, 2026
@TomCC7
TomCC7 force-pushed the pim/feat/g1-quest-teleop-stacked branch 2 times, most recently from 4c85a40 to fa4e476 Compare August 21, 2026 06:51
Base automatically changed from cc/feat/dual-arm-teleop to main August 25, 2026 01:10
@TomCC7
TomCC7 force-pushed the pim/feat/g1-quest-teleop-stacked branch from fa4e476 to 958c50c Compare August 25, 2026 05:35
@mintlify

mintlify Bot commented Aug 25, 2026

Copy link
Copy Markdown
Contributor

Preview deployment for your docs. Learn more about Mintlify Previews.

Project Status Preview Updated (UTC)
dimensional 🟢 Ready View Preview Aug 25, 2026, 5:36 AM

💡 Tip: Enable Workflows to automatically generate PRs for you.

@TomCC7
TomCC7 changed the base branch from main to cc/g1-smooth-bringup August 25, 2026 05:39
@TomCC7
TomCC7 force-pushed the pim/feat/g1-quest-teleop-stacked branch 3 times, most recently from ef9d693 to a48736e Compare August 25, 2026 22:50
@TomCC7
TomCC7 force-pushed the pim/feat/g1-quest-teleop-stacked branch from f3cace1 to 0c97a4a Compare August 25, 2026 22:53
@TomCC7
TomCC7 force-pushed the pim/feat/g1-quest-teleop-stacked branch from 0c97a4a to f6a799e Compare August 25, 2026 23:08
@TomCC7
TomCC7 force-pushed the pim/feat/g1-quest-teleop-stacked branch 2 times, most recently from f8134ee to ac21603 Compare August 25, 2026 23:56
Co-authored-by: Pim Van den Bosch <49974392+Nabla7@users.noreply.github.com>
@TomCC7
TomCC7 force-pushed the pim/feat/g1-quest-teleop-stacked branch from ac21603 to 9a2310d Compare August 26, 2026 06:01
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