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.
- dexbot_utils/__init__.py +49 -0
- dexbot_utils/_helpers.py +49 -0
- dexbot_utils/cfg_modifier.py +99 -0
- dexbot_utils/cli.py +97 -0
- dexbot_utils/configs/__init__.py +31 -0
- dexbot_utils/configs/components/__init__.py +8 -0
- dexbot_utils/configs/components/base.py +28 -0
- dexbot_utils/configs/components/sensors/__init__.py +20 -0
- dexbot_utils/configs/components/sensors/cameras/__init__.py +20 -0
- dexbot_utils/configs/components/sensors/cameras/camera.py +38 -0
- dexbot_utils/configs/components/sensors/cameras/zed_camera.py +102 -0
- dexbot_utils/configs/components/sensors/imu/__init__.py +17 -0
- dexbot_utils/configs/components/sensors/imu/chassis_imu.py +20 -0
- dexbot_utils/configs/components/sensors/imu/zed_imu.py +20 -0
- dexbot_utils/configs/components/sensors/lidar/__init__.py +14 -0
- dexbot_utils/configs/components/sensors/lidar/lidar_3d.py +22 -0
- dexbot_utils/configs/components/sensors/lidar/rplidar.py +20 -0
- dexbot_utils/configs/components/sensors/ultrasonic/__init__.py +13 -0
- dexbot_utils/configs/components/sensors/ultrasonic/ultrasonic.py +20 -0
- dexbot_utils/configs/components/vega_1/__init__.py +30 -0
- dexbot_utils/configs/components/vega_1/arm.py +81 -0
- dexbot_utils/configs/components/vega_1/chassis.py +47 -0
- dexbot_utils/configs/components/vega_1/hand.py +113 -0
- dexbot_utils/configs/components/vega_1/head.py +32 -0
- dexbot_utils/configs/components/vega_1/misc.py +46 -0
- dexbot_utils/configs/components/vega_1/torso.py +41 -0
- dexbot_utils/configs/registry.py +112 -0
- dexbot_utils/configs/robots/base.py +24 -0
- dexbot_utils/configs/robots/vega_1.py +127 -0
- dexbot_utils/configs/robots/vega_1p.py +127 -0
- dexbot_utils/configs/robots/vega_1u.py +102 -0
- dexbot_utils/constants.py +19 -0
- dexbot_utils/hand.py +19 -0
- dexbot_utils/robot_info.py +577 -0
- dexbot_utils/urdf_utils.py +354 -0
- dexbot_utils/validators.py +194 -0
- dexbot_utils-0.4.0.dist-info/METADATA +298 -0
- dexbot_utils-0.4.0.dist-info/RECORD +41 -0
- dexbot_utils-0.4.0.dist-info/WHEEL +4 -0
- dexbot_utils-0.4.0.dist-info/entry_points.txt +2 -0
- dexbot_utils-0.4.0.dist-info/licenses/LICENSE +184 -0
dexbot_utils/__init__.py
ADDED
|
@@ -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
|
+
]
|
dexbot_utils/_helpers.py
ADDED
|
@@ -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,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"]
|