mj — MuJoCo free-flyer sim wrapper

Purpose

FFSim wraps MuJoCo for the free-flying chaser: it builds the scene (target mesh + chaser robot,
optional starfield/mocap marker), drives kinematic display or force-driven playback, counts
non-capsule collisions, and writes offline MP4s. An offline-only, visualization/diagnostic tool —
the live control loop never imports it.

Role in the system

  • Visualization / collision-check layer, not part of the live control chain (no GNC module imports it).
  • Consumes robot (GiordanoRobot for kinematics) and parameter_loader (load_parameters for cfg).
  • Pulls the target mesh path and reach config from cfg.camera_guidance.targeting (built from mesh geometry).
  • Uses infra for next_filename (MP4 naming) and RecursiveNamespace (robot-variant cfg override).
  • render_log_video replays a saved run’s logged q kinematically — pairs with the runner/orchestrator log pipeline.

Inputs / Outputs

  • In: a Pinocchio config q_pin (xyzw quat) or full state x = [q; v]; optional control u (applied as qfrc_applied); a States record (x, u); or a saved NPZ log path.
  • Out: mj_data (forward-evaluated), integer collision counts, and an MP4 written to videos/ (path in self.last_video_path).

Key methods / functions

  • FFSim.create_scene — build the MjSpec (mesh, chaser, lights, stars, mocap) — utils/mj.py:47
  • FFSim.display_config — set qpos and mj_forward (kinematics only, no dynamics) — utils/mj.py:152
  • FFSim.sim_config — set state, apply clipped u as qfrc_applied, mj_forwardutils/mj.py:162
  • FFSim.collision_count — non-capsule contact-pair count at a config — utils/mj.py:193
  • FFSim.configure_camera — auto-frame the chaser+target shot — utils/mj.py:239
  • FFSim.display_traj — live viewer or offline MP4 of a trajectory; returns total collisions — utils/mj.py:291
  • render_log_video — replay a saved log’s q kinematically to an MP4 (robot variant inferred from row width) — utils/mj.py:419
  • pin_to_mj_qpos / mj_to_pin_qpos — quaternion-order conversion (xyzw ↔ wxyz) — utils/mj.py:442 / :451
  • count_contacts_no_capsules — module collision predicate (drops _capsule geoms + self-contacts) — utils/mj.py:486

Pseudocode (offline playback)

FFSim(cfg, q_pin) → create_scene → compile → MjData       # gravity-free free-flyer
for each step q (and optional u):
    sim_config(q, u)  if u else  display_config(q)         # dynamics vs kinematics-only
    n_fr = count_contacts_no_capsules(model, data)         # ignore *_capsule + self pairs
    frame = add_text(renderer.render(), f"collisions: {n_fr}")
write_video(next_filename(stem, "videos", ".mp4"), frames)

robot · parameter_loader · infra · mesh · plotter3d · runner · terminology