Layer 0 — Core Schemas & Exceptions
Part of the OpenRAL public-symbol inventory. Hand-curated;
(LNN)markers are refreshed bytools/refresh_methods_linenos.py.
Authoritative Pydantic v2 contracts. Anything imported from openral_core.__init__ is API. On-disk schemas (RobotDescription, RSkillManifest, SceneGraph, …) are versioned via schema_version and evolve in place unless a change breaks compatibility.
python/core/src/openral_core/schemas.py
openral schema v0 — normative Pydantic v2 contracts for all layers.
Enums
class EmbodimentKind(str, Enum)— Top-level kinematic class. (L67)HUMANOID, MANIPULATOR, BIMANUAL, QUADRUPED, MOBILE_BASE, MOBILE_MANIPULATOR, DRONEclass JointType(str, Enum)— URDF joint type. (L79)REVOLUTE, PRISMATIC, CONTINUOUS, FIXED, FLOATING, PLANARclass ClockOrigin(str, Enum)— Authoritative source forstamp_nsvalues;/clockis a projection, not an origin. (L90)HOST_WALL, SIMULATION, HARDWARE_SYNCEDclass ClockEpoch(str, Enum)— Epoch astamp_nsvalue is measured from. (L102)UNIX, SIMULATION_ELAPSED, HARDWAREJointRole: TypeAlias = Literal[…]— Structural role of aJointSpec(arm/base/gripper/…), read instead of name-substring matching; defaults to"unknown"so legacy manifests stay loadable. (L110)"arm", "base", "gripper", "torso", "leg", "head", "neck", "wheel", "unknown". Used by runner/safety/dataset-bridge to identify a channel without name-substring heuristics. Default"unknown"keeps legacy manifests loadable.class ControlMode(str, Enum)— Action space / control interface. (L214)JOINT_POSITION, JOINT_VELOCITY, JOINT_TORQUE, JOINT_TRAJECTORY, CARTESIAN_POSE, CARTESIAN_DELTA, CARTESIAN_TWIST, BODY_TWIST, FOOT_PLACEMENT, GRIPPER_BINARY, GRIPPER_POSITION, DEX_HAND_JOINT, COMPOSITE_MODECONTROL_MODE_TO_UINT8: dict[ControlMode, int]— Wire encoding forActionChunk.control_mode; mirrors the C++ kernel'svalidator.hpp::ControlModeenum. (L244)UINT8_TO_CONTROL_MODE: dict[int, ControlMode]— Inverse ofCONTROL_MODE_TO_UINT8. (L262)const BODY_TWIST_DIM: int = 6— Width of a BODY_TWIST / CARTESIAN_* twist row(vx, vy, vz, wx, wy, wz); shared by the HAL packers and safety supervisor that validate 6-vec twist payloads. (L267)class SensorModality(str, Enum)— Physical sensing modality. (L282)RGB, DEPTH, STEREO, IR, POINT_CLOUD, LIDAR_2D, IMU, FORCE_TORQUE, JOINT_STATE, TACTILE_VISION, TACTILE_ARRAY, AUDIO, GPS, BATTERYclass Hand(str, Enum)— End-effector laterality. (L301)LEFT, RIGHT, NAclass StateRepresentation(str, Enum)— State vector format. (L1558)JOINT_POSITIONS, EEF_POS_AXISANGLE, EEF_POS_EULER, EEF_POS_QUAT, EEF_POS_AXISANGLE_GRIPPERclass ActionRepresentation(str, Enum)— Action vector format: which coordinates and gripper encoding a policy's output represents. (L1568)class JointUnits(str, Enum)— Angular convention a joint-position checkpoint was trained in. The runner converts deg↔rad at the policy boundary; a joint-position skill reaching the runner without a declaration raisesROSConfigErrorrather than guessing. (L1583)JOINT_POSITIONS, JOINT_VELOCITIES, DELTA_EE_6D_PLUS_GRIPPER, DELTA_EE_6D, CARTESIAN_POSEclass RSkillAction(str, Enum)— Closed vocabulary of action verbs an rSkill can perform; declared onRSkillManifest.actionsand surfaced to the reasoner's tool palette so it can pick a skill by what it does. (L1601) Manipulation primitives:PICK, PLACE, PICK_AND_PLACE, TRANSFER, GRASP, RELEASE; articulated / contact-rich:OPEN, CLOSE, PUSH, PULL, SLIDE, INSERT, POUR, WIPE, ROTATE; motion:REACH; mobile:NAVIGATE; social/expressive:WAVE, SHAKE; generalist marker (foundation / multi-task checkpoints):GENERALIST; perception producer:DETECT(forkind: "detector"rSkills); scene VLM:QUERY(forkind: "vlm"rSkills); reward monitor:MONITOR(forkind: "reward"rSkills); playbook decision procedure:PLAN(forkind: "playbook"rSkills). New entries are additive.class QuantizationDtype(str, Enum)— Weight numeric format. (L5347)FP32, FP16, BF16, INT8, INT4, FP4_NVFP4class QuantizationBackend(str, Enum)— Inference backend. (L5381)PYTORCH, ONNX, TENSORRT, GGUF, MLXclass RSkillState(str, Enum)— Skill lifecycle. (L5453)UNCONFIGURED, INACTIVE, ACTIVE, FINALIZED, ERRORclass RSkillLicensePosture(str, Enum)— License posture. (L5533)APACHE_2_0, MIT, BSD, PERMISSIVE_RESEARCH, NVIDIA_NON_COMMERCIAL, NVIDIA_OPEN_MODEL, RLWRLD_NON_COMMERCIAL, PROPRIETARY, UNKNOWN(NVIDIA_OPEN_MODEL = GR00T N1.7+, commercial OK)class RSkillRuntime(str, Enum)— Manifest runtime hint. (L5548)PYTORCH, ONNX, TENSORRT, TRT_LLM, VLLM, GGUF, MLX, JAXclass PhysicsBackend(str, Enum)— Sim backend. (L10061)MUJOCO, MUJOCO_MJX, PYBULLET, SAPIEN, ISAACSIM, COPPELIASIM, GENESIS, MOCK(SAPIEN = ManiSkill3 / RoboTwin engine; RoboTwin uses it via a py3.10 sidecar;COPPELIASIM= CoppeliaSim/PyRep RLBench backend, out-of-process py3.10 sidecar)
Pydantic models — robot manifest hierarchy
class IntrinsicsPinhole(BaseModel)— Pinhole camera intrinsics. (L312) fields:width, height, fx, fy, cx, cy, distortion_model, distortion_coeffsscale_intrinsics_to(base, width, height) -> IntrinsicsPinhole— Rescales pinhole intrinsics to a new render resolution, preserving FOV and distortion; used when deploy-sim renders at a different resolution than the manifest declares. (L346)class ClockAuthority(BaseModel)— Named origin for OpenRAL timestamps across sim, rSkills, ROS, and hardware; construct viahost_wall(),simulation(), orhardware_synced(). A validator rejects impossible origin/epoch pairs and competing hardware/clockpublishers. (L134)host_wall(cls) -> ClockAuthority[@classmethod] — Real-deployment wall/ROS system time origin. (L166)simulation(cls, clock_id, timestep_s=None, publishes_ros_clock=True) -> ClockAuthority[@classmethod] — Simulator elapsed time projected to/clock. (L171)hardware_synced(cls, clock_id, epoch=UNIX) -> ClockAuthority[@classmethod] — Future synchronized controller/PTP clock origin. (L188)class CameraSimPlacement(BaseModel)— Where an RGB sensor's camera sits in the sim MJCF, so the generic HAL camera rig can splice it into a bare-arm MJCF fordeploy sim. Replaces per-robotscene_defaults.compositionfor camera-only deploy twins. (L400)class SensorSpec(BaseModel)— Generalizable sensor descriptor covering all modalities;sim_camera_namenames the MJCF camera when it differs from the sensorname,sim_placementcarries the camera's sim pose,shares_mount_withnames the sensor of the same physical device whose (per-unit calibrated) mount this one rides (validated byRobotDescription: one level, onto a sensor withparent_frame+static_transform_xyz_rpy), anddeploy_bindingis the real-hardware counterpart (host-specific; a robot camera's lives in its host'sRobotUnitoverlay or robot.yaml, a workcell camera's on its ownDeployScene.sensorsentry).ros2_topicnames only an external driver's image topic (ADR-0108);None(every in-tree manifest) means OpenRAL publishes the sensor undercamera_topic(name, kind). (L444)is_depth_camera[@property] (L555) — A depth / point-cloud camera with intrinsics: the one test for "can this be back-projected into a cloud", shared by the sim bridge's depth synth (openral_hal.depth_cloud.is_depth_sensordelegates to it), the sim cloud topic (deploy_cloud_topic), the Nav2-over-visual-SLAM guard and the launch's depth-camera pick.is_cloud_source[@property] (L570) — Anydepthorpoint_cloudsensor (a 3D lidar needs no intrinsics): a real driver can feed octomap its cloud, so ondeploy runit auto-enables the octomap leg, which then needs the driver topic pinned. fields:name, modality, frame_id, parent_frame, static_transform_xyz_rpy, rate_hz, intrinsics, encoding, fov_h_deg, fov_v_deg, sim_camera_name, sim_placement, n_channels, range_min_m, range_max_m, accel_noise_density, gyro_noise_density, n_axes, tactile_grid, vla_feature_key, ros2_topic, ros2_msg_type, qos_profile, catalog_id, vendor, model, driver_pkg, metadataCAMERA_TOPIC_PREFIX: Final[str]—"/openral/cameras", the root of the canonical camera topic layout (ADR-0108). Consumers that need a pattern usere.escape(CAMERA_TOPIC_PREFIX). (L589)class CameraTopicKind(StrEnum)— Per-camera stream suffix:IMAGE(image),CAMERA_INFO,DEPTH_IMAGE(depth/image),DEPTH_CAMERA_INFO(depth/camera_info),POINTS. (L592)camera_topic(name, kind=CameraTopicKind.IMAGE, *, prefix=CAMERA_TOPIC_PREFIX) -> str—<prefix>/<name>/<kind>; the only place the camera layout is spelled. Every producer (sim bridge, sensor leg) and consumer (world state, perception, reasoner, Foxglove, SLAM, deploy launch, record profiles) builds through it;tests/unit/test_camera_topic_layout.pyrejects a hand-built string. RaisesROSConfigErroron an empty or/-containing name. (L602)class SensorBundle(BaseModel)— Multi-modal sensor group. (L637)sensor_name_to_slot(description) -> dict[str, str]— Maps each RGB sensor name to its VLA slot (vla_feature_keysuffix, else the name). The one camera namespace shared byopenral sim run,deploy simanddeploy run; used byrskill_runner_node,DatasetRecorderBridge,SimSensorBridgeandSimRunner. (L653)check_scene_sensor_overrides(manifest_sensors, scene_sensors) -> None(L698) — RaisesROSConfigErrorwhen aDeployScene.sensorsentry reuses the name of a sensor the robot manifest defines. A deploy scene never redefines a robot camera: its name, modality and frames live inrobots/<robot_id>/robot.yaml, its per-host binding / per-unit calibration in aRobotUnitoverlay; the scene only adds workcell cameras under new names. Called bymerge_deploy_sensors,resolve_launch_invocation(sodeploy sim/run/validate) andopenral check.merge_deploy_sensors(manifest_sensors, scene_sensors) -> list[SensorSpec](L734) — The deploy's sensor set: the manifest's sensors, then the scene's workcell sensors; a checked concatenation (check_scene_sensor_overridesrefuses a name clash). Shared by the CLI, the launch andcompose_runtime.ROBOT_UNIT_ENV: str—"OPENRAL_ROBOT_UNIT", names the host'srobots/<id>/units/<unit>.yaml; wins overDeployScene.robot_unit. (L757)apply_sensor_overlays(sensors, overlays) -> list[SensorSpec]— Lays eachSensorOverlay's set fields (binding, driver topic, mount pose, intrinsics) over the named manifest sensor and re-validates;ROSConfigErroron an unknown or repeated name. Applied byresolve_launch_invocation,deploy_e2e.launch.py,compose_runtime(sensor_overlays=),deploy validateandopenral check. (L763)load_robot_unit(robot_yaml, unit) -> RobotUnit— Loads<robot_yaml dir>/units/<unit>.yaml;ROSConfigErrorwhen missing (lists the available units) or when itsrobot_id/unitdisagree with the directory / request. (L804)gripper_hands(description) -> tuple[tuple[str, ...], ...]— The robot's hands: itsrole: gripperjoints'child_links grouped per hand (joints sharing aparent_link, a chained finger joining its parent's hand). SO-101 → one hand; OpenArm → two one-link hands; R1 Pro's four finger joints → two two-finger hands. Used by the reasoner's grasp grounding (re-exported asopenral_reasoner.gripper_hands), the rSkill runner's goal-scope approach declaration and the HAL's approach-armed grasp target. (L831)resolve_sensor_overlays(robot_yaml, scene_unit, *, required) -> list[SensorOverlay]— The host's overlays: unit =$OPENRAL_ROBOT_UNITor the scene'srobot_unit; none →[], exceptrequired(real deploy) on a robot that shipsunits/→ROSConfigError. (L864)publishing_sensors(manifest_sensors, scene_sensors, hal_mode) -> list[SensorSpec](L895) — The sensors that actually publish a camera topic on a deploy: sim → the manifest's (the sim bridge renders them); real →merge_deploy_sensorsfiltered to sensors with adeploy_binding. The one ruleopenral deploy(detector auto-downgrade) anddeploy_e2e.launch.py(completion, detector, reward-monitor and scene-VLM cameras) share.deploy_cloud_topic(manifest_sensors, *, pinned, hal_mode, estimated_camera=None) -> str(L923) — ThePointCloud2topic octomap'scloud_inand the world-state object-lift fallback read: a pinnedruntime.octomap_cloud_topicwins; thenestimated_camera(runtime.estimated_depth_camera) →camera_topic(<it>, POINTS)in sim and real (the depth provider's DA3 cloud); sim →camera_topic(<the one is_depth_camera>, POINTS)(the sim bridge's back-projection); real →""(nothing in-tree publishes a cloud). RaisesROSConfigErrorin sim for several depth cameras and no pin (declared choice, not first-wins). Shared byopenral deploy's pre-launch refusal anddeploy_e2e.launch.py.required_vla_camera_slots(manifest, description) -> tuple[str, ...]— The robot's RGB slots trimmed to those the rSkill'ssensors_required[].vla_feature_keynames (all slots when it names none); the policy camera keys on deploy and on an empty-scene.camerassim run. (L677) fields:bundle_name, sensors, sync, sync_tolerance_msclass GripperClosureCalibration(BaseModel)— Per-gripper-joint calibration of the position-stall grasp trigger (openral_hal._grasp_trigger.PositionStallTrigger), in the joint's own units, frozen/extra="forbid":closed_position(the fully-closed command; must be an end ofposition_limits),closed_rest_offset >= 0(where an empty close rests),stall_gap > 0(how far beyond the rest offset a settled jaw must sit short of a close command to read as holding something; also the close-command band and, halved, the hysteresis),settle_tolerance > 0(position span that counts as stationary). Robot-type constants of the gripper mechanism, derived from teleop data (not per cell; no unit overrides them), never library defaults. (L977)class JointSpec(BaseModel)— URDF-derived joint spec;origin_xyz/origin_rpy/axis_xyzlet the kernel compute FK for self-collision,roleidentifies gripper/base/arm DoFs structurally instead of by name-substring, andsim_joint_namenames the MJCF joint when it differs from the logicalname(needed only when a sim adapter looks the joint up by name and the loaded MJCF renames it);closure_calibration(arole: gripperjoint'sGripperClosureCalibration,None= uncalibrated, the vision attachment leg refuses it). (L1017) fields:name, joint_type, parent_link, child_link, axis_xyz, origin_xyz, origin_rpy, position_limits, velocity_limit, effort_limit, has_position_sensor, has_velocity_sensor, has_torque_sensor, backlash_estimate, actuator_kind, sim_joint_name, role, closure_calibrationclass EndEffectorSpec(BaseModel)— End-effector spec;actuated=Falsemarks a passive tool (inert flange, kinematic-only mount) so the safety kernel rejects chunks addressed at it.command_convention/command_rangedeclare theGRIPPER_*value this end effector's HAL consumes (range defaults from a normalized convention, required for a physical one). (L1150)resolved_command_range() -> tuple[float, float] | None— The safety kernel's bound for this end effector, orNonewhen undeclared. (L1238)GRIPPER_CONVENTION_RANGES: dict[str, tuple[float, float]]— The value range of each normalizedGripperConvention; physical conventions have none. (L1142) fields:name, kind, hand, n_dof, max_grip_force_n, max_payload_kg, workspace_radius_m, tactile_sensors, actuatedclass ComputeSpec(BaseModel)— Compute profile for one deployment tier (edge/local/cloud), populated byopenral_detect._enrich_computefrom GPU probe results and attached toRobotDescription.compute_edge/local/cloud. (L1274) fields:compute_tops, system_memory_gb, num_gpus, gpu_vram_gb, cuda_compute_capability, cuda_toolkit_version, tensorrt_version, gpu_supported_runtimes, gpu_supported_dtypes, nvmm_available, endpoint, network_latency_mssupports_cumotion() -> bool— True when the host meets the cuMotion (Isaac ROS) GPU floor on compute capability, CUDA toolkit version, and VRAM; used by the MoveIt planner gate to pick cuMotion vs OMPL. (L1341)prop _CUMOTION_MIN_COMPUTE_CAPABILITY, _CUMOTION_MIN_CUDA_MAJOR, _CUMOTION_MIN_VRAM_GIB— The cuMotion GPU floorsupports_cumotion()checks against. (L1256–1258)ReasonerDialect = Literal["anthropic", "openai"]— Wire dialect aReasonerModel/ named endpoint speaks; only needed onOPENRAL_REASONER_DIALECTfor a bare, unclassified URL. (L12266)ReasonerHosting = Literal["cloud", "managed_local", "byo_local"]— Where aReasonerModelruns; drivesReasonerModel.is_local. (L12269)class ReasonerModel(BaseModel)— Frozen curated S2 model registry entry.REASONER_MODELSis the curated map; membership means the model passed the robotics tool-calling contract. (L12279)is_local(self) -> bool[@property] — True formanaged_local/byo_localhosting (needs local compute); False forcloud. (L12348)REASONER_MANAGED_ENDPOINT: str = "managed"— Sentinel forReasonerModel.default_endpointmeaning OpenRAL spawns and manages the local server, resolved to the model's managed loopback endpoint at client-build time. (L12276)_OPENROUTER_ENDPOINT: str— OpenRouter's OpenAI-compatible endpoint URL; default gateway for the curated GPT-5.x entries. (L12355)REASONER_MODELS: dict[str, ReasonerModel]— The curated model registry keyed byid; adding a model means adding one entry here after it clears the tool-calling bar. (L12359)class ReasonerEndpointPreset(NamedTuple)— Everything a namedOPENRAL_REASONER_ENDPOINTimplies beyond its URL (dialect, auth, cold-start timeout, tool_choice). (L12428)REASONER_ENDPOINT_PRESETS: dict[str, ReasonerEndpointPreset]— Presets for the acceptedOPENRAL_REASONER_ENDPOINTnames. (L12462)REASONER_TOOL_CHOICES: tuple[str, ...]—("auto", "required"), the valuesOPENRAL_REASONER_TOOL_CHOICEaccepts. (L12477)parse_reasoner_tool_choice(raw) -> str | None— Validate (case-insensitively) anOPENRAL_REASONER_TOOL_CHOICEvalue,Nonewhen unset;ROSConfigErrorotherwise. Shared by the reasoner client factory andopenral doctor. (L12481)prop ANTHROPIC_BASE_URL, OPENROUTER_BASE_URL, OLLAMA_BASE_URL, VLLM_BASE_URL, GEMINI_BASE_URL, XAI_BASE_URL, DEEPSEEK_BASE_URL, HUGGINGFACE_BASE_URL— Base URLs backing the namedOPENRAL_REASONER_ENDPOINTpresets. (L12408–12425)class RobotCapabilities(BaseModel)— Physical capability flags for skill compatibility;has_vision_slamgates the camera-based SLAM backend for lidar-less robots, independent ofhas_lidar(lidar backend wins when both set). (L1367) fields:locomotion, can_lift_kg, has_dexterous_hands, has_tactile, has_force_control, has_vision, has_lidar, has_vision_slam, has_audio, bimanual, supported_control_modes, supported_vla_embodiments, embodiment_tagsclass SafetyEnvelope(BaseModel)— Constraints handed to the C++ safety kernel (not every field is enforced yet — see the enforcement note below);self_collision_margin_mcan go negative to tolerate a compact arm's known in-distribution grazing contact while gross folds still trip. Also carries the runner's starting-pose approach per joint type (starting_pose_max_joint_speed_rad_s/starting_pose_tolerance_radfor non-prismatic joints,starting_pose_max_joint_speed_m_s/starting_pose_tolerance_mfor prismatic ones) andjoint_state_staleness_limit_s, the one place a rig declares its joint-state freshness window (read bybuild_halanddeploy_e2e.launch.py). (L1415) fields:workspace_box_min_xyz, workspace_box_max_xyz, no_go_zones, max_ee_speed_m_s, max_ee_accel_m_s2, max_joint_speed_factor, max_force_n, max_torque_nm, deadman_required, e_stop_topic, e_stop_qos, contact_force_threshold_n, cycle_time_violation_threshold_ms, human_in_loop_required+ per-mode bounds (max_cartesian_step_m/_rad,max_ee_angular_speed_rad_s,max_base_linear/angular_speed_rad_s) +self_collision_margin_m: float = 0.0. Enforcement: the kernel checks joint position/velocity/torque (max_torque_nm), the workspace box (CARTESIAN_POSE only),max_ee_speed_m_s/max_ee_angular_speed_rad_s(CARTESIAN_TWIST), the per-mode bounds andself_collision_margin_m. Declared, not yet enforced by the kernel:max_force_n(#373),max_ee_accel_m_s2,contact_force_threshold_n(the place-contact force gate takes its threshold from each placement declaration),deadman_required(loaded, never consulted; the deploy launch runs the deadman watchdog unconditionally). Declared, not read by any runtime component:no_go_zones,e_stop_topic(the kernel uses/openral/estop),e_stop_qos,cycle_time_violation_threshold_ms,human_in_loop_requiredclass ObservationSpec(BaseModel)— VLA observation config. (L1659) fields:state_key, state_shape, state_representation, image_flip_180(image_flip_180deprecated, no effect on image processing — setting it emits aFutureWarning; useRSkillManifest.image_preprocessing.flip_180)class ActionSpec(BaseModel)— VLA action config. (L1701)dimis optional (issue #303): a robot with no committed policy action contract declares onlycontrol_freq_hz, and the dataset recorder takes the width from the action itself. fields:dim, representation, control_freq_hz, chunk_sizeclass ActionSlot(BaseModel)— One contiguous slice of an rSkill's action vector, with per-mode field requirements enforced by a validator;discard=Truedrops a slice silently. (L5919) fields:range, control_mode, discard, ee, frame, joint_names, input_boundsclass ActionContract(BaseModel)— Per-rSkill action-vector contract; whenslotsis set, every index is covered by exactly oneActionSlot, else the legacy single-Action JOINT_POSITION path applies. Optionalcontrol_freq_hzis the rate the checkpoint was trained at; the skill runner refuses a goal whose tick rate differs (no resampler). (L6065) fields:dim, representation, slots, cartesian_delta_scale, joint_names, gripper_scale, joint_units—joint_names(policy joint order in robot joint names; forbidden withslots, must matchdim, unique) andgripper_scale(policy gripper units per HAL[0, 1]unit,> 0) are consumed byopenral_rskill._policy_io.PolicyIOCodecon every dispatch path.prop _JOINT_MODES, _CARTESIAN_MODES, _GRIPPER_MODES— TheControlModepartitions used byActionSlot's andControlModeSemantics's per-mode validators. (L6054–6060)prop _EE_6D_WIDTH, _EE_3D_WIDTH— Cartesian slice widthscanonical_slots_for_representationuses to size a representation-onlyActionContract's slots. (L6230–6231)class TaskSpaceFamily(str, Enum)— Coarse classification of aControlModefor task-space views (DRAFT). (L6429)_FAMILY_FOR_MODE: dict[ControlMode, TaskSpaceFamily]— Exhaustive mapping from everyControlModeto itsTaskSpaceFamily, lockstep-tested. (L6449)class TaskSpaceSegment(BaseModel)— One typed slice of an action vector, layer-neutral; the gripper is an explicit 1-D segment. (L6466) fields:family, control_mode, width (>0), targetclass TaskSpaceMatch(BaseModel)— Result oftask_space_compatible. (L6508) fields:ok, reasonsclass TaskSpace(BaseModel)— Layer-neutral view of an action interface as orderedTaskSpaceSegments (DRAFT); derived viafrom_action_contract, never hand-authored, so it cannot drift from the primitives. (L6523)total_dim(self) -> int[@property] — Sum of segment widths — the flat action-vector dimensionality. (L6574)control_modes(self) -> set[ControlMode][@property] — The distinctControlModes this space drives. (L6579)from_action_contract(cls, action: ActionContract, robot: RobotDescription) -> TaskSpace[@classmethod] — Builds the task space an rSkill emits, expandingslots/representation. (L6584)class SceneTaskSpace(BaseModel)— The control interface a scene-adapter family executes, declared once per family inSCENE_FAMILY_TASK_SPACE;runs_via_default_packers=Falsemarks dedicated-controller adapters. (L6800) fields:modes (frozenset[ControlMode]), action_dim (int|None), runs_via_default_packers (bool)class SphereShape(BaseModel)— Sphere collision primitive; discriminatorshape="sphere", fieldradius_m (>0). (L2057)class CapsuleShape(BaseModel)— Capsule collision primitive (segment along local +Z swept by a radius); discriminatorshape="capsule", fieldsradius_m (>0), length_m (>=0). (L2075)class BoxShape(BaseModel)— Oriented box (OBB) collision primitive for blocky links; fits a near-cubic link far tighter than a capsule, whose round section over-reports clearance past flat faces. (L2104)CollisionShape: TypeAlias = Annotated[CapsuleShape | SphereShape | BoxShape, Field(discriminator="shape")]— Discriminated union of convex collision primitives; mesh shapes excluded so the allocation-free kernel checks only analytic convex volumes. Theshapediscriminator is enforced, not just documented, so a bad tag fails clearly rather than silently resolving to the wrong member. Never dump withexclude_defaults=True— it drops the tag field. (L2135)DOP_AXES: tuple[tuple[float, float, float], ...]— The 26-DOP's 13 unit axis directions, in the owning box's own local frame; mirrorskDopAxisin the C++ safety kernel. Its first three entries are the box's own axes, which is load-bearing — checking those three proves containment for the whole polytope without enumerating a vertex. (L2157)MAX_TIGHT_HULL_VERTICES: int—320; ceiling on a stage-2 hull's vertex count, mirroringkMaxTightHullVertices— a cost bound, not a safety one, since a link over the ceiling still runs the DOP-only stage 1. (L2186)TIGHT_CONTAINMENT_EPSILON_M: float—1e-9m of floating-point slack when checking a hull vertex against its own DOP slab; mirrorskTightContainmentEpsilonM. The box-containment check onLinkCollisionGeometrytakes no slack at all. (L2196)class TightCollisionGeometry(BaseModel)— Tight convex geometry refining one link'sBoxShape, used by the safety kernel for the arm-link-vs-world-voxel check only; drives a staged narrow phase (26-DOP bound, then GJK on the exact hull). Generated bytools/generate_tight_geometry.py, not hand-authored. (L2206)check_tight_geometry_fits_box(shape, tight, owner) -> None— Raises unlesstightrefines aBoxShapeand stays inside itshalf_extents_m— the containment check that must not be deferred to the kernel, since a representation reaching outside the box would make the kernel skip cells it should visit. Shared byLinkCollisionGeometryandAttachedCollisionPrimitiveso neither is held to a weaker standard. (L2310)class LinkCollisionGeometry(BaseModel)— One convex collision volume attached to a robot link; hand-authored or emitted by the offline lowering tool from MJCF/URDF. (L2365) fields:link_name, shape: CollisionShape, origin_xyz_rpy, tight_geometry: TightCollisionGeometry | None_tight_geometry_fits_inside_the_box(self) -> Self[@model_validator(mode="after")] — Rejectstight_geometryon any non-BoxShape, or a DOP whose slabs reach outsidehalf_extents_m; no slack is allowed here. (L2412)class FixedAttachment(BaseModel)— One rigid, zero-DoF parent→child link of the kinematic tree, completing the connectivityjointsalone cannot express (a bolted-on hand or bimanual pedestal would otherwise present as disconnected trees). Origins must come from the real URDF/MJCF, never estimated. (L2421) fields:name, parent_link, child_link, origin_xyz, origin_rpyclass MimicJoint(BaseModel)— A link posed by another joint's value,q = multiplier * q[mimics] + offset(the URDF<mimic>/ MuJoCo joint equality): the OpenArm's follower finger, the third edge kind of the collision tree besidejointsandfixed_attachments— moving, but no command channel, invisible to everyjointsconsumer. The kernel poseschild_linkrigidly at the mimicked value (JointKind::kMimicRevolute/kMimicPrismatic);docs/reference/finger-mimic-geometry.md. (L2478) fields:name, parent_link, child_link, mimics, multiplier, offset, joint_type: JointType, axis_xyz, origin_xyz, origin_rpy, sim_joint_name_check_relation(self) -> Self[@model_validator(mode="after")] — Refuses a self-attachment, a non-finite relation, a zero multiplier (a fixed link wearing a moving kind) andjoint_type: fixed. (L2546)value_at(leader_value) -> float— This joint's value at the mimicked joint'sleader_value. (L2568)class RobotDescription(BaseModel)— Top-level robot manifest, one per robot;assetsis the single URDF/MJCF/SRDF reference block,compute_edge/local/cloudhold per-tier compute profiles,collision_geometry/allowed_collision_pairscarry the safety-kernel-facing self-collision data, andfixed_attachmentscompletes the kinematic tree with rigid zero-DoF mounts thatjointsalone can't express. (L2677) fields:name, embodiment_kind, assets, base_frame, odom_frame, map_frame, joints, end_effectors, sensors, sensor_bundles, capabilities, safety, ros2_namespace, middleware, onboard_compute, sdk_kind, hal, observation_spec, action_spec, sim, scene_defaults, base_joints, footprint_radius, base_kinematics, collision_geometry, allowed_collision_pairs, fixed_attachments, mimic_joints, footprint_polygon, compute_edge, compute_local, compute_cloud, schema_versionscene_defaults: SceneDefaults | None = None— Optional scene-level defaults (top-camera POV, etc.) consumed by the MJCF composers as the fallback when an environment does not pin its own values.validate_for_e2e_pipeline(self) -> None— Asserts every actuated joint hasposition_limits/velocity_limit/effort_limitset, so a misshapen manifest fails at launch-parse time rather than mid-actuation. (L3242)lidar_sensor(self) -> SensorSpec | None[@property] — First declaredlidar_2dsensor, or None; single source of truth for the synthetic/scanenvelope. (L3119)nav2_footprint_param(self) -> str— This base's Nav2footprintparameter string fromfootprint_polygon;"[]"when undeclared so a radius-only robot keeps its own circular footprint instead of inheriting the shared param file's shape. (L3135)nav2_param_overrides(self) -> dict[str, str]— Nav2 param substitutions derived fromfootprint_radius,footprint_polygon(its circumscribed radius setsinflation_radius) andbase_kinematics, so one shared base param file serves any mobile base;{}for fixed-base arms. (L3161)control_rate_hz(self) -> float | None[@property] (L2843) —action_spec.control_freq_hzwhen positive, elseNone. The one place a robot's rate lives: the skill runner ticks at it, the HAL node publishes proprio at it, the real ros2_control HAL derives every trajectory deadline from it, and the recorder stamps it as fps (issue #303).REAL_HARDWARE_SAFETY_FIELDS[ClassVar] — theSafetyEnvelopefields the kernel's envelope loader reads and that carry a schema default (max_ee_speed_m_s,max_ee_accel_m_s2,max_joint_speed_factor,max_force_n,max_torque_nm,contact_force_threshold_n,deadman_required,self_collision_margin_m).UNENFORCED_REAL_HARDWARE_SAFETY_FIELDS[ClassVar] — the subset ofREAL_HARDWARE_SAFETY_FIELDSthe kernel loads but no check consults yet (max_ee_accel_m_s2,max_force_n(#373),contact_force_threshold_n,deadman_required). Still required on a real manifest; the validator's error names them as declared-not-enforced._validate_real_hardware_contract(self) -> RobotDescription[model_validator] (L2882) — a manifest withhal.realset must declarecontrol_rate_hz, everyREAL_HARDWARE_SAFETY_FIELDSentry explicitly insafety(an explicit value equal to the default is fine; inheriting it silently is not),safety.joint_state_staleness_limit_s, and the starting-pose approach for each joint type it has —safety.starting_pose_max_joint_speed_rad_s/starting_pose_tolerance_radwith a non-prismatic joint,..._m_s/..._mwith a prismatic one (the runner's approach has no default speed; deriving one from ratedvelocity_limitput the OpenArm at 2 rad/s, and a rad tolerance on a 0.041 m gripper always "arrived"). On any manifest, declaring bothsafety.joint_state_staleness_limit_sandhal.parameters.defaults.staleness_limit_sis refused. Every gap is reported in one error, at load time — beforedeploy validate,build_halor any node. Sim-only manifests keep the schema defaults._validate_fixed_attachments(self) -> RobotDescription[model_validator] (L2974) — each link is defined by exactly one edge (a joint, afixed_attachmentsrow or amimic_jointsrow), no edge attaches a link to itself, and everymimic_joints.mimicsnames ajointsentry.grasp_contact_links(self) -> tuple[str, ...](L3006) — the links a grasp may touch: everyrole: gripperjoint'schild_link, then thechild_linkof everymimic_jointsrow following one of those joints (the other jaw of the same gripper); the launch passes it as the kernel'sgrasp_contact_linksallowlist (ADR-0115).hand_links(self) -> tuple[str, ...](L3026) —grasp_contact_links()plus, once per hand, the link the hand's gripper hangs off (a chained finger climbed to its arm, asgripper_hands), then the wrist that link hangs off (never a root link); OpenArm: both finger pairs, both followers, bothlink7, bothlink6(#349 r23: a hand at a tote rim brings the wrist within one 15 mm voxel of it). The launch passes it as the kernel'sworkspace_contact_links(issue #349).from_yaml(cls, path: str) -> RobotDescription[@classmethod] — Load and validate aRobotDescriptionYAML manifest from disk. (L3224)_refuse_old_schema_version(cls, data: object) -> object[model_validator(mode="before")] (L2861) — refuses any mapping whoseschema_versionis not"0.2"with aROSConfigErrorthat says how to update it; there is no migrator.def extract_base_sim_joint_names(description: RobotDescription) -> tuple[str, str, str] | None— Returns(forward, side, yaw)MJCF joint names for any mobile-base description declaring bothbase_jointsandsim_joint_name. (L3287)const NAV2_INFLATION_CLEARANCE_M: float = 0.05— Costmap inflation clearance added to the circumscribed footprint radius fornav2_param_overrides. (L279)class GripperReadMode(str, Enum)— HowMujocoArmHALreports the gripper qpos. Values:SUM_OVER_SCALE(Franka parallel — normalised to[0,1]),AFFINE_LOW_HIGH(SO-100 revolute Jaw — normalised to[0,1]),PASSTHROUGH(Aloha prismatic / OpenArm revolute — raw qpos in MJCF units). (L1725)class GripperWriteMode(str, Enum)— HowMujocoArmHALmaps an Action's gripper value toctrl. Values:NORMALISED([0,1]→ctrl_range),PASSTHROUGH(raw →ctrl; MuJoCo clips). (L1747)class SimGripperDescription(BaseModel)— Gripper wiring inside a MuJoCo MJCF. (L1763) fields:joint, ctrl_range, qpos_addrs, qpos_scale, read_mode, write_mode, actuator_index, mirror_actuator_indexclass UrdfAsset(BaseModel)— A URDF asset reference plus itsrobot_state_publisherwiring. (L1827) fields:ref: str(validated against theresolve_assetscheme grammar),root_frame: str | None(URDF root link when it differs frombase_frame),base_to_root_xyz_rpy: tuple[float×6] | None(staticbase_frame→root_frametransform [x,y,z,roll,pitch,yaw], metres+radians)class AssetRefs(BaseModel)— UnifiedRobotDescription.assetsblock: one URDF/MJCF/SRDF reference set replacing the former scattered asset fields. (L1864)prop _ASSET_SCHEMES, _ROS2_DYNAMIC— Manifest-side mirror ofopenral_core.assets's scheme grammar, kept in lock-step with the resolver. (L1814–1815) fields:urdf: UrdfAsset | None,mjcf: str | None,srdf: str | None(the last two are bare refs, validated against the same scheme grammar; all defaultNone)class SimDescription(BaseModel)— OptionalRobotDescription.simblock holding MuJoCo joint↔qpos/qvel/actuator wiring forMujocoArmHAL.from_description. (L1895) fields:floating_base, joint_qpos_addr, joint_qvel_addr, actuator_index, grippers, settle_steps_default, keyframe_index, seed_ctrl_from_qposclass HalEntrypoints(BaseModel)—RobotDescription.halblock: the robot's sim + real-hardware HAL import strings, resolved byopenral_hal.build_hal, plus optionalreal_bringup: str | None("<ros_pkg>:<file>.launch.py") — the vendor ros2_control bringupdeploy runincludes;Nonefalls back to the HAL package'slaunch/real_bringup.launch.pyconvention. (L2631) fields:sim: str | None(null → deriveMujocoArmHAL.from_descriptionwhen asim:block exists),real: str | None(null → simulation-only robot),parameters: HalParameters(per-robot HAL construction defaults)class HalParameters(BaseModel)—RobotDescription.hal.parametersblock: per-robot HAL construction defaults merged into the constructor byopenral_hal.build_hal, so a parameterised robot needs no bespoke lifecycle subclass. (L2573) fields:defaults: dict[str, object]class TopCameraDefaults(BaseModel)— Default placement for the scene-level "top"/"base" camera consumed by sim backends that render an overview camera. (L1957) fields:pos: tuple[float, float, float], target: tuple[float, float, float], fovy: float (gt=0, lt=180)- A backend YAML override still wins — this submodel is only the default fed to the composer.
class SceneDefaults(BaseModel)— Per-robot scene rendering defaults consulted when the scene YAML does not override them. (L2022) fields:top_camera: TopCameraDefaults | None,composition: SceneComposition | Noneclass SceneComposition(BaseModel)— Declarative MJCF scene composition;composer: "module:fn"returns(xml, meshdir). (L1987) fields:composer: str,params: dict[str, object]- First consumer is the
openarm_tabletop_pnpMJCF composer; future scenes can extend this as more backend hardcodes are pulled out.
Pydantic models — runtime snapshots
class JointState(BaseModel)— Real-time joint state snapshot. (L3380) fields:name, position, velocity, effort, stamp_nsclass Pose6D(BaseModel)— 6D pose (position + xyzw quaternion). (L3400) fields:xyz, quat_xyzw, frame_idclass DetectedObject(BaseModel)— Object detection. (L3414) fields:label, confidence, pose, bbox_3d, track_idclass AttachmentEvidenceKind(str, Enum)— Evidence source confirming an attachment or its support contact. The two sim kinds are not interchangeable: a simulator's contact list is not a proximity oracle, sosim_geom_distance(a distance probe) can see contact the contact list hides.map_support_proximityis proximity to a support plane the producer measured in the voxel map under the carried payload — never sensed contact, never a proven support.gripper_closureis a position-only gripper that stalled short of its close command with vision unable to confirm the shape (the conservative jaw box);grasp_target_regionis the grasp-target leg's pre-grasp measured region reused as the payload at ATTACH.gripper_forcestays for force-sensing grippers and old records; no in-tree producer stamps it. (L3432)class AttachedCollisionPrimitive(BaseModel)— One sphere/capsule/OBB pluspose_in_object, with an optionaltight_geometryrefining it for the kernel's payload-vs-world-voxel check;Noneis not a defect — sphere/box/capsule sim geoms lower exactly, only mesh geoms leave a gap. Produced byopenral_hal._sim_attachment_evidence._tight_geometry_from_points. (L4414)_tight_geometry_fits_inside_the_box(self) -> Self[@model_validator(mode="after")] — Delegates tocheck_tight_geometry_fits_boxat the producer boundary; the kernel's ingest re-runs the same proof and drops what it can't verify.from_idl(cls, msg, *, object_id) -> AttachedCollisionPrimitive[@classmethod] — Decode one duck-typed IDL message without importing ROS; raisesValueErroron an unknownshape_type. (L4465)fill_idl(self, msg) -> None— Encode to a duck-typed IDL message without importing ROS; raisesROSConfigErrorfor a shape it cannot represent, rather than publishing a default-tagged message with no dimensions. (L4503)class PlaceRegion(BaseModel)— The producer-measured bounded region of a declared place target; inside it, the payload's world-collision margin is reduced so it can reach its earned support contact. Oriented, base-frame only, and producer-specific — no allowance without a measurement (on real hardware the default-off place-target leg measures the slab under the carried payload), and a refusal means no allowance, never a dropped message. Also carries aGraspDeclaration's measured region, under that declaration's tighter caps and withgeometryempty. (L3482)volume_m3(self) -> float— Volume of the region box in cubic metres. (L3608)from_idl(cls, msg) -> Self[@classmethod] — Decode the duck-typed OpenRAL ROS IDL message without importing ROS. (L3614)fill_idl(self, msg, *, primitive_factory=None) -> None— Populate a duck-typed OpenRAL ROS IDL message without importing ROS. (L3639)class StaticBox(BaseModel)(L10515) — One declared static fixture as an oriented box in the robot'sbase_frame:kind="box",source,xyz,quat_xyzw(unit withinUNIT_QUAT_TOL= 0.1),half_extents(≥ 0); all finite. (#349)class StaticMesh(BaseModel)(L10549) — One declared static fixture as a triangle mesh inbase_frame:kind="mesh",source,file(an.npzofvertices(N,3) m andtriangles(M,3), relative to the listing YAML), optionaltrianglescount. (#349)class StaticGeometry(BaseModel)(L10568) — A cell's declared static geometry,static_geometry: list[StaticBox | StaticMesh](discriminated bykind); the fileDeployRuntime.static_geometry_filenames. Only ever ADDS occupancy to the kernel's world grid (docs/reference/manipulation-workspace-contact.md§3.1). (#349)class PlaceDeclaration(BaseModel)— Dispatch's typed statement that a place phase is active for a payload;region, when set, is the only thing that lifts the pick witness's mid-carry anti-scope, and is never inferred from motion or sim introspection; optionalsearch_boxis a hint naming the surface (geometry empty, relayed untouched). Drafted amendment: the real place-target producer attaches the surface it measured under the carried payload as the region of dispatch's goal-scope declaration (target_id="surface", the runner'splace_approach_enabled); it never declares on its own.is_livefails toward dead (retracted, pasttimeout_s, or future-stamped), and itsnow_nsmust read the same clock domain that producedstamp_ns— never wall-clock time. (L3685)is_live(self, *, now_ns) -> bool— Whether this declaration is still in force atnow_ns; fails toward dead. See the class docstring for the clock-domain contract onnow_ns. (L3807)from_idl(cls, msg) -> Self[@classmethod] — Decode the duck-typed OpenRAL ROS IDL message without importing ROS. (L3841)fill_idl(self, msg, *, primitive_factory=None) -> None— Populate a duck-typed OpenRAL ROS IDL message without importing ROS. (L3864)class GraspDeclaration(BaseModel)— Grasp-phase mirror ofPlaceDeclaration(real pick-and-place design §2.1): dispatch namestarget_id+ grippercontact_links(non-empty while active), the producer measuresregion(aPlaceRegion,geometryempty in v1) from the optionalsearch_box(aPlaceRegionthat only seeds perception — on the generic path the reasoner grounds it from a namedGraspTargetRef; an attended direct-dispatch scene may also supply it; the runner passes it through;geometrymust be empty), the kernel bounds it (consumer lands separately, default off). CapsMAX_TIMEOUT_S120 s /MAX_HALF_EXTENT_M0.20 m /MAX_VOLUME_M30.03 m³ are Safety-WG placeholders. Since #349:workspace_box(a scene-declarable manipulation workspace, likesearch_box, arms nothing) andworkspace_region(the producer-confirmed workspace — the same box re-stamped with the confirming grid'ssource_stamp; producer-only, rejected from scenes and stripped by the runner), both capped byMAX_WORKSPACE_HALF_EXTENT_M0.50 m /MAX_WORKSPACE_VOLUME_M30.25 m³ (Safety-WG placeholders) withgeometryempty.is_livehas the same clock-domain contract as the place one;from_idl/fill_idlmirror it. (L3898)is_live(self, *, now_ns) -> bool— Same rule and clock-domain contract asPlaceDeclaration.is_live; retracted, expired and future-stamped are dead. (L4070)from_idl(cls, msg) -> Self[@classmethod] — Decode the duck-typedopenral_msgs/GraspDeclarationwithout importing ROS;regiononly whenregion_valid,search_boxonly whensearch_box_valid,workspace_box/workspace_regiononly when their*_validflag is set. (L4093)fill_idl(self, msg) -> None— Populate a duck-typedopenral_msgs/GraspDeclaration; no primitive factory, a grasp region carries no geometry. (L4126)class ContactForceWitness(BaseModel)— Layer 2's bounded attestation of a measured contact force between a payload and its declared place target; the gate it feeds only ever adds a refusal, never licenses a contact or widens an allowance.magnitude_nis newtons only whenmagnitude_calibrated. Absence of a witness is not evidence of absent contact. (L4267)from_idl(cls, msg) -> Self[@classmethod] — Decode the duck-typed OpenRAL ROS IDL message without importing ROS. (L4345)fill_idl(self, msg) -> None— Populate a duck-typed OpenRAL ROS IDL message without importing ROS. (L4364)class SupportContactWitness(BaseModel)— World State's bounded attestation that a payload rests on a named support surface; geometry is in the attached object's own frame, andmax_penetration_mis the physical depth (occupancy quantisation is accounted for separately). (L4154)from_idl(cls, msg) -> Self[@classmethod] — Decode the duck-typed OpenRAL ROS IDL message without importing ROS. (L4236)fill_idl(self, msg) -> None— Populate a duck-typed OpenRAL ROS IDL message without importing ROS. (L4252)class AttachedCollisionObject(BaseModel)— Collision-active payload rigidly attached to one robot link;support_contact=None(the default) means the safety kernel exempts no payload-vs-world contact. (L4560)from_idl(cls, msg) -> Self[@classmethod] — Decode the duck-typed OpenRAL ROS IDL message without importing ROS. (L4634)fill_idl(self, msg, *, primitive_factory) -> None— Populate a duck-typed OpenRAL ROS IDL message without importing ROS. (L4692)class OccupancyGridRef(BaseModel)— Reference to a 2D occupancy grid for mobile-base world-collision, mirroringnav_msgs/OccupancyGridmetadata. (L4734) fields:frame_id, resolution_m (>0), width (>=0), height (>=0), origin: Pose6D, data_topicclass WorldState(BaseModel)— Snapshot consumed by Reasoner and Skills;policy_statecarries a checkpoint-specific proprio vector when joint state alone can't represent it, andplace_declarationrelays the resolved place phase (region included) to the safety kernel —Nonemeans no place phase, no witness, no allowance;grasp_declarationrelays the grasp phase the same way. (L4882) fields:stamp_ns, joint_state, base_pose, base_twist, ee_poses, contact_forces, images, image_frames, point_clouds, tactile, detected_objects, battery_pct, diagnostics, attached_objects, attachment_revision, attachment_stamp_ns, occupancy_grid- occupancy_grid — Optional 2D occupancy-grid reference for mobile-base footprint checks; an absent or stale grid is treated as unavailable (fail-closed).
- attached_objects / attachment_revision / attachment_stamp_ns — Collision-active payloads plus the producer-owned revision and freshness timestamp; republishing
WorldStatedoes not refresh stale attachment evidence. - image_frames — Optional in-process frame carrier for no-ROS deployments;
Nonekeeps the existingimagestopic-ref path unchanged.
Persistent spatial memory — scene graph
Advisory, queryable Layer-2 world model the S2 Reasoner consults to recall objects/places/agents. Never a safety input — the kernel gates only on the geometric world. Poses anchored in the tf2 map frame.
class SpatialNodeKind(str, Enum)—OBJECT | PLACE | ROOM | AGENT. (L4952)class SpatialRelationKind(str, Enum)—CONTAINS | AT_PLACE | TRAVERSABLE_TO | ON | NEAR. (L4968)class SpatialNode(BaseModel)— A typed scene-graph node; superset ofDetectedObjectforkind=OBJECT. (L4985) fields:node_id, kind, pose: Pose6D, label, confidence, bbox_3d, embedding_ref, is_container, occludes_contents, first_seen_ns, last_seen_ns, observation_countclass SpatialEdge(BaseModel)— Directed relation between two nodes. (L5060) fields:src, dst, kind: SpatialRelationKindclass SceneGraph(BaseModel)— Persistent scene-graph memory; validates unique node ids and that every edge references an existing node. (L5076) fields:schema_version="0.1", nodes: list[SpatialNode], edges: list[SpatialEdge]class RecallObjectQuery(BaseModel)— Read-only object recall query. (L5117) fields:text, label, near: Pose6D | None, max_age_ns, limitclass ApproachViewpoint(BaseModel)— Camera-facing standoff goal. (L5149) fields:pose: Pose6D, standoff_m (>0), camera_frame_idclass RecallObjectMatch(BaseModel)— One ranked recall result. (L5166) fields:node_id, label, pose: Pose6D, score, last_seen_ns, approach: ApproachViewpoint | None, inside_container_id: str | Noneclass RecallObjectResult(BaseModel)—matcheslist; empty means unknown, so the caller raisesROSObjectNotInMemory. (L5191)class ResolvePlaceQuery(BaseModel)— Resolve a place/room/agent reference. (L5206) fields:reference, kind: SpatialNodeKind | Noneclass ResolvePlaceResult(BaseModel)— Resolved node plus atraversable_topath. (L5221) fields:node_id, goal: Pose6D, path_node_ids: list[str]class Action(BaseModel)— Action step or chunk produced by a Skill;tick_indexpreserves multi-slot atomicity across the safety wire,runner_session_id(uint64, 0 = unknown / session-less) names the runner process that numbered it so a HAL can tell a restart from a replay, and optionaljoint_namesnames which joints a sub-slot targets (needed since a zero-padded slot would otherwise read0.0as a legal target). (L5242) fields:control_mode, horizon, joint_targets, joint_velocities, joint_torques, cartesian_pose, cartesian_delta, cartesian_delta_scale, cartesian_twist, body_twist, foot_placements, gripper, dex_hand_joints, confidence, stamp_ns, ee_name, frame_id, safety_overridesclass QuantizationConfig(BaseModel)— Quantization recipe. (L5403) fields:dtype, backend, per_channel, calibration_dataset, extraclass DeviceInfo(BaseModel)— Host compute snapshot. (L5427) fields:device_str, gpu_memory_bytes, cuda_compute_capability, cpu_count, archclass RSkillInfo(BaseModel)— Skill runtime state snapshot. (L5479) fields:name, version, state, weights_loaded, quantized, warmed_up, embodiment_tags, role, latency_budget_ms, last_inference_ms, error_msg, stamp_ns
Pydantic models — skill packaging (rSkill)
class RSkillLatencyBudget(BaseModel)— Per-stage latency budget;max_execution_sis the total execution budget for oneexecute_rskillgoal in seconds on the clock the robot moves on (graph clock underuse_sim_time, else wall), bounding a VLA that never self-terminates. (L5561) fields:per_chunk_ms, warmup_ms, load_ms, max_execution_sclass SensorRequirement(BaseModel)— One sensor an rSkill needs the robot to provide. (L5586) fields:modality, vla_feature_key, min_width, min_height, countclass ImagePreprocessing(BaseModel)— Per-rSkill checkpoint image-preprocessing contract, so the sim adapter doesn't need to learn a checkpoint's frame conventions from a YAML override.aliaseskeys are VLA slots (camera1), never sensor/scene camera names. (L5643)unknown_alias_slots(sensors_required) -> list[str]— Alias keys nosensors_required[].vla_feature_keydeclares as a slot;resolve_image_preprocessingraises on any. (L5720)class ControlModeSemantics(BaseModel)— Action-space semantics on eachActuatorRequirement. (L6997) fields:mode: Literal["absolute","delta"], gripper_convention, joint_order, reference_frame- Cross-validator on
ActuatorRequirement: gripper kinds requiregripper_convention; cartesian kinds requirereference_frame; other kinds forbid both. GripperConvention(TypeAlias = Literal[...]) — Closed gripper-action encoding set. Members:normalized_open_unit, normalized_open_symmetric, normalized_close_symmetric, binary_close_one, raw_joint_rad, width_meters. Declared on both sides of the wire: the rSkill's gripper actuator, and the robot end effector or simulated scene. (L1107)class ActuatorRequirement(BaseModel)— One actuator slot an rSkill emits actions for;n_dof/vla_action_keyauto-fill from the robot YAML for canonical embodiments, required for the"custom"hatch. (L7046) fields:kind, n_dof, vla_action_key, control_mode_semanticskindreusesControlMode;n_dof/vla_action_keyauto-fill from the robot YAML for canonical embodiments, required on the manifest for the"custom"hatch.control_mode_semanticsis required: declares absolute-vs-delta and, when applicable, gripper convention / reference frame.class EmbodimentExtra(BaseModel)— Sensor + actuator surface for the"custom"embodiment hatch. (L7144) fields:sensors: list[SensorRequirement] (≥1), actuators: list[ActuatorRequirement] (≥1)class RSkillProcessors(BaseModel)— Explicit lerobotPolicyProcessorPipelineartefact pointers. (L7381) fields:preprocessor_uri, postprocessor_uri- Per-file URI shape
hf://owner/repo[@rev]/path/to/file.ext— the file tail is required; a bare repo URI is the implicit-snapshot shape this deliberately replaced. - Cross-validator rejects identical pre/post URIs.
_PROCESSOR_URI_PATTERN: str— ValidatesRSkillProcessors.preprocessor_uri/postprocessor_urirequires a file tail. (L7356)class RosIntegration(BaseModel)— Wiring for a wrapped ROS 2 action/service; required whenRSkillManifest.kindisros_action/ros_service, forbidden otherwise. (L7512) fields:package, interface_type, interface_name, result_trajectory_field, default_goal_json, ros_dependenciesresult_trajectory_field is None→ result-only mode (Nav2 shape); set → trajectory mode (MoveIt shape, replaying one waypoint perstep()).default_goal_jsonvalidator round-trips the literal throughjson.loadsand rejects non-dict payloads._ROS_WRAPPER_KINDS: frozenset[str]—{"ros_action", "ros_service"}, the kinds requiringRosIntegration. (L7502)class SegmenterEngine(str, Enum)— Backend selector forkind: "segmenter"rSkills; required onSegmenterContract.engine(no legacy fallback, unlikeDetectorEngine). (L7766)class SegmenterContract(BaseModel)— Manifest contract forkind: "segmenter"rSkills, the sibling ofDetectorContractfor models answering a geometric prompt rather than a semantic one. Deliberately carries nolabels/score_threshold— a segmenter never classifies and its consumer never gates on model confidence. (L7787)class DetectorEngine(str, Enum)— Backend selector forkind: "detector"rSkills, disambiguating backends that otherwise share aruntime;Nonekeeps the legacyruntime-keyed dispatch. (L7624)class DetectorMode(str, Enum)— Invocation mode of a detector, orthogonal toDetectorEngine:CONTINUOUS(always-on, feedsWorldState.detected_objects, not dispatchable) vsON_DEMAND(prompted via thelocate_in_viewtool). (L7660)class DetectorContract(BaseModel)— Manifest contract forkind: "detector"rSkills;max_sidecaps the VLM-sidecar's resize before grounding, trading detection resolution for lower activation VRAM. (L7696) fields:labels: list[str](min_length=1; class-label list indexed by model class-id),input_size: tuple[int, int](width × height, both > 0; default (640, 640)),score_threshold: float(ge=0.0 le=1.0; default 0.5),engine: DetectorEngine | None,mode: DetectorMode(defaultcontinuous)class RewardContract(BaseModel)— Manifest contract forkind: "reward"rSkills; a reward monitor is a pure perception consumer with no actuators or action/state contract, so its progress/success signal is advisory only. (L7842)class PlaybookContract(BaseModel)— Manifest contract forkind: "playbook"rSkills (human-authored S2 decision procedure); content the reasoner reads into its system prompt, never code it executes — no weights, actuators, or action/state contract. (L7945)class RSkillManifest(BaseModel)—rskill.yamlmanifest; a pre-publish surface extended in place several times without a schema-version bump. (L8002) fields:schema_version, name, version, license, role, kind, model_family, embodiment_tags, embodiment_extra, capabilities_required, sensors_required, actuators_required, runtime, quantization, weights_uri, chunk_size, latency_budget, min_vram_gb, fallback_skill_id, benchmarks, evaluated_tasks, sim_env_control_mode, policy_extras, paper_url, dataset_uri, source_repo, description, default_prompt, actions, objects, scenes, processors, image_preprocessing, state_contract, action_contract, n_action_steps, ros_integration, detector, reward, reward_rskill_name, playbook.kindgates which other fields are required or forbidden (see_check_kind_consistencybelow).evaluated_tasksgates a scene's task against what the checkpoint was trained on, raisingROSCapabilityMismatchwhen it doesn't cover the scene.reward_rskill_namenames the reward monitor a VLA pairs with, since a VLA emits no success signal of its own;Nonedefers to the deployment default reward model rather than meaning "run without reward".default_promptis the literal conditioning string a single-task checkpoint was trained on — distinct fromdescription, which is prose for the LLM to pick the skill by.from_yaml(cls, path: str) -> RSkillManifest[@classmethod] — Load and validate anrskill.yaml. (L8824)active_min_vram_gb(self) -> float | None— Declared VRAM for this skill at its active quantization dtype, orNonewhen undeclared; consumed byassert_vla_reward_fits. (L8178)is_commercial_use_allowed: bool[@property] — Derived fromlicense: True for apache-2.0/mit/bsd, False otherwise. (L8266)is_scaffold_placeholder: bool[@property] — True whenname/weights_uri/source_repostill carry an unresolved template sentinel, i.e. this is therskills/template/scaffold; the reasoner palette gate and the publish gate both use it to keep the scaffold from being dispatched or published. (L8278)- Cross-validators:
"custom" ∈ embodiment_tags ↔ embodiment_extra is not None; a"custom"entry requiresn_dofandvla_action_keyon every actuator. - rSkill self-containment audit cross-validator:
processorsrequired for most model families; legacyactmay omit it. - Cross-validator (
_check_kind_consistency): eachkindrequires and forbids a specific field set (e.g.vlaneedsmodel_family+weights_uri,detectorneedsdetector+weights_uriand no actuators);wamvalidates schema-side but the loader rejects it at resolve time. - Cross-validator (
_check_n_action_steps_within_chunk):n_action_steps <= chunk_size(None= the adapter's default, resolved byopenral_rskill._vla_core.resolve_n_action_steps). - The historical
policy_idfield was removed in favour of dispatching onmodel_familydirectly. prop _HF_HUB_ID_PATTERN, _SEMVER_PATTERN, _WEIGHTS_URI_PATTERN, _HF_DATASET_URI_PATTERN, _HTTPS_URL_PATTERN— Regexes validatingRSkillManifest's URI/version/URL fields, pinned at module scope so the patterns stay greppable. (L7314–7323)_LICENSES_ALLOWING_COMMERCIAL: frozenset[RSkillLicensePosture]— LicensesRSkillManifest.is_commercial_use_allowedtreats as commercial-OK:apache_2_0/mit/bsd. (L7361)_MODERN_PROCESSOR_FAMILIES: frozenset[str]— Model families requiringRSkillManifest.processors;actmay omit it via the legacy norm-stats-in-safetensors path. (L7376)RSKILL_TEMPLATE_SENTINELS: tuple[str, ...] = ("TEMPLATE_ORG", "TEMPLATE_ID")— Canonical unresolved-scaffold sentinels theopenral rskill newscaffolder rewrites; shared by the reasoner palette gate and the publish gate so the "is this a published skill?" rule can't drift. (L7333)def contains_rskill_template_sentinel(text: str | None) -> bool— True whentextcarries anRSKILL_TEMPLATE_SENTINELSsubstring; the text-level primitive behindis_scaffold_placeholder. (L7336)def assert_vla_reward_fits(vla: RSkillManifest, reward: RSkillManifest, gpu_total_gb: float, *, margin_gb: float = 0.5) -> float— Pre-load gate verifying a VLA and its paired reward model co-reside in GPU VRAM; raisesROSConfigErrorif either size is undeclared,ROSGPUMemoryErrorif they don't fit, else returns the combined GB. (L9265)- rSkill HF-repo naming, enforced by
tools/rskill_publisher.py. Hyphens are only the segment separator; a name parses bysplit("-")into one of three shapes —rskill-<model>-<robot>-<task>-<quant>(weight-bearing kinds),rskill-<model>-<robot>-<task>(ros_action/ros_service, no weights), orrskill-playbook-<name>. _DEFAULT_RSKILL_OWNER: str = "OpenRAL"— Owner used when a manifestnamecarries no<owner>/prefix. (L8871)_RSKILL_NAME_SEGMENT_RE: re.Pattern[str]— Every name segment must match^[a-z0-9][a-z0-9_]*$. (L8874)prop _RSKILL_NAME_PARTS, _RSKILL_ROS_NAME_PARTS, _RSKILL_PLAYBOOK_NAME_PARTS— Expected hyphen-segment counts for the three name shapes. (L8881–8883)CANONICAL_MODEL_TOKENS: frozenset[str]— Versioned<model>checkpoint vocabulary; distinct fromModelFamilysince several tokens can share one family, and tool models have no family. (L8912)CANONICAL_ROBOT_NAME_TOKENS: frozenset[str]— The reserved robot-agnostic<robot>tokens{"any", "multi"}(multi= a skill declaring more than one concrete robot). Concrete robot tokens are an open registry:repo_name_is_canonicalchecks them by shape, and CI (tests/unit/test_manifest_registry_ids.py) checks in-tree names againstrobots/*/robot.yamltags. (L9015)CANONICAL_QUANT_TOKENS: frozenset[str]—{fp32, fp16, bf16, int8, nf4}; the weightless ROS-wrapper kinds omit the<quant>segment entirely. (L8885)_WEIGHTLESS_KINDS: frozenset[str]—{"ros_action", "ros_service"}— kinds carrying no weights, so their name omits<quant>. (L8890)_NAME_TAIL_QUANT_LIKE: frozenset[str]— Trailing tokens the author-slug fallback strips from a name tail. (L8894)_QUANT_DTYPE_TO_TOKEN: dict[QuantizationDtype, str]— Mapsquantization.dtypeto its<quant>name token. (L8898)_MODEL_FAMILY_ALLOWED_TOKENS: dict[str, frozenset[str]]— Per-family allowlist of<model>tokens; only the special cases (versioned / multi-token families) need an entry. (L8974)def _allowed_model_tokens(model_family: str) -> frozenset[str]—_MODEL_FAMILY_ALLOWED_TOKENSlookup defaulting to{model_family}, so a new family needs no schema edit. (L9002)_MODEL_FAMILY_TO_TOKEN: dict[str, str]—model_family→ canonical<model>suggestion token; a family absent from the map suggests its own id. (L8952)_EMBODIMENT_TO_ROBOT_TOKEN: dict[str, str]— Robot tags whose bare form would collide, mapped to a distinct<robot>token; every other tag uses its bare id. (L9007)def repo_name_is_canonical(name: str, *, kind: RSkillKind, model_family: str \| None = None) -> bool— The enforced validator: kind-selected shape plus<model>vocab (CANONICAL_MODEL_TOKENS, or the family's allowed tokens whenmodel_familyis set);<robot>and<task>are checked by shape only. (L9124)def expected_repo_name(manifest: RSkillManifest) -> str— The canonical name suggestion printed on a mismatch and written by--fix-name; always satisfiesrepo_name_is_canonicalfor the manifest's kind. (L9200)_REGISTRY_ID_PATTERN: str—^[a-z][a-z0-9_]*$, the shape of the four open registry ids below (StateLayout,EmbodimentTag,BenchmarkName,ModelFamily). Membership is checked by the registries and CI, not the core schema. (L5736)EmbodimentTag(TypeAlias = Annotated[str, StringConstraints(pattern=_REGISTRY_ID_PATTERN)]) — Open robot-embodiment id: the tagsrobots/*/robot.yamldeclare, plus"custom"escape hatch,"mobile_base"class tag,"any"(embodiment-agnostic wildcard for perception/playbook kinds), and"multi"(repo-name aggregate). Typo guard:openral_rskill.loader.intree_embodiment_tags+ CI. (L7191)StateLayout(TypeAlias = Annotated[str, StringConstraints(pattern=_REGISTRY_ID_PATTERN)]) — Open per-checkpoint proprioception layout id, naming the trained shape (field order, frame convention, gripper encoding, quaternion handedness); per-robot source bindings live onStateContractBindings. Membership:openral_state_adapter.registered_layouts()(palette drop /assemble_staterefusal) + CI. (L5748)WRAPPED_TASK_SPACE_LAYOUTS: frozenset[StateLayout]— Subset ofStateLayoutcovering Cartesian/FK-derived composites, which requireStateContract.bindings; joint-space layouts are excluded and served verbatim from rawJointState.position. (L5783)class StateContract(BaseModel)— Per-rSkill state-vector contract, surfacing the proprioception layout a checkpoint was trained against so the runtime adapter doesn't learn it from a YAML override; requiresbindingswhenlayoutis inWRAPPED_TASK_SPACE_LAYOUTS, forbids it otherwise. (L5845) fields:layout: StateLayout | None, dim: int | None, bindings: StateContractBindings | NoneStateContractBindings(Pydantic model) — Per-robot source bindings for an rSkill'sstate_contract.layout; the state-side symmetric counterpart ofControlModeSemantics. (L5799) fields:eef_frame: str | None,base_frame: str | None,world_frame: str | None = "map",gripper_qpos_joints: list[str],quaternion_convention: Literal["xyzw","wxyz"] = "xyzw"BenchmarkName(TypeAlias = Annotated[str, StringConstraints(pattern=_REGISTRY_ID_PATTERN)]) — Open benchmark id (RSkillManifest.benchmarkskeys). Membership:openral_rskill.loader.known_benchmark_ids(benchmarks/*.yaml∪scenes/benchmark/*.yamlstems) at writeback / CI;from_pretrainedonly warns. (L7228)ModelFamily(TypeAlias = Annotated[str, StringConstraints(pattern=_REGISTRY_ID_PATTERN)]) — Open VLA/policy family id used by the eval/runner adapter dispatch; required only whenRSkillManifest.kind == "vla"(forbidden on every other kind). Membership:openral_sim.POLICIES+ CI. Several families run out-of-process via a dedicated ZMQ sidecar rather than in-process. (L7249)RSkillKind(TypeAlias = Literal["vla","wam","ros_action","ros_service","detector","vlm","reward","playbook"]) — Discriminator selecting the loader/runner branch;wamis reserved and the loader rejects it at resolve time. (L7428)
Pydantic models — skill benchmark results (rskills/<id>/eval/<benchmark>.json)
class RSkillEvalSource(BaseModel)— Provenance of a benchmark block. (L9333) fields:paper, arxiv, model_variant, evaluated_by, reproduced_locally, reproduction_planned, reproduction_cli, table, statusclass RSkillEvalBenchmark(BaseModel)— Suite identity for a benchmark block. (L9371) fields:name, dataset, protocol, robot, simulatorclass RSkillEvalResult(BaseModel)— On-disk shape ofrskills/<id>/eval/*.json; optionaltrace_idcross-references the OTel trace tree when the run had an OTLP endpoint to export to. (L9393) fields:schema_version, source, benchmark, eval_config, results, baselinesfrom_json(cls, path: str) -> RSkillEvalResult[@classmethod] — Load and validate a single benchmark JSON. (L9443)
Pydantic models — validation-matrix round verdicts (outputs/validation-matrix/<round>/verdicts.json)
Written by tools/validation_matrix.py; the machine-readable half of docs/reference/collision-validation-evidence.md. The kernel's verdict is transcribed verbatim and adjudicated only against the simulator's own ground truth.
ValidationOutcome(TypeAlias = Literal[...]) — How one scene ended. Members:completed, estop-collision-real, estop-collision-false-positive, estop-collision-within-quantization, estop-collision-unadjudicated, estop-initial-configuration, deadline-after-grasp, deadline-no-grasp, harness-error.GroundTruthAdjudication(TypeAlias = Literal["real-contact","false-positive","within-quantization","unadjudicated"]) — Verdict of the simulator's distance probe on a kernel stop;real-contactrequires a solid-geom pair at or below 0 m, an unfiltered snapshot reads asunadjudicated.class ValidationStopEvidence(BaseModel)— The kernel'ssafety.collisionline, transcribed field for field. (L9526) fields:kind, party_a, party_b, horizon_step, min_distance_m, sweep_min_distance_m, place_allowance_active, place_target, depth_is_box_boundexemption_active[@property] — Whether a support witness exempted a deeper cell at the trip. (L9590)involves_payload[@property] — Either party isattached:<object_id>. (L9597)class ValidationGroundTruthAdjudication(BaseModel)— Adjudication of a stop againstsim.estop_ground_truth_snapshot; withdraws tounadjudicatedwhen the probe's distances carry no certified proof, since the simulator's own distance function is known wrong on this pair class. (L9602) fields:verdict, stop_class, sim_time_s, grid_resolution_m, quantization_budget_m, admissible_gap_m, budget_source, probe_collidability_filtered, probe_distance_certified, unadjudicated_reason, nearest_any_m, nearest_tripping_party_m, nearest_pair, discrepancy_m, probed_pairs, probe_truncated, distmax_m, payload_contactsclass ValidationWitnessTimeline(BaseModel)— Attach/witness/place-declaration lifecycle, recorded from both the monitor and the kernel's own log lines since a disagreement is itself a finding. (L9680) fields:attach_t_s, detach_t_s, support_id, kernel_witness_armed, kernel_witness_separated, place_declaration_seen, place_region_armed, place_allowance_active_linesclass ValidationSceneVerdict(BaseModel)— One scene of one round, queryable;config_sha256pins the exact YAML bytes that ran. (L9719) fields:scene, config_path, config_sha256, seed, prompt, rskill_id, outcome, task_success_final, task_success_ever, task_success_steps, task_success_transitions, stop, ground_truth, witness, monitor_records, dispatch_failure_reason, wall_s, artifacts, harness_error_reasonclass ValidationRoundMetadata(BaseModel)— The reproducibility half of a round; every field exists because a past round could not be reproduced without it. (L9792) fields:round_id, started_at, host, executed_sha, worktree_clean, overlay_built_at_ns, launcher_path, repo_root, robot_manifest_path, robot_id, sync_groups, stack_argv, safety_overrides_absent, gpu_name, notes_path, scene_dirs, seed, artifact_stem, imported_from, scene_pinsclass ValidationRoundVerdicts(BaseModel)— On-diskverdicts.json. (L9881) fields:schema_version, metadata, scenesfrom_json(cls, path: str) -> ValidationRoundVerdicts[@classmethod] — Load and validate a round's verdicts. (L9913)scene(self, name: str) -> ValidationSceneVerdict | None— The verdict for one scene key. (L9932)class ValidationSceneDelta(BaseModel)— How one scene moved between rounds. (L9944) fields:scene, baseline_outcome, outcome, changed, changed_fieldsclass ValidationRoundDiff(BaseModel)— Round-over-round comparison. (L9978) fields:schema_version, round_id, baseline_round_id, executed_sha, baseline_executed_sha, seed, baseline_seed, scenessame_sha[@property] — Both rounds ran the same code. (L10020)same_seed[@property] — Both rounds pinned the same scene seed. (L10025)is_reproducibility[@property] —same_sha and same_seed; anything else is a before/after, since a seed change moves the scene's initial configuration however equal the SHAs are. (L10030)changed_scenes[@property] — Scene keys whose outcome moved. (L10040)
Pydantic models — sim eval
class SceneSpec(BaseModel)— Physics scene declaration. (L10092) fields:id, backend, assets_uri, observation_height, observation_width, cameras, backend_optionsclass TaskSpec(BaseModel)— What the robot must achieve. (L10137) fields:id, scene_id, instruction, max_steps: int | None, success_key: str | None, metadataclass VLASpec(BaseModel)— Policy / brain declaration. (L10191) fields:id, weights_uri, device, runtime, quantization, deterministic, extraclass SimEnvironment(BaseModel)— Runtime (robot × scene × task × VLA) tuple, composed at the CLI from aSimScene/BenchmarkSceneYAML plus anRSkillManifest; never loaded from YAML directly. (L10232) fields:robot_id, scene, task, vla, base_pose, seed, n_episodes, record_video, save_dir, metadatabase_pose: Pose6D | None = None— Per-rollout robot mounting pose in the scene's world frame; honoured by free-axis scenes only.model_post_init(_context: object) -> None— Cross-field validationtask.scene_id == scene.id. (L10291)class BenchmarkMetadata(BaseModel)— Provenance block required on everyBenchmarkScene; suite invariants treat it as byte-identical across scenes. (L10301)class LaunchInclude— A vendor ROS 2 launch a deploy must bring up alongside the graph, since aSensorDeployBindingnames a topic to subscribe to but not who publishes it. Carried byDeployScene.drivers, real path only. (L10325)class VisionAttachmentRuntime(BaseModel)—DeployRuntime.vision_attachment: the real-hardware vision attachment leg (SAM 2.1 segmenter lifecycle node + the HAL's attachment-evidence bridge). Fields:enabled: bool = False,camera: str(manifest sensor),rgb_topic/rgb_camera_info_topic/depth_topic/depth_camera_info_topic: str | None(all four required when enabled: the leg projects only through the driver's CameraInfo, never the manifest's nominal intrinsics),segmenter_manifest: str(SAM 2.1 rSkill default),device: str = "auto",deadline_s: float = 0.25,evidence_timeout_s: float = 0.5(jaw-position liveness for the heartbeat),tf_frames: dict[str, str](manifest link → TF frame),grasp_target_enabled/place_target_enabled: bool = False(the bridge's pre-grasp target and real place producer legs; HAL paramsvision_attachment_grasp_target_enabled/_place_target_enabled; throughdeploy_e2ethe place one also turns on the runner'splace_approach_enabledgoal-scope place declaration),grasp_target_approach_m: float | None = None(in (0,GraspDeclaration.MAX_HALF_EXTENT_M], needsgrasp_target_enabled; the approach-armed grasp target with no named target, HAL paramvision_attachment_grasp_target_approach_m, and throughdeploy_e2ethe runner'sgrasp_approach_enabledwhengrasp_allowance_enabledis on),grasp_target_premeasure: bool = False(needsgrasp_target_enabled; HAL paramvision_attachment_grasp_target_premeasure: the grasp-target leg pre-measures every object instance near a hand from head-camera segmentation before any hand arms, each box confirmed by the voxel map, and arms the region from the tracked instance nearest the hand — camera first, map confirms and holds while the hand occludes — so it exists before contact without the policy pausing —docs/reference/object-primitives-design.md, issue #349, prototype),grasp_target_margin_m: float = 0.0(in[0, MAX_GRASP_TARGET_MARGIN_M]= [0, 0.05] m, ClassVarsMAX_GRASP_TARGET_MARGIN_M/DEFAULT_GRASP_TARGET_MARGIN_M= 0.0 — no bloat unless a scene names it, the real OpenArm cell scenes name 0.03; HAL paramvision_attachment_grasp_target_margin_m; the grasp-target bloat: the kernel's pre-handover region is the held region grown by it on every face, downward too — finger links may press up to it into the support under the target — the attached payload, which is also the region the kernel latches at the handover, lowered onto the measured support and grown on the sides and top only; Safety-WG, HZ-0115-32),release_timeout_s: float = 3.0(> 0; the release window's bound, HAL paramvision_attachment_release_timeout_s; its grid age and clearance are launch-derived, not scene knobs). Coupling rule: enabled on real it always turns the kernel's attached check on (attached_collision_enabled, 1000 ms deadline), never the leg alone. Default off pending Safety-WG review. The grasp trigger's thresholds are not scene knobs: they are the manifest'sJointSpec.closure_calibration. (L10363)class DeployRuntime(BaseModel)— Committed deploy-posture toggles for a workcell scene (SLAM, Nav2, octomap, object detector, reward monitor, critic, spatial-memory ingest), all tri-state with explicit CLI flag > sceneruntime:> auto/built-in default precedence.preload_rskill_id/preload_rskill_revision/preload_prompt(optional, scene-only): the rSkill the skill_runner resolves and loads right after it activates, in a worker thread, so the firstexecute_rskillgoal finds it resident — the deadman watchdog opens its first-chunk window on goal ACCEPT, so a multi-minute cold load inside a goal is E-stopped, correctly; revision must be exactly what later goals send (the policy is resident per id + revision); the prompt only warms the inference path, each goal's own prompt reaching the policy per step. Forwarded aspreload_rskill_id:=/preload_rskill_revision:=/preload_prompt:=only when set. (L10591)joint_states_topic: str | None(scene-only): explicit override for theJointStatetopic the deploy runtime's Python nodes ingest;None= derived byopenral_hal.hal_joint_states_topic(a real ros2_control HAL's rate-limited/<hal_node>/joint_states, else/joint_states). The C++ kernel keeps the full-rate topic.clock_origin(host_wall|simulation|None) pins the graph's clock authority;Noneon a twin whoseoctomap_cloud_topiclies outside/openral/cameras/already selectshost_wall(simulationwith it is refused).world_voxel_deadline_s: float = 1.0/max_octree_age_s: float | None: the kernel's voxel deadline and the octomap bridge's octree-age bound, per rig (a source slower than ~1 Hz raises both); a validator refuses an age above the deadline so the kernel, not the bridge, fails closed (hazard log Entry 033). Hard caps (_check_perception_caps, 2x the pre-2026-09-25 values, refused at load with the field, the cap and why):world_voxel_deadline_s <= 2.0,world_voxel_data_age_budget_s <= 3.0,robot_self_filter_padding_m <= 0.10; also exported as the JSON Schemamaximum, and enforced again by the nodes themselves (kernel configure, self-filter, voxel bridge; a deliberate mirror pinned bytests/unit/test_perception_caps_mirror.py).world_voxel_data_age_budget_s: float = 1.5(> 0): how old the world behind a grid may be at check time, from the grid'ssource_stamp; the kernel'sworld_voxel_data_age_budget_ms(Entry 034). Default = the Thor ZED-M measurement (p99 ~1.0 s, max 1.09 s, 2026-09-24); declare a measured value per rig. Independent of the deadline pair (they bound receipt, this bounds the world's age), so no ordering is imposed; smaller is only stricter.robot_self_filter_padding_m: float = 0.02(>= 0; measured at rest on the OpenArm Thor and Orin cells, 2026-09-25: the robot's own returns end 5-7.5 mm outside its hulls; the moving-arm tail is unmeasured): how far past the collision model a real depth return is removed as the robot byrobot_self_filter; derive per rig from depth noise + extrinsic error + capture/joint-state sync motion + half a voxel. Also the width of the blind shell around the arm (Entry 035).grasp_allowance_enabled: bool = False: turns on the safety kernel's grasp-target exemption (grasp_allowance_enabled:=true;deploy_e2epassesgrasp_contact_links= therole: gripperjoints'child_links); ondeploy run(real HAL) it is refused unlessvision_attachment.enabledandvision_attachment.grasp_target_enabledare on with no--haloverride turning them off.workspace_contact_enabled: bool = False/workspace_contact_max_speed_mps: float | None(0 < v ≤ 1.0; required when enabled, a calibration point — the measured hand speed from/joint_statesvelocity; commanded speed, row 0 from the previously accepted command, as the fallback without one) /workspace_contact_max_lead_m: float | None(0 < d ≤ 0.10; required when enabled, a calibration point — the hand's lead over its measured pose, the push bound): the safety kernel's manipulation-workspace contact rule (issue #349) — hand links (RobotDescription.hand_links()) may touch cells inside a live declaration's confirmedworkspace_regionwhile the hand is slow and its lead small; requiresgrasp_allowance_enabledand both bounds (_check_workspace_contact); sim-only until Safety-WG review (deploy runand a non-simdeploy_e2erefuse it).vision_attachment: VisionAttachmentRuntime | None = None: the real-hardware vision attachment leg (seeVisionAttachmentRuntime).voxel_freshness_s -> tuple[float, float][@property] (L10925) —(world_voxel_deadline_s, max_octree_age_s)with the age defaulted to the deadline; whatopenral deployforwards to the launch.class DeployScene(BaseModel)— Unified deploy/workcell scene foropenral deploy sim/run;place_declarationis the committed place-phase declaration for a direct dispatch (Nonemeans no place witness can arm), and a scene may not supply its ownplace_declaration.regionsince that must be producer-measured;grasp_declarationis the grasp-phase sibling under the same no-region rule (_reject_scene_supplied_place_regionrefuses both). Notasksfield — deploy goals come from the operator via--initial-task//openral/prompt.robot_unitnames the cell'sRobotUnitoverlay ($OPENRAL_ROBOT_UNIToverrides). (L11011)from_yaml(cls, path: str) -> Self[@classmethod] — Load and validate a scene YAML from disk; inherited bySimScene/BenchmarkScene, which validate against their own stricter schemas. (L11203)class SimScene(DeployScene)— ExtendsDeployScenewithtask,seed,n_episodes,record_video,save_dir,metadata; cross-validatestask.scene_id == scene.id; accepted byopenral sim run. (L11212)class BenchmarkScene(SimScene)— ExtendsSimScenewith required eval fields (n_episodes,seed,metadata,task.success_key,task.max_steps); consumed byopenral benchmark. (L11239)class ProtocolSpec(BaseModel)— Standalone eval-protocol schema, retained for decision-record drafts and report tooling that quote a published protocol verbatim; never embedded in a benchmark suite. (L11284) fields:n_episodes, seeds, success_key, max_steps, min_repsmodel_post_init(_context: object) -> None— Cross-field validation:len(seeds) >= n_episodesandmin_reps <= n_episodes. (L11327)
Pydantic models — inference runner
On-disk + runtime contracts for the hardware inference runner (openral deploy --config R.yaml), sibling of SimEnvironment / openral sim run. Schemas are additive — SimEnvironment / RSkillEvalResult / BenchmarkScene are untouched.
class FrameEncoding(str, Enum)— HowSensorFramebytes are interpreted. (L4762)BGR8, RGB8, MONO8, DEPTH16, JPEG, PNG, CUDA_NV12, CUDA_RGBA, RAW—CUDA_NV12is the Tegra NVMM handle layout,CUDA_RGBAthe x86 DeepStream oneclass SensorFrame(BaseModel)— Single sensor frame: metadata plus optional inline/topic/handle payload; JSON-serializes the binary payload as base64. (L4784) fields:sensor_id, stamp_monotonic_ns, stamp_wall_ns, encoding, width, height, channels, data, topic, handle, metadata_decode_data(cls, value: Any) -> bytes | None[@field_validator("data", mode="before")] — Accepts rawbytesor a base64-encodedstron JSON parse. (L4851)_encode_data(self, value: bytes | None) -> str | None[@field_serializer("data", when_used="json")] — JSON-serializes the binary payload as base64. (L4867)model_post_init(_context: object) -> None— Cross-field validation: exactly one of(data, topic, handle)must be set. (L4871)class SensorReaderBackend(str, Enum)— WhichSensorReaderimplementation a sensor uses. (L11357)OPENCV_THREAD, ROS2_IMAGE, GSTREAMERclass DeadlineOverrunPolicy(str, Enum)— Behaviour when a tick exceeds1 / rate_hz. (L11385)WARN, DROP, RAISEclass SensorReaderConfig(BaseModel)— Per-sensor reader backend plus optional ROS-tee. (L11399) fields:sensor_id, backend, backend_params, max_age_ms, publish_to_ros, publish_topic, publish_rate_hz, publish_frame_id, publish_camera_info—publish_frame_idstamps the tee'sImage/CameraInfoheaders (defaultsensor_id);publish_camera_info: IntrinsicsPinhole | Nonemakes the tee also publishCameraInfoon the image topic's sibling.model_post_init(self, _context: object) -> None— Cross-field validation for the ROS tee:publish_to_ros ↔ publish_topic;publish_frame_id/publish_camera_inforequirepublish_to_ros. (L11461)class SensorDeployBinding(BaseModel)— OptionalSensorSpec.deploy_bindingpayload lettingopenral deploy runopen the physical camera; the runtime counterpart ofsim_placement. Robot cameras carry it in their host's unit overlay (orrobot.yaml); a deploy scene never touches them. (L11491)class SensorOverlay(BaseModel)— Per-host / per-unit values for one robot-manifest sensor:deploy_binding,ros2_topic,static_transform_xyz_rpy,intrinsics;extra="forbid"refuses identity/semantics (frame_id,parent_frame,modality, …). (L11532) fields:name, deploy_binding, ros2_topic, static_transform_xyz_rpy, intrinsicsclass RobotUnit(BaseModel)— One physical unit / host of a robot type,robots/<robot_id>/units/<unit>.yaml; selected by$OPENRAL_ROBOT_UNITorDeployScene.robot_unit. (L11563) fields:schema_version, robot_id, unit, sensorsfrom_yaml(path) -> RobotUnit[@classmethod] (L11588)class HalConfig(BaseModel)— Which HAL adapter to instantiate plus transport params (serial port / FCI URI / ROS namespace). (L11613) fields:adapter, transport, paramsclass TickResult(BaseModel)— One tick's record returned byInferenceRunner.tick; optional sim-only fields and trace context default toNoneso hardware ticks serialize unchanged from v1. (L11646) fields:stamp_ns, tick_idx, sensors_ms, world_state_ms, inference_ms, safety_ms, hal_ms, tick_ms, chunk_index, safety_violations, action_applied, step_idx, episode_idx, reward, terminated, truncatedclass RunResult(BaseModel)— Aggregated summary returned byInferenceRunner.run. (L11732) fields:n_ticks, success, budget_violations, avg_inference_ms, p99_inference_ms, avg_tick_ms, p99_tick_ms, trace_id, save_dir, metadata
Pydantic models — failure evidence
Discriminated union backing the evidence_json field of openral_msgs/msg/FailureTrigger. Discriminator is kind; decode via pydantic.TypeAdapter(FailureEvidence).validate_json(...). All variants are frozen and reject extra fields.
class _FailureEvidenceBase(BaseModel)— Private base. (L11768)class TimeoutEvidence(L11779) —kind="timeout"; fieldsoperation, deadline_s, elapsed_s.class ForceEvidence(L11796) —kind="force"; fieldsjoint_or_ee, measured_n, limit_n.class WorkspaceEvidence(L11812) —kind="workspace"; fieldsee_name, measured_xyz, box_min, box_max.class PerceptionStaleEvidence(L11830) —kind="perception"; fieldssensor_id, staleness_ms, threshold_ms.class CriticEvidence(L11846) —kind="critic"; fieldscritic_id, score, threshold.class ControllerEvidence(L11862) —kind="controller"; fieldscontroller_name, state, detail.class SelfVerifyEvidence(L11878) —kind="selfverify"; fieldscheck, expected, observed.class HumanEvidence(L11894) —kind="human"; fieldsactor, reason.class WamEvidence(L11908) —kind="wam"; fieldshorizon, discrepancy, wam_id.class ReasonerTimeoutEvidence(L11924) —kind="reasoner_timeout"; fieldsmodel, deadline_s, elapsed_s.class CollisionEvidence(L11940) —kind="collision";horizon_step=-1(REACTIVE_HORIZON_STEP) marks the kernel's reactive measured-state check rather than a predicted chunk step;joint_positions_radis the FK'd configuration for that step, making a predicted stop adjudicatable. Maps toFailureTrigger.KIND_COLLISION. fields:collision_kind: Literal["self"|"world"], link_a, link_b_or_object, horizon_step, min_distance_m, joint_positions_rad: list[float]REACTIVE_HORIZON_STEP: ClassVar[int]— the-1sentinel; use it instead of a literal.is_reactive(property) —Truewhenhorizon_step == REACTIVE_HORIZON_STEP. (L11997)class SuppressedSummaryEvidence(L12002) —kind="suppressed_summary"; fieldswindow_s, kinds: list[int], severities: list[int], counts: list[int]. A model-validator enforces the arrays stay parallel.FailureEvidence: TypeAlias(L12036) — Discriminated union over the twelve variants above.
Pydantic models — perception event metadata
Discriminated union backing the metadata_json field of openral_msgs/msg/PromptStamped when published on /openral/perception/<kind>. Discriminator is kind; decode via pydantic.TypeAdapter(PerceptionEventMetadata).validate_json(...). New kinds mean new topics, not a schema bump.
class _PerceptionEventBase(BaseModel)— Private base; carriessensor_id. (L12071)class ObjectDetection2D(BaseModel)(L12090) — Single 2D detection insideObjectsMetadata;det_idis a stable per-detector/per-camera identity assigned at detection time, letting an object be de-duplicated without the 3D lift, then propagated intoDetectedObject.track_id. fields:label, confidence, bbox_xyxy, det_id: int = -1class MotionMetadata(L12119) —kind="motion"; fieldsmagnitude, threshold, region_bbox.class ObjectsMetadata(L12142) —kind="objects";frame_width/frame_heightmake the pixel space ofbbox_xyxyexplicit so the voxel lifter can scale it to the camera's intrinsics resolution. Optionalcamera_frame_id+camera_intrinsics(set together or not at all, validator-enforced) carry the driverCameraInfo's optical frame and K, which the world-state lift projects through instead of theSensorSpecnamed bysensor_id. fields:detections: list[ObjectDetection2D], model_id, frame_width: int (>0), frame_height: int (>0)class OcrMetadata(L12198) —kind="ocr"; fieldstext, confidence, region_bbox.class SceneChangeMetadata(L12216) —kind="scene_change"; fieldsdistance, threshold, metric.PerceptionEventMetadata: TypeAlias(L12239) — Discriminated union over the four variants above.
Pydantic models — reasoner tool calls
Discriminated union over the closed palette of typed tool calls the reasoner can emit each tick. Discriminator is tool; decode via pydantic.TypeAdapter(ReasonerToolCall).validate_json(...). All variants are frozen and reject extra fields so an LLM cannot smuggle ad-hoc ones onto the wire. The reasoner holds no direct actuation authority — it never publishes ActionChunk itself; ExecuteRskillTool dispatches indirectly via the action server, which gates through safety.
class _ReasonerToolBase(BaseModel)— Private base; carries optionalrationale. (L12509)class ExecuteRskillTool(L12656) —tool="execute_rskill"; fieldsrskill_id: str(min_length=1),prompt: str(default ""),goal_params_json: str(default ""),deadline_s: float(ge=0.0; default 0.0; 0 = use manifest latency budget),patience_s: float | None(default None; gt=0.0; task-adaptive execution ceiling override — None uses the reward model'sdefault_patience_s),progress_tolerance: float | None(default None; ge=0.0; overrides the reward model'splateau_tolerancefor a noisy critic — None uses the model default),grasp_target: GraspTargetRef | Noneandplace_target: PlaceTargetRef | None(default None; the targets the LLM names, grounded by the reasoner at dispatch into the goal'sGraspDeclaration/PlaceDeclaration, or the dispatch is refused — real pick-and-place design §2.2).class GraspTargetRef(BaseModel)(L12544) — Frozen,extra="forbid".label: str(min_length=1; open-vocabulary, matched case-insensitively against live lifted detections),object_id: str | None(arecall_objectnode_id; required when several objects share the label),contact_links: list[str](ALLrole: gripperchild_links of ONE hand — the gripper joints hanging off one arm — in any order; empty only on a single-hand robot, where it means that hand; with several hands an empty list, links of two hands, a non-gripper link, or part of a hand is refused at grounding). Names; arms nothing.class PlaceTargetRef(BaseModel)(L12599) — Frozen,extra="forbid". An OPTIONAL hint naming the surface a goal places onto (the real producer measures the surface under the carried payload without it):label: str(min length 1), and at most one ofobject_id/place_node_id(spatial-memory node ids); grounded at dispatch toPlaceDeclaration.search_box.class ReloadGstPipelineTool(L12735) —tool="reload_gst_pipeline"; fieldssensor_id, pipeline_yaml.class LifecycleTransitionTool(L12759) —tool="lifecycle_transition";shutdownis deliberately absent — that authority belongs to the safety supervisor. Canonical primitive for managing long-lived background services (slam_toolbox, RTAB-Map, perception trees), which are LifecycleNode peers, not rSkills. fields:node, transition: Literal["configure"|"activate"|"deactivate"|"cleanup"]class EmitPromptTool(L12783) —tool="emit_prompt"; the reasoner node publishes ontarget_topicitself via a per-topic publisher cache. fields:target_topic(must start with/),text,metadata_jsonclass WaitTool— deliberate no-op;tool="wait", no fields beyondrationale. Since the reasoner's tool choice is forced, this lets the LLM choose "observe and wait" instead of acting every tick. No actuation authority. (L13169)class RecallObjectTool— read-only query;tool="recall_object"; recalls an object from the scene-graph memory. No actuation authority. Dispatch is planned Phase 2, not yet in the live provider palette. (L12811) fields:query(free-text/label),limitclass ResolvePlaceTool— read-only query;tool="resolve_place"; resolves a place/room/agent to a goal pose plus path. No actuation authority. Dispatch is planned Phase 2. (L12833) fields:reference("the kitchen", "where I was standing")class LocateInViewTool— read-only query;tool="locate_in_view"; asks a live VLM detector whether an object is in the current frame (vsrecall_object's remembered objects). No actuation authority. (L12850) fields:query(concrete object noun(s)),camera(optional viewpoint id, default primary),detector(optional locator selector, default the deployment default)class QuerySceneTool— read-only query;tool="query_scene"; asks a scene VLM an open-ended question about the current frame, answer fed back as a re-prompt. Distinct fromlocate_in_view: returns free text, not boxes. (L12896) fields:question(open-ended scene-state question, min_length=1),camera(optional viewpoint id)class QueryTaskProgressTool— read-only query;tool="query_task_progress"; asks the reward monitor for a windowed progress/success assessment, fed back to drive the replanning ladder. Distinct fromquery_scene: returns normalized scalars, not free text. (L12929) fields:window_s(seconds of recent frames to assess, > 0, default 8.0),task(optional instruction override)MemorySection: TypeAlias = Literal[...]— the five fixed sections of the self-maintainedMEMORY.mdcore:home_map,preferences,lessons,object_locations,open_tasks.class MemoryWriteTool— write; the reasoner's first write-capable variant;tool="memory_write"; edits the advisoryMEMORY.mdvia an explicit add/update/supersede/delete op. Writes the memory file only — no actuation authority. (L12974) fields:op(add/update/supersede/delete),section: MemorySection,content(required unlessdelete),importance(0–1, default 0.5),target(required forupdate/supersede/delete)class MemorySearchTool— read-only;tool="memory_search"; pages archived entries evicted from the bounded core back in. No actuation. (L13015) fields:query(min_length=1),section: MemorySection | None,limit(1–100, default 5)is_collective_target(text) -> bool— True whentexttargets a set rather than one specific object (a quantifier or bare generic plural); shared byGroundedSubtask's validator and the reasoner node's runtime execute gate. (L13051)_COLLECTIVE_TARGET_RE: re.Pattern[str]— Backing regex foris_collective_target. (L13045)class GroundedSubtask— One subtask bound to exactly one specific object; a validator forbids a collectiveobject_ref/textand requirestextto nameobject_ref, so "the first batch of objects" isn't representable. (L13067) fields:object_ref: str(min_length=1),text: str(min_length=1)render(self) -> str— The instruction string handed toMissionState/ the skill. (L13122)class DecomposeMissionTool— task-ledger write;tool="decompose_mission"; the typed path for a playbook to write the deterministicMissionState— emptytarget_task_idreplaces the whole queue, a set one flat-splices into that blocked task. Edits the S2 task ledger only, no actuation authority. (L13127) fields:subtasks: list[GroundedSubtask](min_length=1),target_task_id: str(default"")rendered_subtasks(self) -> list[str]— The ordered subtask instruction strings forMissionState. (L13164)ReasonerToolCall: TypeAlias— Discriminated union over the thirteen variants above.
Module-level functions (Layer 0)
def control_modes_for_representation(rep: ActionRepresentation) -> set[ControlMode](L6234) — Maps a VLA's declaredActionRepresentationto theControlModes it drives; single source of truth for the reasoner's deploy-path palette gate (a skill is offered only when the target robot advertises every returned mode).SIM_EXECUTABLE_CONTROL_MODES: frozenset[ControlMode](L6296) — Canonical set ofControlModes the default sim HAL action-packers can execute; single source of truth for the reasoner's sim-mode palette gate, pinned to the packers by a lockstep test. Excludes modes that are decoded but never pack-executed (would E-stop mid-run) or have no sim controller.def canonical_slots_for_representation(rep: ActionRepresentation, *, dim: int, description: RobotDescription) -> list[ActionSlot] | None(L6308) — Builds the canonicalActionSlotlayout the skill_runner dispatches a representation-onlyActionContractthrough. Joint representations returnNone(legacy whole-vector path). RaisesROSConfigErrorwhen the representation needs an EE the robot lacks, ordimis too small.def task_space_compatible(skill_space: TaskSpace, robot: RobotDescription, *, hal_mode: Literal["sim", "real"] = "real") -> TaskSpaceMatch(L6686) — DRAFT cross-layer gate subsuming today's implicit embodiment-tag/dim/adapter wiring; checks control-mode executability plus EE existence and joint-width bounds, returningok+ a reason per incompatibility. Wired warn-only so far.def scene_family(task_id: str) -> str— Reduces anevaluated_tasksentry to its scene-family key (leading token before any/). (L6837)SCENE_FAMILY_TASK_SPACE: dict[str, SceneTaskSpace]— Single source of truth for the control interface each scene-adapter family executes, keyed byscene_family(evaluated_task). (L6858)def scene_task_space_compatible(family: str, skill_space: TaskSpace) -> TaskSpaceMatch— Third leg of the cross-layer gate: everyControlModethe rSkill emits must be in the scene family's executed set. Pairs withtask_space_compatibleto close the rSkill × robot × scene triangle. (L6942)
python/core/src/openral_core/loaders.py
Strict YAML loaders for the three scene tiers.
def load_scene_strict(path: str, expected: type[DeployScene | SimScene | BenchmarkScene]) -> DeployScene | SimScene | BenchmarkScene(L36) — Loadspathas exactlyexpected, rejecting other tiers with a redirect message naming the right CLI command, so a YAML one tier too rich isn't silently widened.def load_benchmark_suite(path: str) -> list[BenchmarkScene](L148) — Loads a barelist[BenchmarkScene]frombenchmarks/<id>.yaml; per-scene validation runs here, suite-level invariants do not — callraise_on_invalid_suiteseparately. RaisesFileNotFoundError/ROSConfigError, never a bareValidationError.def raise_on_invalid_suite(scenes: list[BenchmarkScene], *, suite_id: str) -> None(L222) — Enforces the suite invariants: non-empty, everytask.idunique, androbot_id/n_episodes/seed/metadataidentical across scenes (per-scenesuccess_key/max_stepsmay differ). First violation wins; raisesROSConfigError.
python/core/src/openral_core/assets.py
The single resolver for robot description assets — URDF / MJCF / SRDF.
class AssetRefError(ValueError)(L43) — A description-asset reference is malformed or cannot be resolved.class AssetFetchError(AssetRefError)(L47) — A well-formed reference whose pinned upstream could not be fetched on this host (raised byresolve_package_uri); the one resolution failure an offline host may skip on, so tests check the type instead of matching the message.def resolve_asset(ref: str, kind: AssetKind, *, manifest_dir: Path | None = None) -> Path | None(L55) — Resolves one assetrefto a concrete file path for the requested kind; one grammar replacing several prior scheme-specific loaders. RaisesAssetRefErrorfor an unresolvable or malformed ref.def resolve_package_uri(uri: str) -> Path(L99) — Resolves one ROSpackage://<pkg>/<relpath>mesh URI to a file inside the pinned clone OpenRAL fetches for<pkg>(openral_hal.ros_package_overlay.PUBLIC_ROS_PACKAGES, lazily imported as_resolve_openarmdoes); a sourced ROS workspace is not consulted. RaisesAssetFetchErrorwhen the clone cannot be fetched (cause: the fetcher'sROSConfigError),AssetRefErrorfor a malformed URI, a package OpenRAL does not fetch, or a missing file._REPO_ROOT: Path— Resolved repo root; the basefile:<relpath>refs resolve against after the manifest dir. (L38)_ROS2_DYNAMIC: str = "ros2://robot_description"— The dynamic-detection marker scheme;resolve_assetreturnsNonefor it so the caller subscribes at runtime instead. (L39)_RD_ATTR: dict[AssetKind, str]— Mapskindto therobot_descriptionsmodule attribute it reads for therd:<module>scheme. (L40)
HalParameters also carries can_bus_bindings: dict[str, str], mapping a defaults key to the role token naming which physical CAN bus fills it — matched by token, never position, since a CAN interface name is a host property, not a robot one.
python/core/src/openral_core/gpu.py
Torch-free GPU probes shared across layers: one nvidia-smi VRAM query for the CLI and the reasoner ROS node, and one Tegra/L4T host probe for the CLI, the GStreamer platform probe and the hardware detector.
- const
TEGRA_RELEASE_PATH: Final[Path]—/etc/nv_tegra_release, present on every L4T (Jetson) image. (L23) is_tegra_host(release_path=None) -> bool— The one Tegra/L4T probe (NonereadsTEGRA_RELEASE_PATHat call time, so tests point that constant at a captured fixture), shared byopenral_sim._sidecar_common.default_expandable_segments(allocator default),openral_runner…gstreamer.pipeline.detect_platformandopenral_detect.probes.gpu._probe_jetson. Answers "L4T image", not "unified memory": DGX Spark (GB10) runs DGX OS. (L26)detect_gpu_vram_gb(field) -> float(L42) — Onenvidia-smi --query-gpu=<field>value for GPU 0 in GB;0.0on any failure so callers skip their check rather than block.
python/core/src/openral_core/can.py
Robot-agnostic SocketCAN transport discovery — a CAN-bus robot is invisible to USB/serial discovery, so this is the one place that reads the kernel's view of CAN links. Linux-only, dependency-free, needs no root, and never perturbs a running robot.
_ARPHRD_CAN: int = 280— The/sys/class/net/<if>/typevalue marking a CAN link. (L40)_CLASSIC_CAN_MTU: int = 16— Classic CAN's MTU; CAN FD needs 72, so MTU is the FD indicator on hosts withoutip. (L44)SYSFS_NET: str = "/sys/class/net"— Sysfs root for network devices, as a module constant so tests can point enumeration at a fixture tree. (L48)class CanInterface(NamedTuple)— One SocketCAN interface on the host;stateis the field to check when a detected arm won't move. (L51)enumerate_can_interfaces(*, sysfs_net=None) -> list[CanInterface]— Lists CAN interfaces from sysfs, enriched with bitrate/FD/state viaip -details -json link showwhen available. (L208)can_link_state(interface, *, sysfs_net=None) -> tuple[bool, str]— Single-interface counterpart:(is_up, reason)naming the specific problem. (L274)preflight_can_links(interfaces, *, hal_label, remedy="", sysfs_net=None) -> dict[str, str]— The connect-time gate every CAN robot needs; reports every failing bus in one message and raisesROSConfigErrorotherwise. (L303)
python/core/src/openral_core/depth_extrinsic.py
The depth-camera extrinsic a real world-voxel deploy runs on. OpenRAL does not measure it: the operator calibrates the mount and declares it in the unit overlay; this module states the accuracy that needs (MAX_*, derived from the real world-voxel margin) and the provenance gate openral deploy run applies. numpy-free, outside openral_core.__init__, so the launch file can import the margin cheaply.
REAL_WORLD_VOXEL_MARGIN_M: Final[float] = 0.02(L30) — The kernel's real-deployworld_voxel_margin_m(deploy_e2e.launch.py::_world_voxel_margin_mreturns it); the required accuracy below derives from it.CHECKED_RANGE_M: Final[float] = 1.0(L33) — Range at which an angular error is converted to metres.MAX_HEIGHT_ERR_M: Final[float](L36) — Half the margin (10 mm).MAX_TILT_DEG: Final[float](L37) —atan(MAX_HEIGHT_ERR_M / CHECKED_RANGE_M)(~0.57°): tilt error at 1 m plus height error never exceed the margin.MAX_PLANAR_ERR_M: Final[float](L40) — Three quarters of the margin (15 mm): the camera's horizontal error.MAX_YAW_DEG: Final[float](L41) —atan(MAX_PLANAR_ERR_M / CHECKED_RANGE_M)(~0.86°).depth_extrinsic_problems(description, overlays, scene_sensors=(), *, estimated_camera=None) -> list[str](L44) — Every cloud source whose mount a real world-voxel deploy may not trust (estimated_camera's mount — its own or the one itshares_mount_with— counts as one): a robot-mounted one (SensorSpec.is_cloud_source) must get itsstatic_transform_xyz_rpyfrom one of the unit'sSensorOverlays, never the manifest's nominal value; a scene-mounted one must declareparent_frame+static_transform_xyz_rpy. Provenance, not correctness. Empty = go.class EstimatedDepthMount(NamedTuple)(L110) —cloud_frame(REP-103 optical frame DA3's depth/CameraInfo/cloud are stamped in),optical_parent(body-convention mount the launch hangs it under, orNone),mount_sensor(whose mount places the camera; the real extrinsic gate checks it),problems.resolve_estimated_depth_camera(sensors, camera, *, hal_mode, scene_sensor_names=(), calibrated_intrinsics=()) -> EstimatedDepthMount(L130) — Any RGB camera with intrinsics (top, context, wrist) tied to the robot: a declaredparent_frame+static_transform_xyz_rpyon it or on itsshares_mount_withsensor (sim and real; body mounts get a<frame>_optical_framechild), or in sim an*_optical_framethe bridge places from the MJCF. Refusesworld, bare robot links, depth sensors, missing intrinsics, on a real deploy a camera with nodeploy_bindingor with only the manifest's nominal intrinsics (DA3's metres scale with the focal: it needs its driver's CameraInfo — aros2_imagebinding with atopic— or this unit's calibrated intrinsics,calibrated_intrinsics= the overlays that set them) or a non-boolbackend_params.rectified, and REFUSES any camera whenever the robot or the scene has any measured depth or point-cloud sensor (is_cloud_source), in sim and real, no override — naming each such sensor as robot or scene (scene_sensor_names) (HZ-0382-6). Shared byopenral deployanddeploy_e2e.launch.py.
python/core/src/openral_core/geometry.py
Shared rotation geometry — look-at/camera gaze poses plus planar yaw↔quaternion helpers, so every layer uses one implementation instead of duplicating them. Import-on-demand, not re-exported by openral_core.__init__, so schemas stay numpy-free on the fast CLI path.
ViewAxis(TypeAlias =Literal["-z", "+z", "+x"]) — Camera forward-axis conventions:"-z"MuJoCo,"+z"ROS optical frames,"+x"body-frame forward._ZERO_NORM: float = 1e-9— Below this vector norm,look_at_quat_wxyztreats the gaze direction as degenerate. (L48)_PARALLEL: float = 0.999— Above this|cos|between gaze andup,look_at_quat_wxyzswaps to the alternate up vector. (L49)_QUAT_NORM_EPS: float = 1e-12— Below this squared norm, a quaternion is treated as degenerate. (L50)look_at_quat_wxyz(eye, target, *, up=(0,0,1), view_axis="-z") -> tuple[float, float, float, float]— Unit quaternion orienting a camera ateyesoview_axispoints attarget; never raises, falling back to a fixed orientation on degenerate input. (L187)compute_gaze_pose(camera_xyz, target_xyz, *, frame_id="map", up=(0,0,1), view_axis="+z") -> Pose6D— Full 6-DOF camera pose whose view axis hitstarget_xyz. (L250)rotation_to_quat_wxyz(rot: 3x3) -> tuple[w, x, y, z]— Matrix→quaternion conversion (Shepperd's method). (L173)homogeneous_from_quat_xyz(translation, quat_xyzw) -> NDArray[np.float64]— The canonical TF2 transform→4x4-matrix step; raisesROSConfigErroron a degenerate rotation rather than guessing. (L53)yaw_to_quat_xyzw(yaw: float) -> tuple[x, y, z, w]— Unit quaternion (ROS order) forRz(yaw). (L109)yaw_to_quat_wxyz(yaw: float) -> tuple[w, x, y, z]— Same rotation in MuJoCo order. (L120)quat_xyzw_to_yaw(x, y, z, w) -> float— Planar yaw in[-pi, pi], roll/pitch ignored. (L131)
python/core/src/openral_core/detection_tracker.py
Camera-space 2D detection tracker — pure, ROS-free, stateful; the 2D analog of ObjectMemory.
def aabb_iou_2d(a: tuple[int, int, int, int], b: tuple[int, int, int, int]) -> float— 2D axis-aligned bbox IoU in[0, 1];0.0for disjoint/degenerate boxes. (L21)class DetectionTracker2D(*, iou_threshold=0.3, max_misses=3)— Stateful per-camera 2D-IoU tracker assigning a stabledet_idto each detection, so an object can be de-duplicated without a 3D lift. (L60)assign(self, detections: list[ObjectDetection2D]) -> list[ObjectDetection2D]— Stamps each detection with a stabledet_idvia greedy same-label IoU association; retires tracks unseen formax_missesframes. (L90)
python/core/src/openral_core/time_base.py
The deploy-sim time base — one env.step / send_action is one control period (issues #355, #358). Every sim backend derives its physics steps per tick here and every sim HAL holds the backend to the robot's rate here.
TIME_BASE_TOL: float—0.01: tolerance onsim_dt_per_tick_s * control_freq_hz == 1. (L18)physics_steps_per_tick(control_freq_hz, physics_dt_s) -> tuple[int, float]—(steps, dt_s)withsteps * dt_s == 1 / control_freq_hzexactly; (L21) keeps the engine dt when it already divides the period, otherwise shrinks it (never grows) to the largest value at or belowphysics_dt_sthat does (MuJoCo's 0.002 s at 30 Hz: 16.67 steps → 17 at 1/510 s).ROSConfigErroron a non-finite / non-positive rate or dt. Used byMujocoArmHAL._resolve_time_baseandopenral_sim.rollout.pin_robosuite_time_base.check_time_base(sim_dt_per_tick_s, control_freq_hz, *, backend, robot) -> None— Refuses (ROSConfigError) a tick that is not one control period withinTIME_BASE_TOL(NaN refused too), or a manifest with no rate (control_freq_hz=None). (L59) The one guard behindSimAttachedHAL._check_time_baseand the twin.
python/core/src/openral_core/exceptions.py
openral exception hierarchy — use these, do not invent new base classes.
class ROSError(Exception)— Base class for all OpenRAL errors. (L41)class ROSConfigError(ROSError)— Bad manifest, missing weights, invalid YAML/URDF. (L48)class ROSCapabilityMismatch(ROSError)— Skill requires a capability the robot lacks. (L52)class ROSRuntimeError(ROSError)— General runtime failure. (L59)class ROSQuantizationError(ROSRuntimeError)— Quantization failed. (L63)class ROSGPUMemoryError(ROSRuntimeError)— Out of GPU memory. (L67)class ROSSafetyViolation(ROSError)— Safety constraint violated; never silently caught. (L74)class ROSWorkspaceViolation(ROSSafetyViolation)— Action outside allowed workspace. (L82)class ROSForceLimitExceeded(ROSSafetyViolation)— Contact force exceeds limit. Not raised anywhere yet — no check compares a force againstSafetyEnvelope.max_force_n; reserved for the force/current contact layer (#373). (L86)class ROSCollisionImminent(ROSSafetyViolation)— Proposed motion would self-collide or strike a world obstacle. (L95)class ROSEStopRequested(ROSSafetyViolation)— Emergency stop requested. (L104)class ROSPerceptionStale(ROSError)— Sensor reading exceeds staleness deadline. (L111)class ROSObjectNotInMemory(ROSPerceptionStale)— A scene-graph query matched no node or only stale nodes; caller degrades to "unknown", never fabricates a pose. (L115)class ROSPlanningError(ROSError)— Reasoner failed to produce valid plan. (L128)class ROSReasonerInvalidPlan(ROSPlanningError)— LLM returned invalid plan. (L132)class ROSFleetError(ROSError)— Fleet-level / dispatch error. (L139)class ROSDispatchUnavailable(ROSFleetError)— No dispatcher available. (L143)class ROSRskillGoalSatisfied(ROSError)— Typed control-flow completion signal raised once a wrapped-ROS rSkill finishes; caught only at the runner's execute-callback boundary, which closes the goal withsuccess=True. Not an error despite the base class. (L154)class ROSDeadlineMissed(ROSFleetError)— Cloud RTT exceeded skill deadline. (L147)