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
that accepts the function to call, a named tuple of both the names of and symbolic values representing
440
449
values in the system to be modified, a named tuple of the values that are merely observed (that is, used from
441
450
the system but not modified), and a context that's passed to the affect function.
442
451
443
452
In our example, each event merely changes whether the furnace is on or off. Accordingly, we pass a `modified` tuple
444
-
`(; furnace_on)` (creating a `NamedTuple` equivalent to `(furnace_on = furnace_on)`). `ImperativeAffect` will then
453
+
`(; furnace_on)` (creating a `NamedTuple` equivalent to `(furnace_on = furnace_on)`). `ImperativeAffect` will then
445
454
evaluate this before calling our function to fill out all of the numerical values, then apply them back to the system
446
455
once our affect function returns. Furthermore, it will check that it is possible to do this assignment.
447
456
448
457
The function given to `ImperativeAffect` needs to have one of four signatures, checked in this order:
449
-
*`f(modified::NamedTuple, observed::NamedTuple, ctx, integrator)::NamedTuple` if the function needs the low-level integrator,
450
-
*`f(modified::NamedTuple, observed::NamedTuple, ctx)::NamedTuple` if the function needs the user-defined context,
451
-
*`f(modified::NamedTuple, observed::NamedTuple)::NamedTuple` if the function also reads observed values from the system,
452
-
*`f(modified::NamedTuple)::NamedTuple` if the function only writes values (unknowns or parameters) to the system.
453
-
The `do` block in the example implicitly constructs said function inline. For exposition, we use the full version (e.g. `x, o, i, c`) but this could be simplified to merely `x`.
458
+
459
+
-`f(modified::NamedTuple, observed::NamedTuple, ctx, integrator)::NamedTuple` if the function needs the low-level integrator,
460
+
-`f(modified::NamedTuple, observed::NamedTuple, ctx)::NamedTuple` if the function needs the user-defined context,
461
+
-`f(modified::NamedTuple, observed::NamedTuple)::NamedTuple` if the function also reads observed values from the system,
462
+
-`f(modified::NamedTuple)::NamedTuple` if the function only writes values (unknowns or parameters) to the system.
463
+
The `do` block in the example implicitly constructs said function inline. For exposition, we use the full version (e.g. `x, o, i, c`) but this could be simplified to merely `x`.
454
464
455
465
The function `f` will be called with `observed` and `modified``NamedTuple`s that are derived from their respective `NamedTuple` definitions.
456
-
In our example, if `furnace_on` is `false`, then the value of the `x` that's passed in as `modified` will be `(furnace_on = false)`.
466
+
In our example, if `furnace_on` is `false`, then the value of the `x` that's passed in as `modified` will be `(furnace_on = false)`.
457
467
The modified values should be passed out in the same format: to set `furnace_on` to `true` we need to return a tuple `(furnace_on = true)`.
458
468
We use Setfield to do this in the example, recreating the result tuple before returning it.
459
469
460
-
Accordingly, we can now interpret the `ImperativeAffect` definitions to mean that when `temp = furnace_off_threshold` we
470
+
Accordingly, we can now interpret the `ImperativeAffect` definitions to mean that when `temp = furnace_off_threshold` we
461
471
will write `furnace_on = false` back to the system, and when `temp = furnace_on_threshold` we will write `furnace_on = true` back
Here we see exactly the desired hysteresis. The heater starts on until the temperature hits
@@ -477,71 +488,76 @@ point the furnace turns on again until `furnace_off_threshold` and so on and so
477
488
is effectively regulating the temperature of the plant.
478
489
479
490
### [Quadrature Encoder](@id quadrature)
491
+
480
492
For a more complex application we'll look at modeling a quadrature encoder attached to a shaft spinning at a constant speed.
481
493
Traditionally, a quadrature encoder is built out of a code wheel that interrupts the sensors at constant intervals and two sensors slightly out of phase with one another.
482
494
A state machine can take the pattern of pulses produced by the two sensors and determine the number of steps that the shaft has spun. The state machine takes the new value
483
495
from each sensor and the old values and decodes them into the direction that the wheel has spun in this step.
0 commit comments