Repository navigation
Releases: isc-fs/IFSSIM
Release list
IFSSIM v1.0.1 — macOS build
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.
- Download and unzip. You get
IFSSIM.app— everything is inside the bundle, including the cooked content,settings.jsonand the track CSVs. - 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 - 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.ymlneeds 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
Download & run
Windows 10/11, x64. No installer, no admin.
- Download
IFSSIM-v1.0.0-Windows-x64.zip(312 MB) below. - Verify (optional):
sha256: 4b0ea48cfe4f7ecd2b06f921e7a382ecc2295e824f16426aa22b2ea6878e1f31 - Extract anywhere writeable (
C:\IFSSIM\works; a network drive doesn't). - Run
IFSSIM.exein 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 plantchaos, LiDARcpu. Baseline this release tracks.dev-manual— default plantshadow(orfmu). Ongoing FMU/Simulink plant integration; merges todevonce #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 stallDV_RUNNINGsteady, 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
No prebuilt binaries in this release. Build from source with
./package_mac.sh(macOS) orbash 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 abuild_*.mscript so a regenerated
model is reviewable in a diff rather than an opaque binary. Every
parameter comes fromsettings.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
.fmufrom inside the engine, including a ZIP reader written against
zlib because the engine's own only links underbBuildEditor. State
save/restore round-trips bitwise exact. Plant.Typeinsettings.json—chaos,shadoworfmu. In
shadow, the FMU steps alongside Chaos on identical inputs and the
divergence is logged; it drives nothing, so it cannot change
behaviour. Infmuthe FMU integrates the vehicle and the mesh
becomes a kinematic target written from the plant's pose each tick —
sensors already readPlantState, 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 fromL/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.
resetScenarioRPC, a seeded scenario
runner,-fsds.seed=override, and a verifier that proves the RNG
reproduces — which on first run failed, showingresetScenario
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>_carparitybags
(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 atpipeline/. Pipeline changes go to that repo.
After pulling, rungit submodule update --init --recursive. - Breaking —
MaxSteerAngle28° → 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_pointson 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.
SquaredFunctionwas
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 ofsettings.json's
VehiclePhysicsblock 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/cmdrelay, 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. resetScenarioleft 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 secondInstantiate
segfaults rather than failing. Teardown is now deterministic in
EndPlay, since PIE restartsBeginPlayon a new pawn while the old
one is still alive.
Known limitations
- Chaos remains the default and the reference. The FMU drives the
car underPlant.Type="fmu", butchaosis 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.020and 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; seedocs/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
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
[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 intovy, so/odom.vydrifted unbounded (4+ m/s after
68 s of cornering) and the inflatedstate.speedinside
PurePursuit was the trackdrive ceiling. The new EKF cancels the
Coriolis term inv̇yexactly when the model is consistent; the
gtest regressionCoriolisCornering.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
vxwith
sigma_rpm = 2 cm/s, so RPM dominates over IMU accel integration
forvxtracking. Steering kinematic-bicycle
(ω_pred = (vx/L)·tan δ) is a gated update onω— applied
when|residual| < threshold, raisesslip_flagand rejects the
update otherwise (the kinematic-bicycle model is wrong under slip,
so folding it in would corrupt yaw).Breaking surface:
/brake_pressuresubscription dropped from
odometry_filter_node. Brake authority pulledα_vxtoward
zero during heavy braking pre-rewrite; the EKF's Kalman gating
handles wheel-lockup naturally via covariance. Bridge still
publishes/brake_pressurefor replay parity, but no autonomy
consumer subscribes./odom_diag/effective_alpha_vxtopic retired.OdometryFilter::push_brake()method,Paramsstruct (replaced
byEkfParams),kAlphaVx*,kBetaVyLeak,kBrakeLockup*,
kRpmStaleSall removed.
Preserved:
/odom(now with non-trivial covariance populated
from the EKF P matrix),odom→base_linkTF, lifecycle, QoS,
frame names, and the/odom_diag/yaw_residual_rad_s+
/odom_diag/slip_flagtopics.
Added
-
Auto-pull bag onto host filesystem on session stop (#498,
closes the manualpull-bag.shstep from #490). When Record bag
(mcap) is ticked, clicking Stop Session now:- Finalises the bag in the docker volume (
ifssim_bags, on
container ext4 — fast). - Streams the bag tarball out of
dv_pipeline_stackvia the
Python docker SDK (container.get_archive) and extracts it
into the host's./bags/<name>/(bind-mounted to mc_backend
as/host_bags/). - 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.shis 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(default1). Set to0to
disable and keep the manualpull-bag.shflow.Why the Python SDK and not the docker CLI: the Linux docker CLI
inside mc_backend can't pass a Windows host path todocker cp
(the first:inC:/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 safefilter="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, setIFSSIM_BAG_AUTO_PULL=0AND drop both mounts
fromdocker-compose.yml.The
./bags:/host_bagsbind-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. - Finalises the bag in the docker volume (
-
Two-phase mission lifecycle:
SetMission→RuntimeControl
(#499, #518). The singleStartMissionaction that previously
combined configure + activate is replaced by an explicit two-step
protocol onmission_control_node:SetMission(mission_id)— prepare phase. Resolves the
mission viaMODE_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~/setupservice with
(mode_name, behavior), then drives theconfigurelifecycle
transition. Per-node progress streams back asFeedback.stage
so the operator sees live bring-up state instead of a single
"starting" wait. Numba JIT (~10-20 s oncone_detection_node)
lands here, not inRuntimeControl.RuntimeControl— activate + run. OnceSetMissionreturns
success=true, the client opensRuntimeControl;
mission_control_nodeactivates the prepared stack and streams
throttle/steering/emergency/finished feedback at 40 Hz.
sim_supervisor_nodesubscribes to the feedback topic and
relays each frame onto/fsds/control_commandfor 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++) provideBaseLifecycleNodewith
the~/setupplumbing; 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.pyis now a thin include of these. -
odometry_filter_node(#499 / #518). The IMU+RPM
complementary filter that previously lived inside
sim_supervisor_nodewas lifted into a standalone C++
BaseLifecycleNode(pipeline/odometry_filter_node/, backed by
pipeline/odometry_filter/for the algorithm library). Same
/odomcontract (100 Hz, IMU+RPM+steering+brake_pressure,
odom→base_linkTF, identical diagnostics on
/odom_diag/*) — but now part of the standard managed bring-up
viaactivate_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
runsdocker compose up -dthendocker compose watchin the
foreground, syncing host edits underpipeline/*into named
src volumes for live Python iteration. Replaces the pre-#490
bind-mount workflow;tools/refresh-bridge.shis 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 thebehavior
string passed via~/setup—pure_pursuitfor trackdrive/accel,
stanleyfor 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. Allpackage.xmlfiles under
pipeline/andros2/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
uniformGPL-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...
- New
IFSSIM v0.1.1 — bag recording UI + lifecycle progress + Windows/Mac docker perf
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_stackso it shares the SHM-tuned DDS context with the publishers — recording from mc_backend dropped ~96% of/lidar/Lidar1scans, 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_managernow publishes/mode_manager/progress— one message perchange_statetransition across the autonomy fan-out. Session-start spinner shows per-node progress instead of an opaque wait. -
Docker performance, Windows + macOS (#490).
/bagsis 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
.dockerignorecuts the docker build context from 33 GB to ~200 MB. - New helpers:
tools/list-bags.sh,tools/pull-bag.sh, rewrittentools/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 -dOn 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
IFSSIM v0.1.0 — first release
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 openIFSSIM-Mac-Shipping.app. - Windows:
IFSSIM-v0.1.0-Windows-x64.zip(~312 MB) — extract and runIFSSIM.exe.
First-launch setup
- Install Docker Desktop, clone the repo,
docker compose up -d. - Extract the archive for your platform.
- Launch the executable.
- 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.