You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
* ENH: added discrte and continuous controller functions
* linted rocketpy/rocket/rocket.py
* lint fix return None to return self in discrete controller function
* BUG: fixed cont ctrl calls integrated into the ODE solver
* lint fixes
* lint fix: removed return None
* implemented copilot suggestions
* lint fix, extra spaces
* ENH: merged dis+con and added None for sampling rate of cont
* BUG: copilot comments addressed
* ENH: finalize continuous controller handling
Optimize continuous controller state-history handling to avoid repeated list rebuilding, align controller sampling-rate docs with None-based continuous mode, and add regression coverage to ensure continuous controllers do not create time nodes.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* DOC: update changelog for PR 946
Add unreleased changelog entry for Discrete and Continuous Controllers in PR #946.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* BUG: pass self.solution to continuous controllers for parity with discrete
The continuous-controller path fed the controller a time-stripped
`_controller_state_history` (rows `[x, y, z, vx, vy, vz, ...]`), while the
discrete path (__process_sensors_and_controllers_at_current_node) passes
`self.solution`, whose rows are time-prefixed (`[t, x, y, z, vx, vy, vz, ...]`).
A single controller function therefore received two different state_history
layouts depending on discrete vs continuous mode: index [5] was vy for discrete
but vz for continuous. Controllers written/tuned against the discrete layout
(e.g. the airbrakes example) misbehaved under continuous control -- reading vz
where they expected vy, deployment logic exploded and apogee was crushed.
Pass `self.solution` directly, matching the discrete path exactly. This makes
the two paths behaviorally identical, removes the parallel _controller_state_history
list (and its per-step append / initialization), and is O(1) per step.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
* MNT: add _Controller.is_continuous and fix prints for continuous controllers
- Add a single `_Controller.is_continuous` property (sampling_rate is None) and
use it as the one source of truth for the continuous/discrete dispatch in
Flight (__init_controllers and time-node creation), replacing two duplicated
`sampling_rate is None` checks.
- Fix _ControllerPrints.controller_function(): `f"{sampling_rate:.3f}"` raised
TypeError for continuous controllers (sampling_rate=None). Print
"continuous (every solver step)" instead.
- __str__ now reads "with continuous sampling." instead of "... None Hz."
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
* DOC: correct state_history contract for controller functions
The state_history handed to controller functions is `Flight.solution`, whose
rows are TIME-PREFIXED `[t, x, y, z, vx, vy, vz, ...]` -- one leading time
element ahead of the `state` layout, and the last row is the most recent
recorded step (not the "previous" state). The docstrings previously described
the rows as bare state vectors `[x, y, z, ...]` with `[-1]` as the previous
state, an off-by-one-column contract that silently breaks controllers (this
is what caused the airbrakes continuous-mode misbehavior). Also document that
`sampling_rate` is None for continuous controllers.
Updated in _Controller.__init__, _Controller.__call__, and
Rocket.add_air_brakes controller docstrings.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
* TST: cover continuous controller per-step invocation and state_history layout
Adds an integration test that runs a real flight with a continuous air-brakes
controller (sampling_rate=None) and asserts it is invoked on every solver step
(>50 calls), always receives sampling_rate=None, and receives time-prefixed
state_history rows (len == len(state)+1) -- the same layout as the discrete
path. Previously only node-skipping was covered; per-step invocation was not.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
* MNT: satisfy ruff format and pylint in CI lint job
- flight.py: collapse the _continuous_controllers comprehension to one line
(ruff format --check).
- test_flight.py: drop the useless `return None` at the end of the recording
controller (pylint R1711).
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
---------
Co-authored-by: Gui-FernandesBR <guilherme_fernandes@usp.br>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
0 commit comments