Add machine workshop, typed logic, mechanics and sensor-driven ECUs

This commit is contained in:
max
2026-11-02 07:27:13 +01:00
parent eb2b6366c2
commit abfcce0f46
99 changed files with 28835 additions and 145 deletions

View File

@@ -0,0 +1,354 @@
# Component implementation progress
Active goal started 2026-11-01: implement the full
[machine systems roadmap](MECHANICAL_BUILDER_PLAN.md), in its integrated order.
The scope includes the later components; they have not been dropped because they
need additional physical models. Preserve existing working-tree changes and
user-edited machine files.
## First implementation: typed port foundation
Implemented:
- Shared descriptors for Gas, Rotational, Translational, Boolean, Number and
legacy ECU assignment. Direction, cardinality, quantity, pressure reference,
required/default values and numeric ranges are explicit.
- Typed Boolean/Number values with validity and simulation timestamps. Finite
numeric checks and explicit type matching prevent implicit truth conversions.
- A shared compatibility function used by connection previews, edits and
document validation. Runtime compilation validates the same document.
- Explicit gas-domain filtering in pipe geometry updates, fluid compilation and
fuel-source searches, avoiding assumptions that every non-ECU link carries gas.
- Version 5 stable port/method names, custom physical-port identities and loading
of versions 1 through 4. Zero-storage junctions expose one shared port; old
numeric aliases migrate to it.
- Shared UI port colors and silhouettes: red Boolean, green Number, input rings,
filled outputs, neutral bidirectional gas connectors; legacy assignments blue.
The foundational types are real APIs. Boolean/Number nodes remain subsequent work;
the first mechanical parts are implemented below.
## Mechanical parts milestone
Implemented Shaft / crankshaft, Flywheel, Drive motor and Brake / load with typed
gold attachment ports, real runtime behavior, 3D meshes, Mech picker category,
inspectors, live motor/load/friction tuning and named rotational instruments.
Shaft inertia and initial states require Build. Effective flywheel inertia appears
in the shaft inspector. Cylinders and pumps use their attached shaft; each ECU's
cylinders must share one shaft. Moving a shaft leaves gas geometry unchanged.
The independent-shaft solver tracks kinetic energy, source/drive work and losses.
Its drag integration splits stops and reversals without allowing brakes to create
motion. Ideal speed drives report their supplied/absorbed work, including startup.
Engine-connected shafts currently enforce forward-only timing. The legacy starter
remains explicit shaft calibration until the dedicated starter milestone; new
shafts default to zero starter torque.
Version 6 saves mechanical parameters/connections. Older documents migrate to
visible shafts/drives/loads and keep legacy gauge definitions. Examples/imports,
copy/paste, assembly references, live tuning and benchmark tools use explicit
mechanics. Existing user files are not rewritten on load. The new
`machines/shaft-drive-bench.machine.toml` is a ready-to-run mechanical example.
Validation: nine focused suites pass, including analytic acceleration and damping,
work/energy accounting, brakes/static hold/reversal, two independent engines at
1200/2400 RPM, live tuning one to 3600 RPM, required attachments, mixed-shaft ECU
rejection, migration, save/load, builder/menu interactions and prior physics cases.
Rendered review covers every mechanical inspector and a running bench at
1920x1080 and 1280x720. This is not a global gas-plus-mechanics conservation study;
the existing explicit component-coupling timestep limitations remain relevant.
## Sensor attachment milestone
Implemented six ideal sensor assemblies: absolute pressure / MAP, differential
pressure, gas temperature / IAT, signed total pipe mass flow, crank speed/position
and throttle position. They attach to existing physical hosts without consuming
gas ports, adding storage or changing the fluid mesh. Pipe taps use normalized
arclength. Total mass flow is explicitly distinct from the future fresh-air MAF
sensor; gas temperature is not a head/coolant temperature model.
Sensor outputs use the typed port descriptors, sample timestamps and validity.
Sampling occurs initially and after each audio sample's physics, providing the
next signal-graph boundary's readings. Crank speed, wrapped angle and Boolean
ideal synchronized status share a sample; shaft identity and unwrapped angle are
retained for future timing consumers. A stopped shaft supplies valid zero speed.
Sensor channels are independent of the eight recorded instrument channels.
Version 7 saves stable sensor identities, named kinds, host labels, normalized
locations and pickup offsets, and preserves deleted-ID counters. Versions 1..6
still load. Host deletion leaves a visible unresolved entity; copy/paste and
assemblies remap internal hosts and retain unresolved external bindings.
The **Sense** inspector creates supported sensors, binds hosts/reference taps,
adjusts tap positions and pickup offsets, focuses/removes attachments and shows
live typed outputs. Right-click **Add sensor here** uses the clicked pipe location.
3D markers select their sensor; unresolved-binding checks navigate to it.
Attachments are Build-only and remain inspectable while running/paused.
The new `machines/sensor-bench.machine.toml` demonstrates all six assemblies.
Validation covers sampling/units/signs, coherent timing and reverse crossings,
stopped pickups, remeshing/transforms, no fluid/audio perturbation, more than eight
sensor channels, host deletion, incompatible bindings, copy/paste and save/load,
plus UI placement, undo/redo, diagnostics and Test edit locks. Rendered review
covers pressure, crank and differential-pressure screens at 1920x1080/1280x720.
All ten focused regression suites pass, as does migration/round-trip validation
of the saved machines found in the workspace. The desktop executable is rebuilt.
## Logic runtime milestone
The document now owns a separate typed signal graph with stable node/pin keys,
saved canvas coordinates, shared port compatibility and atomic connection edits.
Version 8 saves that graph; versions 1..7 still load. Physical gas/mechanical
links and legacy blue ECU assignments retain their separate meanings.
Implemented 35 runtime node kinds: Boolean constants, switches/buttons, numeric
constants/sliders/inputs, six Boolean gates with configurable fan-in, comparisons,
windows/hysteresis, arithmetic, clamp/gain/map, number selection, Bool-to-number,
sensor references, command references, lamps/readouts, and Boolean/Number delays.
Polymorphic numeric nodes currently use explicit configured quantities/references.
Multiply/divide use a scalar second operand; pressure subtraction produces a
differential, while absolute-pressure addition requires a differential offset.
Graph evaluation occurs before each physics sample, consuming the previous
boundary's sensor sample and latching commands across gas CFL substeps. Evaluation
uses a compiled order, rejects combinational cycles with a named cycle path and
commits explicit memory next states together. Required unwired inputs block Test;
commands have declared inactive defaults. Invalid math/sensors stay invalid with
runtime diagnostics, and actuator consumers apply inactive fallbacks. Short button
press/release sequences survive between boundaries; fresh Test resets transient
controls and memory. Constants/thresholds can be tuned without restarting physics.
Commands own individual motor enable/speed/torque, brake enable, throttle opening
or legacy shaft starter fields. Duplicate ownership and ECU/opening conflicts are
rejected; dormant signal-owned fields start inactive. A shaft allows only one
potentially enabled ideal speed drive. The physical inspector identifies signal
ownership and the live drive HUD uses the effective enabled state.
Connected harnesses follow physical assembly copy/paste. Internal parts/sensors/
nodes remap independently; omitted physical bindings remain explicitly unresolved.
The new `machines/logic-compressor-bench.machine.toml` runs actual pressure ->
below-threshold hysteresis -> master-enable AND -> compressor motor enable, with
a speed slider, targeted readouts and recorded pressure/RPM/drive-power channels.
Core acceptance covers gate truth tables, unit/reference rules, fan-out/cardinality,
unknown keys/types, ordering/cycles, delayed feedback, math faults, manual event
ordering/reset, live tuning, command ownership/fallbacks, automatic compressor
shutdown, brake/starter commands, sample-vs-CFL timing, saved harnesses and
independent copied compressors. Twelve focused regression suites pass, along
with workspace save migration checks. Rendered review covers signal-owned drive
controls and the running pressure bench at 1920x1080 and 1280x720. The desktop is
rebuilt at this runtime milestone. Timers, edge nodes and latches remain later work.
## Logic editor milestone
Implemented **3D / Logic / Split** workspace tabs with one document, selection
and Test runtime. Canvas pan/zoom and the 3D camera remain independent. Selecting
a sensor/command reference selects its physical host; **Focus in 3D** opens the
split workspace. **Sense -> Show Logic** and physical **Command** buttons create
or reveal references to existing entities without duplicating physical parts.
The node library has search, categories, an Objects list and compatible-node
filtering while a pin is pending. New compatible numeric nodes adopt that pin's
quantity/reference. Nodes drag by their headers, Shift/box selection supports
groups, Home/F fit the graph/selection, and wheel zoom preserves the point under
the pointer. Saved node positions are independent of 3D geometry.
Connections support click/click, dragging, fan-out, input rewiring, right-click
pin disconnection and undo/redo. Rejected edits keep the old wiring and redo
history. Boolean pins/wires are red, Number green; inputs are rings and outputs
filled circles. Live values include units, required/default metadata, ranges,
pressure references and validity. Candidate combinational cycles highlight the
actual cycle nodes and retain the compiler's named path diagnostic.
Inspectors edit names, quantities/references, sensor/command bindings and node
parameters. Invalid numeric text remains editable. Topology, control ranges,
initial states and physical bindings require Build; safe constants/thresholds
and canvas layout can change during Test. Switches, momentary buttons, sliders
and numeric controls operate at simulation boundaries. Paused controls show queued
values separately from frozen pins; slider motion coalesces. Focus loss, leaving
Logic and stopping Test release momentary buttons. Numeric readouts have compact
UI-sampled trends; the recorded meter channels remain separate.
Graph copy/paste preserves internal wires. Same-document sensor references share
their existing sensor; cross-document references detach while retaining labels.
Pasted command nodes require a new explicit target, preventing competing owners.
Physical assembly copy/paste continues to remap complete internal harnesses.
Validation: thirteen focused regression suites pass. Interaction cases cover
placement/search, typed wiring/rewiring, failed-edit rollback/redo, one-entry drag
undo, zoom anchoring, live tuning, paused controls, focus/view-close button release,
shared physical selection, split-view bounds and uninterrupted simulation time.
Rendered review covers 1920x1080/1280x720, including live graphs, split view and the
threshold inspector. Pixel checks confirm red/green filled outputs and hollow
input centers. Updated rendering libraries are linked into
`out/build/windows-gcc/fluidsim_desktop_preview.exe`; the canonical executable is
currently locked by the user's running workshop, which was left intact.
Further graph/UI work remains on the roadmap: pinned operator panels, richer
binding pickers/property help, visual wire waypoints and graph-wide automatic
type inference, in addition to DPI scaling and visibility groups. Basic stage 2
is usable; those refinements and the later component stages are not dropped.
## Sensor ECU and fuel-delivery milestone
Implemented the runtime primitives for the next component stage:
- Physical crank outputs now carry pickup/shaft identity, original acquisition
time, unwrapped angle and measured speed through the signal graph. Unchanged
routing retains that evidence; arithmetic creates ordinary numeric values.
Delays retain their original acquisition time, so retimestamping a delayed
value cannot make it a current timing measurement.
- A crank-only wasted-spark clock validates matching current speed/angle channels,
counts unwrapped crossings, accepts stopped pickups and rejects stale/mixed or
reverse timing. Acquisition/recovery does not replay missed sparks. Changing
advance cannot fire twice for one revolution.
- Separate sensor ECU core with ignition-only and Alpha-N strategies. Ignition
uses measured RPM and an advance map; Alpha-N requires measured TPS and uses a
calibrated two-dimensional RPM/TPS table in kg per cylinder per four-stroke
cycle. It never receives trapped cylinder air mass or global pedal demand.
Required sensor faults cut outputs; the RPM limiter has hysteresis.
- Explicit injector delivery core with capacity limiting, declared ideal or
finite regulated rail supply, depletion and fail-closed command handling.
Delivery adds conserved fuel species, fuel-origin tracer and sensible energy
to an existing gas volume. This is continuous/batch-average delivery, not
sequential pulse-width control or a liquid-pressure circuit.
- Four-stroke cylinders accept consumed external spark pulses and cut commands.
This path requires transported fuel and does not fall back to hidden internal
spark timing. Burn progression follows the received event.
The cores are now integrated into saved machines and the workshop. The ECU
inspector selects labeled Legacy ideal, Crank ignition or Alpha-N EFI presets.
**Show ECU connector in Logic** creates/reveals one grouped connector. Crank
speed/position are required green Number inputs; Alpha-N additionally requires
actual TPS. The connector selects its physical ECU and copied graph-only
connectors detach ownership. Physical assembly copies remap the complete harness.
Blue assignments declare controlled cylinders. Sensor-driven ECUs do not own
throttle opening or read the global pedal; manual or separately commanded
throttles remain available. Each cylinder has an explicit **Pickup TDC deg**
calibration in the crank sensor's coordinate system. Its physical 720-degree
phase is not used as hidden ECU synchronization. Commands and spark events use
the existing simulation-sample boundaries, not UI updates.
An explicit injector attachment can be added to a chamber, bound to an Alpha-N
ECU and configured with capacity, cylinder-dose count, fuel mass/temperature and
finite or ideal regulated supply. A nozzle appears on its host. Total injector
cylinder doses must match assigned cylinders; fuel is added once per physics
sample and then transported by the gas solver. Live inspectors show delivered
flow, remaining fuel, depletion and ECU fault/limiter status. Ignition maps and
RPM limits can be tuned live; strategy, fuel tables, attachments and pickup
calibration require Build.
Version 9 saves ECU strategy/fuel maps, grouped input schemas, pickup calibration
and injector bindings. Versions 1..8 retain their legacy controller behavior.
Deleted/omitted ECU references stay unresolved with labels; IDs remap on assembly
insertion. Existing user files are not rewritten. Ready-to-run examples are
`machines/sensor-ignition-bench.machine.toml` and
`machines/sensor-alpha-n-bench.machine.toml`, both driven at 3000 RPM.
The delivered EFI model is open-loop, continuous/batch-average intake delivery.
It does not claim sequential pulse timing, modeled liquid rail pressure or
evaporation/wall-film dynamics. Those abstractions remain explicitly labeled;
advanced sensor strategies remain in later stages.
The new sensor-ECU acceptance target covers physical sensor -> graph timing,
stale/mixed/arithmetic rejection, delayed acquisition evidence, spark crossings,
RPM/TPS interpolation, fault/recovery and limiter behavior, ECU demand -> gas-host
fuel delivery, finite-supply mass/energy accounting and external spark actuation.
Acceptance also covers actual combustion in both sensor-driven examples,
live loss/recovery of timing, foreign-shaft and constant-number rejection,
depletion in the machine runtime, live ignition tuning without restarting time,
save/load, partial/full assemblies and UI preset/connector/injector controls.
All fourteen focused suites pass after rebuilding affected targets. Workspace
machine migration/round trips pass from the repository root. Rendered review
covers the new graph, ECU and injector screens at 1920x1080 and 1280x720.
Wasted exhaust sparks retain the last trapped-charge AFR reading; valid timing
still samples fresh charge when ignition is cut by the limiter.
The Alpha-N example was opened in Build mode with
`out/build/windows-gcc/fluidsim_desktop_preview.exe`, leaving the original
workshop intact. The final checked binary, including the last charge-instrument
fix, is `out/build/windows-gcc/fluidsim_desktop_ecu_preview.exe`. Open sessions
were not restarted to replace a locked executable; recheck live processes before
linking or launching the next review build.
## Speed-density ECU milestone (stage 4, first slice)
Added a third sensor-driven preset, **Speed-density EFI**. Its grouped connector
requires four Number inputs from three physical sensor assemblies: crank speed,
crank position, manifold **absolute** pressure and intake gas temperature. TPS is
not required in this basic mode. Gauge/differential pressure cannot connect to
MAP; invalid, zero or stale MAP/IAT values cut fuel and new ignition events.
Fuel demand uses a declared dry ideal-gas estimate:
`air_kg_per_cylinder_cycle = MAP * displacement * VE / (R_air * IAT)`, followed
by target AFR and the four-stroke RPM/120 conversion. Displacement, air gas
constant, target AFR and the RPM/MAP volumetric-efficiency table are calibration,
not hidden cylinder measurements. VE interpolates both axes and clamps to table
edges. The gas network still transports the explicitly injected fuel. This
open-loop estimate does not measure fresh-air fraction in diluted intake gas or
provide warm-up, acceleration enrichment, lambda trim or sequential timing.
The preset, required input schema, calibration fields and EFI injector target
picker are integrated into the workshop. **SD** calibration fields display cc,
kPa and VE percent and require Build. Ignition-map/RPM-limit tuning remains live.
Shared strategy names/keys validate the document, graph, runtime and serializer;
unknown strategies fail explicitly. Format 10 saves the new VE/displacement
calibration and connector schema; versions 1..9 still load.
`machines/sensor-speed-density-bench.machine.toml` is a working 3000 RPM example
with physical intake MAP/IAT taps, an explicit injector and actual combustion.
Its calibration is set when constructing the example; runtime fuel estimation
does not query cylinder air mass or geometry.
Validation: fifteen focused suites pass, including ideal-gas charge cases,
pressure/temperature/displacement scaling, two-axis VE interpolation, required
sensor faults, live MAP loss/recovery with combustion, missing IAT host, input
reference types, save/load, assembly remapping and UI preset/connector controls.
Workspace machine migration/round trips pass from the repository root. Rendered
review at 1920x1080 and 1280x720 covers the four-input graph and ECU/injector
inspectors. Pneumatic valves and the pressure-switch supply circuit remain the
next stage-4 delivery; they are not implemented by this ECU milestone.
Checked desktop build: `out/build/windows-gcc/fluidsim_desktop_speed_density_preview.exe`.
Existing workshop windows were left intact. Next session should start with the
physical valve slice below; no valve implementation is currently in progress.
### Next physical component slice
Implement needle, solenoid shutoff, differential relief and non-relieving
pressure-regulator behavior through the existing conservative gas boundaries.
Use explicit inlet/outlet paths and real body/downstream pressure; do not enforce
a setpoint by assigning gas pressure. Needle opening and solenoid coils need
typed signal command ownership; the regulator's pressure demand must declare an
absolute/gauge reference. Relief needs cracking/reseat hysteresis, solenoids need
normally-open/closed rest states and finite travel, and regulator response must
remain bounded when supply falls below demand. Include a pressure-switch preset
and a finite-tank circuit with flow, depletion and conservation acceptance cases.
Integrate picker modes, inspectors, save/load and assemblies before further UI
polishing. Keep this and all later roadmap stages in the active goal.
## Delivery backlog
| Stage | Scope | State |
| --- | --- | --- |
| 0 | Typed ports, validation, stable identities and migration | Complete |
| 1 | Explicit shafts, flywheel, drive motor, brake/load, sensor attachments and shaft instruments | Complete; six basic sensor assemblies implemented |
| 2 | Logic canvas; buttons, switches, constants/sliders; gates, thresholds, arithmetic, mapping, sensors, commands and displays | Basic runtime and editor integrated/verified; advanced graph UX and operator panels remain |
| 3 | Crank sensing, ignition and Alpha-N ECU presets, explicit fuel delivery and ECU connector UI | Basic presets integrated/verified, including physical combustion, saved bindings and workshop controls |
| 4 | MAP/IAT sensing, speed-density ECU, needle/shutoff/regulator/relief valves and pressure-switch control | Speed-density preset integrated/verified; pneumatic valves and pressure-switch circuit remain |
| 5 | Gears, clutch, starter; directional valves, pneumatic cylinders, linear loads/springs/dampers and quick exhaust; latches/timers/memory | Planned |
| 6 | MAF/sequential ECU options; air motors, rotary compressors, filters, nozzles and resonator/silencer assemblies | Planned |
| Later | Belt/pulley drives, heated/cooled chambers, ejectors, turbines/turbochargers and general linkages | Planned |
Each stage needs actual runtime behavior, save/load and assembly support, usable
UI controls and focused acceptance checks. Keep this file current at milestones.
Stage 0 validation: six focused suites pass (machine ports, machine physics and
serialization, builder interactions, menu navigation, native maximization and
desktop UI). Tests cover all current part descriptors, signal types/references,
invalid values/defaults, input direction/cardinality, custom-port reordering,
legacy ECU fan-out, old junction aliases and all saved machines found locally.
Unknown part kinds now fail explicitly instead of inheriting gas ports/storage.
Source whitespace checks pass. Existing user machine files were read and copied
to temporary test locations; they were not migrated in place.

620
docs/MACHINE_BUILDER.md Normal file
View File

@@ -0,0 +1,620 @@
# 3D machine builder
Open **Machine Workshop** from the maximized main menu. Choose **New machine**, or
select a saved machine and choose **Edit** or **Play**. Pressing **B** in the
scenario browser opens a new design directly.
The builder supports general pneumatic circuits as well as engines. The two
example benches provide a four-stroke engine and a piston vacuum pump. The
parts picker uses cached 3D previews of the same meshes that appear in the world.
**Import engine layout** (I) transfers the existing 450 single, parallel twin,
flat six and V8 H-pipe layouts into new editable documents. The importer preserves
pipe routes and diameters, storage dimensions, bore/stroke, firing phases, cam
profiles, valve dynamics, shaft calibration, fuel calibration and ECU settings.
It inserts a visible carburetor or throttle into the final inlet segment and adds
the appropriate ECU with control wires. The metering body and stub replace part
of that inlet segment, preserving its total route length and gas volume.
## Build and configure
The workshop uses a dark editor layout with resizable, collapsible Library and
Inspector panels. Drag their dividers to resize; widths and collapse states are
saved locally. **Reset UI** restores the default panel layout. The **Library**
offers categories, search and part previews; **Objects** lists the current parts.
**Ctrl+F** focuses search. Long control names fit their available width and reveal
their full text on hover. Property labels sit above their editable values.
The inspector tabs are **Part**, **Links**, **Setup**, **Checks**, **Meters** and **Sense**.
The oscilloscope has a separate bottom dock; drag its upper edge to resize it.
The minimum window size is 1280x720, with the layout reviewed at 1920x1080 too.
Entering the workshop maximizes the Windows window; the application no longer
shrinks when moving between the workshop, home menu and engine scenarios.
1. Pick a part on the left and click the world to place it. Placement uses the
horizontal plane set by **Machine → Place Y mm**. Hold Shift for repeated placement.
2. Select a placed part to open its properties. Right click a part for its context
menu. Click the part name to rename it.
3. **G** selects Move. Drag a colored X, Y, or Z handle to translate in world axes,
or drag a selected body to move in the screen plane.
**R** selects Rotate; drag a colored ring to rotate about that world axis.
**X** toggles snapping. Translation uses the configured grid; rotation snaps to
15 degrees. Numeric position and rotation fields also allow precise changes.
4. Click a numeric property, type its value and press Enter. Escape cancels typing.
The minus/plus buttons make incremental changes. Scroll over the inspector to
reach additional properties.
5. Select a part to reveal its ports, then drag between ports or click a port
followed by its target. **C** optionally shows all ports. Neutral markers are
bidirectional gas ports; at least one end of a gas connection must be a pipe.
The pipe endpoint snaps to the other part. Blue pins connect existing ECU
assignment wires; ECU outputs are filled and inputs hollow. The **Links** tab
configures or disconnects connections. Use the Move gizmo to move a small
boundary symbol whose port occupies its center. **Escape** cancels a wire;
**G** returns to Move. Route mode prioritizes editing pipe points.
After choosing the first port, hover the target: a blue preview shows the
snapped pipe route or control wire; a red preview explains why it cannot connect.
Previewing does not change the design. Clicking an invalid target leaves the
first port selected so you can choose another target.
6. **P** selects Route for a selected pipe. Use **Add path point**, select a point,
then drag its X/Y/Z handles. The inspector edits the selected point's local
coordinates. Disconnect an attached endpoint before moving it independently.
Select a numbered point and edit **Point dia mm** to change its bore. Every
point has its own diameter; adjacent values form a linear taper along that
segment. This replaces the former inlet/outlet diameter fields.
**Ctrl-click** near the selected pipe's centerline to insert a bend at that
location, or right click a pipe and choose **Insert bend here**. The new point
starts on the original route, preserving length and gas volume until moved.
Length, the selected point's bore and volume are shown above the viewport while editing.
Alt+left drag or right drag on empty space orbits the view. Middle drag pans;
the wheel zooms; Home fits the design and **F** focuses the selected part or group.
Q selects without a transform tool.
Shift-click adds/removes parts from a selection. Shift-drag on empty space selects
a group; Ctrl+A selects the whole machine. Move and Rotate operate on that group.
Ctrl+C copies the selected parts, their internal air/control connections and
attached probes; Ctrl+V inserts a translated copy. Ctrl+D duplicates immediately.
Connections to parts outside the copied group are not copied. Delete removes the
selection. Ctrl+Z/Ctrl+Y undo/redo. The copied group remains available when loading
another machine during the same workshop session. Right-clicking a selected part
keeps the group selected and opens Copy, Paste, Duplicate and Save as assembly.
Click **Assemblies** to save the selected group for reuse or insert a saved
assembly into the current design. Assemblies are stored in
`machines/assemblies/` as `*.assembly.toml` files and can be copied between
workspaces. Their internal connections, component settings, pipe profiles and
attached probes are preserved. On insertion, part and probe IDs are remapped and
the group is placed near the current selection (or the view center), selected and
focused for positioning. The destination machine's shaft and simulation settings
apply to the inserted components. Shaft gauges remain specific to each machine.
Escape cancels a placement/connection or clears selection; it never leaves the
workshop. Use **Menu** to return to the scenario menu, or close the application
window to exit.
In Move mode, grab an atmosphere symbol directly to select and drag it, or use
its X/Y/Z handles. Its attached pipe endpoint follows the move. Atmosphere
symbols remain selectable at the end of a wide pipe.
## Machine checks
Press **H** or click **Checks** to open the checks panel in Build or Test. Warnings
identify cylinders without a connected fuel source, ECUs without assigned parts,
and fixed throttles that are closed without an assigned ECU. Notes identify
sealed pipe/cylinder ports and remind you to crank a stopped free shaft.
Click a check to select and focus its part. Use the Part or Connections tabs to
configure it. Wheel or Previous/Next browses longer lists. Checks refresh after
edits, undo and redo; they do not change or prevent testing a design. A sealed
port can be intentional. Fuel checks establish wiring/plumbing reachability;
they do not guarantee flow through valves, correct calibration or combustion.
Unresolved sensor checks open the affected attachment in **Sense**.
Ideal junctions support multiple pipes on the same point. Connect free pipe ends
to the junction's center marker. Connecting a third pipe to an occupied
pipe-to-pipe join automatically replaces that join with a shared node. Switching
to stored-volume mode gives branches distinct ports on the visible box; switching
back to an ideal node brings them to its center.
## Physical dimensions
There is one design geometry shared by rendering, picking and simulation:
- **Pipes and reducers:** centerline segment lengths determine the simulated
length. Each route point defines a diameter. Diameter varies linearly between
adjacent points, allowing expansions, necks and reducers within one pipe. The
finite-volume mesh integrates the exact frustum volumes across each cell,
including cells that cross multiple profile segments. This preserves gas
volume across mesh densities. Bends stay at their edited positions.
Visual route points do not force extra simulation cells: the physics mesh follows
total arclength at the selected cell density. A genuinely short pipe remains short
and can require more CFL substeps.
Sharp changes in area also constrain the timestep by the ratio between face
area and the gas volume stored in a cell.
- **Chambers and storage junctions:** the visible internal box dimensions define
capacity as X × Y × Z. Rotation changes the port locations and appearance,
and preserves volume.
- **Cylinders and piston pumps:** bore, stroke and compression ratio define the
gas cavity and clearance. The rendered piston and current simulated volume
use the same displacement. Engine cylinders also expose valve diameters/counts,
cam timing/lift, valve mass, spring, damping, preload, AFR and spark advance.
- **Throttle and check valve bodies:** throttles use their visible elliptical
tube dimensions for gas storage; check valves use their box dimensions.
Diameter and discharge coefficient define the restriction. Throttles
can use the test pedal or a fixed opening. Check valves pass flow from their
local -X inlet to +X outlet above the configured cracking pressure.
- **Ideal junctions:** characteristic and legacy modes have zero stored volume
and are drawn as node symbols. The storage mode is drawn as a physical box.
- **Carburetor:** the elliptical throat stores gas according to its length and
Y/Z diameters. The restriction diameter controls flow. Pilot/main/needle jets
meter liquid fuel from the float bowl into that gas; the solver transports it
through pipes into the cylinders. Jets, needle corrections, fuel density, bowl
capacity/refill, fuel film and discharge settings are editable.
- **ECU:** a controller housing with no gas storage. Blue wires assign injection
and ignition to cylinders, and throttle control to a throttle or carburetor.
One ECU can control multiple parts. An unconnected ECU controls none.
- **Pressure/atmosphere and end-cap symbols:** these represent boundary conditions
and have no storage volume. A pressure boundary is an infinite reservoir with
the configured pressure and temperature; an end cap reflects flow.
Moving, rotating or resizing a connected component updates the attached pipe
endpoints. Its pipes therefore change length when their routes change. There is
no pressure-driven visual expansion in this editor.
The flow equations remain one dimensional in pipes and lumped in chambers.
The 3D layout supplies physical sizes and junction directions; this is not a 3D
CFD mesh. Valve restrictions and zero-volume fittings use the existing boundary
models. Ideal pressure-actuated check valves have no moving reed mechanics.
## Test and return to editing
Press **Tab** or **Test** to compile the design and run it with audio and pressure
colors. Select a part to read its current pressure and volume. W/S or the pedal
bar changes throttle; hold V for starter torque on a free shaft. Space pauses
or resumes both physics and audio. Test offers **1x, 0.5x, 0.25x, 0.1x and 0.01x**
playback; Page Down halves the speed and Page Up doubles it (1% to 100%).
**Step 10 ms** advances a paused machine by exactly 0.01 simulated seconds.
The physics timestep and engine calibration stay the same at every playback speed;
audio pitch slows with playback. Buffered audio scales with speed to keep controls
responsive. The four existing pipe solvers and five audio
environments are selectable under **Machine** before starting a test.
New engine benches use a free shaft at zero initial RPM. Hold **Hold to start**
or V to crank. A cylinder only receives fuel from an explicitly assigned injection
ECU or from fuel physically delivered through a connected carburetor. There is no
implicit cylinder injector. A carburetor can run with mechanical ignition; an
optional ignition/idle ECU can control spark and opening.
For EFI, connect the ECU's blue output to each cylinder's blue input. Connect
that output to the throttle's blue input for idle/throttle control. ECU settings
include idle target/opening limits, PI gains, ignition-map points, cruise/power
AFR, throttle response, overrun cuts, rev limit, resume RPM and minimum cut time.
Fuel and spark cuts are independent. A cut lasts at least its configured time and
resumes only below the resume RPM. Carburetor ECUs use **Ignition / idle only**
so they do not add an invisible second fuel source.
The **Mech** category contains **Shaft / crankshaft**, **Flywheel**, **Drive motor**
and **Brake / load**. Connect their gold mechanical ports. Cylinders and piston
pumps also have a gold shaft port; each must attach to a named shaft before Test.
Moving a shaft changes its attachment lines without moving its cylinders or pipes.
Each shaft has independent angle, initial speed, base inertia and friction.
Flywheels add inertia once; the shaft inspector shows the connected total.
Motors can apply signed torque or impose an ideal target speed. The ideal speed
drive reports the work it supplies or absorbs, including speed changes. A brake
applies opposing torque and drag, dissipates work and cannot drive a stopped shaft
backward. Pure mechanical machines can run without any gas pipes.
Use **Setup** to choose the primary readout shaft, or pin it from a shaft's
inspector. Each ECU's controlled cylinders must share a shaft. Engine timing is
currently forward-only; standalone mechanical shafts support reverse rotation.
The legacy starter calibration remains on migrated shafts until explicit starter
parts are added. New shafts have no hidden starter torque by default.
The saved **Shaft, flywheel and brake bench** demonstrates acceleration, motor
power and absorbed load power. Its file is `machines/shaft-drive-bench.machine.toml`.
The overlay distinguishes **SPEED CONTROLLED**, **TORQUE DRIVEN**, **FREE SHAFT**, **FUEL OR SPARK CUT**,
**VALVE FLOAT**, and **NO FUEL SOURCE**. The model has no fixed 16,000 RPM cap.
With limiting disabled, controlled checks ran at 16,000, 20,000 and 24,000 RPM
without positivity repairs. The unloaded bench settled around 17,500 RPM as net
torque fell toward zero. This depends on geometry, valve dynamics, fuel/spark
calibration and losses; increasing a rev limit does not guarantee engine torque
at that speed.
Unconnected gas ports on pipes and cylinders are sealed; the status line reports
their count. Unused tank faces are simply walls. Unconnected mechanical attachments
receive a navigable check and prevent Test.
Invalid dimensions, duplicate connections and physically separated connected
ports are rejected. Numerical failures stop the test and report an error.
Press **Tab** again to stop playback and return to the same design and camera.
Starting another test initializes a fresh gas and mechanical state.
## Live tuning
Properties are editable during Test unless marked **BUILD** and dimmed. Live changes
are validated and synchronized between physics batches, preserving gas state,
shaft state, simulation time, carburetor fuel film and controller history. Carb
jets, needle corrections, fuel settings, ECU calibration, fixed throttle opening,
check-valve cracking pressure, cylinder combustion settings, shaft losses,
motor torque/target speed and brake loads can be adjusted live. Live edits support undo/redo and saving,
and remain in the design when returning to Build.
Pipe routes/diameters, transforms, part dimensions, bore/stroke, cam profiles and
valve mechanics, connections, initial gas conditions, solver/mesh settings and
compiled boundary coefficients, initial shaft states and shaft/flywheel inertia
require Build. A live undo that would change one
of these properties is rejected without changing the running machine.
## Instruments and traces
Press **M** or **Meters**. Select a part, then choose **Pressure**, **Temp**, **Flow**,
**AFR**, **Lambda** or **Charge AFR**. **RPM**, **Torque** and **Power** target the
selected shaft or attached rotational part; without a compatible selection they
use the declared primary shaft. Up to eight channels can be attached.
Probes add no gas volume or restriction. Colored P1/P2 markers locate probes in
the world; clicking one in Select or Test opens its instrument settings.
Use **< Probe / Probe >** to choose the channel plotted on the scope.
Pipe taps use a fraction of arclength from Start to End, adjustable in the panel.
Measurements use the cell containing the tap, so spatial detail follows mesh
resolution. Lumped-part flow is net flow into the part; pipe flow is signed
Start-to-End. Pressure is absolute kPa, temperature K, flow g/s, torque Nm and
power kW. Motor gauges report drive torque/work, brakes report signed reaction
torque and positive absorbed power, and new shaft gauges report net acceleration
torque and kinetic power. Migrated legacy output gauges retain their running
averages of engine output after shaft friction, excluding bench drive and load;
the inspector identifies that measurement mode.
**Bulk AFR and lambda** track fuel origin as a conserved passive tracer, including
fuel already burned. Exhaust readings therefore travel with the gas through
pipes, chambers and shared junctions and mix according to transported mass.
Put a downpipe probe after a collector to read the combined exhaust there.
The exhaust starts as clean air, so downstream readings can remain very lean
until the original air has been purged by exhaust gas.
Lambda is bulk AFR divided by the probe's stoichiometric reference (default 14.7).
Changing the reference changes the displayed ratio, not the combustion chemistry.
**Charge AFR**, available on cylinders, reads current unburned fresh-air mass
divided by remaining unburned fuel mass. It becomes undefined after that fuel is
used. No fuel is shown as **--**, rather than an invented stoichiometric reading.
These are ideal model instruments; sensor heating, response delay and detailed
oxygen chemistry are not simulated.
The scope samples at 2,756.25 Hz in simulation time and retains the latest 32,768
samples (about 11.9 simulated seconds). Choose a 0.05, 0.2, 1 or 5 second display
window; the graph shows min/max/mean and preserves peaks when compressing samples
onto screen pixels. Frequencies above half the sampling rate cannot be resolved.
The scope stays open while switching to Part settings, allowing live carb/ECU
tuning while watching a trace. X closes the scope. Space freezes the machine for
inspection. The last capture remains available after returning to Build.
**Export captured CSV** writes simulation timestamps and labeled channel units to
`verification/measurements/`; undefined readings are empty cells. **Clear captured
trace** starts a new capture without resetting the machine. Adding/removing a
channel or changing a tap/reference clears the capture to keep its schema
consistent. Instruments can be configured during Test without reloading physics.
## Saving
Ctrl+S saves the design. A new design asks for a file name; Ctrl+Shift+S saves a
separate copy. Files use the versioned `*.machine.toml` format in `machines/`
relative to the working directory, or `FLUIDSIM_MACHINE_DIR` when set. Coordinates
and dimensional values are stored in SI units; inspector fields show their units.
Open/Saved files refreshes the library and provides separate Edit and Play
buttons. The scenario browser discovers saved machines each time it opens.
The document is validated before saving, and the written temporary file is read
back through the same loader before replacement. Unsaved changes prompt before
opening a different design, returning to the menu or closing the window.
Version 2 adds explicit fuel/control parts, control wires, imported port locations,
cam profiles and shaft losses. Version 1 files still load, but cylinders no longer
receive automatic fuel; add a connected carburetor or injection ECU to an older
engine design. The importer currently supports four-stroke layouts with uniform
ducts. Two-stroke crankcase/scavenge assemblies and profiled silencers are not yet
imported. Existing engine TOML files retain their separate schema.
Version 3 stores `point_diameters_m`, one diameter in metres per `points_m` entry,
for each pipe. Version 1 and 2 pipes load with their former linear taper sampled
at each point's arclength, preserving the original shape and volume. Saving writes
version 3. Inserted points inherit the interpolated diameter; moving a point keeps
its assigned diameter. Undo/redo and duplicated assemblies retain the full profile.
Version 4 also saves instrument channels, tap positions and lambda references.
Versions 1 through 3 still load. Recorded samples are exported separately as CSV.
Version 5 saves connection ports and methods by stable names instead of enum
indices. Custom chamber ports retain paired coordinate/key lists. Versions 1
through 4 migrate on load, including legacy aliases of a shared ideal junction.
Saving writes version 5; existing files are not rewritten until explicitly saved.
Port descriptors now identify gas, rotational, translational, Boolean, Number
and legacy ECU-assignment domains. Only implemented parts appear in the picker;
declaring a domain does not create its future components.
Version 6 adds explicit shafts and mechanical configurations. Loading versions 1
through 5 creates a visible shaft and any required speed drive/load, preserves
cylinder phase offsets and retargets legacy shaft instruments. Saving writes
version 6 with named mechanical connections; no existing file is changed merely
by loading it. Copy/paste and assemblies retain internal mechanical attachments
and instrument targets; external attachments remain unresolved.
Version 7 adds sensor attachments with stable IDs and named kinds, host/reference
bindings, normalized pipe taps and crank offsets. Part/sensor ID counters survive
save/load so deleted identities are not reused. Versions 1 through 6 still load.
Version 8 also saves a separate typed logic graph with stable node/pin keys,
parameters, references and independent canvas positions. Saving writes version 8;
loading alone does not rewrite an existing file.
## Sensor attachments
Open `machines/sensor-bench.machine.toml` for a ready-to-run demonstration of all
six sensor assemblies, a filling tank, fixed valve and independently driven shaft.
Select a physical part and open **Sense**. Only supported sensor buttons are
enabled: pressure/MAP and gas temperature/IAT on gas storage, pipes and environment
boundaries; differential pressure on two such taps; signed total mass flow on a
pipe; crank speed/position on an explicit shaft; TPS on a throttle or carburetor.
Right-click a pipe and choose **Add sensor here...** to use the clicked arclength
location. Otherwise a new pipe sensor starts at 50%. Move its tap in Sense.
For differential pressure, add the positive tap first. Select the reference
physical part, return to Sense, switch to **Reference (-) tap** and choose
**Bind reference to selected part**. The output is positive pressure minus
reference pressure, in pascals. Absolute pressure outputs use pascals absolute;
temperature uses kelvin; total mass flow uses kg/s, positive from pipe Start to
End. A volume has no unique through-flow direction, so flow sensors require a pipe.
The ideal crank pickup supplies signed angular speed in rad/s, crank angle in
0..2pi radians and a Boolean synchronized output. The pickup's configurable
reference offset applies to its angle, while the runtime retains the shaft ID
and unwrapped crossings. Zero speed while stopped is valid. This is an ideal
pickup, without tooth acquisition or cam-phase inference. TPS reports mechanism
opening fraction, including the existing ECU throttle response, rather than
substituting pedal demand for a fixed opening.
Sensors sample once per simulation audio sample and display sample time and
validity during Test. Number outputs have filled green dots; Boolean outputs have
filled red dots. Attached sensors introduce no gas storage or flow resistance,
and do not use any of the eight recorded meter channels. Use their Logic
references to wire sensor-driven ECUs; the labeled legacy ECU retains its
compatibility behavior.
Click an S-numbered marker to inspect its sensor. Previous/Next browses all
attachments, including unresolved ones. To rebind, select a compatible physical
part, reopen Sense and choose **Bind host to selected part**. Deleting a host
keeps the sensor and its former host label; missing/incompatible bindings show
invalid outputs rather than ordinary zero readings. Copy/paste and assemblies
remap internal sensor hosts; omitted external references remain unresolved.
Creation, binding, pickup offsets and removal require Build and support undo/redo.
These sensors measure gas temperature and total mass flow. Fresh-air MAF, cam
phase, lambda and material/head temperature sensors follow their own roadmap
stages and physical models.
## Logic editor and runtime
`machines/logic-compressor-bench.machine.toml` demonstrates an automatic air
supply: tank pressure feeds below-threshold hysteresis (120/150 kPa absolute),
an AND gate combines demand with a master switch, and a command node owns the
compressor motor's enable field. A numeric control supplies angular speed. The
saved defaults run the demonstration from Test. Choose **Logic** or **Split**
in the workspace toolbar to inspect its graph beside the physical machine.
The Logic library offers node categories, search and an Objects list. Pick a node,
then click the canvas to place it. Drag node headers to arrange the graph; Shift
and a selection rectangle select groups. Middle drag pans, wheel zooms about the
pointer, Home fits the active view, and F focuses its selection. Switching views
keeps the camera, canvas navigation, selection and running simulation. In Split,
click the desired pane to choose its navigation/inspector context.
Drag between compatible pins, or click a pin and then its target. Inputs are
hollow rings; outputs are filled circles. Boolean is red and Number green. One
output can fan out. Starting from a connected input rewires it atomically;
rejection leaves the original connection intact. Right-click a pin to disconnect
its wires. Escape cancels a pending connection. The library filters compatible
node kinds while a pin is pending, and a newly placed numeric node adopts that
pin's quantity/reference. Other numeric schemas are configured in the inspector.
Select a node to edit its name, parameters, quantity and pressure reference.
Numbers use the units shown on their fields/pins (SI internally). Enter applies
a text edit; Escape cancels it. Invalid text remains editable. Hover pins for
type, direction, units, validity, supported ranges and required/default metadata.
Combinational-cycle candidates highlight their cycle nodes and report the path.
H opens diagnostics; clicking a signal warning reveals the affected node.
Create sensors in 3D **Sense**, then choose **Show Logic** to reveal their reference.
The **Command** button on supported physical parts creates/reveals a command
reference. Its inspector chooses a command function and compatible physical
target. Selecting a sensor/command node selects that physical host; **Focus in
3D** opens Split and focuses the host. Reference nodes do not add gas storage or
duplicate a physical sensor/actuator.
During Test, node topology, schemas, bindings, control ranges and initial memory
require Build. Safe constants, thresholds and canvas layout remain editable.
Click switch controls, hold momentary buttons, drag sliders, or type into numeric
controls on their nodes. Paused control changes queue for the next physics sample;
their control widgets identify queued values while pin values stay frozen. Momentary
buttons release on focus loss, leaving Logic, or stopping Test. Manual Test inputs
do not silently overwrite their configured initial states. Readouts show compact
UI-sampled trends; recorded meter channels and CSV export remain separate.
Ctrl+C/V copies nodes and internal wires; Ctrl+D duplicates, Delete removes, and
Ctrl+Z/Y undo/redo. Same-document sensor copies reference the same sensor entity.
Copies pasted into another document detach external sensor references and keep
their labels. Pasted command nodes require an explicit new target so they cannot
take over an existing actuator field accidentally. Copying physical assemblies
remaps their internal sensors, command targets and connected control harnesses.
The graph runtime supports typed controls, Boolean gates, comparisons, arithmetic,
mapping, selectors, sensors, commands, displays and explicit one-tick delays.
Each audio sample evaluates the graph before physics and holds commands during
fluid substeps. Unknown types/ports, incompatible quantities, multiple drivers
and combinational cycles are rejected. Required unconnected inputs block Test.
Missing measurements and math faults carry invalid status; motor/valve commands
apply their declared inactive fallback rather than retaining a previous command.
The graph is saved in `[logic]` tables, including independent canvas positions.
Physical inspector controls identify signal-owned fields; existing manual or ECU
controls cannot simultaneously own them. Existing engine ECUs retain their
labeled legacy compatibility model; new sensor-driven presets use explicit
measurements as described below.
## Sensor-driven ignition and Alpha-N EFI
Open `sensor-ignition-bench.machine.toml` or `sensor-alpha-n-bench.machine.toml`
from saved machines for a working 3000 RPM test bench. The first uses a physical
carburetor; the second transports fuel from an attached intake injector. Both
have crank-to-ECU wiring visible in **Logic**. Press Test to run, then inspect
inputs and physical parts in Logic/3D or Split.
Select an ECU and cycle its preset between **Legacy ideal**, **Crank ignition**
and **Alpha-N EFI**. Sensor presets assign only cylinders through blue links;
choose **Show ECU connector in Logic** and connect crank speed and angle from
one physical pickup. Alpha-N also requires a throttle-position sensor. No driver
demand wire is needed for a manually adjusted throttle. The cylinder's **Pickup
TDC deg** is its calibrated TDC in the sensor's wrapped crank coordinates; for a
pickup offset of zero, a cylinder physical phase of 90 degrees has TDC at 270.
Crank-only ignition is wasted spark, without hidden cam/cycle synchronization.
For EFI, select an intake chamber and choose **Attach fuel injector**, then
choose its Alpha-N fuel ECU. Scroll its properties to set injector capacity,
initial fuel mass, fuel temperature, finite/ideal rail supply and cylinder-dose
count. A common-plenum injector can deliver several cylinder doses; their total
must match the ECU's assigned cylinders. The ECU's **Fuel RPM**, **Fuel TPS** and
**Fuel cell** fields edit the calibrated table (RPM rows, TPS columns, displayed
mg per cylinder per four-stroke cycle). This is an open-loop calibration, not a
measurement of trapped air mass.
Required input faults, stale or mixed pickups, and pickup/engine shaft mismatch
cut new spark events and EFI delivery. Constants and arithmetic cannot substitute
for physical crank timing. Previously ignited fuel finishes its physical burn.
The ECU inspector reports sensor faults and rev limiting; injector hosts report
flow and remaining fuel. Ignition maps and RPM limits allow live tuning. Fuel
maps, injector setup, strategy and pickup calibration require Build.
Fuel delivery currently uses a declared regulated rail and continuous/batch-average
vaporized fuel addition into the gas volume. There is no liquid rail-pressure
sensor or sequential pulse-width/evaporation model yet. Format 9 saves the new
bindings and calibrations; older machines continue loading without being rewritten.
## Speed-density EFI
Open `sensor-speed-density-bench.machine.toml` for the minimal MAP/IAT engine
example. Select **Speed-density EFI** in the ECU preset cycle and choose **Show
ECU connector in Logic**. Connect crank speed/position, an absolute-pressure MAP
pickup in the intake manifold and a gas-temperature IAT pickup at the intake.
TPS is not required for this basic preset. Missing or invalid measurements cut
fuel and new ignition events; the controller does not read hidden cylinder charge.
In the ECU properties, **SD displacement cc** is the calibrated swept volume per
cylinder. **SD target AFR**, air gas constant and the VE table determine the
open-loop estimate `MAP * displacement * VE / (R_air * IAT)`. **SD VE RPM** gives
the rows and **SD VE MAP kPa** the columns; **SD VE cell %** edits row-major table
values. Values outside the table axes use its edge calibration. These settings
require Build; the ignition map and rev limiter still permit live tuning.
Injector attachments can target Alpha-N or speed-density ECUs. Their explicit
capacity and finite/ideal rail supply continue to limit actual delivered fuel.
The dry ideal-gas estimate does not measure fresh-air fraction under intake-gas
dilution and currently has no warm-up, acceleration or lambda corrections. Format
10 saves this strategy and its calibration while preserving loading of versions
1..9.
## Architecture and further work
The proposed expansion is documented in the
[machine systems roadmap](MECHANICAL_BUILDER_PLAN.md): typed ports and logic,
explicit shafts, pneumatic parts, sensor attachments and sensor-driven ECU
presets, with one integrated delivery order. See the linked implementation
progress for completed parts and the remaining planned features.
`MachineDocument` stores parts with stable IDs, local geometry and explicit port
connections. `MachineSimulation` compiles that document into the existing
`Pipe1D`, `Volume0D`, `FourStrokeCylinder`, `BoundarySystem`, `Solver` and
`MechanicalSystem` components.
Shaft, ECU, cam, combustion and fuel-metering updates run once per audio sample,
as in the original engine scenarios. Gas transport and pressure-operated check
valves retain CFL substeps. Compiled part/gate lists avoid repeated graph scans.
The editor consumes snapshots while testing and owns its document separately.
Pipe meshes are cached until their local route or diameters change; transforms
and pressure colors reuse the mesh. Part icons share a cached texture atlas.
The editor includes fifteen part types, gas and mechanical example circuits, four preset imports,
save/load, group transforms, pipe routing, shared nodes, undo/redo, selection
copy/paste, reusable assemblies, and Build/Test. Remaining workshop work is
focused on port-picking and control-wire visibility in dense assemblies, clearer
group-edit feedback, property help, and adjustable port placement. New machine
types, gears and clutches remain on the component roadmap; explicit shafts are implemented.
### Next session
Continue the active component goal: explicit shafts, flywheels, drives, brakes
and six basic sensor assemblies are implemented and verified. The typed logic
runtime, persistence, physical commands and basic Logic/split editor are integrated
with thirteen focused suites passing at the editor milestone. Sensor-driven
ignition/Alpha-N presets, grouped ECU inputs, pickup calibration and explicit
injector attachments are now integrated, saved and tested with actual combustion
in two new benches. Speed-density EFI now adds a third working bench with actual
MAP/IAT inputs, calibrated VE/displacement, saved bindings and workshop controls.
Fifteen focused suites pass. Continue stage 4 with physical
needle/shutoff/regulator/relief valves and pressure-switch control; see the next
physical component slice in the progress file. Keep advanced graph UX/operator panels on the UI
backlog. See [component progress](COMPONENT_IMPLEMENTATION.md). Preserve the
existing uncommitted working tree and user-edited machine files.
### Historical session notes
The user asked to stop polishing and launch the current build on 2026-10-30.
The updated desktop executable was built and launched with
`machines/single-450-imported.machine.toml`. Changes are saved locally and remain
uncommitted. Preserve the existing working tree.
Continue with small usability refinements, particularly port picking and control
wire visibility in dense assemblies, group-edit feedback, and property help.
The 2026-10-31 usability pass added validated connection previews, click-position
bend insertion, focus selection and navigable machine checks. It also corrected
the OpenGL/SFML state handoff so controls remain visible after raw 3D rendering.
If the reported 16,000 RPM stop persists, reproduce it with the user's exact
machine/settings: controlled tests passed through 24,000 RPM and the free bench
settled around 17,500 RPM, so a universal 16,000 RPM cap was not reproduced.
Legacy version 1 engine files need an explicit carburetor or injection ECU now.
Workshop performance was fixed on 2026-10-30. Arclength meshing, sample-rate
control updates, compiled gate lists and cached rendering reduced flat6 simulation
cost from 104.4 to 8.8 us/sample at 3,000 RPM and 35% pedal. It now uses 98 cells
and approximately one CFL substep/sample, matching the native layout's mesh.
The importer positions its metering body to allow a longer outlet stub while
preserving the inlet endpoints, total route length and gas volume. Untouched stock
imports were refreshed; custom saved designs retain their authored geometry.
Flat6 and V8 audio-driven playback kept real time with no measured underruns.
See the [performance report](../verification/performance/2026-10-30/workshop-report.md)
for timings, validation and reproducible commands. Further work can focus on the
usability items above and closer calibration parity with native engine scenarios;
the workshop still represents its metering hardware as explicit editable parts.
## Checks
`fluidsim_machine_tests` covers centerline/profile volumes, rotated tanks,
connection snapping, malformed graphs, file round trips, closed/open throttle
behavior, shared nodes, group transforms, explicit fuel sources, ECU cut duration,
carburetor-only combustion, preset imports, vacuum pumping and an EFI bench.
`fluidsim_machine_builder_tests` checks projection and picking, world rotations,
mouse-driven translation, Shift selection, assembly duplication/deletion, undo
and Build/Test transitions. Assembly checks cover connected subset copies,
air/control endpoint remapping, geometry and probe persistence, cross-document
paste, library saving/browsing/insertion, and insertion undo/redo. Escape and
explicit Menu/window exit paths are checked separately.
Its `--preview <directory>` option writes editor screenshots for layout review.
It also checks pipe-cache invalidation, transform/pressure cache reuse, deleted
parts and the icon atlas. Physics checks cover route-knot-independent meshing,
real short-pipe CFL limits and pump sample-rate refinement.
Additional checks cover non-mutating connection previews, incompatible air/control
pins, occupied ports and collapsed pipes; shared fuel-source diagnosis; perspective
bend insertion with undo/redo; and check-to-part navigation. Preview mode also
verifies rendered UI pixels after both scene and icon rendering.
Instrument checks cover probe persistence, exhaust AFR/lambda after combustion,
conserved fuel-origin transport through solvers and junctions, pause/step/slow
playback, live tuning without a reload, locked geometry, live undo/redo and CSV
channel units. The [instrument verification report](../verification/performance/2026-10-31/workshop-instruments.md)
records the playback checks with eight channels active.
`fluidsim_machine_tests --rpm-sweep` checks high RPM and a 30-second free-running
acceleration trace with the ECU rev limiter disabled.

View File

@@ -0,0 +1,621 @@
# Machine systems roadmap: mechanics, pneumatics, logic and ECU sensors
Planning draft, 2026-11-01. This describes proposed work, not implemented features.
Implementation has started; see [component progress](COMPONENT_IMPLEMENTATION.md)
for completed foundations and the remaining delivery backlog.
## Goal
Build machines from explicit gas, mechanical and signal connections. Engines,
pumps and actuators exchange physical work; sensors measure named locations;
logic and ECUs control declared targets. The workshop should make those paths
easy to connect, inspect and diagnose.
Originally cylinders and piston pumps used one implicit machine-wide crankshaft.
Explicit shaft, flywheel, drive and brake parts are now implemented, with migrated
legacy layouts and targeted instruments. Six basic sensor assemblies and their
physical bindings/live inspector are also implemented. The basic logic runtime
and 3D/Logic/Split editor, sensor-driven ignition/Alpha-N presets and explicit
intake injector attachments are integrated and verified. Stage 4 now also has a
working speed-density preset using actual MAP/IAT signals and calibrated VE.
Advanced graph UX, the stage-4 pneumatic valves and the later physical systems
remain on the delivery backlog.
## Agreed design rules
- Boolean signals are red; Number signals are green. Directed inputs are hollow
rings and outputs filled circles. Physical ports such as gas/pressure remain
bidirectional and use distinct neutral domain symbols.
- Establish typed ports, stable identities and validation before adding parts
that depend on them. Types must exist in the document and runtime, not only UI.
- Use one machine document across 3D Build, Logic and Test. Canvas references,
sensors and instruments do not create duplicate physical machines.
- Sensor attachments belong at named physical locations. Readouts may fan out
to ECUs, logic and instruments. Controllers use connected measurements and
explicit calibration/defaults rather than hidden access to unrelated state.
- Provide simple starting presets with few mandatory connections; expand their
visible optional inputs as features are enabled. Missing and invalid data
have explicit, different behavior.
- Preserve legacy machines through versioned migrations and labeled compatibility
controllers. Keep their operating behavior reviewable before changing models.
- UI work prioritizes consistent appearance, responsive layout and preventing
text/control overlap at the primary 1920x1080 desktop target. Test starts running
in the existing workspace; panels resize/collapse and retain their widths.
## Integrated delivery order
This is the authoritative implementation order. The track sections below detail
their own parts and acceptance targets; their local numbering is not a separate
release schedule.
| Stage | Deliverable | Completion example |
| --- | --- | --- |
| 0 | Shared port descriptors, quantity/reference types, stable keys, validation and migration scaffolding | Every connection path rejects the same incompatible types; existing machines still load. |
| 1 | Explicit shafts, flywheel, drive/load, basic sensor attachments and targeted instruments | Two independent engines; one shaft driving a loaded piston pump. |
| 2 | Logic canvas, manual controls, gates, thresholds, live values and valve/motor command ownership | Sensor -> threshold -> enable switch -> drive, with red/green signal wiring. |
| 3 | Sensor-driven ignition ECU and Alpha-N EFI, crank sensing and ECU connector UI | Carbureted ignition control and minimal EFI both run from explicit sensors; missing crank stops controlled combustion. |
| 4 | MAP/IAT sensors, speed-density ECU, regulator/relief/shutoff valves and pressure-switch preset | Sensor-driven engine and automatic regulated air supply bench. |
| 5 | Gears, clutch, starter; directional valves, linear actuators and loads; stateful logic | Geared pump, clutched load and timed pneumatic actuator circuits. |
| 6 | MAF/sequential ECU options, air motor, rotary compressor, acoustic assemblies and remaining UI refinement | Stored-air motor and richer sensor/actuator examples. |
| Later | Thermal parts, belt detail, ejector, turbine/turbocharger and general linkages | Add only with a defined physical model and acceptance cases. |
Ship small usable slices within each stage. Stage 3 depends on defining sensor
timing and explicit fuel delivery, not merely drawing extra ECU input pins.
## Proposed parts
| Part | Purpose and editable properties | Delivery |
| --- | --- | --- |
| Shaft / crankshaft | Named rotational node; angle, initial RPM, base inertia and friction. Cylinders and pumps attach with individual phase offsets. | First release |
| Flywheel | Adds inertia to its connected shaft; explicit inertia initially, with geometry-derived inertia as a later option. | First release |
| Drive motor | Ideal speed-controlled bench drive or torque-controlled motor; target speed or torque and direction. Report required drive torque and power in speed mode. | First release |
| Brake / load | Applies a constant opposing torque and optional speed-dependent drag; reports absorbed power. | First release |
| Gear pair | Fixed signed speed ratio between two shafts, with an explicit efficiency/loss model. Tooth counts determine the ratio. | Second release |
| Clutch | Connects two shafts through a torque-limited friction coupling; engagement, torque capacity, slip and dissipated power. | Second release |
| Starter | Torque-limited drive with a one-way coupling and hold-to-start input. Initially uses a specified torque curve. | Second release |
| Belt / pulley drive | Same-direction or crossed drive with pulley ratio; an ideal fixed-ratio model first, slip/tension later. | Later |
| Rotary compressor / pump | Continuous shaft load coupled to gas flow; requires a defined displacement or performance-map model. | Later |
Existing cylinders and piston pumps gain mechanical attachment ports. Their
phase is relative to the attached shaft. A shaft can have multiple attachments;
there is no automatic connection because parts happen to be nearby.
For the initial release, one shaft part represents a rigid rotational node.
Its visible length helps placement; it does not introduce torsional flexibility.
Base shaft inertia and attached flywheel inertia are counted once. Separate
shafts rotate independently until connected by a supported coupling.
## Connection and simulation rules
- Distinguish gas ports, control pins and rotational ports by shape, label and
color. Preview compatibility and explain rejected connections before clicking.
- Mechanical attachment lines identify the shaft association. They do not
silently move cylinders or imply a physically supported bent driveshaft.
- Keep shaft angle/speed per shaft. Route cylinder torque, pump torque, losses,
drives and loads to the correct shaft; sample its RPM for each attached ECU.
- Initially require cylinders controlled by one ECU to share a shaft. Diagnose
mixed-shaft assignments until explicit speed-reference selection is added.
- Ideal gears impose a speed/angle relationship. Solve connected rigid groups
with inertia reflected through their ratios; do not use competing independent
RPM updates or stiff penalty torques to approximate a rigid connection.
- Validate contradictory ratios, incompatible prescribed speeds and unsupported
constraint loops. Start with tree-shaped gear networks and reject loops with
actionable diagnostics until a general constraint solver is available.
- Friction and brake torque oppose motion, and must not push a stopped shaft
into reverse. Drive torque can select direction. Check existing cylinder/cam
assumptions before enabling reverse engine operation.
- Track external work, rotational kinetic energy and coupling losses. Clutch
slip dissipates energy; an ideal prescribed-speed drive supplies or absorbs
whatever work is required and reports it.
- Connection changes and initial state changes require Build. Safe torque,
speed-target and engagement tuning can remain available during Test.
## Workshop UI
The [workshop UI rework](WORKSHOP_UI_PLAN.md) specifies the workspace layout,
interaction conventions and user-selected preferences in more detail.
### First release: connecting and understanding the machine
- Searchable parts picker with Gas, Engine, Mechanical and Control categories.
- Connection filters for Gas, Mechanical and Control; fade unrelated links.
- Larger screen-space port targets, hover labels, endpoint highlighting and
candidate cycling where ports overlap. Preserve existing gas connection rules.
- Mechanical overview listing each shaft, its attached parts and its drive/load.
Selecting a row selects and focuses the corresponding assembly in 3D.
- Shaft inspector groups Initial state, Inertia and losses, and Connections.
Show total connected inertia separately from editable base inertia.
- Cylinder/pump inspector shows the named shaft and phase offset, with an action
to select the shaft. Unattached mechanical parts receive a navigable check.
- RPM, torque and power instruments require a named target. Torque readings
identify what is measured, such as cylinder output, motor input or load torque;
a shaft network has no single universal transmitted-torque value.
- Test overlay shows the selected shaft's RPM and operating state. With several
shafts, let the user pin the main readout instead of silently choosing one.
### Second release: coupled machines and editing feedback
- Gear connection preview shows input/output shafts, ratio and rotation direction.
- Clutch control and instruments show engagement, slip RPM and lost power.
- A compact power-path view highlights the selected shaft's connected network.
- Group inspector shows selection count, pivot and mixed property values;
offer only edits applicable to the selected parts.
- Add concise property help with units, physical meaning and Build/Test status.
- Add named saved visibility groups for dense assemblies. Hiding a part only
affects editing visibility, never simulation membership.
Adjustable gas port placement is a separate follow-up. Ports represent physical
openings, so editing them must update connected geometry and preserve validation;
they should not be freely dragged as purely cosmetic connection markers.
## Save files, imports and assemblies
- Introduce a new machine format version with explicit shaft references and
mechanical connections, using stable IDs.
- Upgrade older files to one visible shaft with their existing inertia, losses,
initial speed, drive and load settings. Create drive/load parts as needed and
attach all existing cylinders and pumps with their original phase offsets.
- Preserve existing starter behavior during migration; replace it with an
explicit starter when the starter model is available.
- Retarget legacy shaft instruments to the migrated shaft. Retain the existing
torque metric's meaning and label it explicitly during the transition.
- Engine imports create explicit mechanical parts. Copy/paste and assemblies
remap internal shaft references and retain external attachments as visibly
unresolved; they must never attach to a destination shaft by coincidence.
## Mechanical track scope and acceptance
Before these implementation stages, deliver the typed port foundation described
in the logic section below. Mechanical and pneumatic additions should use that
shared contract from their first implementation.
1. **Explicit shaft foundation:** document/serialization migration, independent
shaft runtime state, cylinder/pump attachment, rendering and selection.
Acceptance: two disconnected engines can run at different speeds; existing
imported machines retain their operating behavior and phase relationships.
2. **Usable mechanical bench:** flywheel, drive motor and brake/load; connection
filters, port picking, shaft inspector and targeted instruments.
Acceptance: assemble and inspect an engine driving a loaded piston pump;
disconnected attachments and fuel/control problems are easy to locate.
3. **Coupled shafts:** fixed gears, clutch and explicit starter, with ratio and
power-path feedback. Acceptance: accelerate a second inertia through a clutch,
observe slip losses, and drive a pump at a different speed through gears.
4. **Broader machines:** belt drives and a rotary compressor/pump after choosing
and validating their physical models; adjustable gas ports and visibility
groups as workshop follow-ups.
Validation should cover legacy migration, assembly ID remapping, independent
shafts, phase continuity, inertia response, gear direction/ratio and reflected
inertia, prescribed-drive work, clutch losses and stop/reversal behavior.
Use focused simulation and builder checks as each stage is implemented.
The first mechanical slice covers the shaft foundation and usable bench above.
Detailed electrical motors,
batteries, gear contact dynamics, shaft flex and belt tension need separate models
and are outside that milestone.
## Pneumatic and fluid-powered expansion
Extend the current compressible-gas system with useful circuits: store compressed
air, regulate it, switch it, and convert its pressure into linear or shaft work.
Existing chambers already serve as finite tanks, and the piston pump can form a
reciprocating compressor with external check valves. Add useful presets and
assemblies for these before introducing redundant part types.
This roadmap initially targets gas. Liquid hydraulics would need a separately
defined fluid model, including compressibility, cavitation and appropriate
boundary treatment, before the same UI could promise hydraulic behavior.
### Proposed fluid parts
| Part | Behavior and properties | Priority |
| --- | --- | --- |
| Adjustable restriction / needle valve | Two-port metering with editable opening and effective flow area; supports reverse flow and choking through the shared gas boundary model. | A: basic circuits |
| Shutoff / solenoid valve | Two-port on/off valve; normally open/closed state, commanded opening and finite actuation time. | A |
| Pressure relief valve | Opens from a protected node to an explicit outlet above a differential-pressure setting; reseat behavior prevents chatter. | A |
| Pressure regulator | Reduces downstream pressure using a bounded inlet restriction with response dynamics; cannot increase pressure or hold a target without supply capacity. Non-relieving initially. | A |
| Pressure switch | Senses a chosen pressure and emits a Boolean signal with separate on/off thresholds; starts/stops a compressor or operates a valve. | A |
| Directional valve | 3/2 first, then 5/2; named supply, work and exhaust ports, explicit internal paths and transition behavior. | B: actuators |
| Pneumatic actuator | Single-acting spring-return first, then double-acting; bore, rod, stroke, moving mass, friction, dead volumes and end stops. | B |
| Linear load / spring | Opposing force, attached mass, spring and damping for an actuator's translational port. | B |
| Quick-exhaust valve | Vents an actuator locally through its own outlet when the supply path depressurizes. | B |
| Air motor | Positive-displacement gas motor with inlet, outlet and shaft port; displacement, leakage and mechanical losses. | C: shaft power |
| Rotary compressor | Shaft-driven gas compression with displacement/map, leakage and losses; load arises from gas work. | C |
| Nozzle / venturi | Converging/diverging pipe profile preset first; a later ejector adds a suction port and a validated entrainment/mixing model. | C |
| Filter / porous restriction | Calibrated pressure loss and optional gas storage; acoustic attenuation requires an additional defined model. | C |
| Silencer / resonator | Pipe/chamber assemblies first: expansion chamber, side branch and Helmholtz-style resonator. Absorptive silencers need an explicit loss model. | C |
| Cooler / heated chamber | Defined wall temperature or thermal mass and gas-wall heat transfer; report heat flow alongside gas state. | Later |
| Turbine / turbocharger | Map-based turbine and compressor on explicit shaft nodes; requires performance data and operating-range handling. | Later |
Priority letters describe the pneumatic track, not a promise to finish it before
the mechanical milestones. Prioritize A alongside the shaft foundation, B next,
and C once independent shafts and component coupling are established.
### Physical behavior and scope
- Valves transfer conserved mass, species and energy through actual ports.
A regulator must not overwrite a chamber pressure to enforce its setpoint.
- Supply and exhaust are visible connections. An unconnected outlet remains
sealed under the current builder rule; warn when a valve needs an exhaust path.
- Regulator and switch inspectors state whether settings are absolute, gauge or
differential pressure. Store physical pressures in SI and define the reference.
- Actuator force uses the pressures on both piston faces and their effective
areas. Each chamber volume follows piston motion, with positive dead volume;
gas work and mechanical work must balance.
- Add translational mechanical ports for actuators and linear loads. An actuator
is distinct from the existing crank-driven piston pump. A general linkage
mechanism can connect translation to rotation in a later milestone.
- Resolve moving valves, actuator stops and small chambers with appropriate
component timesteps. The existing pipe CFL limit alone is insufficient.
- Air motors and compressors exchange torque/work with the attached shaft.
Their models define starting, stall, reversal and off-design behavior rather
than extrapolating efficiency formulas through zero speed.
- Pressure switches and solenoids use typed signal ports. Add a manual switch
and a simple hysteretic controller; define their update order. Keep ECU
assignments intact while extending the control connection system.
### Fluid UI and instruments
- Add Supply/storage, Valves, Actuators, Rotating machines and Thermal/acoustic
subcategories, plus searchable saved circuit assemblies.
- Label valve ports P (supply), A/B (work), and R/S (exhaust), with tooltips in
plain language. Show connected paths and moving valve state during Test.
- Preview actuator stroke limits and current rod position in 3D. Its inspector
shows chamber pressures, net force, position and velocity.
- Add differential pressure, actuator force/travel/velocity, valve state and
switch output instruments. Flow probes must identify the measured port and
direction; show mass flow by default and label volumetric reference conditions.
- Highlight a selected supply path and its exhaust route; distinguish blocked
flow from disconnected parts. Add checks for missing exhausts, absent supply,
unattached mechanical loads and incompatible signal connections.
- Show regulator target beside actual pressure, tank stored gas state, and
absorbed/delivered shaft power. Keep invalid or out-of-range readings explicit.
### Playable circuit milestones
1. **Air supply bench:** existing piston pump + check valves + tank, pressure
switch, relief valve and regulator. Charge a finite tank, cycle the drive
between pressure thresholds and feed a restricted downstream branch.
2. **Actuator bench:** regulated supply + 3/2 valve + spring-return actuator;
follow with a 5/2 valve and double-acting actuator driving a linear load.
3. **Stored-air motor:** charge the tank, disconnect the compressor drive, and
run an air motor connected to a flywheel and brake until pressure falls.
4. **Acoustic bench:** interchangeable resonator/silencer assemblies with inlet
and outlet pressure traces and source captures. Compare pressure loss and
acoustic response at consistent operating points.
5. **Boost system:** shaft compressor first, then a map-based turbine/compressor
assembly with intake and exhaust connections once those models are ready.
Acceptance checks should include sealed-system mass/energy accounting, choking
and reverse flow, relief opening/reseating, regulator response and insufficient
supply, switch hysteresis, valve port states, actuator force/work and end stops,
and motor/compressor gas-work-to-shaft-work balance. These belong to the future
implementation stages; this document adds planning only.
## Typed signals and logic nodes
### Confirmed current implementation
The shared typed-port foundation, physical sensor attachments and a general
signal-graph runtime are now implemented. `MachineDocument::logic` stores nodes
and named typed wires separately from physical connections. Runtime nodes include
controls, gates, thresholds, numeric operations, sensor/command references,
readouts and explicit delays. See [component progress](COMPONENT_IMPLEMENTATION.md)
for the verified scope. The basic Logic canvas, shared 3D/Logic/split workspace,
typed wire editing, interactive controls and graph inspectors are now integrated.
Advanced graph UX, operator panels and the later component stages remain planned.
`MachineConnectionKind::Control` remains legacy ECU assignment. Those blue wires
assign a controller; the new Boolean/Number graph does not reinterpret them.
### Shared port contract: implement first
- Give each port an explicit domain: Gas, Rotational, Translational, Boolean,
Number, or the existing ECU assignment domain during migration. Domain and
signal direction must be data, not inferred from a part kind or rendered color.
- Define ports through a shared descriptor with a stable key, display name,
domain, input/output direction for signals, cardinality, and typed defaults.
Number ports also declare quantity/unit, supported range and any required
pressure reference. Physical ports retain their domain-specific behavior.
- Use stable serialized port keys, versioned migration for old numeric indices,
and stable part/node kind keys. Adding a port or reordering an enum must not
silently reconnect an existing saved machine to a different function.
- Store signal values as Boolean or finite numeric values with explicit validity.
Do not encode Booleans as arbitrary floating-point values or use NaN as truth.
- Only connect matching signal types from output to input. One output may feed
multiple inputs; one input accepts one driver. No automatic Bool/Number cast.
Explicit conversion nodes handle thresholding and Boolean-to-number selection.
- For numbers, also validate quantity compatibility. Pressure, RPM and opening
fraction must not connect interchangeably because all are numeric. Store SI
values; present convenient units, and require explicit scaling/mapping where
a quantity changes. Enforce arithmetic quantity rules and configure constants
with a quantity. Infer polymorphic node ports consistently when compiling.
- Required unwired inputs produce a navigable check and block Test; optional
inputs show a declared default in the UI. Invalid sensor/math output remains
visibly invalid and follows a documented per-consumer fallback; actuator
command inputs default to a declared inactive state, not a previous command.
- Use the same descriptors and compatibility checks for connection previews,
actual edits, loading, validation, compilation and runtime binding. Keep
signal links out of gas connectivity walks, pipe snapping and fuel searches.
- Preserve existing ECU assignments as their own relation; migrate them through
explicit adapters or dedicated ports when individual ECU commands are exposed.
Never reinterpret old ECU links as Boolean or Number links.
### Color and node editing
- **Boolean ports and wires: red. Number ports and wires: green.** These hues
identify the type consistently in 3D, node view, picker, inspector and legend.
- **Inputs are hollow rings; outputs are filled circles.** Apply this convention
consistently to directed ports on every node and part in both 3D and Logic
views. Shape communicates direction; red/green communicates Boolean/Number
type. Labels and hover text identify both type and direction without color.
- Physical ports without an input/output direction, such as pressure/gas
connections, remain bidirectional and use a distinct neutral physical connector
symbol. Their appearance must not imply one-way flow. A pressure sensor's gas
connection is bidirectional; its numeric measurement output is a filled green
circle. Rotational and translational attachments likewise use their physical
domain symbol rather than suggesting a fixed power-flow direction.
- Bright/dim styling and true/false text show Boolean state while retaining the
red type color and input-ring/output-circle silhouette. Number hover labels
show value, units and validity.
- Replace green as the gas identity with neutral gas markers. Connection validity
uses a separate checkmark or cross/message so success/error feedback cannot be
mistaken for a signal type or input/output direction.
- Add a **Logic** view: a pannable, zoomable node canvas for the same machine.
Logic nodes have saved canvas positions; sensors and actuators appear as
references to their existing physical parts, not duplicated simulated parts.
- Inputs appear on the left, outputs on the right. Drag to connect, branch from
outputs, reroute wires, disconnect and undo. Filter compatible nodes when
dragging from a pin. Label incompatible targets with a rejection reason.
- Keep 3D part placement separate from canvas layout. Selecting a sensor or
actuator reference can focus its physical part, and vice versa. Logic nodes
need no gas storage or physical 3D housing to function.
- Add live pin values, Boolean state and compact number traces during Test.
Pause freezes logic with physics; stepping advances both. A control panel can
pin buttons, switches, sliders and readouts for use without opening the graph.
### Initial node library
| Group | Nodes | Defined behavior |
| --- | --- | --- |
| Manual Boolean controls | Toggle switch, momentary button, Boolean constant | Switch retains its state; button is true while held. Release on focus loss, view close or Test stop. |
| Manual numeric controls | Number constant, slider, numeric input | Quantity, unit, range and initial value are explicit; user edits arrive at simulation boundaries. |
| Boolean gates | AND, OR, NOT, XOR, NAND, NOR | AND/OR start with two inputs and can add inputs; named, deterministic truth tables. |
| Threshold and comparison | Greater than, less than, equal within tolerance, range/window, hysteresis threshold | Number inputs produce Boolean outputs; comparisons use compatible quantities. Hysteresis has separate on/off thresholds and an initial state. |
| Numeric arithmetic | Add, subtract, multiply, divide, min, max, absolute value, clamp | Compatible quantity rules; division by zero produces an invalid value and a diagnostic. |
| Mapping and selection | Gain/offset, map range, Boolean-controlled number selector, Bool-to-number | Selector chooses between two compatible numbers; Bool-to-number emits configured false/true values. Mapping declares quantities and clamping behavior. |
| State and timing | Set/reset latch, rising/falling edge, on-delay, off-delay, pulse timer | Reset wins if set and reset coincide. Timers use simulation time. Edge nodes initialize from their input without emitting a false startup edge. |
| Number memory | One-tick delay, sample-and-hold | Explicit initial value; held quantities remain typed. Delay separates feedback across ticks. |
| Sensors | Pressure, differential pressure, temperature, mass flow, shaft RPM, actuator position, limit switch | Attach to a physical target/port without changing its gas volume. Supply validity and quantity metadata. |
| Outputs and commands | Valve enable, valve opening, motor enable/target, clutch engagement, starter command | Each target exposes its supported type, units/range and fallback. Explicit manual, signal or existing-controller ownership prevents competing commands. |
| Displays | Boolean lamp, numeric readout, trace | Observe a typed signal without changing its evaluation. |
Starter nodes are switches, buttons, constants/sliders, AND/OR/NOT, thresholds
with hysteresis, number selection, pressure/RPM sensors, command inputs and
displays. Add the rest after the core graph and timing semantics are established.
### Evaluation, feedback and persistence
- Initially evaluate the compiled signal graph once per audio sample, using the
configured sample period (currently typically 1/44100 s). Sample physical
sensors at the boundary, evaluate the graph, latch actuator commands, then
advance physics. Fluid CFL substeps hold those commands. Slower playback does
not change control time relative to simulated time.
- Topologically evaluate combinational nodes. Treat memory/delay outputs as
stored state, then commit their next state simultaneously after evaluation.
Reject combinational cycles with a highlighted cycle path; explicit state
permits feedback. Physical sensor/actuator feedback crosses a physics step.
- Consume manual-input events in order at a simulation boundary. Preserve a
press/release pair between boundaries for one tick; edge outputs last one
tick, and delayed output validity/initialization is defined explicitly.
- Save graph topology, port keys, node parameters, canvas layout and configured
initial states. Each fresh Test resets to those initial states; transient
button presses, timer state and latch state do not silently become defaults.
- Topology edits require Build. Allow validated constants, thresholds and manual
controls during Test at synchronized boundaries. Copy/paste and assemblies
remap internal references and expose unresolved external sensor/target bindings.
### Foundation acceptance and delivery order
1. **Typed ports:** shared descriptors, typed links, stable serialization keys,
validation and legacy migration. Confirm all declared domains are represented
before mechanical and pneumatic nodes depend on them.
2. **Basic logic:** red Boolean and green Number pins/wires, node canvas, manual
controls, gates, thresholds, sensors, commands and live values.
3. **Stateful control:** timers, latch, edge detection, memory and numeric mapping,
followed by reusable control assemblies and pinned control panels.
Required implementation checks: Bool-to-Bool and Number-to-compatible-Number
connections succeed; Bool/Number mismatches, quantity mismatches, reversed
direction and multiple drivers fail consistently in preview, load and compile.
Also verify fan-out, defaults, unknown port keys, save/load and copy/paste,
ECU migration, invalid math, graph ordering, cycle rejection, delayed feedback,
pause/step behavior and momentary-button release. Core runtime checks now cover
types, wiring validation, evaluation, persistence, faults, delayed feedback and
button-event release/reset. Canvas interactions, live inspector edits, focus/view-
close release, shared selection, pause/step and split layouts now have interaction
and rendered checks. Pinned operator panels and the remaining UI refinements still
need their own acceptance work.
First demonstration: pressure sensor -> hysteresis threshold -> AND with a
manual enable switch -> compressor drive enable. Show tank pressure as a green
Number wire and compressor demand as a red Boolean wire. Follow with a button
and timer driving a pneumatic valve, and a slider commanding a proportional
valve through an explicit range mapping.
## Sensor-driven ECUs
### Current behavior and intended boundary
The current `Ecu::step` receives pedal and the implicit shaft RPM directly.
`Ecu::fuel_for_air` doses fuel from cylinder air mass, and cylinder code supplies
the timing context. There are no general wired MAP, TPS, crank or IAT inputs.
Existing AFR/lambda instruments are ideal transported fuel-origin measurements,
not oxygen-sensor or heater models.
Retain a labeled **Legacy ideal ECU** for migrated machines until equivalent
sensor-driven examples are established. New ECU presets use explicit sensor
inputs, controller calibration and declared actuator targets. Do not disguise
direct cylinder-air-mass access as speed-density or MAF fuel estimation.
### ECU family and minimum connections
Use one shared ECU runtime with selectable strategy/capability presets. Different
picker entries can provide the desired ECU types without duplicating validation,
sensor binding and fault handling. Keep calibration separate from measurements.
| ECU preset | Required measurements in its basic mode | Optional features and their added requirements |
| --- | --- | --- |
| Ignition / carburetor | Crank speed and crank position | MAP or TPS for load-based spark; TPS/driver demand and a commanded throttle for electronic idle. Fuel remains physically supplied by the carburetor. |
| Alpha-N EFI | Crank speed/position and throttle position (TPS) | IAT, engine temperature and barometric corrections; lambda trim; cam phase for sequential operation. Basic mode uses a calibrated RPM/TPS fuel table. |
| Speed-density EFI | Crank speed/position, manifold absolute pressure (MAP), intake air temperature (IAT) | TPS for acceleration enrichment/overrun logic, temperature warm-up correction, barometric correction, lambda trim and cam phase. Requires displacement and volumetric-efficiency calibration. |
| MAF EFI | Crank speed/position and fresh-air mass flow | TPS, MAP, temperature corrections, lambda trim and cam phase. Requires a stated manifold-filling/charge-allocation model; inlet flow is not automatically trapped cylinder charge. |
| Advanced / custom | Required set of the explicitly selected base strategy | Configure supported feature modules; each declares added sensors, targets and fallback behavior. Initially no arbitrary scripting. |
All presets also need declared controlled cylinders/ignition targets; EFI needs
explicit enabled fuel-delivery targets. These are configuration/actuator bindings,
not extra sensor inputs. Engine geometry, firing order, trigger offset, fuel
properties and maps are calibration, not wires.
Basic crank-only modes use supported batch injection and wasted-spark or
distributor timing. Four-stroke sequential injection/individual-cycle ignition
requires cam phase or another explicit cycle-synchronization source. Do not
silently read the simulated cylinder's 720-degree phase to remove that requirement.
Temperature, lambda, TPS and other optional inputs are not universally mandatory.
Features activate their requirements: no TPS means no TPS-based enrichment;
no lambda means open-loop fueling. Fixed reference values are editable and labeled
where a preset supports them. Required base-strategy inputs cannot silently fall
back to hidden physics values. A manual throttle can be used without driver-demand
or throttle-actuation wires; electronic throttle adds its own demand/feedback needs.
The strategy split follows the Speeduino manual's MAP/speed-density and
TPS/Alpha-N distinction. MegaSquirt documentation provides trigger/cam examples
for batch/wasted-spark versus sequential operation. The exact minimum sets above
are proposed simulation presets, not a claim about a particular hardware ECU.
### Sensor placement and representation
| Sensor | Attachment / physical representation | Outputs and scope |
| --- | --- | --- |
| Crank position/speed | Attach to a named shaft, with visible pickup marker and reference offset | Number speed and crank angle; explicit synchronized/valid status. One sensor assembly supplies both. |
| Cam phase | Attach to an explicit cam drive when available; initially a configured phase pickup associated with the engine shaft | Number cycle phase and Boolean synchronized status. The initial pickup is an ideal cycle-reference abstraction, not simulated cam gearing. |
| MAP / pressure | Tap a pipe at normalized arclength or attach to a chamber/plenum | Number absolute pressure. Select the manifold downstream of the throttle; support per-runner or configured combined readings for individual throttles. |
| Differential pressure | Reference two named gas taps | Number pressure difference with labeled positive/reference sides. |
| IAT / gas temperature | Pipe tap or chamber gas attachment | Number temperature; ideal gas reading first, optional lag later. |
| TPS | Attach to throttle/carburetor mechanism | Number actual opening fraction, distinct from commanded opening or pedal demand. |
| Driver demand / pedal | Standalone manual/control part | Number demand fraction; optional for manual-throttle engines. |
| MAF | Pipe tap for an ideal mass-flow sensor; later an inline body if its restriction/storage is modeled | Number signed fresh-air mass flow, with declared reverse-flow behavior. Preserve total-flow instruments as a separate quantity. |
| Lambda | Exhaust pipe/collector attachment | Number lambda plus validity. Start with a labeled ideal mixture tracer; defer wideband oxygen chemistry, heater and response modeling. Closed-loop use requires explicit opt-in to that approximation. |
| Engine/head temperature | Attach to a cylinder/head thermal node when implemented | Number material temperature. Until then use a declared fixed calibration input; cylinder gas temperature is not coolant/head temperature. |
| Barometric pressure | Standalone ambient sensor or tap of an explicitly selected environment boundary | Number absolute pressure; never substitute manifold pressure during running. |
| Fuel pressure | Attach to a fuel rail/circuit once one exists | Number pressure; until then injector pressure is a declared calibration, not a pretend sensor reading. |
| Knock, oil pressure, battery voltage | Future dedicated physical models | Expose only after their state/model exists; do not synthesize plausible readings from unrelated gas variables. |
Sensors are saved entities with stable IDs and host references; their Logic view
nodes refer to those same entities. Store pipe locations by arclength fraction,
not mesh cell index, and chamber/shaft targets by stable identity. Placement must
survive mesh rebuilds, transforms and valid geometry edits. Invalid/deleted hosts
leave visible unresolved bindings rather than silently retargeting another part.
Use **Add sensor** on the selected part or pipe location, then offer only supported
measurements. Attached taps do not consume a gas connection, create storage or
alter flow. A standalone hose-connected pressure sensor has a bidirectional gas
port and real hose/dead volume if included; its Number output is still a filled
green circle. Flow sensors that add a body must explicitly add its losses/volume.
Each sensor exposes measured quantity, units, location, sample time, validity and
optional response/filter settings. Ideal sensors come first; lag, noise, range
limits and fault injection are later options with deterministic initialization.
Existing probes may share sampling code; ECU inputs must not depend on the
instrument UI's eight-channel limit or its lower-rate recording samples.
### Numeric timing inputs and synchronization
ECU measurement inputs are Number rings, including speed, crank angle, MAP,
TPS and temperature. Crank speed and position are separate typed quantities,
not a single overloaded number. Optional Boolean sync/run/kill inputs are red.
An ideal crank pickup outputs phase in a declared 360-degree reference frame and
speed from the same timestamp. Cam reference resolves the four-stroke cycle.
Keep unwrapped rotation/crossing information in the timing subsystem so wraparound
or a crossing within one simulation step cannot lose an ignition/injection event.
Validate coherent sensor provenance and phase offsets against controlled shafts.
A constant RPM or an unrelated shaft sensor is not sufficient timing authority.
The declared ideal timing channel may supply synchronization metadata alongside
the numeric reading; it is not an invisible additional physics-state lookup.
Raw Hall/VR tooth waveforms and missing-tooth decoders are a later fidelity mode.
They need timestamped edge delivery and a decoder that outputs these same typed
measurements; sampling a Boolean once per audio sample must not be assumed to
capture every tooth at high speed. General logic may process speed and angle,
but transformations used for timing must preserve or explicitly invalidate the
phase/time reference. Ordinary stale or incoherent values cause a visible fault.
### Actuation and fuel estimation
- EFI computes fuel demand from the selected sensor strategy and calibration.
Account explicitly for speed-density charge estimates, Alpha-N table meaning,
or MAF manifold filling before assigning fuel to cylinders.
- Initially allow labeled per-cylinder ideal injector targets with explicit fuel
mass commands and delivery timing. Fuel mass/energy enters through that modeled
injection boundary; do not call the old `fuel_for_air` path behind the new ECU.
Separate injector/rail parts can replace that abstraction later.
- Expose per-cylinder fuel dose, spark advance and enable/cut commands with clear
units and scheduling semantics. Numeric advance is an angle before TDC, not an
arbitrary instantaneous spark pulse. Cylinder phase offsets remain calibrated
mechanical relationships used by the timing scheduler.
- ECU outputs and standalone logic must not simultaneously drive an actuator
input. Use an explicit selector/command owner. Multiple sensor consumers are
allowed. Each ECU initially controls cylinders on one crankshaft.
- Loss of required crank synchronization cuts its controlled fuel and spark;
missing optional lambda disables trim. Define preset-specific responses to MAP,
IAT, TPS and MAF faults. Never automatically switch fuel strategy unless an
explicit configured fallback has the required sensors and calibration.
### ECU connector UI and diagnostics
- Show Required, Connected and Optional input groups, with expandable Timing,
Air/load, Temperatures, Mixture and Auxiliary sections. Keep every connected
pin visible; show more optional pins on demand to avoid a wall of connectors.
- Every input displays required/optional status, quantity/unit, current value,
source sensor and any active fallback. Feature selection updates requirements
immediately; hiding a pin does not disconnect it or disable its validation.
- Add an ECU setup checklist: choose preset, assign cylinders/shaft, place required
sensors, connect measurements, assign actuators, verify timing and enable Test.
Offer sensor creation at a selected physical location; never guess a plenum.
- Highlight a sensor's physical marker and its wire when selecting an ECU input.
Show named ports and connection lists for dense ECU layouts; support reroutes
and saved harness groups without merging distinct signals into an untyped bus.
- Diagnose missing input, invalid measurement, synchronization loss, wrong shaft,
incorrect measurement kind/location, target conflicts and uncalibrated maps.
A valid zero RPM while stopped is not a missing sensor or a sensor failure.
- Provide compact status: stopped/cranking/running, synchronized, fueling strategy,
open/closed-loop mixture, active cuts and fallback reason. Retain ring/filled
circle direction shapes and red Boolean/green Number colors throughout.
### Migration and acceptance
Legacy imports initially retain Legacy ideal ECU behavior. Offer a deliberate
**Convert to sensor ECU** workflow that creates/reuses named shaft sensors and
selected TPS/MAP/IAT attachments, preserves geometry, and reports calibration that
cannot be converted. Do not promise an existing ideal-air-mass fuel calibration
will produce equivalent behavior from a newly invented VE or Alpha-N table.
Demonstrations: minimal crank-driven ignition with carburetor; Alpha-N with crank
and TPS; speed-density with crank, MAP and IAT; optional lambda correction using
the declared ideal tracer; independent ECUs for two shafts. Add sequential and
MAF examples only after their prerequisites are complete.
Acceptance includes required/optional input matrices, sensor positioning after
mesh/geometry changes, assembly remapping and host deletion, zero-RPM startup,
phase wrap and event crossings, cam loss, wrong-shaft rejection, stale input and
fault recovery, deterministic pause/step, explicit fuel-mass accounting, actuator
ownership and optional-feature degradation. Compare controller estimates against
physical state diagnostically without feeding that ground truth back secretly.
Planning references:
- [Speeduino overview: supported strategies and trigger inputs](https://wiki.speeduino.com/en/Overview)
- [Speeduino tuning: MAP and air-density/load estimation](https://wiki.speeduino.com/en/tuning/Tuning)
- [MegaSquirt MS3 hardware guide: crank/cam triggering examples](https://www.msextra.com/doc/pdf/MS3XV30_Hardware-1.4.pdf)

258
docs/WORKSHOP_UI_PLAN.md Normal file
View File

@@ -0,0 +1,258 @@
# Workshop UI rework
Design specification, updated 2026-11-01. Implementation status is listed below.
Physical parts, typed signals and ECU requirements are defined in the
[machine systems roadmap](MECHANICAL_BUILDER_PLAN.md).
## Implementation status
The first UI pass implements the dark theme, shared adaptive panel geometry,
resizing/collapse with saved preferences, library search/categories and previews,
an Objects list, a measured inspector with stacked property fields, fitted control
labels and hover disclosure, direct click/drag connections, persistent Run/Pause/
Step controls, navigable checks, and a separate resizable oscilloscope dock.
Existing ECU assignment ports use input rings and filled output circles; gas
ports retain their physical semantics. The Sense inspector now adds physical
sensor taps, unresolved binding repair and per-sample live outputs, using green
Number and red Boolean output dots. Sensor attachments remain locked during Test.
The builder and desktop UI regressions pass. Rendered review covers empty, ECU,
Checks, Meters, running/paused and collapsed layouts at 1920x1080 and 1280x720.
Logic/split views now share the running machine, with a searchable node library,
typed click/drag wiring, reference selection, live values/controls, parameter
inspectors and compact number trends. Input rings/output circles and red Boolean/
green Number colors are checked in rendered output. Thirteen focused suites pass;
graph and split layouts are reviewed at 1920x1080 and 1280x720.
Grouped ECU connectors follow their runtime systems. Automatic DPI/UI scale
overrides, an object hierarchy with
visibility groups, richer property grouping/help and pinned operator controls
remain follow-up UI work. Their design below remains the intended direction.
## Confirmed direction
- Dark engineering editor with compact toolbars, clear panels and restrained
colors. Reserve strong colors for signal types, selection and relevant state.
- Separate **3D** and **Logic** tabs, with an optional split view. Selection and
running simulation are shared across views; camera and canvas navigation state
remain independent. Switching views does not restart Test.
- Connect by dragging between ports or clicking a port then its target. A
dedicated Connect mode is not required. Escape cancels a pending connection.
- Signal inputs are hollow rings; outputs are filled circles. Boolean is red,
Number green. Bidirectional physical ports use neutral domain symbols.
- Panels remain in predictable positions, resize and collapse, and remember
their widths. Provide a reset-layout action and constrain restored sizes to
the current window so the central workspace stays usable.
- The library uses compact rows with small previews, categories and search.
Selecting an item shows a larger preview with its purpose and essential ports.
- Starting Test preserves the current workspace, selection and navigation state.
Lock structural edits while allowing safe live tuning and logic inspection.
- Test starts running. Pause and Step remain visible; Step is enabled when
paused, with a tooltip explaining that state when disabled.
- Primary design target is a 1920x1080 desktop window. The first priority is
consistent appearance and layout, especially preventing text/control overlap.
- Remaining routine design decisions are made autonomously, per user direction.
## Layout and visual baseline
Use a shared layout/component layer rather than individually positioned controls.
Rendering and hit testing consume the same computed rectangles. Define shared
theme values for spacing, typography, surfaces, borders and interaction states.
Initial dimensions below are logical pixels at 100% UI scale, and may be tuned
through visual review while preserving the agreed structure.
| Element | Default |
| --- | --- |
| Spacing | 4 px base unit; 8 px control gaps; 12 px panel padding; 16 px section gaps |
| Typography | 14 px body/fields, 12 px secondary labels, 16 px section titles; measured line height |
| Controls | 30 px minimum row height, increased when text or UI scale requires it |
| Top command bar | 44 px, with less-used file actions in a menu |
| Workspace toolbar | 36 px; 3D/Logic tabs and split toggle stay discoverable |
| Left panel | 260 px default; resizable between 220 and 420 px |
| Inspector | 340 px default; resizable between 280 and 520 px |
| Bottom area | Collapsed initially; 240 px default when opened, vertically resizable |
| Status bar | 24 px minimum; longer messages go to Checks or a tooltip |
| UI scale | Auto from display scaling, plus 100%, 125%, 150% and 200% overrides |
Use a neutral charcoal palette with clear panel boundaries and one restrained
selection accent. Reuse the same fields, buttons, tabs, badges and menus across
all views. Strong red/green remains reserved for the agreed signal types; add
icons/text to distinguish faults and success from those types.
Support a 1280x720 window at 100% scale through a compact layout. As available
logical space shrinks, move secondary toolbar actions into an overflow menu,
collapse the library/object panel, and offer the inspector as a temporary panel.
Preserve access to required actions and readable text instead of shrinking fonts.
If split view cannot fit two usable canvases, use a single tab and explain why
split is unavailable. Large UI scaling follows the same compact behavior.
Choose a vertical split by default: 3D left, Logic right, with a draggable divider
and a swap action. Remember divider position, panel widths/collapse states and
active view in user preferences; clamp them on restore. Store machine-specific
camera/canvas layout separately from physical geometry and signal values.
### Text and overlap rules
- Measure text before layout. Use content-sized rows and explicit minimum sizes;
never assume every property label fits a fixed width.
- Inspector rows place label, value, unit and optional action in separate layout
cells. Narrow inspectors stack labels above fields; units never cover digits.
- Wrap help and diagnostic text and grow the row. Ellipsize long names only in
compact lists/tabs, with the complete name available on hover and in selection.
- Clip rendering and pointer handling to the same panel scroll region. Fixed
headers and footers reserve their own space so scrolling content cannot cover
buttons, tabs or trace controls.
- Tooltips and menus reposition within the window and respect their anchor.
Keep the focused text field visible when scrolling or opening a panel.
- Lay out ECU ports from descriptor rows with adequate label/value space; nodes
grow vertically as ports expand. Wires route away from pin labels before bends.
- World labels use screen-space placement with collision suppression; prioritize
selected/hovered labels and expose the rest on demand. Hidden labels must not
hide the underlying port's tooltip or named connection-list access.
## Workspace structure
Proposed layout: a slim document/command bar, workspace tabs, a left library/object
panel, central workspace, right inspector, and optional bottom diagnostics/traces.
Use resize handles and collapse controls within this predictable layout.
- Top bar: machine name, unsaved status, file actions, undo/redo and simulation
controls. Show current run state unambiguously even in Logic view.
- 3D toolbar: Select, Move, Rotate, Route, snapping and fit/focus. Connection
gestures work directly on visible ports and do not start a transform drag.
- Logic toolbar: node search/add, frame selection/all, connection filters and
live-value visibility. Node creation targets the canvas under the pointer.
- Library: parts, sensors, logic nodes and saved assemblies with search and
categories, displayed as compact rows with small previews. Show a larger
selected-item preview and compatibility when adding from a signal port.
- Objects: named parts, sensors, shafts, ECUs and assemblies. Search, select,
focus, rename and hide without removing simulation membership.
- Inspector: selection identity, grouped properties, connections and contextual
help. Show units next to editable values and explain locked Build properties.
- Bottom area: navigable checks, traces and event history. Selecting an issue
locates the relevant part, port or connection in the appropriate view.
- Status bar: current gesture, keyboard hints and short feedback. Important
failures remain in Checks rather than disappearing with a transient message.
## Core workflows
### Place and configure
Search for a part, select it, preview placement, then click to place. Shift repeats
placement. Escape cancels. Placed parts immediately expose a name and the small
set of essential properties; advanced groups expand on demand. Preserve current
copy/paste, assembly and undo workflows as the UI changes.
For multiple selections show selection count, pivot and mixed values. Edits apply
only to compatible properties; do not display one arbitrary part's value as a
shared value. Selection/focus is synchronized with the object tree and Logic view.
### Connect
Hover highlights a port with name, domain, direction, units and connection state.
Dragging from it or clicking it begins a preview. Compatible targets stand out;
incompatible targets explain the reason. A separate checkmark/cross communicates
validity without overwriting the red/green signal colors.
Keep ring centers easy to pick and port target size readable at any zoom. For
overlapping ports provide a named candidate chooser. Clicking a part body selects
it; hovering a hidden port must not silently steal a move gesture.
Signal connections do not move physical parts. Gas connections keep their current
geometry/snapping rules and show the proposed pipe path before commit. Physical
port alignment errors are visible. Disconnect/reconnect commands are available
from ports and the inspector; all connection edits are undoable.
### Add sensors and configure ECUs
Use Add sensor on a selected part or a specific pipe location. Offer supported
sensor types, show the tap/pickup marker, and create a matching Logic reference.
Selecting either representation reveals its host and measurement location.
ECU inspector groups Required, Connected and Optional inputs by function. Keep
connected ports visible and let optional groups expand. A guided checklist helps
choose a strategy, attach required sensors and assign actuator targets. Every
measurement displays units, source, validity and fallback state.
### Inspect and test
Simulation controls are independent of 3D/Logic tab selection. Distinguish Run,
Pause, Step and Stop/return-to-edit. Show simulation speed and time. Structural
properties explain why editing is locked during Test; safe live tuning shows
its applied value without resetting the machine.
Entering Test does not switch to a different workspace or change selection.
Keep the current 3D camera, Logic canvas and split-view arrangement. Stopping
returns to editing in that same context; live tuning retains existing persistence
and undo behavior. Start running immediately, with Pause and Step available in
the persistent simulation controls.
Hovering a signal reveals its current value; the inspector can pin it to a trace
or control panel. Physical measurements can also be added from the selected part.
Readouts identify the shaft, sensor or port they measure. Missing and invalid
signals never display as an ordinary zero or false state.
## Readability and interaction requirements
- Text and controls respond to window size and UI scaling. Scroll panels rather
than drawing controls outside their bounds; avoid the current fixed-coordinate
overlap risk as parts and properties grow.
- Focused numeric fields accept keyboard edits, units are visible, and invalid
input remains editable with a local explanation. Escape cancels the edit;
shortcuts do not trigger transforms while typing in a field.
- Preserve useful shortcuts, add visible tooltips, and keep camera gestures
separate from node-canvas gestures. Document both in a compact help overlay.
- Selection, warning and disabled states remain legible in the dark theme.
Signal meaning is also conveyed through labels and direction shapes.
- Keep the viewport stable when changing selection. Fit/focus is explicit.
Unrelated panel refreshes must not jump scroll position or steal text focus.
- Keep raw rendering and UI state ownership explicit so panel rendering remains
reliable after 3D drawing. Rendering optimization must preserve hit testing.
## Delivery slices
1. Appearance and layout foundation: shared controls/theme, responsive panels,
typography, text measurement, clipping and consistent input handling. Rework
the existing workshop first so today's parts already have a coherent UI.
2. Descriptor-driven inspector, connection gestures, named ports and filters.
3. Searchable library/object tree, then Logic tab and optional split view with
shared selection, stable node layout and live values.
4. Sensor placement and grouped ECU connector workflow.
5. Integrated test controls, traces, checks and pinned operator controls.
Coordinate these slices with the systems roadmap: UI can display a type only
after document/runtime descriptors define it. Validate layouts at the agreed
minimum window size and scaling, connection picking in dense assemblies, keyboard
focus, save/restore behavior and the same workflows across 3D, Logic and split view.
## Navigation decisions
Keep the existing familiar 3D controls: Alt+left drag or right drag on empty space
orbits, middle drag pans, wheel zooms, F focuses selection and Home fits all.
An actual drag orbits; right click without dragging opens the context menu.
UI interaction consumes input before viewport handling, and text editing captures
its shortcuts. Escape cancels the active gesture before clearing selection.
Logic uses wheel zoom about the pointer and middle drag to pan. Plain left click
selects, Shift modifies selection, and dragging empty canvas makes a selection
rectangle. Drag nodes by their header, ports by their connector and panel sizes
by their divider; the pointer/hover state identifies the pending action.
## First milestone acceptance
Review the existing single-cylinder, flat-six and V8 imports with long names,
multi-selection, pipe route editing, ECU properties, Checks and instruments.
Exercise empty, selected, hovered, disabled, focused, invalid and running states.
At 1920x1080 and 1280x720 at 100% scale, and at representative larger display
scales, verify that text never overlaps unrelated controls, field units remain
readable, panels scroll within bounds and essential commands stay reachable.
Resize while editing, reopen saved panel layouts, expand long property groups
and open menus near window edges. Appearance/layout review is required before
adding the new systems' more complex panels. Later slices repeat this review for
the dense ECU connector view, Logic and split view as they become available.
No further preference decisions are blocking this plan. Implementation will use
these defaults and adjust details through focused visual and interaction review.