dexbot-utils 0.4.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (41) hide show
  1. dexbot_utils/__init__.py +49 -0
  2. dexbot_utils/_helpers.py +49 -0
  3. dexbot_utils/cfg_modifier.py +99 -0
  4. dexbot_utils/cli.py +97 -0
  5. dexbot_utils/configs/__init__.py +31 -0
  6. dexbot_utils/configs/components/__init__.py +8 -0
  7. dexbot_utils/configs/components/base.py +28 -0
  8. dexbot_utils/configs/components/sensors/__init__.py +20 -0
  9. dexbot_utils/configs/components/sensors/cameras/__init__.py +20 -0
  10. dexbot_utils/configs/components/sensors/cameras/camera.py +38 -0
  11. dexbot_utils/configs/components/sensors/cameras/zed_camera.py +102 -0
  12. dexbot_utils/configs/components/sensors/imu/__init__.py +17 -0
  13. dexbot_utils/configs/components/sensors/imu/chassis_imu.py +20 -0
  14. dexbot_utils/configs/components/sensors/imu/zed_imu.py +20 -0
  15. dexbot_utils/configs/components/sensors/lidar/__init__.py +14 -0
  16. dexbot_utils/configs/components/sensors/lidar/lidar_3d.py +22 -0
  17. dexbot_utils/configs/components/sensors/lidar/rplidar.py +20 -0
  18. dexbot_utils/configs/components/sensors/ultrasonic/__init__.py +13 -0
  19. dexbot_utils/configs/components/sensors/ultrasonic/ultrasonic.py +20 -0
  20. dexbot_utils/configs/components/vega_1/__init__.py +30 -0
  21. dexbot_utils/configs/components/vega_1/arm.py +81 -0
  22. dexbot_utils/configs/components/vega_1/chassis.py +47 -0
  23. dexbot_utils/configs/components/vega_1/hand.py +113 -0
  24. dexbot_utils/configs/components/vega_1/head.py +32 -0
  25. dexbot_utils/configs/components/vega_1/misc.py +46 -0
  26. dexbot_utils/configs/components/vega_1/torso.py +41 -0
  27. dexbot_utils/configs/registry.py +112 -0
  28. dexbot_utils/configs/robots/base.py +24 -0
  29. dexbot_utils/configs/robots/vega_1.py +127 -0
  30. dexbot_utils/configs/robots/vega_1p.py +127 -0
  31. dexbot_utils/configs/robots/vega_1u.py +102 -0
  32. dexbot_utils/constants.py +19 -0
  33. dexbot_utils/hand.py +19 -0
  34. dexbot_utils/robot_info.py +577 -0
  35. dexbot_utils/urdf_utils.py +354 -0
  36. dexbot_utils/validators.py +194 -0
  37. dexbot_utils-0.4.0.dist-info/METADATA +298 -0
  38. dexbot_utils-0.4.0.dist-info/RECORD +41 -0
  39. dexbot_utils-0.4.0.dist-info/WHEEL +4 -0
  40. dexbot_utils-0.4.0.dist-info/entry_points.txt +2 -0
  41. dexbot_utils-0.4.0.dist-info/licenses/LICENSE +184 -0
@@ -0,0 +1,49 @@
1
+ """
2
+ dexbot-utils: Common robot utility classes and functions.
3
+
4
+ This package provides utilities for:
5
+ - Robot identification and configuration
6
+ - Component validation
7
+ - URDF parsing for joint information
8
+ """
9
+
10
+ __version__ = "0.1.0"
11
+
12
+ # Main interface
13
+ from .hand import HandType
14
+ from .robot_info import RobotInfo
15
+
16
+ # URDF utilities
17
+ from .urdf_utils import (
18
+ get_joint_names,
19
+ get_movable_joint_names,
20
+ parse_urdf,
21
+ )
22
+
23
+ # Component validation
24
+ from .validators import (
25
+ ComponentValidationError,
26
+ has_all_components,
27
+ has_component,
28
+ validate_component,
29
+ validate_components,
30
+ )
31
+
32
+ __all__ = [
33
+ # Version
34
+ "__version__",
35
+ # Main interface
36
+ "RobotInfo",
37
+ # Validators
38
+ "ComponentValidationError",
39
+ "validate_component",
40
+ "validate_components",
41
+ "has_component",
42
+ "has_all_components",
43
+ # Hand
44
+ "HandType",
45
+ # URDF utilities
46
+ "parse_urdf",
47
+ "get_joint_names",
48
+ "get_movable_joint_names",
49
+ ]
@@ -0,0 +1,49 @@
1
+ """Internal helper functions for robot configuration."""
2
+
3
+ from functools import lru_cache
4
+
5
+
6
+ @lru_cache(maxsize=None)
7
+ def build_robot_type_abbreviation_mapping() -> dict[str, str]:
8
+ """Build robot type abbreviation mapping from registered configurations.
9
+
10
+ Scans all registered robot configurations and builds a mapping of abbreviations
11
+ to robot types (e.g., "vg" -> "vega").
12
+
13
+ Note: vega_1u (upper body) uses "vg" abbreviation with "u" suffix in robot name
14
+ (e.g., "dm/vg0123456789-1u" for vega upper body).
15
+
16
+ Returns:
17
+ Dictionary mapping abbreviations to robot types.
18
+
19
+ Example:
20
+ >>> mapping = build_robot_type_abbreviation_mapping()
21
+ >>> print(mapping)
22
+ {'vg': 'vega'}
23
+ """
24
+ from .configs import ConfigRegistry
25
+
26
+ mapping = {}
27
+
28
+ # Get all registered variants
29
+ for variant in ConfigRegistry.list_variants():
30
+ config = ConfigRegistry.get(variant)
31
+
32
+ # Get abbreviation and robot_model from config
33
+ abbr = config.abbr
34
+ robot_model = config.robot_model
35
+
36
+ # Extract robot type from robot_model (e.g., "vega_1" -> "vega")
37
+ # Split on '_' and take everything except the last part (version)
38
+ parts = robot_model.rsplit("_", 1)
39
+ robot_type = parts[0] if len(parts) > 1 else robot_model
40
+
41
+ # Add to mapping if not already present
42
+ if abbr not in mapping:
43
+ mapping[abbr] = robot_type
44
+
45
+ return mapping
46
+
47
+
48
+ # Build once at module load
49
+ ROBOT_TYPE_ABB_MAPPING = build_robot_type_abbreviation_mapping()
@@ -0,0 +1,99 @@
1
+ from loguru import logger
2
+
3
+ from .configs import BaseRobotConfig
4
+ from .configs.components.vega_1.hand import (
5
+ DexDGripperConfig,
6
+ DexSGripperConfig,
7
+ F5D6HandV1Config,
8
+ F5D6HandV2Config,
9
+ )
10
+ from .hand import HandType
11
+
12
+
13
+ def runtime_override_robot_config(
14
+ config: BaseRobotConfig,
15
+ hand_types: dict[str, HandType],
16
+ enable_hand_type_override: bool = True,
17
+ disable_estop_checking: bool = False,
18
+ disable_heartbeat: bool = False,
19
+ ):
20
+ """Apply runtime-driven overrides to a robot's configuration.
21
+
22
+ This function mutates `robot_info.config` in place based on runtime inputs:
23
+ - Optionally disables the `estop` and `heartbeat` components.
24
+ - Updates end-effector (hand) components per detected `hand_types`.
25
+ - Removes a hand component when the detected type is `HandType.UNKNOWN`.
26
+ - Replaces a mismatched hand component when `enable_hand_type_override` is True.
27
+ - Disables arm end-effector pass-through (`enable_ee_pass_through = False`)
28
+ when a concrete hand type is provided.
29
+ - Emits warnings via the logger when overrides or removals occur.
30
+
31
+ Args:
32
+ robot_info: Robot metadata and configuration container to be mutated.
33
+ hand_types: Mapping from side name (`"left"`, `"right"`) to detected
34
+ `HandType`. Use `HandType.UNKNOWN` when no hand is detected.
35
+ enable_hand_type_override: If True, replaces an existing hand component in
36
+ the config when it does not match the detected `HandType`. If False,
37
+ leaves the original component and logs a warning.
38
+ disable_estop_checking: If True, disables the `estop` component (when
39
+ present) and logs a warning.
40
+ disable_heartbeat: If True, disables the `heartbeat` component (when
41
+ present) and logs a warning.
42
+
43
+ """
44
+
45
+ if disable_estop_checking:
46
+ if "estop" in config.components:
47
+ config.components["estop"].enabled = False
48
+ logger.warning("EStop checking is disabled via environment variable")
49
+
50
+ if disable_heartbeat:
51
+ if "heartbeat" in config.components:
52
+ config.components["heartbeat"].enabled = False
53
+ logger.warning("Heartbeat is disabled via environment variable")
54
+
55
+ # Handling hand types
56
+ hand_type_mapping = {
57
+ DexSGripperConfig: HandType.DexGripper,
58
+ DexDGripperConfig: HandType.DexGripper,
59
+ F5D6HandV1Config: HandType.HandF5D6_V1,
60
+ F5D6HandV2Config: HandType.HandF5D6_V2,
61
+ }
62
+ hand_type_reverse_mapping = {
63
+ HandType.DexGripper: DexDGripperConfig,
64
+ HandType.HandF5D6_V1: F5D6HandV1Config,
65
+ HandType.HandF5D6_V2: F5D6HandV2Config,
66
+ }
67
+ for side in ("left", "right"):
68
+ if side in hand_types:
69
+ hand_type = hand_types[side]
70
+ if f"{side}_arm" in config.components:
71
+ arm = config.components[f"{side}_arm"]
72
+ # EE pass-through is disabled when hand type is specified
73
+ if hand_type != HandType.UNKNOWN:
74
+ arm.enable_ee_pass_through = False
75
+
76
+ hand_key = f"{side}_hand"
77
+ if hand_key in config.components:
78
+ if hand_type == HandType.UNKNOWN:
79
+ # config.components.pop(hand_key)
80
+ logger.warning(
81
+ f"No {side}_hand detected at runtime, the future version will remove the hand component from the config in this case. For now, we will keep the hand component in the config."
82
+ )
83
+ else:
84
+ desired_hand_type = hand_type_mapping[
85
+ type(config.components[hand_key])
86
+ ]
87
+ if desired_hand_type != hand_type:
88
+ if enable_hand_type_override:
89
+ override_hand_cfg = hand_type_reverse_mapping[hand_type](
90
+ side=side
91
+ )
92
+ config.components[hand_key] = override_hand_cfg
93
+ logger.warning(
94
+ f"Override {side}_hand config to {override_hand_cfg} based on detected hand type {hand_type}"
95
+ )
96
+ else:
97
+ logger.warning(
98
+ f"Detected {side}_hand type is {hand_type}, but the input config is {desired_hand_type}."
99
+ )
dexbot_utils/cli.py ADDED
@@ -0,0 +1,97 @@
1
+ #!/usr/bin/env python3
2
+ """Command-line interface for dexbot-utils.
3
+
4
+ Provides CLI commands for exploring robot configurations and utilities.
5
+ """
6
+
7
+ from pathlib import Path
8
+
9
+ import typer
10
+
11
+ from dexbot_utils.configs import get_available_variants, get_robot_config
12
+
13
+ app = typer.Typer(
14
+ name="dexbot",
15
+ help="DexBot Utilities - Robot configuration and utility tools",
16
+ no_args_is_help=True,
17
+ )
18
+
19
+ cfg_app = typer.Typer(
20
+ name="cfg",
21
+ help="Robot configuration management commands",
22
+ no_args_is_help=True,
23
+ )
24
+ app.add_typer(cfg_app, name="cfg")
25
+
26
+
27
+ @cfg_app.command("list")
28
+ def config_list() -> None:
29
+ """List all available robot configuration variants."""
30
+ variants = get_available_variants()
31
+
32
+ typer.echo(f"Available robot configurations: {len(variants)}")
33
+ for variant in sorted(variants):
34
+ typer.echo(f" - {variant}")
35
+
36
+
37
+ @cfg_app.command("show")
38
+ def config_show(
39
+ config: str = typer.Argument(
40
+ ...,
41
+ help="Robot variant name (e.g., vega_1) or path to config file",
42
+ ),
43
+ ) -> None:
44
+ """Show detailed information for a specific robot configuration.
45
+
46
+ CONFIG can be either:
47
+ - A variant name (e.g., vega_1, vega_1_gripper)
48
+ - A path to a configuration file
49
+ """
50
+ # Check if config is a file path
51
+ config_path = Path(config)
52
+ if config_path.exists() and config_path.is_file():
53
+ typer.echo(f"Loading config from file: {config_path}")
54
+ # TODO: Implement file-based config loading if needed
55
+ typer.echo("File-based config loading not yet implemented.", err=True)
56
+ raise typer.Exit(1)
57
+
58
+ # Treat as variant name
59
+ variant = config
60
+ try:
61
+ robot_config = get_robot_config(variant)
62
+
63
+ typer.echo(f"Robot Configuration: {variant}")
64
+ typer.echo("=" * 70)
65
+ typer.echo(f"Robot Model: {robot_config.robot_model}")
66
+ typer.echo(f"Abbreviation: {robot_config.abbr}")
67
+ typer.echo(f"URDF Path: {robot_config.urdf_path}")
68
+
69
+ # List components
70
+ typer.echo(f"\nComponents ({len(robot_config.components)}):")
71
+ for comp_name in sorted(robot_config.components.keys()):
72
+ comp = robot_config.components[comp_name]
73
+ comp_type = type(comp).__name__
74
+ typer.echo(f" - {comp_name}: {comp_type}")
75
+
76
+ # List sensors
77
+ if hasattr(robot_config, "sensors") and robot_config.sensors:
78
+ typer.echo(f"\nSensors ({len(robot_config.sensors)}):")
79
+ for sensor_name in sorted(robot_config.sensors.keys()):
80
+ sensor = robot_config.sensors[sensor_name]
81
+ sensor_type = type(sensor).__name__
82
+ typer.echo(f" - {sensor_name}: {sensor_type}")
83
+
84
+ # List queryables
85
+ if hasattr(robot_config, "querables") and robot_config.querables:
86
+ typer.echo(f"\nQueryables ({len(robot_config.querables)}):")
87
+ for query_name in sorted(robot_config.querables.keys()):
88
+ query_path = robot_config.querables[query_name]
89
+ typer.echo(f" - {query_name}: {query_path}")
90
+
91
+ except ValueError as e:
92
+ typer.echo(f"Error: {e}", err=True)
93
+ raise typer.Exit(1)
94
+
95
+
96
+ if __name__ == "__main__":
97
+ app()
@@ -0,0 +1,31 @@
1
+ """Robot configuration system using dataclasses."""
2
+
3
+ from .components import BaseComponentConfig
4
+ from .registry import (
5
+ ConfigRegistry,
6
+ get_available_variants,
7
+ get_robot_config,
8
+ register_variant,
9
+ )
10
+ from .robots.base import BaseRobotConfig
11
+ from .robots.vega_1 import Vega1Config, Vega1DGripperConfig, Vega1F5D6Config
12
+ from .robots.vega_1p import Vega1pConfig, Vega1pDGripperConfig, Vega1pF5D6Config
13
+ from .robots.vega_1u import Vega1UConfig, Vega1UDGripperConfig, Vega1UF5D6Config
14
+
15
+ __all__ = [
16
+ "ConfigRegistry",
17
+ "register_variant",
18
+ "get_robot_config",
19
+ "get_available_variants",
20
+ "BaseRobotConfig",
21
+ "BaseComponentConfig",
22
+ "Vega1Config",
23
+ "Vega1DGripperConfig",
24
+ "Vega1F5D6Config",
25
+ "Vega1UConfig",
26
+ "Vega1UDGripperConfig",
27
+ "Vega1UF5D6Config",
28
+ "Vega1pConfig",
29
+ "Vega1pDGripperConfig",
30
+ "Vega1pF5D6Config",
31
+ ]
@@ -0,0 +1,8 @@
1
+ """Component configuration dataclasses for robot components."""
2
+
3
+ from .base import BaseComponentConfig, BaseJointComponentConfig
4
+
5
+ __all__ = [
6
+ "BaseComponentConfig",
7
+ "BaseJointComponentConfig",
8
+ ]
@@ -0,0 +1,28 @@
1
+ """Base component configuration classes."""
2
+
3
+ from dataclasses import MISSING, dataclass, field
4
+
5
+
6
+ @dataclass
7
+ class BaseComponentConfig:
8
+ """Base configuration for a generic robot component.
9
+
10
+ Attributes:
11
+ enabled: Whether the component is enabled in the configuration
12
+ """
13
+
14
+ enabled: bool = True
15
+
16
+
17
+ @dataclass
18
+ class BaseJointComponentConfig(BaseComponentConfig):
19
+ """Base configuration for a robot component with joints.
20
+
21
+ Subclasses must define a `joints` attribute, either as a dataclass field
22
+ or as a property that computes joint names dynamically.
23
+
24
+ Attributes:
25
+ joints: List of joint names for the component (field or property)
26
+ """
27
+
28
+ joints: list[str] = field(default=MISSING, init=False)
@@ -0,0 +1,20 @@
1
+ """Vega-specific component configuration dataclasses.
2
+
3
+ This module contains Vega robot family specific component configurations.
4
+ """
5
+
6
+ from .cameras import CameraConfig, ZedXCameraConfig, ZedXOneCameraConfig
7
+ from .imu import ChassisIMUConfig, ZedIMUConfig
8
+ from .lidar import Lidar3DConfig, RPLidarConfig
9
+ from .ultrasonic import UltraSonicConfig
10
+
11
+ __all__ = [
12
+ "CameraConfig",
13
+ "ZedXCameraConfig",
14
+ "ZedXOneCameraConfig",
15
+ "ChassisIMUConfig",
16
+ "ZedIMUConfig",
17
+ "Lidar3DConfig",
18
+ "RPLidarConfig",
19
+ "UltraSonicConfig",
20
+ ]
@@ -0,0 +1,20 @@
1
+ # Copyright (C) 2025 Dexmate Inc.
2
+ #
3
+ # This software is dual-licensed:
4
+ #
5
+ # 1. GNU Affero General Public License v3.0 (AGPL-3.0)
6
+ # See LICENSE-AGPL for details
7
+ #
8
+ # 2. Commercial License
9
+ # For commercial licensing terms, contact: contact@dexmate.ai
10
+
11
+ """Camera sensor configurations."""
12
+
13
+ from .camera import CameraConfig
14
+ from .zed_camera import ZedXCameraConfig, ZedXOneCameraConfig
15
+
16
+ __all__ = [
17
+ "CameraConfig",
18
+ "ZedXCameraConfig",
19
+ "ZedXOneCameraConfig",
20
+ ]
@@ -0,0 +1,38 @@
1
+ # Copyright (C) 2025 Dexmate Inc.
2
+ #
3
+ # This software is dual-licensed:
4
+ #
5
+ # 1. GNU Affero General Public License v3.0 (AGPL-3.0)
6
+ # See LICENSE-AGPL for details
7
+ #
8
+ # 2. Commercial License
9
+ # For commercial licensing terms, contact: contact@dexmate.ai
10
+
11
+ """Configuration for USB camera sensor."""
12
+
13
+ from dataclasses import dataclass
14
+
15
+ from ...base import BaseComponentConfig
16
+
17
+
18
+ @dataclass
19
+ class CameraConfig(BaseComponentConfig):
20
+ """Configuration for camera sensor.
21
+
22
+ This configuration supports both Zenoh (reliable, JPEG compressed) and
23
+ RTC (low latency, hardware accelerated video) transports.
24
+
25
+ Attributes:
26
+ name: Camera name identifier
27
+ transport: Transport protocol ("zenoh" or "rtc")
28
+ topic: Topic for camera data publishing
29
+ rtc_channel: Channel name for RTC transport
30
+ """
31
+
32
+ enabled: bool = False
33
+
34
+ name: str = "usb_camera"
35
+ transport: str = "zenoh" # or "rtc"
36
+ topic: str = "sensors/camera/rgb"
37
+
38
+ rtc_channel: str = "sensors/camera/rgb_rtc"
@@ -0,0 +1,102 @@
1
+ # Copyright (C) 2025 Dexmate Inc.
2
+ #
3
+ # This software is dual-licensed:
4
+ #
5
+ # 1. GNU Affero General Public License v3.0 (AGPL-3.0)
6
+ # See LICENSE-AGPL for details
7
+ #
8
+ # 2. Commercial License
9
+ # For commercial licensing terms, contact: contact@dexmate.ai
10
+
11
+ """Configuration for ZED camera sensor."""
12
+
13
+ from dataclasses import dataclass
14
+
15
+ from ...base import BaseComponentConfig
16
+ from .camera import CameraConfig
17
+
18
+
19
+ @dataclass
20
+ class ZedXCameraConfig(BaseComponentConfig):
21
+ """Configuration for ZED stereo camera sensor.
22
+
23
+ This configuration supports multi-stream ZED cameras with independent
24
+ transport settings for each RGB stream. Depth always uses Zenoh.
25
+
26
+ Attributes:
27
+ name: Camera name identifier
28
+ transport: Transport protocol for RGB streams ("zenoh" or "rtc")
29
+ enable_rgb: Enable left and right RGB stream capture
30
+ enable_depth: Enable depth stream capture
31
+ left_rgb: Property returning left RGB camera configuration
32
+ right_rgb: Property returning right RGB camera configuration
33
+ depth: Property returning depth camera configuration
34
+ """
35
+
36
+ enabled: bool = False
37
+ name: str = "head_camera"
38
+ transport: str = "zenoh"
39
+ enable_rgb: bool = True
40
+ enable_depth: bool = True
41
+
42
+ @property
43
+ def left_rgb(self) -> CameraConfig:
44
+ return CameraConfig(
45
+ enabled=self.enabled & self.enable_rgb,
46
+ name="left_rgb",
47
+ transport=self.transport,
48
+ topic=f"sensors/{self.name}/left_rgb",
49
+ rtc_channel=f"sensors/{self.name}/left_rgb_rtc",
50
+ )
51
+
52
+ @property
53
+ def right_rgb(self) -> CameraConfig:
54
+ return CameraConfig(
55
+ enabled=self.enabled & self.enable_rgb,
56
+ name="right_rgb",
57
+ transport=self.transport,
58
+ topic=f"sensors/{self.name}/right_rgb",
59
+ rtc_channel=f"sensors/{self.name}/right_rgb_rtc",
60
+ )
61
+
62
+ @property
63
+ def depth(self) -> CameraConfig:
64
+ return CameraConfig(
65
+ enabled=self.enabled & self.enable_depth,
66
+ name="depth",
67
+ transport=self.transport,
68
+ topic=f"sensors/{self.name}/depth",
69
+ )
70
+
71
+
72
+ @dataclass
73
+ class ZedXOneCameraConfig(BaseComponentConfig):
74
+ """Configuration for ZED stereo camera sensor.
75
+
76
+ This configuration supports multi-stream ZED cameras with independent
77
+ transport settings for each RGB stream. Depth always uses Zenoh.
78
+
79
+ Attributes:
80
+ name: Camera name identifier
81
+ transport: Transport protocol for RGB streams ("zenoh" or "rtc")
82
+ enable_rgb: Enable left and right RGB stream capture
83
+ enable_depth: Enable depth stream capture
84
+ left_rgb: Property returning left RGB camera configuration
85
+ right_rgb: Property returning right RGB camera configuration
86
+ depth: Property returning depth camera configuration
87
+ """
88
+
89
+ enabled: bool = False
90
+ name: str = "wrist_camera"
91
+ transport: str = "zenoh"
92
+ side: str = "left"
93
+
94
+ @property
95
+ def rgb(self) -> CameraConfig:
96
+ return CameraConfig(
97
+ enabled=self.enabled,
98
+ name="rgb",
99
+ transport=self.transport,
100
+ topic=f"sensors/{self.side}_{self.name}/rgb",
101
+ rtc_channel=f"sensors/{self.name}/rgb_rtc",
102
+ )
@@ -0,0 +1,17 @@
1
+ # Copyright (C) 2025 Dexmate Inc.
2
+ #
3
+ # This software is dual-licensed:
4
+ #
5
+ # 1. GNU Affero General Public License v3.0 (AGPL-3.0)
6
+ # See LICENSE-AGPL for details
7
+ #
8
+ # 2. Commercial License
9
+ # For commercial licensing terms, contact: contact@dexmate.ai
10
+
11
+ from .chassis_imu import ChassisIMUConfig
12
+ from .zed_imu import ZedIMUConfig
13
+
14
+ __all__ = [
15
+ "ChassisIMUConfig",
16
+ "ZedIMUConfig",
17
+ ]
@@ -0,0 +1,20 @@
1
+ # Copyright (C) 2025 Dexmate Inc.
2
+ #
3
+ # This software is dual-licensed:
4
+ #
5
+ # 1. GNU Affero General Public License v3.0 (AGPL-3.0)
6
+ # See LICENSE-AGPL for details
7
+ #
8
+ # 2. Commercial License
9
+ # For commercial licensing terms, contact: contact@dexmate.ai
10
+
11
+ from dataclasses import dataclass
12
+
13
+ from ...base import BaseComponentConfig
14
+
15
+
16
+ @dataclass
17
+ class ChassisIMUConfig(BaseComponentConfig):
18
+ enabled: bool = False
19
+ topic: str = "state/chassis_imu"
20
+ name: str = "chassis_imu"
@@ -0,0 +1,20 @@
1
+ # Copyright (C) 2025 Dexmate Inc.
2
+ #
3
+ # This software is dual-licensed:
4
+ #
5
+ # 1. GNU Affero General Public License v3.0 (AGPL-3.0)
6
+ # See LICENSE-AGPL for details
7
+ #
8
+ # 2. Commercial License
9
+ # For commercial licensing terms, contact: contact@dexmate.ai
10
+
11
+ from dataclasses import dataclass
12
+
13
+ from ...base import BaseComponentConfig
14
+
15
+
16
+ @dataclass
17
+ class ZedIMUConfig(BaseComponentConfig):
18
+ enabled: bool = False
19
+ topic: str = "sensors/head_camera/imu"
20
+ name: str = "head_camera_imu"
@@ -0,0 +1,14 @@
1
+ # Copyright (C) 2025 Dexmate Inc.
2
+ #
3
+ # This software is dual-licensed:
4
+ #
5
+ # 1. GNU Affero General Public License v3.0 (AGPL-3.0)
6
+ # See LICENSE-AGPL for details
7
+ #
8
+ # 2. Commercial License
9
+ # For commercial licensing terms, contact: contact@dexmate.ai
10
+
11
+ from .lidar_3d import Lidar3DConfig
12
+ from .rplidar import RPLidarConfig
13
+
14
+ __all__ = ["RPLidarConfig", "Lidar3DConfig"]
@@ -0,0 +1,22 @@
1
+ # Copyright (C) 2025 Dexmate Inc.
2
+ #
3
+ # This software is dual-licensed:
4
+ #
5
+ # 1. GNU Affero General Public License v3.0 (AGPL-3.0)
6
+ # See LICENSE-AGPL for details
7
+ #
8
+ # 2. Commercial License
9
+ # For commercial licensing terms, contact: contact@dexmate.ai
10
+
11
+ from dataclasses import dataclass
12
+
13
+ from ...base import BaseComponentConfig
14
+
15
+
16
+ @dataclass
17
+ class Lidar3DConfig(BaseComponentConfig):
18
+ """Configuration for 3D LIDAR point cloud sensor."""
19
+
20
+ enabled: bool = False
21
+ topic: str = "sensors/lidar_3d/points"
22
+ name: str = "lidar_3d"
@@ -0,0 +1,20 @@
1
+ # Copyright (C) 2025 Dexmate Inc.
2
+ #
3
+ # This software is dual-licensed:
4
+ #
5
+ # 1. GNU Affero General Public License v3.0 (AGPL-3.0)
6
+ # See LICENSE-AGPL for details
7
+ #
8
+ # 2. Commercial License
9
+ # For commercial licensing terms, contact: contact@dexmate.ai
10
+
11
+ from dataclasses import dataclass
12
+
13
+ from ...base import BaseComponentConfig
14
+
15
+
16
+ @dataclass
17
+ class RPLidarConfig(BaseComponentConfig):
18
+ enabled: bool = False
19
+ topic: str = "sensors/lidar_front/scan"
20
+ name: str = "rplidar"
@@ -0,0 +1,13 @@
1
+ # Copyright (C) 2025 Dexmate Inc.
2
+ #
3
+ # This software is dual-licensed:
4
+ #
5
+ # 1. GNU Affero General Public License v3.0 (AGPL-3.0)
6
+ # See LICENSE-AGPL for details
7
+ #
8
+ # 2. Commercial License
9
+ # For commercial licensing terms, contact: contact@dexmate.ai
10
+
11
+ from .ultrasonic import UltraSonicConfig
12
+
13
+ __all__ = ["UltraSonicConfig"]