Enh/tank geometry fluid density#72
Conversation
Exposes structured drawing geometry that mirrors rocketpy.Rocket.draw(), so clients can redraw a rocket using the same shape math rocketpy uses without server-side rendering or duplicated geometry logic in the UI. Response carries per-surface shape_x/shape_y arrays, body tube segments, motor patch polygons (nozzle, chamber, grains, tanks, outline), rail button positions, sensors, t=0 CG/CP, and drawing bounds. Coordinates are already transformed into the draw frame rocketpy uses. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Align MotorModel and MotorTank with RocketPy's actual constructor requirements so invalid motors are rejected at the API boundary with a clear error rather than crashing deep inside RocketPy at simulate time. - MotorModel.validate_dry_inertia_for_kind: SOLID / LIQUID / HYBRID motors in RocketPy require dry_inertia with no default. Only GenericMotor accepts (0, 0, 0). Reject the default tuple for every kind except GENERIC with a message the user can act on. - MotorTank.discretize: change to Optional[int] = 100 to match the RocketPy Tank classes' default. Forms can now omit the field and still submit successfully. - stub_motor_dump fixture: use dry_inertia=[0.1, 0.1, 0.1] so tests that override motor_kind to SOLID / LIQUID / HYBRID still pass the new validator without each having to add a dry_inertia override locally.
RocketPy's rocket.draw() does not draw a combustion chamber for GenericMotor because _MotorPlots._generate_combustion_chamber reads grain-only attributes (grain_initial_height, grain_outer_radius, etc.) that GenericMotor lacks — it only emits a nozzle. Users who populate chamber_radius / chamber_height / chamber_position then saw no chamber in the jarvis playground. Add a GenericMotor branch in RocketService._build_motor_geometry that constructs an equivalent rectangular chamber patch from the chamber_* fields. Vertex ordering mirrors _generate_combustion_chamber so the patch flows through _generate_motor_region for outline assembly the same way a SolidMotor chamber does. Patch is emitted with role='chamber', flowing through the existing drawingMotorSchema + GeometryRocket renderer without frontend changes.
…nh/rocket-drawing-geometry
…eneric kinds Two related fixes surfaced during jarvis form refactor. 1. MotorModel.burn_time: float → Optional[float] = None. RocketPy's LiquidMotor / HybridMotor / SolidMotor all auto-detect burn_time from the thrust_source array span — forcing clients to supply it was wrong. GenericMotor still requires it; the service now raises a 422 at the API boundary when the GENERIC path receives None, instead of letting rocketpy error deeper in construction. 2. MotorService.from_motor_model: nozzle_position previously landed in motor_core only for the GenericMotor branch; Liquid / Hybrid / Solid silently ignored the user's value and took rocketpy's default of 0. Now forwarded via motor_core for every kind (conditionally, so a null still falls back to rocketpy's default). Removed the redundant nozzle_position kwarg on the GenericMotor constructor call. 3. Optional-forwarding convention: motor_core only carries burn_time / nozzle_position when the client actually supplied them, so rocketpy picks its own default otherwise instead of receiving None for number-typed args. Verified against real rocketpy: - LIQUID, burn_time=None → LiquidMotor auto-detects burn window - LIQUID, burn_time=2.0 → LiquidMotor builds with explicit window - LIQUID, nozzle_position=0.3 → LiquidMotor.nozzle_position == 0.3 - LIQUID, nozzle_position=None → LiquidMotor.nozzle_position == 0 - GENERIC, burn_time=None → 422 'burn_time is required for generic motors.' All 173 unit tests pass.
… guard Paired API-side work for the jarvis tank/fluid migration (branch feat/tank-fluid-schema-migration in jarvis-ts). Mirrors what that repo now sends on the wire: Schema (src/models/sub/tanks.py): - MotorTank.geometry is a discriminated union on geometry_kind: * custom → legacy piecewise (TankGeometry) * cylindrical → CylindricalTank(radius, height, spherical_caps) * spherical → SphericalTank(radius) - TankFluids.density accepts float or List[(T_K, rho)] temperature samples; pressure dependence deferred. - New validate_tank_kind_fields model_validator mirrors the validate_dry_inertia_for_kind pattern from motor.py — rejects payloads whose tank_kind omits required kind-specific fields at the API boundary with a kind-named 422 instead of letting rocketpy crash deeper in construction. - discretize is now optional (defaults to 100). Service (src/services/motor.py): - _build_rocketpy_tank_geometry dispatches on geometry_kind to TankGeometry/CylindricalTank/SphericalTank. - _build_rocketpy_fluid instantiates a real rocketpy.Fluid and wraps sampled density in a 1D Function-of-temperature callable; scalars pass through. (Eliminates the duck-typed Pydantic-into-rocketpy pattern that worked by accident.) Inverse path (src/services/flight.py): - _extract_fluid_density collapses Function-valued density back to a scalar at rocketpy's reference state (273.15 K, 101325 Pa) — lossy round-trip is documented; samples-roundtrip not supported in this iteration. - Geometry inverse always emits the 'custom' segment list shape; all three rocketpy geometry subclasses expose a piecewise .geometry dict so one code path covers them uniformly. Tests: - test_motors_route.py: 8 new cases covering each geometry_kind, sampled density, invalid discriminator, and all four tank_kind guard paths (MASS / MASS_FLOW / LEVEL / ULLAGE missing sub-fields). - tests/unit/test_services/test_motor_service.py: new suite exercising the adapter end-to-end against real rocketpy for each geometry×variant combination plus sampled density roundtrip. Routes (src/routes/motor.py): - POST /motors docstring gained an example payload showing the discriminated geometry union and sampled density shape. Gitignore: - Added .context and .pylint.d/ to keep local tooling artifacts out of the tree. Full suite: 173/173 pass.
|
Important Review skippedDraft detected. Please check the settings in the CodeRabbit UI or the ⚙️ Run configurationConfiguration used: defaults Review profile: CHILL Plan: Pro Plus Run ID: You can disable this status message by setting the Use the checkbox below for a quick retry:
✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
…luid-density # Conflicts: # src/services/motor.py # src/services/rocket.py # src/views/rocket.py
…n tests pylint W0613 (unused-argument) on 5 schema-validation tests failed the build step (pylint exit 4), blocking this PR and the stacked KML PR #73. These tests only assert a 422 from schema validation, so they never touch the controller; and mock_controller_instance is @pytest.fixture(autouse=True), so it still runs for every test regardless — the parameter was vestigial. No behavior change. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
CI unblocked ✅ — and why this PR matters for the Jarvis betaPushed a small commit that gets the build green again: the Why this is on the critical path: the Jarvis web client's motor wire-schema was written against this PR's tank model. Against Remaining (your call, @aasitvora99): mark this out of draft → merge → then #73 (stacked on this) → and deploy to — pushed as part of a Claude Code audit of the beta (Gui). |
No description provided.