Skip to content

refactor(manipulation): cut over to single robot model - #3431

Draft
TomCC7 wants to merge 2 commits into
cc/feat/cc-refactor-1from
cc/feat/cc-refactor-2
Draft

refactor(manipulation): cut over to single robot model#3431
TomCC7 wants to merge 2 commits into
cc/feat/cc-refactor-1from
cc/feat/cc-refactor-2

Conversation

@TomCC7

@TomCC7 TomCC7 commented Aug 10, 2026

Copy link
Copy Markdown
Member

Contribution path

Problem

Manipulation still models configuration, planning state, execution, and visualization as maps of independently named robots. That duplicates namespaces, requires local/global joint-name translation, and prevents a bimanual robot from being planned as one coherent model.

Solution

  • Replace ManipulationModuleConfig.robots with one prepared model.
  • Use canonical model joint names throughout planning, IK, collision, FK, monitoring, execution, and visualization.
  • Make planning-group IDs stable declared names such as left_arm; groups select canonical subsets of the one model.
  • Solve multi-group Pink targets in one model context.
  • Forward one canonical trajectory to the coordinator without splitting or mapping inversion.
  • Remove robot selectors, registries, lookup APIs, compatibility aliases, and robot-prefixed group parsing from migrated manipulation surfaces.
  • Cut the dual-xArm manipulation blueprint over to the prepared bimanual model with left_arm, right_arm, and both_arms groups.

The legacy gripper hardware-ID path remains intentionally deferred to PR6 in the OpenSpec stack.

How to Test

./bin/pytest-fast
uv run pytest dimos/manipulation
uv run pytest dimos/robot/test_all_blueprints_generation.py
openspec validate refactor-control-coordinator-connections --strict

Validated locally:

  • Fast suite: 3,846 passed, 34 skipped.
  • Manipulation suite: 324 passed, 15 skipped, 12 deselected.
  • Ruff format/check, blueprint registry generation, strict OpenSpec validation, and all available pre-commit hooks passed.
  • Drake and RoboPlan optional integration tests were migrated but skipped where their optional packages were unavailable.
  • Mypy and deno fmt were unavailable in the local environment.

AI assistance

Codex with GPT-5 implemented the refactor, migrated tests and blueprints, and ran validation under human direction.

Checklist

  • I have read and approved the CLA.

@codecov

codecov Bot commented Aug 10, 2026

Copy link
Copy Markdown

❌ 3 Tests Failed:

Tests completed Failed Passed Skipped
3679 3 3676 175
View the top 3 failed test(s) by shortest run time
dimos.robot.manipulators.xarm.test_model_config::test_prefixed_xarm_model_uses_coordinator_facing_names_in_asset
Stack Traces | 3.11s run time
def test_prefixed_xarm_model_uses_coordinator_facing_names_in_asset() -> None:
        config = make_xarm6_model_config(add_gripper=False, prefix="xarm_arm/")
    
>       model = validate_robot_model_config(config)

config     = <[RuntimeError("Failed to pull LFS file .../dimos/data/.lfs/xarm_description.tar.gz after 3 attemp...m_description.tar.gz']' returned non-zero exit status 1.") raised in repr()] RobotModelConfig object at 0xff92a9890190>

.../manipulators/xarm/test_model_config.py:43: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 
.../planning/spec/validation.py:47: in validate_robot_model_config
    model = parse_model(
        config     = <[RuntimeError("Failed to pull LFS file .../dimos/data/.lfs/xarm_description.tar.gz after 3 attemp...m_description.tar.gz']' returned non-zero exit status 1.") raised in repr()] RobotModelConfig object at 0xff92a9890190>
dimos/robot/model_parser.py:71: in parse_model
    path = Path(path)
        package_paths = {'xarm_description': <[RuntimeError("Failed to pull LFS file .../dimos/data/.lfs/xarm_description.....lfs/xarm_description.tar.gz']' returned non-zero exit status 1.") raised in repr()] LfsPath object at 0xff93190f32d0>}
        path       = <[RuntimeError("Failed to pull LFS file .../dimos/data/.lfs/xarm_description.tar.gz after 3 attemp.../.lfs/xarm_description.tar.gz']' returned non-zero exit status 1.") raised in repr()] LfsPath object at 0xff93190f3ed0>
        xacro_args = {'attach_rpy': '0 0 0', 'attach_xyz': '0 0 0', 'dof': '6', 'limited': 'true', ...}
....../usr/lib/python3.12/pathlib.py:1164: in __init__
    super().__init__(*args)
        __class__  = <class 'pathlib.Path'>
        args       = (<[RuntimeError("Failed to pull LFS file .../dimos/data/.lfs/xarm_description.tar.gz after 3 attem...lfs/xarm_description.tar.gz']' returned non-zero exit status 1.") raised in repr()] LfsPath object at 0xff93190f3ed0>,)
        kwargs     = {}
        self       = <[AttributeError("'PosixPath' object has no attribute '_raw_paths'") raised in repr()] PosixPath object at 0xff92a987f530>
....../usr/lib/python3.12/pathlib.py:362: in __init__
    if arg._flavour is ntpath and self._flavour is posixpath:
        arg        = <[RuntimeError("Failed to pull LFS file .../dimos/data/.lfs/xarm_description.tar.gz after 3 attemp.../.lfs/xarm_description.tar.gz']' returned non-zero exit status 1.") raised in repr()] LfsPath object at 0xff93190f3ed0>
        args       = (<[RuntimeError("Failed to pull LFS file .../dimos/data/.lfs/xarm_description.tar.gz after 3 attem...lfs/xarm_description.tar.gz']' returned non-zero exit status 1.") raised in repr()] LfsPath object at 0xff93190f3ed0>,)
        ntpath     = <module 'ntpath' (frozen)>
        paths      = []
        self       = <[AttributeError("'PosixPath' object has no attribute '_raw_paths'") raised in repr()] PosixPath object at 0xff92a987f530>
dimos/utils/data.py:364: in __getattribute__
    resolved = object.__getattribute__(self, "_ensure_downloaded")()
        name       = '_flavour'
        self       = <[RuntimeError("Failed to pull LFS file .../dimos/data/.lfs/xarm_description.tar.gz after 3 attemp.../.lfs/xarm_description.tar.gz']' returned non-zero exit status 1.") raised in repr()] LfsPath object at 0xff93190f3ed0>
dimos/utils/data.py:347: in _ensure_downloaded
    cache = get_data(filename)
        cache      = None
        filename   = 'xarm_description/urdf/xarm_device.urdf.xacro'
        self       = <[RuntimeError("Failed to pull LFS file .../dimos/data/.lfs/xarm_description.tar.gz after 3 attemp.../.lfs/xarm_description.tar.gz']' returned non-zero exit status 1.") raised in repr()] LfsPath object at 0xff93190f3ed0>
dimos/utils/data.py:304: in get_data
    archive_path = _decompress_archive(_pull_lfs_archive(archive_name))
        archive_name = 'xarm_description'
        data_dir   = PosixPath('.../dimos/dimos/data')
        file_path  = PosixPath('.../dimos/dimos/data/xarm_description/urdf/xarm_device.urdf.xacro')
        name       = 'xarm_description/urdf/xarm_device.urdf.xacro'
        nested_path = PosixPath('urdf/xarm_device.urdf.xacro')
        path_parts = ('xarm_description', 'urdf', 'xarm_device.urdf.xacro')
dimos/utils/data.py:248: in _pull_lfs_archive
    _lfs_pull(file_path, repo_root)
        file_path  = PosixPath('.../dimos/data/.lfs/xarm_description.tar.gz')
        filename   = 'xarm_description'
        repo_root  = PosixPath('.../work/dimos/dimos')
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

file_path = PosixPath('.../dimos/data/.lfs/xarm_description.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(
                    ["git", "lfs", "pull", "--include", str(relative_path)],
                    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/xarm_description.tar.gz after 3 attempts: Command '['git', 'lfs', 'pull', '--include', 'data/.lfs/xarm_description.tar.gz']' returned non-zero exit status 1.

attempt    = 3
env        = {'ACCEPT_EULA': 'Y', 'ACTIONS_ID_TOKEN_REQUEST_TOKEN': 'eyJhbGciOiJSUzI1NiIsImtpZCI6IjM4ODI2YjE3LTZhMzAtNWY5Yi1iMTY5LT...-version=2.0', 'ACTIONS_ORCHESTRATION_ID': '241503d3-d034-4e7e-9970-d6e8ace9d544.tests.ubuntu-24_04-arm_3_14_fal', ...}
file_path  = PosixPath('.../dimos/data/.lfs/xarm_description.tar.gz')
last_err   = CalledProcessError(1, ['git', 'lfs', 'pull', '--include', 'data/.lfs/xarm_description.tar.gz'])
relative_path = PosixPath('data/.lfs/xarm_description.tar.gz')
repo_root  = PosixPath('.../work/dimos/dimos')
retries    = 2

dimos/utils/data.py:216: RuntimeError
dimos.robot.manipulators.openarm.test_openarm::test_openarm_dual_model_contains_every_canonical_joint_and_group_frame
Stack Traces | 3.11s run time
def test_openarm_dual_model_contains_every_canonical_joint_and_group_frame() -> None:
        config = openarm_dual_model_config()
    
>       description = validate_robot_model_config(config)

config     = <[RuntimeError("Failed to pull LFS file .../dimos/data/.lfs/openarm_description.tar.gz after 3 att...m_description.tar.gz']' returned non-zero exit status 1.") raised in repr()] RobotModelConfig object at 0xff8697e6a760>

.../manipulators/openarm/test_openarm.py:22: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 
.../planning/spec/validation.py:47: in validate_robot_model_config
    model = parse_model(
        config     = <[RuntimeError("Failed to pull LFS file .../dimos/data/.lfs/openarm_description.tar.gz after 3 att...m_description.tar.gz']' returned non-zero exit status 1.") raised in repr()] RobotModelConfig object at 0xff8697e6a760>
dimos/robot/model_parser.py:71: in parse_model
    path = Path(path)
        package_paths = {'openarm_description': <[RuntimeError("Failed to pull LFS file .../dimos/data/.lfs/openarm_descri...s/openarm_description.tar.gz']' returned non-zero exit status 1.") raised in repr()] LfsPath object at 0xff86a38497d0>}
        path       = <[RuntimeError("Failed to pull LFS file .../dimos/data/.lfs/openarm_description.tar.gz after 3 att...fs/openarm_description.tar.gz']' returned non-zero exit status 1.") raised in repr()] LfsPath object at 0xff86a3848150>
        xacro_args = {}
....../usr/lib/python3.12/pathlib.py:1164: in __init__
    super().__init__(*args)
        __class__  = <class 'pathlib.Path'>
        args       = (<[RuntimeError("Failed to pull LFS file .../dimos/data/.lfs/openarm_description.tar.gz after 3 at.../openarm_description.tar.gz']' returned non-zero exit status 1.") raised in repr()] LfsPath object at 0xff86a3848150>,)
        kwargs     = {}
        self       = <[AttributeError("'PosixPath' object has no attribute '_raw_paths'") raised in repr()] PosixPath object at 0xff8697fe5bd0>
....../usr/lib/python3.12/pathlib.py:362: in __init__
    if arg._flavour is ntpath and self._flavour is posixpath:
        arg        = <[RuntimeError("Failed to pull LFS file .../dimos/data/.lfs/openarm_description.tar.gz after 3 att...fs/openarm_description.tar.gz']' returned non-zero exit status 1.") raised in repr()] LfsPath object at 0xff86a3848150>
        args       = (<[RuntimeError("Failed to pull LFS file .../dimos/data/.lfs/openarm_description.tar.gz after 3 at.../openarm_description.tar.gz']' returned non-zero exit status 1.") raised in repr()] LfsPath object at 0xff86a3848150>,)
        ntpath     = <module 'ntpath' (frozen)>
        paths      = []
        self       = <[AttributeError("'PosixPath' object has no attribute '_raw_paths'") raised in repr()] PosixPath object at 0xff8697fe5bd0>
dimos/utils/data.py:364: in __getattribute__
    resolved = object.__getattribute__(self, "_ensure_downloaded")()
        name       = '_flavour'
        self       = <[RuntimeError("Failed to pull LFS file .../dimos/data/.lfs/openarm_description.tar.gz after 3 att...fs/openarm_description.tar.gz']' returned non-zero exit status 1.") raised in repr()] LfsPath object at 0xff86a3848150>
dimos/utils/data.py:347: in _ensure_downloaded
    cache = get_data(filename)
        cache      = None
        filename   = '.../urdf/robot/openarm_v10_bimanual.urdf'
        self       = <[RuntimeError("Failed to pull LFS file .../dimos/data/.lfs/openarm_description.tar.gz after 3 att...fs/openarm_description.tar.gz']' returned non-zero exit status 1.") raised in repr()] LfsPath object at 0xff86a3848150>
dimos/utils/data.py:304: in get_data
    archive_path = _decompress_archive(_pull_lfs_archive(archive_name))
        archive_name = 'openarm_description'
        data_dir   = PosixPath('.../dimos/dimos/data')
        file_path  = PosixPath('.../dimos/dimos/data/.../urdf/robot/openarm_v10_bimanual.urdf')
        name       = '.../urdf/robot/openarm_v10_bimanual.urdf'
        nested_path = PosixPath('urdf/robot/openarm_v10_bimanual.urdf')
        path_parts = ('openarm_description', 'urdf', 'robot', 'openarm_v10_bimanual.urdf')
dimos/utils/data.py:248: in _pull_lfs_archive
    _lfs_pull(file_path, repo_root)
        file_path  = PosixPath('.../dimos/data/.lfs/openarm_description.tar.gz')
        filename   = 'openarm_description'
        repo_root  = PosixPath('.../work/dimos/dimos')
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

file_path = PosixPath('.../dimos/data/.lfs/openarm_description.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(
                    ["git", "lfs", "pull", "--include", str(relative_path)],
                    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/openarm_description.tar.gz after 3 attempts: Command '['git', 'lfs', 'pull', '--include', 'data/.lfs/openarm_description.tar.gz']' returned non-zero exit status 1.

attempt    = 3
env        = {'ACCEPT_EULA': 'Y', 'ACTIONS_ID_TOKEN_REQUEST_TOKEN': 'eyJhbGciOiJSUzI1NiIsImtpZCI6IjM4ODI2YjE3LTZhMzAtNWY5Yi1iMTY5LT...-version=2.0', 'ACTIONS_ORCHESTRATION_ID': '241503d3-d034-4e7e-9970-d6e8ace9d544.tests.ubuntu-24_04-arm_3_14_fal', ...}
file_path  = PosixPath('.../dimos/data/.lfs/openarm_description.tar.gz')
last_err   = CalledProcessError(1, ['git', 'lfs', 'pull', '--include', 'data/.lfs/openarm_description.tar.gz'])
relative_path = PosixPath('data/.lfs/openarm_description.tar.gz')
repo_root  = PosixPath('.../work/dimos/dimos')
retries    = 2

dimos/utils/data.py:216: RuntimeError
dimos.robot.manipulators.xarm.test_model_config::test_dual_xarm6_is_one_prepared_model_with_canonical_groups
Stack Traces | 3.12s run time
def test_dual_xarm6_is_one_prepared_model_with_canonical_groups() -> None:
        config = make_dual_xarm6_model_config()
    
>       model = validate_robot_model_config(config)

config     = <[RuntimeError("Failed to pull LFS file .../dimos/data/.lfs/xarm_description.tar.gz after 3 attemp...m_description.tar.gz']' returned non-zero exit status 1.") raised in repr()] RobotModelConfig object at 0xff92a9439d60>

.../manipulators/xarm/test_model_config.py:27: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 
.../planning/spec/validation.py:47: in validate_robot_model_config
    model = parse_model(
        config     = <[RuntimeError("Failed to pull LFS file .../dimos/data/.lfs/xarm_description.tar.gz after 3 attemp...m_description.tar.gz']' returned non-zero exit status 1.") raised in repr()] RobotModelConfig object at 0xff92a9439d60>
dimos/robot/model_parser.py:71: in parse_model
    path = Path(path)
        package_paths = {'xarm_description': <[RuntimeError("Failed to pull LFS file .../dimos/data/.lfs/xarm_description.....lfs/xarm_description.tar.gz']' returned non-zero exit status 1.") raised in repr()] LfsPath object at 0xff93190f32d0>}
        path       = <[RuntimeError("Failed to pull LFS file .../dimos/data/.lfs/xarm_description.tar.gz after 3 attemp.../.lfs/xarm_description.tar.gz']' returned non-zero exit status 1.") raised in repr()] LfsPath object at 0xff93190f3b50>
        xacro_args = {'dof_1': '6', 'dof_2': '6', 'limited': 'true', 'prefix_1': 'left/', ...}
....../usr/lib/python3.12/pathlib.py:1164: in __init__
    super().__init__(*args)
        __class__  = <class 'pathlib.Path'>
        args       = (<[RuntimeError("Failed to pull LFS file .../dimos/data/.lfs/xarm_description.tar.gz after 3 attem...lfs/xarm_description.tar.gz']' returned non-zero exit status 1.") raised in repr()] LfsPath object at 0xff93190f3b50>,)
        kwargs     = {}
        self       = <[AttributeError("'PosixPath' object has no attribute '_raw_paths'") raised in repr()] PosixPath object at 0xff92a93b47b0>
....../usr/lib/python3.12/pathlib.py:362: in __init__
    if arg._flavour is ntpath and self._flavour is posixpath:
        arg        = <[RuntimeError("Failed to pull LFS file .../dimos/data/.lfs/xarm_description.tar.gz after 3 attemp.../.lfs/xarm_description.tar.gz']' returned non-zero exit status 1.") raised in repr()] LfsPath object at 0xff93190f3b50>
        args       = (<[RuntimeError("Failed to pull LFS file .../dimos/data/.lfs/xarm_description.tar.gz after 3 attem...lfs/xarm_description.tar.gz']' returned non-zero exit status 1.") raised in repr()] LfsPath object at 0xff93190f3b50>,)
        ntpath     = <module 'ntpath' (frozen)>
        paths      = []
        self       = <[AttributeError("'PosixPath' object has no attribute '_raw_paths'") raised in repr()] PosixPath object at 0xff92a93b47b0>
dimos/utils/data.py:364: in __getattribute__
    resolved = object.__getattribute__(self, "_ensure_downloaded")()
        name       = '_flavour'
        self       = <[RuntimeError("Failed to pull LFS file .../dimos/data/.lfs/xarm_description.tar.gz after 3 attemp.../.lfs/xarm_description.tar.gz']' returned non-zero exit status 1.") raised in repr()] LfsPath object at 0xff93190f3b50>
dimos/utils/data.py:347: in _ensure_downloaded
    cache = get_data(filename)
        cache      = None
        filename   = 'xarm_description/urdf/dual_xarm_device.urdf.xacro'
        self       = <[RuntimeError("Failed to pull LFS file .../dimos/data/.lfs/xarm_description.tar.gz after 3 attemp.../.lfs/xarm_description.tar.gz']' returned non-zero exit status 1.") raised in repr()] LfsPath object at 0xff93190f3b50>
dimos/utils/data.py:304: in get_data
    archive_path = _decompress_archive(_pull_lfs_archive(archive_name))
        archive_name = 'xarm_description'
        data_dir   = PosixPath('.../dimos/dimos/data')
        file_path  = PosixPath('.../dimos/dimos/data/xarm_description/urdf/dual_xarm_device.urdf.xacro')
        name       = 'xarm_description/urdf/dual_xarm_device.urdf.xacro'
        nested_path = PosixPath('urdf/dual_xarm_device.urdf.xacro')
        path_parts = ('xarm_description', 'urdf', 'dual_xarm_device.urdf.xacro')
dimos/utils/data.py:248: in _pull_lfs_archive
    _lfs_pull(file_path, repo_root)
        file_path  = PosixPath('.../dimos/data/.lfs/xarm_description.tar.gz')
        filename   = 'xarm_description'
        repo_root  = PosixPath('.../work/dimos/dimos')
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

file_path = PosixPath('.../dimos/data/.lfs/xarm_description.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(
                    ["git", "lfs", "pull", "--include", str(relative_path)],
                    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/xarm_description.tar.gz after 3 attempts: Command '['git', 'lfs', 'pull', '--include', 'data/.lfs/xarm_description.tar.gz']' returned non-zero exit status 1.

attempt    = 3
env        = {'ACCEPT_EULA': 'Y', 'ACTIONS_ID_TOKEN_REQUEST_TOKEN': 'eyJhbGciOiJSUzI1NiIsImtpZCI6IjM4ODI2YjE3LTZhMzAtNWY5Yi1iMTY5LT...-version=2.0', 'ACTIONS_ORCHESTRATION_ID': '241503d3-d034-4e7e-9970-d6e8ace9d544.tests.ubuntu-24_04-arm_3_14_fal', ...}
file_path  = PosixPath('.../dimos/data/.lfs/xarm_description.tar.gz')
last_err   = CalledProcessError(1, ['git', 'lfs', 'pull', '--include', 'data/.lfs/xarm_description.tar.gz'])
relative_path = PosixPath('data/.lfs/xarm_description.tar.gz')
repo_root  = PosixPath('.../work/dimos/dimos')
retries    = 2

dimos/utils/data.py:216: 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.

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