Skip to content

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

Description

@ocots

Raising this as a question rather than a proposal — I hit it while writing flow-API tests for OptimalControl.jl and could not tell whether the current behaviour is intended.

What happens today

is_autonomous removes the time argument uniformly across the three control-law kinds. Measured on a Fixed, variable-free OCP (CTBase 0.28):

kind is_autonomous=true is_autonomous=false
OpenLoop u() u(t)
ClosedLoop u(x) u(t, x)
DynClosedLoop u(x, p) u(t, x, p)

The rule is consistent. Its consequence for OpenLoop is that the autonomous form takes no arguments, since time is the only thing an open loop depends on:

Flow(ocp, OpenLoop(t -> 0.0))                        # MethodError at integration time
Flow(ocp, OpenLoop(() -> 0.0))                       # ok — a constant control
Flow(ocp, OpenLoop(t -> 0.0; is_autonomous=false))   # ok — u(t)

Why I am asking

OpenLoop(t -> 0.0) reads as obviously correct, and the failure is a bare MethodError raised when the flow is run, not when the law is constructed — so the mistake surfaces some distance from its cause:

MethodError: no method matching (::var"#6#7")()

Two readings seem possible, and I do not have a view on which is right:

  • The trait is the invariant. is_autonomous means "does not read t", uniformly, and OpenLoop is simply the degenerate case where that leaves nothing. An autonomous open loop is a constant, which is a coherent thing to be able to express.
  • The kind is the invariant. OpenLoop means u(t) by definition, so t would always be passed and is_autonomous would not apply to this kind (or would be rejected for it).

Whichever way it settles, a construction-time check or a MethodError that mentions the expected arity would make the current behaviour much easier to discover.

Context

Found while writing test/suite/flows/test_flow_api.jl in control-toolbox/OptimalControl.jl#826, which now pins the table above so the answer — whatever it is — stays pinned.

🤖 Generated with Claude Code

Metadata

Metadata

Assignees

Labels

No labels
No labels

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions