You could abstractly structure the computation as a graph (there are many concrete approaches to that) and only recompute the parts that change due to changed input or changed intermediate results.
If you have multiple outputs you can also have a scheduling/prioritization system for the subtasks.
And yes, use interrupts or multiple timers to detect only changed parts without having to compare current input to previous input.
It's basically the same problem as updating a browser DOM in response to application state changes.
Right, but since you typically want timing guarantees (for example, "respond to change in measured acceleration within 20ms"), you'd often end up structuring and resourcing everything for the worst case (everything needs to be computed) anyways... which means that your graph optimization didn't end up saving any resources.
Also, there sometimes ARE interrupts meshed in with these main loop based systems (for whatever reason). They just aren't predominant. If your willing to through more hardware at things, you can typically always transform anything into a buffer.
That pretty well describes the board in front of me ATM. Most of the system runs on a 20ms (I think) tick to manage the sensor read/evaluate/control loops, but there's a 10kHz timer interrupt always going that handles commutation of a stepper motor if it needs to run. 99.9% of the time, the interrupt fires, sees there's nothing to do and just returns.
for battery electric use cases it saves energy: you do just the necessary computations and you sleep the CPU until the next cycle. if little has changed you can sleep a lot. if a lot of rumpus is happening, you use the full cycle.
Remind me not to drive a vehicle where you implemented the control systems.
This is a great example of a little knowledge being dangerous. There's a reason control systems are not implemented the same way as a browser DOM. There's a reason control systems are designed to avoid subtasks, conditional execution, interrupts (as much as possible) and complex data models. The reasons are pretty damn solid, IMO.
Conceptually, you can talk about the two domains as being somehow equivalent. That says nothing about the appropriate implementations.
No, as in a the graph starts from nodes corresponding to sensor inputs, with edges going to nodes that represent computations based on those, to further computations, to the outputs that drive actuators.
If only one sensor input changes then intermediate computations that don't depend on it don't need to be updated.
Right. I can see how that could be useful in some situations but presumably it wouldn't work very well for a very dynamic situation like a rocket in flight (changing height, orientation, fuel, thrust every millisecond)
And you still need a control loop to look for sensor changes? Its just a way of caching most of the computation?
It can work well for dynamic event-driven problems, with no need for a central busy loop[1]. Any sensor changes are responsible for triggering an update in any nodes that depend on it, who are responsible for triggering nodes that depend on those, and so on. One way to do it: abstract class Node, which has a list of child nodes that it loops through and alerts whenever there's been a state change in the parent node.
[1] There is a busy loop but it's only there to trigger tasks on a timer.
I’ve never seen this implemented well in a real-time setup. I’ve come to associate it with everything falling apart and otherwise being taped together in weird ways to function.
It sounds elegant, but I’m not convinced there’s a benefit to a model of abstractions of abstractions like this unless it’s done at the language level. In practice, I’ve only seen this produce a web of race conditions, performance issues, and system complexity. My experience is anecdotal.
One reason why this is dangerous is that you can see extremely large changes in the CPU load. For a bunch of cycles, there's apparently nothing to do, then there's a whole bunch of stuff to do, then there's almost nothing etc.
This makes it hard to reason about the overall capacity of the system (in terms of numbers of sensors and actuators). You will always end up uncertain whether you've ever really evaluated the "full load" condition, even if you formally test it in ways that say you have.
If you have multiple outputs you can also have a scheduling/prioritization system for the subtasks.
And yes, use interrupts or multiple timers to detect only changed parts without having to compare current input to previous input.
It's basically the same problem as updating a browser DOM in response to application state changes.