Skip to content

ENH: Controller Implementation Refactor - #1065

Draft
MateusStano wants to merge 15 commits into
enh/eventsfrom
enh/control-refactor
Draft

ENH: Controller Implementation Refactor#1065
MateusStano wants to merge 15 commits into
enh/eventsfrom
enh/control-refactor

Conversation

@MateusStano

Copy link
Copy Markdown
Member

TBD

MateusStanoand others added 15 commits June 22, 2026 21:55
- _ControllerPrints read the removed 'interactive_objects' attribute, so
controller.info()/all_info() raised AttributeError; renamed to
controlled_objects() reading controller.controlled_objects.
- Event docstring and event_usage.rst claimed context keys are unpacked
into the callback kwargs, but Event.__call__ never does that; access is
via kwargs['event'].context.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
… tracking
A Controller is now a public Event subclass (periodic, trigger-less,
changes_dynamics, priority 3) instead of a private wrapper around one.
This removes the mirrored enabled/log/context state and fixes the
context-lifecycle bug where the dict mutated by the controller function
diverged from the event context reset between flights.
- After every execution the controller snapshots the control_state of
each controlled object into control_history; recorded_schedule exposes
it as Functions of time for prints/plots and open-loop replay.
- New ControlledObject protocol (control_state/set_control/_reset), not
surface-specific so future TVC actuators can conform.
- ControllableGenericSurface gains initial_control_state and _reset();
AirBrakes inherits them. Controller.reset() restores every tracked
object, generalizing the airbrakes-only reset previously in Flight.
- Positional controller_function signatures are now rejected with a
migration error; the add_air_brakes legacy shim is the only remaining
compatibility path (DeprecationWarning).
- _Controller removed from the public API; new Flight.controllers
property; new _ControllerPlots.control_history plot and richer
controller prints.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Covers Event integration, callback kwargs injection, positional-signature
rejection, automatic control-state history and recorded_schedule
interpolation, context/history/object reset semantics, controlled-object
rebinding, and to_dict/from_dict round trips.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…llable_surface
- SurfaceController(Controller) validates its controlled objects are
ControllableGenericSurface instances and exposes .surfaces; tracking
and reset stay in the base so future non-surface controllers (TVC)
need no changes here.
- AirBrakesController(SurfaceController) pins the 'air_brakes' friendly
name, exposes .air_brakes and .deployment_level_history (Function of
time), and ships deployment-focused prints/plots.
- Rocket.add_air_brakes now builds an AirBrakesController; pure **kwargs
controller functions are passed through unwrapped, hybrid and legacy
positional signatures keep the (deprecation-warned) wrapper.
- New Rocket.add_controllable_surface wires surface(s) into
aerodynamic_surfaces and registers a SurfaceController, resolving the
previously dangling docstring references.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Air brakes now join rocket.aerodynamic_surfaces and are summed in the
standard generic-surface loop of all u_dot variants, instead of the
dedicated drag-only branch in _aerodynamic_drag_force.
- add_air_brakes gains a position parameter. Without it, the force
application point is pinned to the center of dry mass (zero moment
arm), matching historical results; the pin survives add_motor because
__evaluate_single_surface_cp_to_cdm short-circuits on the sentinel.
With an explicit position, deployed brakes produce proper moments at
angle of attack.
- The airbrake cD is now 0 at deployment level 0 unconditionally;
override_rocket_drag became a body-drag suppression branch (body drag
applies while brakes are retracted, is replaced by the surface-loop
airbrake drag while deployed).
- Result note: drag is now decomposed along the freestream like every
other surface, adding small lateral components at nonzero incidence
(previously pure axial).
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
- AirBrakes surface: deployment-0 => cD 0 (incl. override mode), curve
passthrough, incidence/rate independence, clamp on/off parity with the
integration tests, reset protocol, serialization round trip.
- Rocket wiring: surface-loop membership, cp pinned to CDM surviving
add_motor, explicit-position path, static-margin invariance, legacy
signature deprecations, add_controllable_surface wiring (with surface
validation moved before add_surfaces for a clear error).
- Derivatives without Flight: body-drag suppression semantics and force
equivalence of the surface-loop path with the legacy drag formula.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
- New ScheduledController replays a control schedule open-loop via
set_control (clamping applies); ScheduledController.from_controller
rebuilds a flight's control inputs from a recorded control_history.
- Controller.to_dict now records needs and the controlled objects' names
(controlled_objects_ref), plus the control_history under
include_outputs; from_dict restores them, and falls back to a
ScheduledController (with a warning) when the pickled controller
function cannot be decoded but a history is available.
- Rocket.from_dict rewires controllers to the decoded surfaces by name,
replacing the dead _interactive_objects_hash path that raised
AttributeError on every load of a rocket with controllers.
- Air brakes are serialized once, inside aerodynamic_surfaces (the
air_brakes key is dropped from Rocket.to_dict and rebuilt on load,
preserving instance identity with the controller); legacy files with
only the air_brakes key still load, pinned to the CDM. The pin flag
round-trips via AirBrakes.to_dict.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…texts
- Per-sample controllers are rebuilt as AirBrakesController with a deep
copy of the base context, so nested mutables (observed-variable lists)
are no longer shared across Monte Carlo samples.
- Sampled air brakes are wired through Rocket._attach_air_brakes so they
join the aerodynamic surface loop (a plain list append would leave
them with zero drag under the unified force path); add_air_brakes
accepts an optional position forwarded to each sample.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
- airbrakes.rst: kwargs controller contract, deprecation of positional
signatures and initial_observed_variables, position parameter,
automatic deployment tracking and plots, replay section.
- event_usage.rst: note that controllers are Event subclasses.
- Reference stubs for Controller, SurfaceController,
AirBrakesController and ScheduledController.
- CHANGELOG entries for the controller refactor (also includes the
pre-existing uncommitted entries for the reduced-rates change and the
center_of_pressure removal from earlier branch work).
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Resolve ScheduledController dynamically in the from_dict fallback so the
module graph stays acyclic (scheduled_controller already imports
controller at top level).
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Introduce Effector/GenericEffector and Rocket.add_effector: a non-aerodynamic
control path that injects a body-frame force and/or moment directly into the
equations of motion, driven by the existing Controller.
- New rocketpy/rocket/effector package (Effector base implementing the
ControlledObject protocol + GenericEffector with user force/moment callables).
- Rocket gains an effectors registry, effectors_cp_to_cdm moment arms,
add_effector(...) (optionally wiring a Controller), and save/load support;
effectors are excluded from the aerodynamic-surface / stability-margin math.
- flight_derivatives sums effector force+moment in u_dot and u_dot_generalized
(force only in 3-DOF); guarded so effector-free flights are unchanged.
- Exports plus unit tests and a slow roll-damper integration test.
Also fix compute_needs_union so a controller/event that self-enables via
enable_on while declaring needs gets its expensive kwargs on the enabling node.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@MateusStanoMateusStano self-assigned this Jul 11, 2026
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant

@MateusStano