Units & Conventions
This page documents the unit system and conventions used throughout the Space Robotics Bench.
Unit System
SRB uses SI units consistently, following the conventions of NVIDIA Isaac Sim and Isaac Lab.
| Quantity | Unit | Symbol |
|---|---|---|
| Length | meter | m |
| Mass | kilogram | kg |
| Time | second | s |
| Angle | radian | rad |
| Force | newton | N |
| Torque | newton-meter | N·m |
| Gravity | meters per second squared | m/s² |
Coordinate Frame
SRB uses a right-handed coordinate system with Z-up convention:
- X — forward
- Y — left
- Z — up
- Gravity — applied in the negative Z direction
Quaternion Format
Quaternions follow the (x, y, z, w) convention throughout SRB and Isaac Lab. This is important to keep in mind when interfacing with external libraries that may use the (w, x, y, z) order.
Note: Some USD/OpenUSD APIs (e.g.,
Gf.Quatf) use the (w, x, y, z) order internally. SRB handles the conversion automatically when interacting with these APIs.
Frame Suffix Convention
State variables use suffixes to indicate the reference frame:
| Suffix | Reference Frame | Example |
|---|---|---|
_w | World frame (absolute) | root_pos_w, body_quat_w |
_b | Body/base frame (relative) | ee_vel_b |
Domain-Specific Gravity
Each simulation domain defines its own gravitational acceleration:
| Domain | Gravity (m/s²) |
|---|---|
| Earth | 9.80665 |
| Mars | 3.72076 |
| Moon | 1.62496 |
| Asteroid | 0.14219 |
| Orbit | 0.0 |
Spec Authoring (@spec decorator)
New ActionGroup, SensorBase, and observation-manager classes should declare their spec via the @spec decorator from srb.core.spec. The decorator registers a ComponentDescriptor at import time; the env aggregates these into a queryable EnvSpec accessible via env.srb_spec (distinct from gymnasium’s own env.spec slot).
Two authoring styles
Explicit fields= — best for short, fixed schemas:
from srb.core.spec import spec, TermSpec
@spec(kind="action", fields=[
TermSpec(name="lin", shape=(1,), dtype="float32",
units="m/s", min=-2.0, max=2.0),
TermSpec(name="ang", shape=(1,), dtype="float32",
units="rad/s", min=-1.0, max=1.0),
])
class WheeledDriveActionGroup(ActionGroup):
...
spec_field attributes — best for longer schemas (>5 fields) where field-by-field readability matters:
from srb.core.spec import spec, spec_field
@spec(kind="action")
class SmoothOSCActionGroup(ActionGroup):
ee_pos = spec_field("ee_pos", dtype="float32", shape=(3,), units="m")
ee_rot = spec_field("ee_rot", dtype="float32", shape=(4,), units="quat")
stiffness = spec_field("stiffness", dtype="float32", shape=(6,),
units="N/m, Nm/rad")
Picking one or the other is mandatory — passing both fields= and using spec_field() in the same class raises at decoration.
What kind= to choose
"action"—ActionGroupsubclasses"sensor"—SensorBasesubclasses"observation"— observation-manager classes (currently per-task; passgroup="policy"as a keyword extra to scope to a specific group)
Privileged terms
Mark observation terms that must NOT appear in deployed policies (e.g. ground-truth particle positions) with privileged=True:
TermSpec(name="particles_xyz", shape=(N, 3), dtype="float32",
privileged=True,
semantic_label="excavation.particle_positions")
projections.onnx_export_mask(spec.observation) returns the set of term names to filter from ONNX export: every term with privileged=True plus any low-trust term whose provenance starts with <fallback> — pass this mask to the ONNX exporter to filter them out.
CI gate
A regression test in tests/unit/test_spec_decorator_audit.py enforces that every concrete ActionGroup and SRB-native SensorBase subclass is registered. Adding a new subclass without @spec(...) fails the test.