-
Notifications
You must be signed in to change notification settings - Fork 10
mujoco sim module #1035
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Open
jca0
wants to merge
48
commits into
dev
Choose a base branch
from
jing-sim
base: dev
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
+1,450
−0
Open
mujoco sim module #1035
Changes from all commits
Commits
Show all changes
48 commits
Select commit
Hold shift + click to select a range
07c18f6
add original files
jca0 4821255
rebased with dev for new controller orchestrator arch
jca0 b9adc9b
clean up code + comments
jca0 ac1c647
tests for testing
jca0 ca898c5
address race condition
jca0 8116d1f
fix mypy errors
jca0 d7fd12e
Merge branch 'jing-sim' of github.com:dimensionalOS/dimos into jing-sim
jca0 3461348
syntax error :(
jca0 f46ec17
CI code cleanup
jca0 97508ee
skeleton for modular sim arch
jca0 89f462a
mujoco engine/bringup script
jca0 6073d80
manipulation interface that plugs into different sims
jca0 328a019
simulation model that supports any sim engine
jca0 c153c13
add support for xarm in sim
jca0 6d9e135
clean up code
jca0 86a3c06
more cleanup
jca0 4121640
mypy error fix
jca0 a2b66f7
delete joint limits
jca0 91cd6a3
remove get_blueprint() and set constant
jca0 bcbe1be
sim module takes in xml file and parses it for robot properties
jca0 f392af0
Track xarm7 assets with LFS
jca0 19f886a
make blueprint runnable
jca0 c3d0c2b
e2e test and unit tests for sim module
jca0 90c8297
move xarm7 arm to data folder
jca0 b61e4db
move xml parser to utils folder
jca0 460f24a
remove 'mujoco' from sim module
jca0 ca4afc9
no time.sleeps for clock. monotonic time instead
jca0 2d118e4
connect() and disconnect() return bool
jca0 7fec092
consolidate write commands into one and fix velocity control
jca0 104c4fe
config_path changed to Path type and mandatory
jca0 e62a249
engine typing
jca0 22d71ec
typing fix, no default so set kw_only=True
jca0 f06fb46
add hold_current_position() to base
jca0 7a6662d
fix locks and make sure array length is as expected
jca0 bc98dd3
revise e2e tests to spin up blueprint
jca0 499ede5
fix sim module tests
jca0 ede93fc
Merge branch 'dev' into jing-sim
jca0 2c52669
fix mypy errors
jca0 645a5f0
fetch LFS when module starts
jca0 6ced566
Merge branch 'jing-sim' of github.com:dimensionalOS/dimos into jing-sim
jca0 9f5f919
clean up
jca0 2245752
Update test_simulation_module.py
jca0 d3962cd
Merge branch 'dev' into jing-sim
jca0 64f5979
remove duplicated blueprint
jca0 001a053
run all blueprints generation test
jca0 5d62c4f
Merge branch 'dev' into jing-sim
spomichter a527d07
CI code cleanup
spomichter de58166
fixed all blueprints
spomichter File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
Git LFS file not shown
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,86 @@ | ||
| # Copyright 2025-2026 Dimensional Inc. | ||
| # | ||
| # Licensed under the Apache License, Version 2.0 (the "License"); | ||
| # you may not use this file except in compliance with the License. | ||
| # You may obtain a copy of the License at | ||
| # | ||
| # http://www.apache.org/licenses/LICENSE-2.0 | ||
| # | ||
| # Unless required by applicable law or agreed to in writing, software | ||
| # distributed under the License is distributed on an "AS IS" BASIS, | ||
| # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
| # See the License for the specific language governing permissions and | ||
| # limitations under the License. | ||
|
|
||
| """End-to-end tests for the simulation module.""" | ||
|
|
||
| import os | ||
|
|
||
| import pytest | ||
|
|
||
| from dimos.msgs.sensor_msgs import JointCommand, JointState, RobotState | ||
|
|
||
|
|
||
| def _positions_within_tolerance( | ||
| positions: list[float], | ||
| target: list[float], | ||
| tolerance: float, | ||
| ) -> bool: | ||
| if len(positions) < len(target): | ||
| return False | ||
| return all(abs(positions[i] - target[i]) <= tolerance for i in range(len(target))) | ||
|
|
||
|
|
||
| @pytest.mark.skipif(bool(os.getenv("CI")), reason="LCM doesn't work in CI.") | ||
| @pytest.mark.e2e | ||
| class TestSimulationModuleE2E: | ||
jca0 marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| def test_xarm7_joint_state_published(self, lcm_spy, start_blueprint) -> None: | ||
| joint_state_topic = "/xarm/joint_states#sensor_msgs.JointState" | ||
| lcm_spy.save_topic(joint_state_topic) | ||
|
|
||
| start_blueprint("simulation-xarm7") | ||
| lcm_spy.wait_for_saved_topic(joint_state_topic, timeout=15.0) | ||
|
|
||
| with lcm_spy._messages_lock: | ||
| raw_joint_state = lcm_spy.messages[joint_state_topic][0] | ||
|
|
||
| joint_state = JointState.lcm_decode(raw_joint_state) | ||
| assert len(joint_state.name) == 8 | ||
| assert len(joint_state.position) == 8 | ||
|
|
||
| def test_xarm7_robot_state_published(self, lcm_spy, start_blueprint) -> None: | ||
| robot_state_topic = "/xarm/robot_state#sensor_msgs.RobotState" | ||
| lcm_spy.save_topic(robot_state_topic) | ||
|
|
||
| start_blueprint("simulation-xarm7") | ||
| lcm_spy.wait_for_saved_topic(robot_state_topic, timeout=15.0) | ||
|
|
||
| with lcm_spy._messages_lock: | ||
| raw_robot_state = lcm_spy.messages[robot_state_topic][0] | ||
|
|
||
| robot_state = RobotState.lcm_decode(raw_robot_state) | ||
| assert robot_state.mt_able in (0, 1) | ||
|
|
||
| def test_xarm7_joint_command_updates_joint_state(self, lcm_spy, start_blueprint) -> None: | ||
| joint_state_topic = "/xarm/joint_states#sensor_msgs.JointState" | ||
| joint_command_topic = "/xarm/joint_position_command#sensor_msgs.JointCommand" | ||
| lcm_spy.save_topic(joint_state_topic) | ||
|
|
||
| start_blueprint("simulation-xarm7") | ||
| lcm_spy.wait_for_saved_topic(joint_state_topic, timeout=15.0) | ||
|
|
||
| target_positions = [0.2, -0.2, 0.1, -0.1, 0.15, -0.15, 0.05] | ||
| lcm_spy.publish(joint_command_topic, JointCommand(positions=target_positions)) | ||
|
|
||
| tolerance = 0.03 | ||
| lcm_spy.wait_for_message_result( | ||
| joint_state_topic, | ||
| JointState, | ||
| predicate=lambda msg: _positions_within_tolerance( | ||
| list(msg.position), | ||
| target_positions, | ||
| tolerance, | ||
| ), | ||
| fail_message=("joint_state did not reach commanded positions within tolerance"), | ||
| timeout=10.0, | ||
| ) | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,25 @@ | ||
| """Simulation engines for manipulator backends.""" | ||
|
|
||
| from __future__ import annotations | ||
|
|
||
| from typing import Literal | ||
|
|
||
| from dimos.simulation.engines.base import SimulationEngine | ||
| from dimos.simulation.engines.mujoco_engine import MujocoEngine | ||
|
|
||
| EngineType = Literal["mujoco"] | ||
|
|
||
| _ENGINES: dict[EngineType, type[SimulationEngine]] = { | ||
| "mujoco": MujocoEngine, | ||
| } | ||
|
|
||
|
|
||
| def get_engine(engine_name: EngineType) -> type[SimulationEngine]: | ||
| return _ENGINES[engine_name] | ||
|
|
||
|
|
||
| __all__ = [ | ||
| "EngineType", | ||
| "SimulationEngine", | ||
| "get_engine", | ||
| ] |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,84 @@ | ||
| # Copyright 2025-2026 Dimensional Inc. | ||
| # | ||
| # Licensed under the Apache License, Version 2.0 (the "License"); | ||
| # you may not use this file except in compliance with the License. | ||
| # You may obtain a copy of the License at | ||
| # | ||
| # http://www.apache.org/licenses/LICENSE-2.0 | ||
| # | ||
| # Unless required by applicable law or agreed to in writing, software | ||
| # distributed under the License is distributed on an "AS IS" BASIS, | ||
| # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
| # See the License for the specific language governing permissions and | ||
| # limitations under the License. | ||
|
|
||
| """Base interfaces for simulator engines.""" | ||
|
|
||
| from __future__ import annotations | ||
|
|
||
| from abc import ABC, abstractmethod | ||
| from typing import TYPE_CHECKING | ||
|
|
||
| if TYPE_CHECKING: | ||
| from pathlib import Path | ||
|
|
||
| from dimos.msgs.sensor_msgs import JointState | ||
|
|
||
|
|
||
| class SimulationEngine(ABC): | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. nice |
||
| """Abstract base class for a simulator engine instance.""" | ||
|
|
||
| def __init__(self, config_path: Path, headless: bool) -> None: | ||
| self._config_path = config_path | ||
| self._headless = headless | ||
|
|
||
| @property | ||
| def config_path(self) -> Path: | ||
| return self._config_path | ||
|
|
||
| @property | ||
| def headless(self) -> bool: | ||
| return self._headless | ||
|
|
||
| @abstractmethod | ||
| def connect(self) -> bool: | ||
| """Connect to simulation and start the engine.""" | ||
|
|
||
| @abstractmethod | ||
| def disconnect(self) -> bool: | ||
| """Disconnect from simulation and stop the engine.""" | ||
|
|
||
| @property | ||
| @abstractmethod | ||
| def connected(self) -> bool: | ||
| """Whether the engine is connected.""" | ||
|
|
||
| @property | ||
| @abstractmethod | ||
| def num_joints(self) -> int: | ||
| """Number of joints for the loaded robot.""" | ||
|
|
||
| @property | ||
| @abstractmethod | ||
| def joint_names(self) -> list[str]: | ||
| """Joint names for the loaded robot.""" | ||
|
|
||
| @abstractmethod | ||
| def read_joint_positions(self) -> list[float]: | ||
| """Read joint positions in radians.""" | ||
|
|
||
| @abstractmethod | ||
| def read_joint_velocities(self) -> list[float]: | ||
| """Read joint velocities in rad/s.""" | ||
|
|
||
| @abstractmethod | ||
| def read_joint_efforts(self) -> list[float]: | ||
| """Read joint efforts in Nm.""" | ||
|
|
||
| @abstractmethod | ||
| def write_joint_command(self, command: JointState) -> None: | ||
| """Command joints using a JointState message.""" | ||
|
|
||
| @abstractmethod | ||
| def hold_current_position(self) -> None: | ||
| """Hold current joint positions.""" | ||
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.