Skip to content

Releases: isc-fs/IFSSIM

IFSSIM v1.0.1 — macOS build

Choose a tag to compare

@raulmoranguerra raulmoranguerra released this 21 Sep 22:13
36267c0

Same simulator as v1.0.0 — this release adds the macOS build.

Tagged at the same commit (36267c0662). No engine, plugin or configuration changes. If you are already running v1.0.0 on Windows there is nothing here for you.

v1.0.0 was published before the macOS artifact existed, and immutable releases meant it could not be added afterwards — hence a patch release rather than an edit. The Windows zip below is byte-identical to the one on v1.0.0 (sha256 4b0ea48c…, verified before re-publishing).


Downloads

platform file sha256
Windows 10/11 x64 IFSSIM-v1.0.1-Windows-x64.zip 4b0ea48cfe4f7ecd2b06f921e7a382ecc2295e824f16426aa22b2ea6878e1f31
macOS, Apple Silicon IFSSIM-v1.0.1-macOS-arm64.zip a345ea5ccd90c061a85d0772cf2a29818b3afca9789148911e6426ec4155567d

macOS

Apple Silicon only. The binary is arm64; there is no Intel or universal build. On an Intel Mac it will not launch.

  1. Download and unzip. You get IFSSIM.app — everything is inside the bundle, including the cooked content, settings.json and the track CSVs.
  2. First launch needs one extra step. The app is ad-hoc signed, not notarised, so Gatekeeper will refuse a double-click with "IFSSIM.app is damaged" or "cannot be opened". Either right-click the app → Open → Open, or clear the quarantine flag once:
    xattr -dr com.apple.quarantine /path/to/IFSSIM.app
    
  3. Allow the incoming-connection prompt on first run — that is the RPC endpoint on TCP 41451 the ROS 2 bridge connects to.

Changing settings. settings.json ships inside the bundle at IFSSIM.app/Contents/UE/IFSSIM/settings.json. Rather than editing in there, put your overrides at:

~/Library/Application Support/IFSSIM/settings.json
~/Library/Application Support/IFSSIM/tracks/

Both loaders already check that location, and it survives replacing the app.

Verified on an M1 Max: launches headless, RPC server bound on TCP 41451 within 2 s.

Windows

Unchanged from v1.0.0 — see those notes for the full instructions.


Known gaps

  • No Intel macOS build. Apple Silicon only.
  • Not notarised on either platform, hence the Gatekeeper and SmartScreen prompts.
  • The macOS artifact was built by hand. package-mac.yml needs a self-hosted macOS runner with UE5 and there isn't one registered, so the workflow cancels on tag pushes. It also had a bug that would have shipped an app with no cooked content — fixed in #618.

v1.0.0

Choose a tag to compare

@raulmoranguerra raulmoranguerra released this 20 Sep 21:21
Immutable release. Only release title and notes can be modified.
36267c0

Download & run

Windows 10/11, x64. No installer, no admin.

  1. Download IFSSIM-v1.0.0-Windows-x64.zip (312 MB) below.
  2. Verify (optional):
    sha256: 4b0ea48cfe4f7ecd2b06f921e7a382ecc2295e824f16426aa22b2ea6878e1f31
    
  3. Extract anywhere writeable (C:\IFSSIM\ works; a network drive doesn't).
  4. Run IFSSIM.exe in the extracted folder. On first launch Windows Firewall will prompt once for TCP port 41451 (the RPC endpoint the ROS 2 bridge connects to) — allow on private networks.

Expected minimum hardware: 6-core CPU, 16 GB RAM, a discrete GPU with 4 GB VRAM. The CPU LiDAR path uses ~50–60 % of one core; the rendered scene is the usual UE5 cost, which dominates.

The zip is the whole shipping stage — IFSSIM.exe at the root, plus Engine/, IFSSIM/ (cooked pak), tracks/, settings.json, UECommandLine.txt. Don't move the .exe out of the extracted folder or it won't find its content.

The ROS 2 pipeline runs in Docker on the same host — docker compose up -d in the repo, then hit Play in the sim, then start a mission from Mission Control at http://localhost:3000. See docs/OPERATING.md for the full loop.


What changed vs 0.2.0

Setting 0.2.0 1.0.0 Why
Plant.Type shadow chaos Shadow-plant is meant to be behaviour-neutral downstream but leaks state into odometry and stalls SLAM (#606)
LidarPath gpu cpu GPU readback path was tuned for ARM Mac unified memory; Windows/x86 stalls on PCIe transfer
PointsPerSecond 1 740 000 300 000 CPU-friendly at the current density; still 0.47° H-resolution at 30 m
ProjectVersion 0.2.0 1.0.0 First checkout-to-trackdrive release without a workaround

Branch layout

  • dev — default plant chaos, LiDAR cpu. Baseline this release tracks.
  • dev-manual — default plant shadow (or fmu). Ongoing FMU/Simulink plant integration; merges to dev once #606 resolves and the shadow-neutrality contract holds.

Verified

Trackdrive on a generated 356-cone loop, tag v1.0.0, Windows 11 + UE 5.7 editor:

  • /imu @ 418 Hz
  • /lidar_points @ 10.0 Hz (nominal Hesai ATX_S01 rotation rate)
  • /Conos_raw @ 10.0 Hz (cone perception producing detections)
  • /slam/pose @ 10.0 Hz sustained — no cascade, no stall
  • DV_RUNNING steady, no /watchdog/emergency
  • Autonomy released EBS, applied throttle + steering, tracked the corridor

The same setup with Plant.Type: shadow reliably trips the pipeline watchdog inside the first 60 s (/slam/pose silent 0.67s (budget 0.60s) → /slam/pose never published (5.03s since armed)).


Full changelog

CHANGELOG.md — [1.0.0] entry. Commit range from 0.2.0: git log --oneline v0.2.0..v1.0.0.

Tagged on dev at 36267c0. Autonomy pipeline (submodule) pinned at 3eae497.

IFSSIM v0.2.0 — the vehicle dynamics left Chaos

Choose a tag to compare

@AlvaroGonzalez05 AlvaroGonzalez05 released this 02 Sep 21:46
Immutable release. Only release title and notes can be modified.
b6f0e1b

No prebuilt binaries in this release. Build from source with
./package_mac.sh (macOS) or bash package_windows.sh (Windows) —
see docs/SETUP.md
§2 Option B. Platform zips will be attached here once a self-hosted
runner is available.

The vehicle dynamics left Chaos. This release is dominated by one
thread: the car's physics moved out of Unreal's arcade vehicle
simulator and behind an interface, and a team-authored Simulink model
now drives the car. Alongside that, the autonomy pipeline became a
submodule, every stochastic source became seedable, and a series of
long-standing physics defects were found — several of which had been
silently wrong since the project started.

Two changes are breaking for anyone tracking settings.json or the
repository layout: the autonomy pipeline is no longer in this repo, and
MaxSteerAngle has changed.

Added

  • IFSDSPlant — the platform/plant seam. The simulator now has an
    explicit boundary between the world (terrain, sensors, cones,
    referee — Unreal's job) and the vehicle (tyres, suspension,
    powertrain, aero — the dynamics engineers' job). SI units, ISO 8855
    body frame, ENU world. Two implementations: FFSDSChaosPlant
    (default, and still the only validated reference) and
    FFSDSFmuPlant.
  • A Simulink vehicle model, in matlab/plant/. Six subsystems with
    named owners — chassis, tyre/suspension, steering, powertrain, aero,
    brakes — each generated from a build_*.m script so a regenerated
    model is reviewable in a diff rather than an opaque binary. Every
    parameter comes from settings.json, with per-field provenance
    (measured / default / ASSUMPTION). Runs in MATLAB alone; no
    Unreal, Docker or ROS needed to work on it.
  • An FMI 3.0 co-simulation importer. Reads, extracts and gates an
    .fmu from inside the engine, including a ZIP reader written against
    zlib because the engine's own only links under bBuildEditor. State
    save/restore round-trips bitwise exact.
  • Plant.Type in settings.json — chaos, shadow or fmu. In
    shadow, the FMU steps alongside Chaos on identical inputs and the
    divergence is logged; it drives nothing, so it cannot change
    behaviour. In fmu the FMU integrates the vehicle and the mesh
    becomes a kinematic target written from the plant's pose each tick —
    sensors already read PlantState, so they follow for free.
  • The FMU drives the car (Phase 6). Measured: 0 → 21.8 m/s in 10 s
    with all four wheels in contact, and a 0.5 steering command giving an
    8.3 m radius against 8.22 m from L/tan(δ) — within 1% of an
    independent kinematic prediction rather than a number tuned to match
    anything.
  • A road probe. The platform now answers what is under each wheel
    — five rays per wheel, least-squares plane fit, reporting height,
    normal and an RMS residual so the plant can detect a bad fit rather
    than trust it. Validated against a ramp/crown/step test level with
    analytic ground truth, because on flat terrain a working probe and a
    stub returning zero produce identical logs.
  • Seeded determinism. resetScenario RPC, a seeded scenario
    runner, -fsds.seed= override, and a verifier that proves the RNG
    reproduces — which on first run failed, showing resetScenario
    alone was insufficient.
  • Benchmarking toolkit (tools/sim_benchmark/) — offline
    perception/SLAM/control benchmarks, the real C++ EKF driven through
    pybind11, bag-based drift checks with frame alignment.
  • Real-car parity for bag lift — a sim uDV emulator on the stock
    Mission Control surface, and auto-derived <name>_carparity bags
    (LiDAR + IMU only) for replaying onto the car on stands.

Changed

  • Breaking — the autonomy pipeline is now a submodule. Cone
    detection, SLAM, planning and control moved to
    isc-fs/IFS08-DV-PIPELINE
    and are consumed at pipeline/. Pipeline changes go to that repo.
    After pulling, run git submodule update --init --recursive.
  • Breaking — MaxSteerAngle 28° → 22.4°. Constant-steer sweeps
    show lateral acceleration peaks at 22.4° (1.336 g) and falls to
    1.268 g by 28°, while yaw/kinematic collapses 0.873 → 0.651. Past the
    peak, more lock buys less turn, which inverts the sign of a path
    controller's feedback — it runs wide, adds lock, turns less, adds
    more. Nothing is lost: every angle removed produced less curvature
    than 22.4° already does. The 28° it replaced was never measured.
  • The sim LiDAR publishes on /lidar_points, matching the car.
    Bags recorded before this need
    --remap /lidar/Lidar1:=/lidar_points on replay.
  • UE sim time is the authoritative capture clock end-to-end.

Fixed

Most of these had been wrong since the project started, and were found
by building the plant seam rather than by anything failing loudly.

  • Chaos was squaring the steering command. SquaredFunction was
    the engine default and never overridden, so a 0.5 command produced
    0.25 of full lock — the autonomy had been getting roughly half the
    steering it asked for in the mid-range, on top of a rate limit
    needing 0.4 s to reach full lock.
  • The Pacejka tyre model never reached the solver. Chaos builds its
    physics wheels from the wheel class's class default object before
    BeginPlay, so everything written to the per-instance wheels — the
    tyre curve, friction, brake torque, radius, steer limit — landed on
    an object the solver never reads. Much of settings.json's
    VehiclePhysics block had been decoration.
  • The tyre curve was far too peaky once it did reach the solver:
    LatC 1.9 → 1.4, LatE −1.5 → −0.3. The old shape peaked at 4.9° of
    slip and returned 34% of grip at full lock.
  • Regen never reached the sim. The brake/regen channel was dropped
    in the /ctrl/cmd relay, so the car could only coast, never brake —
    the root cause of corner overshoot at speed.
  • IMU accelerometer noise was 100× too small — applied in cm/s²
    while configured in m/s². The EKF had been tuned against a far too
    clean IMU.
  • Spring rate was 2.3× too soft, aero was applied twice, the aero
    moment arm was 10× too long, steering ran reverse Ackermann, and the
    speed-dependent steering curve was authored in km/h while Chaos
    evaluates it in MPH.
  • Multi-gate tracks spawned the car 90° off (acceleration, skidpad).
  • A finished bag could be abandoned when the recorder's stop
    service timed out while finalising a multi-GB mcap — the caller read
    the timeout as failure and skipped the copy to the host.
  • resetScenario left scoring permanently blind — every repeat run
    scored 0/0/0.
  • Plants were initialised twice on the same object. Invisible for
    years because the Chaos plant is idempotent; it only became a crash
    once something non-reentrant sat behind the same call — the FMU
    declares one instance per process, and a second Instantiate
    segfaults rather than failing. Teardown is now deterministic in
    EndPlay, since PIE restarts BeginPlay on a new pawn while the old
    one is still alive.

Known limitations

  • Chaos remains the default and the reference. The FMU drives the
    car under Plant.Type="fmu", but chaos is still what a fresh
    checkout runs, and it is the implementation every prior lap was
    validated against. Same-state parity between the two is ~0.8 m/s²
    mean.
  • Crr = 0.020 and the 22.4° steering clamp both rest on a
    shape-fitted Pacejka, not measured tyre data.
    Every dynamics number
    in this release is internally consistent and none of it is anchored
    to the real Hoosier. This is the measurement that would turn a
    self-consistent simulator into a validated one.
  • Four sources still disagree on maximum steering lock — 28°
    (invented), 22.4° (tyre peak), 18.2° (uDV firmware), 19.25° (the
    IFS-08 workbook). The workbook's figure may derive from the IFS-07
    wheelbase; see docs/IFS_08_measured_parameters.md. Tracked at #462.
  • The controller normalises steering by 18.2° while the sim maps full
    lock to 22.4° — a 1.23× scale mismatch. The clamp makes it safe, not
    consistent.

v0.0.1-test

v0.0.1-test Pre-release
Pre-release

Choose a tag to compare

@github-actions github-actions released this 27 Aug 22:43
Immutable release. Only release title and notes can be modified.
1a56e2f
Prueba del runner. Reintento tras rebajar las dependencias de iOS/Mac…

IFSSIM v0.1.2 — 9-state EKF + Schmidt-Kalman bias-freeze + two-phase mission lifecycle

Choose a tag to compare

@raulmoranguerra raulmoranguerra released this 27 May 06:17
Immutable release. Only release title and notes can be modified.
547b84a

[0.1.2] — 2026-05-26

The biggest autonomy-pipeline release since v0.1.0. Three intersecting
threads: a clean 9-state EKF with Coriolis-correct mechanics
(rewrite + post-rewrite hardening), a two-phase mission lifecycle
that separates SetMission (configure) from RuntimeControl (run),
and a stack of SLAM hardening changes that took mid-lap /odom
position drift from 56 m down to under 2 m on the autocross course
and eliminated the late-corner SLAM yaw-cascade pattern.

Sim-side: documentation overhaul, GPL-3.0-or-later relicense, auto-
pull bags onto the host on session-stop, and a compose-watch-based
inner-loop for Python edits without rebuilding the image.

Changed

  • Breaking — odometry filter rewritten as a 9-state EKF.
    The complementary filter that previously lived in
    pipeline/odometry_filter/ is replaced by a hand-rolled EKF over
    state [x, y, θ, vx, vy, ω, ba_x, ba_y, bg_z]. The predict step
    now carries the Coriolis cross-terms (v̇x = ax + ω·vy,
    v̇y = ay − ω·vx), which the complementary filter could not.
    During steady-state cornering the IMU's body-y axis reads
    centripetal acceleration ω·vx — the old filter integrated this
    directly into vy, so /odom.vy drifted unbounded (4+ m/s after
    68 s of cornering) and the inflated state.speed inside
    PurePursuit was the trackdrive ceiling. The new EKF cancels the
    Coriolis term in v̇y exactly when the model is consistent; the
    gtest regression CoriolisCornering.SteadyVyIsNearZero
    synthesises a 60 s constant-radius turn and asserts
    |vy| < 0.10 m/s (pre-rewrite this fails by ~14×).

    Measurements: motor-RPM is now a Kalman update on vx with
    sigma_rpm = 2 cm/s, so RPM dominates over IMU accel integration
    for vx tracking. Steering kinematic-bicycle
    (ω_pred = (vx/L)·tan δ) is a gated update on ω — applied
    when |residual| < threshold, raises slip_flag and rejects the
    update otherwise (the kinematic-bicycle model is wrong under slip,
    so folding it in would corrupt yaw).

    Breaking surface:

    • /brake_pressure subscription dropped from
      odometry_filter_node. Brake authority pulled α_vx toward
      zero during heavy braking pre-rewrite; the EKF's Kalman gating
      handles wheel-lockup naturally via covariance. Bridge still
      publishes /brake_pressure for replay parity, but no autonomy
      consumer subscribes.
    • /odom_diag/effective_alpha_vx topic retired.
    • OdometryFilter::push_brake() method, Params struct (replaced
      by EkfParams), kAlphaVx*, kBetaVyLeak, kBrakeLockup*,
      kRpmStaleS all removed.

    Preserved: /odom (now with non-trivial covariance populated
    from the EKF P matrix), odom→base_link TF, lifecycle, QoS,
    frame names, and the /odom_diag/yaw_residual_rad_s +
    /odom_diag/slip_flag topics.

Added

  • Auto-pull bag onto host filesystem on session stop (#498,
    closes the manual pull-bag.sh step from #490). When Record bag
    (mcap)
    is ticked, clicking Stop Session now:

    1. Finalises the bag in the docker volume (ifssim_bags, on
      container ext4 — fast).
    2. Streams the bag tarball out of dv_pipeline_stack via the
      Python docker SDK (container.get_archive) and extracts it
      into the host's ./bags/<name>/ (bind-mounted to mc_backend
      as /host_bags/).
    3. Cleans the volume-side copy via container.exec_run(rm -rf …).

    All inside the StopBag callback. No user action required to get
    the bag onto the host filesystem; tools/pull-bag.sh is now the
    manual-recovery path, not the default flow. Session log surfaces
    progress + the final host path. Failure semantics are best-effort:
    if the transfer fails (host disk full, etc.), the bag stays in
    the volume and the user gets a clear log line pointing at the
    manual recovery command.

    Env-gated via IFSSIM_BAG_AUTO_PULL (default 1). Set to 0 to
    disable and keep the manual pull-bag.sh flow.

    Why the Python SDK and not the docker CLI: the Linux docker CLI
    inside mc_backend can't pass a Windows host path to docker cp
    (the first : in C:/Users/... gets parsed as a container name,
    and the daemon doesn't recognise /c/Users/... as a host mount).
    The SDK uses the daemon's HTTP API directly — no argv parsing.
    Tarball extraction uses Python 3.12+'s safe filter="data"
    policy, plus a member-path traversal check for defence in depth.

    One security note: the mc_backend container now mounts
    /var/run/docker.sock (for the SDK) and ./bags:/host_bags
    (for the extraction target). docker.sock means anything that
    compromises mc_backend can root the host. The blast radius for
    mc_backend was already broad (it talks RPC to the sim, runs ROS
    actions, holds the API key), so this doesn't materially change
    the threat model for this dev/sim stack. For a hardened
    deployment, set IFSSIM_BAG_AUTO_PULL=0 AND drop both mounts
    from docker-compose.yml.

    The ./bags:/host_bags bind-mount partially reverses #490's
    retirement of host bind-mounts on the autonomy stack — but it
    only applies to mc_backend (low-traffic) and only at session-stop
    (write-only, not on any hot path), so the 30-90 s startup-time
    cost #490 was targeting doesn't apply here. Recording itself
    still lands in the named volume on container ext4 (fast); this
    bind-mount only takes the finalised tarball at the end.

  • Two-phase mission lifecycle: SetMission → RuntimeControl
    (#499, #518). The single StartMission action that previously
    combined configure + activate is replaced by an explicit two-step
    protocol on mission_control_node:

    • SetMission(mission_id) — prepare phase. Resolves the
      mission via MODE_REGISTRY (single source of truth for
      mission → ordered (node, behavior) in
      pipeline/mode_manager/mode_manager/mode_registry.py),
      calls each autonomy node's new ~/setup service with
      (mode_name, behavior), then drives the configure lifecycle
      transition. Per-node progress streams back as Feedback.stage
      so the operator sees live bring-up state instead of a single
      "starting" wait. Numba JIT (~10-20 s on cone_detection_node)
      lands here, not in RuntimeControl.
    • RuntimeControl — activate + run. Once SetMission returns
      success=true, the client opens RuntimeControl;
      mission_control_node activates the prepared stack and streams
      throttle/steering/emergency/finished feedback at 40 Hz.
      sim_supervisor_node subscribes to the feedback topic and
      relays each frame onto /fsds/control_command for the bridge —
      a clean split from before, where the supervisor was the action
      server.

    New packages: pipeline/node_base/ (Python) and
    pipeline/node_base_cpp/ (C++) provide BaseLifecycleNode with
    the ~/setup plumbing; every managed autonomy node now inherits
    from it. pipeline/bringup/ consolidates the launch files
    (sim_pipeline.launch.py, car_pipeline.launch.py,
    full_pipeline.launch.py) — docker/dv_pipeline_stack/ pipeline.launch.py is now a thin include of these.

  • odometry_filter_node (#499 / #518). The IMU+RPM
    complementary filter that previously lived inside
    sim_supervisor_node was lifted into a standalone C++
    BaseLifecycleNode (pipeline/odometry_filter_node/, backed by
    pipeline/odometry_filter/ for the algorithm library). Same
    /odom contract (100 Hz, IMU+RPM+steering+brake_pressure,
    odom→base_link TF, identical diagnostics on
    /odom_diag/*) — but now part of the standard managed bring-up
    via activate_mode, alongside the other four autonomy nodes.
    Matches the real-car split where the uDV's odometry firmware is
    a separate subsystem from the mission interface.

  • supervisor_cli (#518). Terminal client that mirrors the web
    backend's two-phase flow without needing Mission Control:
    ros2 run sim_supervisor supervisor_cli {set_mission, start_mission, run}.
    Reproduces production lifecycle from a shell — useful for
    developing missions/behaviors and triaging session-start bugs.
    Mission IDs match the registry (1=trackdrive, 2=autocross,
    3=accel, 4=skidpad, 5=scruti, 0=tear down).

  • tools/compose-up-and-watch.sh|ps1 (#518). Wrapper that
    runs docker compose up -d then docker compose watch in the
    foreground, syncing host edits under pipeline/* into named
    src volumes for live Python iteration. Replaces the pre-#490
    bind-mount workflow; tools/refresh-bridge.sh is still the
    go-to for C++ / msg / launch / setup.py changes.

  • DriveController / CompositeDriveController / Stanley in
    pipeline/control/control/controllers/. The control node now
    picks its lateral+longitudinal strategy from the behavior
    string passed via ~/setup — pure_pursuit for trackdrive/accel,
    stanley for autocross/skidpad/scruti — instead of a runtime
    ROS parameter. Composite wraps both into a single
    ActuationCommand-returning interface.

Changed

  • Project relicensed to GPL-3.0-or-later. Top-level LICENSE
    added with the full GPL-3.0 text. All package.xml files under
    pipeline/ and ros2/src/ updated from their previous mix of
    MIT (7 packages), Apache-2.0 (4 packages), and GPLv2 (2 packages —
    fs_msgs + ifssim_bridge inherited from upstream FSDS-Sim) to a
    uniform GPL-3.0-or-later. Motivation: keep the stack on a single
    copyleft-compatible licence so prospective GPL-3-only SLAM /
    perception dependencies can be linked in without per-package
    licence-conflict audits. Apache-2.0 contributions remain
    attributable through git history; the relicense reflects forward
    distribution only.

  • Documentation overhaul (#492). Consolidated the three setup
    entry points (readme.md → QUICKSTART.md → GETTING_STARTED_DOCKER.md)
    into one unified path:

    • New docs/SETUP.md — single first-time-user setup, parallel
      Windows + macOS sections. Covers prereqs, submodule init, sim
      b...
Read more

IFSSIM v0.1.1 — bag recording UI + lifecycle progress + Windows/Mac docker perf

Choose a tag to compare

@raulmoranguerra raulmoranguerra released this 14 May 18:43
633c440

Follow-up to v0.1.0. Three landed PRs.

First time here?

→ docs/SETUP.md is the unified first-time setup guide (Windows + macOS in parallel, 20–45 min end-to-end). It replaces the old QUICKSTART.md + GETTING_STARTED_DOCKER.md that several v0.1.0 users got lost in.

After setup, docs/OPERATING.md is the daily-ops reference: refreshing the bridge after a source edit, recording + retrieving MCAP bags (the new feature below), switching tracks, troubleshooting common failures.

For autonomy integration: docs/AUTONOMY.md. For the full technical reference (every sensor, every topic, every RPC): docs/REFERENCE.md.

Highlights

  • Record MCAP bags from Mission Control (#486, closes #465). New "Record bag (mcap)" checkbox in EventSetup. Recording happens inside dv_pipeline_stack so it shares the SHM-tuned DDS context with the publishers — recording from mc_backend dropped ~96% of /lidar/Lidar1 scans, so v2 of #465 moved the recorder into the bridge container. Live state surfaced via /api/referee/state. Full bag flow (start → list → pull) documented in OPERATING.md § Recording.

  • Granular lifecycle progress (#489, closes #387). mode_manager now publishes /mode_manager/progress — one message per change_state transition across the autonomy fan-out. Session-start spinner shows per-node progress instead of an opaque wait.

  • Docker performance, Windows + macOS (#490).

    • /bags is now a named volume → StopBag goes from 20-40 s to <1 s.
    • Source bind mounts removed; ROS source COPY'd into the image at build time. Saves 30-90 s on container startup.
    • New repo-wide .dockerignore cuts the docker build context from 33 GB to ~200 MB.
    • New helpers: tools/list-bags.sh, tools/pull-bag.sh, rewritten tools/refresh-bridge.sh. See OPERATING.md § Source-edit cycle for the new edit workflow.

Platform support

Same as v0.1.0 — Windows + macOS first-class. Linux deferred (see SETUP.md § Linux for the manual path).

Upgrading from v0.1.0

git pull
git submodule update --init --recursive   # if you skipped it before
tools/refresh-bridge.sh                    # rebuild + recreate dv_pipeline_stack
docker compose build mission_control_backend mission_control_frontend
docker compose up -d

On Windows: for max perf, clone the repo inside WSL2's native ext4 (~/IFSSIM) instead of /mnt/c/Users/<user>/IFSSIM. No code change needed — just a git clone in a different place. See SETUP.md § Windows: where you clone matters.

Known issue carried over

#483 cone-floor clipping — splined cones still sit a few cm into the asphalt. Re-tagged for v0.1.2. Autonomy unaffected.

Full changelog

CHANGELOG.md § 0.1.1.

IFSSIM v0.1.0 — first release

Choose a tag to compare

@raulmoranguerra raulmoranguerra released this 14 May 12:27
b2e0272

First public release of IFSSIM — a UE5.7-native Formula Student Driverless simulator with a ROS 2 bridge and a Mission Control web stack.

Highlights

  • Sensors: GPU-rendered Hesai ATX-S01 LiDAR (10 Hz, ~1.74M points/s), BMI088 IMU (400 Hz), GPS, GSS, Bosch LWS steering sensor.
  • Vehicle: IFS-08 chassis, Chaos physics, EMRAX 228 MV motor with NX-tech LUT torque envelope, regen gated by cell-input current limit.
  • Wire layer: TCP RPC + TCP LiDAR stream (#482) on a single port 41451 — no per-OS proxy quirks, no Docker Desktop toggle required. UDP fallback retained as an env-var escape hatch.
  • ROS 2 bridge (Humble): all sensor topics, Foxglove WebSocket on 8765.
  • Mission Control: FastAPI backend (8000) + React frontend (3000) for FS-DV lifecycle, scoring, replay.
  • Tracks: 10 built-in (acceleration, skidpad, trackdrive variants), CSV-validated, random-track generator included.
  • Referee: FS-Rules 2026 D 9.1.1 single-run scoring across all four DV disciplines.

Platform support

Platform Status
macOS 14+ (Apple Silicon) ✅ shipping
Windows 10/11 (x64) ✅ shipping
Linux not in scope for v0.1.0

Download

  • Mac: IFSSIM-v0.1.0-Mac.zip (~986 MB) — extract and open IFSSIM-Mac-Shipping.app.
  • Windows: IFSSIM-v0.1.0-Windows-x64.zip (~312 MB) — extract and run IFSSIM.exe.

First-launch setup

  1. Install Docker Desktop, clone the repo, docker compose up -d.
  2. Extract the archive for your platform.
  3. Launch the executable.
  4. First launch:
    • Windows: Windows Firewall prompts for TCP 41451 — allow.
    • macOS: Gatekeeper will warn about an unidentified developer on first run. Right-click → Open, then confirm. The build is ad-hoc signed with the sandbox-server entitlement for binding to TCP/41451; no notarisation in v0.1.0.

QUICKSTART: docs/QUICKSTART.md.

Known issue (deferred to v0.1.1)

  • #483 — cone-floor clipping. Spline-spawned cones sit a few cm below the visible asphalt on every track. Visual + LiDAR-perf impact (bottom rings get occluded). Autonomy logic is unaffected. Diagnosis + fix recipe in docs/cone_floor_clipping_fix.md.

Full changelog

See CHANGELOG.md for the complete feature list, post-scaffold accumulator entries, and the Windows-port series (#477–#482) that brought first-class Windows support.


🤖 Built from commit b2e0272 on dev.