Skip to content

fix(data): OpenLoop is unconditionally non-autonomous - #523

Merged
ocots merged 1 commit into
mainfrom
fix/openloop-drop-time-dependence-515
Jul 30, 2026
Merged

fix(data): OpenLoop is unconditionally non-autonomous#523
ocots merged 1 commit into
mainfrom
fix/openloop-drop-time-dependence-515

Conversation

@ocots

@ocots ocots commented Jul 30, 2026

Copy link
Copy Markdown
Member

Summary

is_autonomous currently strips the time argument uniformly across all three control-law kinds.

For OpenLoop, since t is the only possible argument, the default (is_autonomous=true) built a zero-argument natural call u(), so OpenLoop(t -> 0.0) silently constructed a law that only failed with a bare MethodError once a flow was later integrated — not at construction.

Autonomy is a property of the OCP, not of the control — an open-loop control for an autonomous OCP can still depend on time. OpenLoop's natural call is now unconditionally u(t) (or u(t, v)).

  • OpenLoop's TimeDependence is fixed to Traits.NonAutonomous. This is not hidden: Traits.time_dependence/Traits.is_autonomous on an OpenLoop control law still answer normally — always NonAutonomous/false.
  • is_autonomous is kept in OpenLoop's signature purely as a misuse detector, defaulting to the CTBase.Core.NotProvided sentinel. Passing it explicitly (true/false) emits an @warn and has no effect.
  • The low-level typed constructor ControlLaw(f, Traits.OpenLoopFeedback, Traits.Autonomous, VD) now raises Exceptions.IncorrectArgument instead of silently building an uncallable law.
  • ClosedLoop/DynClosedLoop are unaffected — is_autonomous remains a real choice for those.
  • Base.show for OpenLoop drops the now-meaningless time-dependence label.

Version bumped to 0.28.9-beta; CHANGELOG.md and BREAKING.md updated with migration notes.

Fixes #515.

Test plan

  • test/suite/data/test_control_law.jl — updated for the new contract (no is_autonomous on OpenLoop, always u(t)), plus new coverage for the misuse-warning (Test.@test_logs) and the rejected typed-constructor combo.
  • test/suite/data/test_composed_hamiltonian.jl, test/suite/data/test_composed_vector_field.jl — updated zero-arg OpenLoop closures to t -> ....
  • docs/src/guide/data.md, docs/src/guide/traits.md — narrative + executed examples updated.
  • Full suite green: 4964/4964.

🤖 Generated with Claude Code

is_autonomous stripped the time argument uniformly across all three
control-law kinds; for OpenLoop that made the default build a zero-argument
u(), so OpenLoop(t -> 0.0) silently constructed a law that only failed with
a bare MethodError once a flow was integrated, not at construction.

Autonomy is a property of the OCP, not of the control, so OpenLoop's natural
call is now always u(t) (or u(t, v)). is_autonomous is kept as a
misuse-detector keyword only (warns, no effect); the typed constructor
rejects the (OpenLoopFeedback, Autonomous) combination outright.

Fixes #515.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
@ocots
ocots merged commit 4998c81 into main Jul 30, 2026
3 checks passed
@ocots
ocots deleted the fix/openloop-drop-time-dependence-515 branch July 30, 2026 08:19
@ocots ocots mentioned this pull request Jul 30, 2026
Sign up for free to 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.

Should an autonomous OpenLoop control law take no argument at all?

1 participant