# Path: robel/components/robot/dynamixel_robot.py
# class DynamixelRobotState(RobotState):
# class DynamixelGroupConfig(HardwareRobotGroupConfig):
# class DynamixelRobotComponent(HardwareRobotComponent):
#     def __init__(self, *args, current: Optional[np.ndarray] = None, **kwargs):
#     def __init__(self,
#                  *args,
#                  motor_ids: Optional[Iterable[int]] = None,
#                  **kwargs):
#     def is_active(self) -> bool:
#     def set_all_motor_ids(self, all_motor_ids: Sequence[int]):
#     def __init__(self, *args, groups: Dict[str, Dict], device_path: str,
#                  **kwargs):
#     def _process_group(self, **config_kwargs) -> DynamixelGroupConfig:
#     def set_motors_engaged(self, groups: Union[str, Sequence[str], None],
#                            engaged: bool):
#     def _get_group_states(
#             self,
#             configs: Sequence[DynamixelGroupConfig],
#     ) -> Sequence[DynamixelRobotState]:
#     def _set_group_states(
#             self,
#             group_states: Sequence[Tuple[DynamixelGroupConfig, RobotState]],
#             block: bool = True,
#             **block_kwargs):
#     def _perform_timestep(
#             self,
#             group_controls: Sequence[Tuple[DynamixelGroupConfig, np.ndarray]]):
#     def _set_hardware_control(
#             self,
#             group_control: Sequence[Tuple[DynamixelGroupConfig, np.ndarray]]):
#     DEVICE_CLIENTS = {}
# 
# Path: robel/utils/testing/mock_sim_scene.py
# class MockSimScene:
#     """Mock object that implements the SimScene interface."""
# 
#     @staticmethod
#     def create(*unused_args, **unused_kwargs):
#         raise NotImplementedError('`patch_sim_scene` must be called.')
# 
#     def __init__(self, *args, step_duration: float = 1, **kwargs):
#         """Initializes a new mock SimScene."""
#         self.sim = mock.Mock()
#         self.sim.model = MockMjModel(*args, **kwargs)
# 
#         self.model = self.sim.model
#         self.sim.data = self.model
#         self.data = self.model.data
# 
#         self.step_duration = step_duration
# 
#         self.close = mock.Mock()
#         self.advance = mock.Mock()
# 
#         self.renderer = mock.Mock()
#         self.renderer.render_offscreen = lambda w, h, **_: np.zeros((w, h))
# 
# Path: robel/utils/testing/mock_time.py
# def patch_time(module_path: str, **kwargs):
#     return mock.patch(module_path, MockTime(**kwargs))


from typing import Any, Sequence
from absl.testing import absltest
from absl.testing.absltest import mock
from robel.components.robot.dynamixel_robot import (
    DynamixelRobotComponent, RobotState)
from robel.utils.testing.mock_sim_scene import MockSimScene
from robel.utils.testing.mock_time import patch_time
import numpy as np
    def test_step(self):
        """Tests stepping with an action for multiple groups."""
        sim_scene = MockSimScene(nq=10, ctrl_range=[-1, 1])  # type: Any
        robot = DynamixelRobotComponent(
            sim_scene,
            groups={
                'a': {
                    'qpos_indices': [0, 1, 2],
                    'motor_ids': [10, 11, 12],
                    'calib_offset': [1] * 3,
                    'calib_scale': [-1] * 3,
                    'qpos_range': [(-0.5, 0.5)] * 3,
                },
                'b': {
                    'qpos_indices': [2, 3],
                },
            },
            device_path='test')
        with patch_time('robel.components.robot.hardware_robot.time'):
            robot.step({
                'a': np.array([.2, .4, .6]),
                'b': np.array([.1, .3]),
            })
        dxl = DynamixelRobotComponent.DEVICE_CLIENTS['test']  # type: Any

        np.testing.assert_allclose(dxl.qpos, [.9, .8, .7])

    @patch_dynamixel
    def test_set_state(self):
        """Tests stepping with an action for multiple groups."""

# Path: robel/components/robot/dynamixel_robot.py
# class DynamixelRobotState(RobotState):
# class DynamixelGroupConfig(HardwareRobotGroupConfig):
# class DynamixelRobotComponent(HardwareRobotComponent):
#     def __init__(self, *args, current: Optional[np.ndarray] = None, **kwargs):
#     def __init__(self,
#                  *args,
#                  motor_ids: Optional[Iterable[int]] = None,
#                  **kwargs):
#     def is_active(self) -> bool:
#     def set_all_motor_ids(self, all_motor_ids: Sequence[int]):
#     def __init__(self, *args, groups: Dict[str, Dict], device_path: str,
#                  **kwargs):
#     def _process_group(self, **config_kwargs) -> DynamixelGroupConfig:
#     def set_motors_engaged(self, groups: Union[str, Sequence[str], None],
#                            engaged: bool):
#     def _get_group_states(
#             self,
#             configs: Sequence[DynamixelGroupConfig],
#     ) -> Sequence[DynamixelRobotState]:
#     def _set_group_states(
#             self,
#             group_states: Sequence[Tuple[DynamixelGroupConfig, RobotState]],
#             block: bool = True,
#             **block_kwargs):
#     def _perform_timestep(
#             self,
#             group_controls: Sequence[Tuple[DynamixelGroupConfig, np.ndarray]]):
#     def _set_hardware_control(
#             self,
#             group_control: Sequence[Tuple[DynamixelGroupConfig, np.ndarray]]):
#     DEVICE_CLIENTS = {}
# 
# Path: robel/utils/testing/mock_sim_scene.py
# class MockSimScene:
#     """Mock object that implements the SimScene interface."""
# 
#     @staticmethod
#     def create(*unused_args, **unused_kwargs):
#         raise NotImplementedError('`patch_sim_scene` must be called.')
# 
#     def __init__(self, *args, step_duration: float = 1, **kwargs):
#         """Initializes a new mock SimScene."""
#         self.sim = mock.Mock()
#         self.sim.model = MockMjModel(*args, **kwargs)
# 
#         self.model = self.sim.model
#         self.sim.data = self.model
#         self.data = self.model.data
# 
#         self.step_duration = step_duration
# 
#         self.close = mock.Mock()
#         self.advance = mock.Mock()
# 
#         self.renderer = mock.Mock()
#         self.renderer.render_offscreen = lambda w, h, **_: np.zeros((w, h))
# 
# Path: robel/utils/testing/mock_time.py
# def patch_time(module_path: str, **kwargs):
#     return mock.patch(module_path, MockTime(**kwargs))


# Path: robel/components/robot/dynamixel_robot_test.py
from typing import Any, Sequence
from absl.testing import absltest
from absl.testing.absltest import mock
from robel.components.robot.dynamixel_robot import (
    DynamixelRobotComponent, RobotState)
from robel.utils.testing.mock_sim_scene import MockSimScene
from robel.utils.testing.mock_time import patch_time
import numpy as np

    def test_step(self):
        """Tests stepping with an action for multiple groups."""
        sim_scene = MockSimScene(nq=10, ctrl_range=[-1, 1])  # type: Any
        robot = DynamixelRobotComponent(
            sim_scene,
            groups={
                'a': {
                    'qpos_indices': [0, 1, 2],
                    'motor_ids': [10, 11, 12],
                    'calib_offset': [1] * 3,
                    'calib_scale': [-1] * 3,
                    'qpos_range': [(-0.5, 0.5)] * 3,
                },
                'b': {
                    'qpos_indices': [2, 3],
                },
            },
            device_path='test')
        with patch_time('robel.components.robot.hardware_robot.time'):
            robot.step({
                'a': np.array([.2, .4, .6]),
                'b': np.array([.1, .3]),
            })
        dxl = DynamixelRobotComponent.DEVICE_CLIENTS['test']  # type: Any

        np.testing.assert_allclose(dxl.qpos, [.9, .8, .7])

    @patch_dynamixel
    def test_set_state(self):
        """Tests stepping with an action for multiple groups."""

        sim_scene = MockSimScene(nq=10)  # type: Any