Audience

Verification level

Configuration only. The example validates the robot manifest, resolves its real URDF, and inspects the portable vocabulary. It does not start PyBullet or validate actuation, dynamics, IK, or planning.

Files

  • run.yaml adds one two-joint arm and its initial joint positions.
  • main.py asserts joints, links, frames, groups, and instance state.
  • Robot manifest declares the reusable robot contract.

Component manifest, line by line

yaml
schema: fastsim-component/1
id: robot://fastsim/component-demo-arm   # Stable robot identity.
version: 1.0.0                           # Immutable component release.
kind: robot                              # Legal under scenario.scene.robots.
semantics:
  joints: [joint_1, joint_2]             # Portable joint names.
  links: [base_link, link_1, link_2]     # Portable link names.
  frames: [base_link, link_2]            # Named application-facing frames.
  joint_units:
    joint_1: rad                         # State/control unit for joint_1.
    joint_2: rad                         # State/control unit for joint_2.
  groups:
    arm: [joint_1, joint_2]              # Ordered arm command group.
variants:
  pybullet:
    resources:
      model:
        uri: ../../_shared/assets/two_joint_arm.urdf
        format: model/vnd.urdf+xml
        role: simulation

A useful robot manifest separates portable intent from backend representation. Application code uses stable joint, link, frame, and group names. Each backend variant supplies the model it can consume. More complex robots can declare multiple groups such as base, left_arm, right_arm, and gripper without changing the Run structure.

When authoring your own robot, make these names match the public vocabulary you want users to depend on. A manifest is not a controller implementation and does not hide missing native actuators or bad dynamics.

run.yaml, line by line

yaml
schema: fastsim/2
name: robot-component
backend: pybullet                        # Select the PyBullet-compatible model.

runtime:
  physics_hz: 60                         # Physics frequency declaration.
  control_hz: 30                         # Control admission frequency.
  seed: 104                              # Reproducible run seed.

scenario:
  scene:
    robots:
      arm:                               # Local entity alias: robots.arm.
        use: robot://fastsim/component-demo-arm
        pose:
          xyz_m: [0.0, 0.0, 0.0]       # Robot root in world metres.
          quat_xyzw: [0.0, 0.0, 0.0, 1.0]
        initial_state:
          joints:
            joint_1: 0.20               # Radians, as declared by the manifest.
            joint_2: -0.40              # Negative angles are valid.

arm is an instance alias; it need not equal the component name. A Run can create multiple instances of one robot under unique aliases.

What main.py proves

Using only from fastsim.config import load_project, the program compiles the Run and asserts:

  • the selected component has kind: robot;
  • its ordered joint, link, and frame declarations are available to upper layers;
  • group arm resolves to both joints in order;
  • the initial joint mapping reaches the immutable entity record.

Run it

bash
cd demo/components/04_robot_component
fastsim config validate run.yaml --json
fastsim config expand run.yaml
fastsim config explain run.yaml scenario.scene.robots.arm.initial_state.joints.joint_1
fastsim config lock run.yaml --output run.lock.yaml
fastsim config verify-lock run.lock.yaml --json
python main.py

Expected output

text
Entity: robots.arm
Joints: ('joint_1', 'joint_2')
Links: ('base_link', 'link_1', 'link_2')
Frames: ('base_link', 'link_2')
Group 'arm': ('joint_1', 'joint_2')

Common errors

  • An initial-state joint absent from semantics.joints is rejected.
  • Group order matters for vector commands; keep it deliberate and documented.
  • A tool frame declaration is a name contract, not proof that every asset variant has been calibrated correctly. Native onboarding must verify it.
  • A robot component describes a robot entity. A refrigerator or laptop with joints belongs in an articulation:// component instead.

Next

Previous: articulation component · Next: environment component