Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
27 commits
Select commit Hold shift + click to select a range
fe7a7de
spec: openspec init
TomCC7 Jun 4, 2026
76158b2
chore: revert change to doc folder
TomCC7 Jun 8, 2026
35c8b14
Merge branch 'main' into cc/feat/openspec
TomCC7 Jun 8, 2026
12d4346
Merge branch 'main' into cc/feat/openspec
TomCC7 Jun 10, 2026
6cd2fd3
Merge remote-tracking branch 'origin/main' into cc/feat/openspec
TomCC7 Jun 12, 2026
45f7f73
Merge branch 'main' into cc/feat/openspec
TomCC7 Jun 15, 2026
86a600d
Merge remote-tracking branch 'origin/main' into cc/feat/openspec
TomCC7 Jun 18, 2026
43fd853
Merge branch 'main' into cc/feat/openspec
TomCC7 Jun 20, 2026
8394a61
Merge remote-tracking branch 'origin/main' into cc/feat/openspec
TomCC7 Jun 20, 2026
bae46c4
Merge remote-tracking branch 'origin/main' into cc/feat/openspec
TomCC7 Jun 23, 2026
4cf815e
Merge remote-tracking branch 'origin/main' into cc/feat/openspec
TomCC7 Jun 30, 2026
2c80dab
Merge remote-tracking branch 'origin/main' into cc/feat/openspec
TomCC7 Jul 7, 2026
bc381cb
Merge remote-tracking branch 'origin/main' into cc/feat/openspec
TomCC7 Jul 11, 2026
3a976da
Merge remote-tracking branch 'origin/main' into cc/feat/openspec
TomCC7 Jul 14, 2026
4e25297
add mattskill
TomCC7 Jul 20, 2026
11f0d7f
Merge remote-tracking branch 'origin/main' into cc/feat/openspec
TomCC7 Jul 23, 2026
9ffcd58
Merge remote-tracking branch 'origin/main' into cc/feat/openspec
TomCC7 Jul 23, 2026
f873ddf
Merge remote-tracking branch 'origin/main' into cc/feat/openspec
TomCC7 Jul 24, 2026
e87e93e
Merge remote-tracking branch 'origin/main' into cc/feat/openspec
TomCC7 Jul 27, 2026
e689348
Merge remote-tracking branch 'origin/main' into cc/feat/openspec
TomCC7 Jul 28, 2026
794e585
Merge remote-tracking branch 'origin/main' into cc/feat/openspec
TomCC7 Jul 29, 2026
cfa3e3a
Merge remote-tracking branch 'origin/main' into cc/feat/openspec
TomCC7 Aug 1, 2026
d221a4f
Merge remote-tracking branch 'origin/main' into cc/feat/openspec
TomCC7 Aug 4, 2026
df82a32
Merge remote-tracking branch 'origin/main' into cc/feat/openspec
TomCC7 Aug 5, 2026
5409a37
fix(manipulation): upgrade RoboPlan to 0.6
TomCC7 Aug 5, 2026
ec21a60
spec: remove
TomCC7 Aug 5, 2026
ee7fee9
fix(manipulation): default Cartesian plans to time optimal
TomCC7 Aug 5, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 2 additions & 4 deletions dimos/manipulation/planning/planners/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ class RoboPlanCartesianPathConfig(BaseConfig):
"""Runtime options for the official RoboPlan Cartesian path planner."""

backend: Literal["roboplan"] = "roboplan"
speed_mode: Literal["bounded", "time_optimal"] = "bounded"
speed_mode: Literal["bounded", "time_optimal"] = "time_optimal"
dt: float = Field(default=0.01, gt=0.0)
max_linear_speed: float = Field(default=0.1, gt=0.0)
max_angular_speed: float = Field(default=0.5, gt=0.0)
Expand All @@ -49,10 +49,8 @@ class RoboPlanCartesianPathConfig(BaseConfig):
config_task_weight: float = Field(default=0.05, ge=0.0)
velocity_scale: float = Field(default=1.0, gt=0.0, le=1.0)
acceleration_scale: float = Field(default=1.0, gt=0.0, le=1.0)
limit_ratio_tolerance: float = Field(default=1.05, ge=1.0)
toppra_blend_deviation: float = 0.05
toppra_blend_deviation: float = Field(default=0.05, ge=0.0)
position_limit_gain: float = Field(default=1.0, gt=0.0, le=1.0)
max_attempts_per_step: int = Field(default=16, ge=1)


CartesianPathConfig = RoboPlanCartesianPathConfig
Expand Down
8 changes: 6 additions & 2 deletions dimos/manipulation/planning/planners/test_config.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,14 +20,18 @@
from dimos.manipulation.planning.planners.config import RoboPlanCartesianPathConfig


def test_roboplan_cartesian_path_config_defaults_to_time_optimal_and_allows_bounded() -> None:
assert RoboPlanCartesianPathConfig().speed_mode == "time_optimal"
assert RoboPlanCartesianPathConfig(speed_mode="bounded").speed_mode == "bounded"


@pytest.mark.parametrize(
"path_config",
[
{"dt": 0.0},
{"velocity_scale": 1.1},
{"acceleration_scale": 0.0},
{"limit_ratio_tolerance": 0.99},
{"max_attempts_per_step": 0},
{"toppra_blend_deviation": -0.01},
],
)
def test_roboplan_cartesian_path_config_rejects_invalid_limits(
Expand Down
2 changes: 0 additions & 2 deletions dimos/manipulation/planning/world/roboplan_world.py
Original file line number Diff line number Diff line change
Expand Up @@ -812,10 +812,8 @@ def _cartesian_planner_options(
"config_task_weight",
"velocity_scale",
"acceleration_scale",
"limit_ratio_tolerance",
"toppra_blend_deviation",
"position_limit_gain",
"max_attempts_per_step",
):
setattr(options, field_name, getattr(config, field_name))
return options
Expand Down
48 changes: 2 additions & 46 deletions dimos/manipulation/test_roboplan_world.py
Original file line number Diff line number Diff line change
Expand Up @@ -99,24 +99,6 @@ def __init__(self) -> None:
self.group_name = ""
self.speed_mode = FakeCartesianSpeedMode.TimeOptimal
self.dt = 0.01
self.max_linear_speed = 0.1
self.max_angular_speed = 0.5
self.max_linear_acceleration = 0.5
self.max_angular_acceleration = 2.5
self.max_position_error = 0.005
self.max_orientation_error = 0.01
self.position_cost = 1.0
self.orientation_cost = 1.0
self.task_gain = 1.0
self.lm_damping = 0.01
self.regularization = 1e-6
self.config_task_weight = 0.05
self.velocity_scale = 1.0
self.acceleration_scale = 1.0
self.limit_ratio_tolerance = 1.05
self.toppra_blend_deviation = 0.05
self.position_limit_gain = 1.0
self.max_attempts_per_step = 16


class FakeCartesianPathPlanner:
Expand Down Expand Up @@ -1446,32 +1428,11 @@ def test_native_planner_coordinates_groups_across_two_robots(
assert result.path[-1].position == [0.1, 0.3, 0.4, 0.2]


def test_cartesian_planner_returns_timed_global_joint_states_and_options(
def test_cartesian_planner_returns_timed_global_joint_states(
fake_roboplan: None, robot_config: RobotModelConfig
) -> None:
world, _ = _make_world(fake_roboplan, robot_config)
selection = _selection((robot_config,), "arm/manipulator")
option_overrides = {
"dt": 0.02,
"max_linear_speed": 0.2,
"max_angular_speed": 0.6,
"max_linear_acceleration": 0.7,
"max_angular_acceleration": 2.0,
"max_position_error": 0.006,
"max_orientation_error": 0.02,
"position_cost": 2.0,
"orientation_cost": 3.0,
"task_gain": 0.8,
"lm_damping": 0.02,
"regularization": 2e-6,
"config_task_weight": 0.1,
"velocity_scale": 0.9,
"acceleration_scale": 0.8,
"limit_ratio_tolerance": 1.02,
"toppra_blend_deviation": 0.0,
"position_limit_gain": 0.7,
"max_attempts_per_step": 8,
}

result = world.plan_cartesian_path(
world,
Expand All @@ -1485,10 +1446,7 @@ def test_cartesian_planner_returns_timed_global_joint_states_and_options(
)
)
},
RoboPlanCartesianPathConfig(
speed_mode="time_optimal",
**option_overrides,
),
RoboPlanCartesianPathConfig(speed_mode="time_optimal", dt=0.02),
)

assert result.status == PlanningStatus.SUCCESS
Expand All @@ -1498,8 +1456,6 @@ def test_cartesian_planner_returns_timed_global_joint_states_and_options(
assert result.path[1].velocity == pytest.approx([0.5, 0.5])
planner = FakeCartesianPathPlanner.instances[-1]
assert planner.options.speed_mode == FakeCartesianSpeedMode.TimeOptimal
for field_name, expected in option_overrides.items():
assert getattr(planner.options, field_name) == pytest.approx(expected)
assert planner.paths[0].base_frames == ["dimos_world"]
np.testing.assert_allclose(planner.paths[0].tforms[0][0], np.eye(4), atol=1e-12)
expected_rotation = np.array(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -617,7 +617,7 @@ def test_cartesian_space_mode_plans_absolute_pose_targets_with_auxiliary_groups(
targets, config, auxiliary_ids = module.cartesian_plans[0]
assert tuple(targets) == (pose_group.id,)
assert targets[pose_group.id].frame_id == "world"
assert config.speed_mode == "bounded" # type: ignore[attr-defined]
assert config.speed_mode == "time_optimal" # type: ignore[attr-defined]
assert auxiliary_ids == (auxiliary_group.id,)
assert gui.state.plan_state.status == PlanStatus.FRESH
assert gui.state.last_result == "plan_cartesian_space=True"
Expand Down
39 changes: 29 additions & 10 deletions docs/capabilities/manipulation/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -123,24 +123,43 @@ from dimos.manipulation.planning.planners.config import (
RoboPlanCartesianPathConfig,
)

path_config = RoboPlanCartesianPathConfig(
path_config = RoboPlanCartesianPathConfig()

module.plan_cartesian_targets(
{"arm/manipulator": (current_tcp_pose, goal_tcp_pose)},
path_config,
)
```

The default `time_optimal` mode returns the TOPP-RA trajectory constrained by
the robot's joint velocity and acceleration limits. To enforce Cartesian speed
and acceleration maxima instead, opt into bounded mode:

```python skip
bounded_config = RoboPlanCartesianPathConfig(
speed_mode="bounded",
max_linear_speed=0.1,
max_angular_speed=0.5,
max_linear_acceleration=0.5,
max_angular_acceleration=2.5,
max_position_error=0.005,
max_orientation_error=0.01,
)

module.plan_cartesian_targets(
{"arm/manipulator": (current_tcp_pose, goal_tcp_pose)},
path_config,
)
```

The remaining settings mirror RoboPlan's standard Cartesian planner options,
including bounded and time-optimal speed modes, sample time, solver weights,
linear/angular acceleration limits, joint velocity/acceleration scaling,
TOPP-RA corner blending, joint-limit handling, and per-step attempts.
RoboPlan first resolves the Cartesian reference as a geometric joint path, then
uses TOPP-RA to produce the timed trajectory. Both speed modes follow this
pipeline. Time-optimal mode returns the joint-limit-constrained trajectory;
bounded mode slows it further when needed to respect the configured Cartesian
speed and acceleration maxima. `toppra_blend_deviation` controls TOPP-RA corner
rounding in both modes and influences how aggressively the resolved path is
decimated before timing.

The remaining settings mirror RoboPlan's Cartesian planner options, including
sample time, solver weights, linear/angular acceleration limits, joint
velocity/acceleration scaling, TOPP-RA corner blending, and joint-limit
handling. RoboPlan 0.6 removed the former `limit_ratio_tolerance` and
`max_attempts_per_step` settings.

Cartesian path planning remains a low-level internal capability in this
release. `ManipulationModule.plan_cartesian_targets()` accepts an ordered
Expand Down
4 changes: 2 additions & 2 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -292,7 +292,7 @@ manipulation = [
# Other
"matplotlib>=3.7.1",
"pyyaml>=6.0",
"roboplan>=0.5.1",
"roboplan>=0.6.0,<0.7.0",
]

cpu = [
Expand Down Expand Up @@ -457,7 +457,7 @@ lint = [
"pytest==8.3.5",
"python-can>=4",
"python-socketio>=5.16.1",
"roboplan>=0.5.1",
"roboplan>=0.6.0,<0.7.0",
"sounddevice>=0.5.5",
"trimesh>=4.12",
"watchdog>=3.0.0",
Expand Down
28 changes: 14 additions & 14 deletions uv.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading