From e8d84b3fbfa3036c98c766fa2acd770d5d4e49b0 Mon Sep 17 00:00:00 2001 From: "Edward A. Lee" Date: Thu, 11 Jan 2024 11:55:07 -0800 Subject: [PATCH 1/2] Added watchdog example --- examples/C/README.md | 5 +- examples/C/src/watchdog/README.md | 27 ++++++ examples/C/src/watchdog/Watchdog.lf | 115 +++++++++++++++++++++++ examples/C/src/watchdog/img/Watchdog.png | Bin 0 -> 13111 bytes 4 files changed, 145 insertions(+), 2 deletions(-) create mode 100644 examples/C/src/watchdog/README.md create mode 100644 examples/C/src/watchdog/Watchdog.lf create mode 100644 examples/C/src/watchdog/img/Watchdog.png diff --git a/examples/C/README.md b/examples/C/README.md index e9fd4742..67f1fd7e 100644 --- a/examples/C/README.md +++ b/examples/C/README.md @@ -1,7 +1,7 @@ # C Examples * [Patterns](src/patterns/README.md): Common communication patterns. * [Deadlines](src/deadlines/README.md): Uses of deadlines in Lingua Franca. -* [Car Brake](src/car-brake/README.md): Sketch of ADAS system illustrating CAL theorem. +* [Car Brake](src/car-brake/README.md): Sketch of ADAS system illustrating the CAL theorem. * [Rosace](src/rosace/README.md): Aircraft controller illustrating periodic systems with multiple periods. * [Simulation](src/simulation/README.md): Using Lingua Franca for simulation. * [Keyboard](src/keyboard/README.md): Responding to keyboard input using ncurses. @@ -10,4 +10,5 @@ * [Rhythm](src/rhythm/README.md): Sound generation and terminal user interface demos. * [SDV](src/sdv/README.md): Software defined vehicle sketch integrating user input, a web display, and sound. * [Train Door](src/train-door/README.md): Train door controller from a verification paper. -* [Distributed](src/distributed/README.md): Basic federated hello-world examples. \ No newline at end of file +* [Distributed](src/distributed/README.md): Basic federated hello-world examples. +* [Watchdog](src/watchdog/README.md): Federated illustration of watchdogs. diff --git a/examples/C/src/watchdog/README.md b/examples/C/src/watchdog/README.md new file mode 100644 index 00000000..c788c153 --- /dev/null +++ b/examples/C/src/watchdog/README.md @@ -0,0 +1,27 @@ +# Watchdog -- Reacting to Absent Inputs + +The LF deadline handlers react to inputs that are late. +What if you want to react the fact that an input has _not_ arrived by a certain time? +The deadline construct, by itself, will not do this. +It does not react until an input actually arrives. + +The watchdog construct provides a mechanism for this. +A watchdog is started using `lf_watchdog_start` at some logical time _t_. +It will expire at _physical_ time _t_ + _W_, where _W_ is the watchdog delay, +unless it gets restarted with `lf_watchdog_start` or stopped using `lf_watchdog_stop` +before that physical time elapses. + +When a watchdog expires, two things happen. First, the watchdog handler is invoked. +Second, an event identified by the name of the watchdog is scheduled at the earliest +available tag (typically the current tag plus one microstep). +The watchdog handler is invoked asynchronously, and therefore has limited access +to the reactor's infrastructure, such as inputs and outputs. +However, the scheduled watchdog event can trigger an ordinary reaction +which has full access to the state variables and inputs and outputs of the reactor. + + + + + +
Watchdog + Watchdog.lf: Illustration of the use of the watchdogs in LF.
\ No newline at end of file diff --git a/examples/C/src/watchdog/Watchdog.lf b/examples/C/src/watchdog/Watchdog.lf new file mode 100644 index 00000000..581b17df --- /dev/null +++ b/examples/C/src/watchdog/Watchdog.lf @@ -0,0 +1,115 @@ +/** + * @brief Demonstration of watchdogs in LF. + * + * This program has a periodic source that triggers events every 500 ms, + * but where every fourth event is delayed before being delivered to the + * downstream Watcher. This delay models either communication or + * computation time. + * + * The Watcher has a deadline of 200 ms. It wants to see events within + * 200 ms of their logical time, but, because of the delay every fourth event, + * the deadline will be violated. The deadline violation handler is invoked + * in this case, but it is only invoked after the event arrives, which is late. + * What if we need to react to the deadline violation sooner, e.g. in order to + * drive an actuator? + * + * To handle this, the Watcher includes watchdog named "dog" that triggers if + * any input event is more than 250 ms late. + * + * @author Benjamin Asch + * @author Edward A. Lee + */ +target C { + timeout: 5 s +} + +reactor SometimesSlowSource { + output out: int + // Offset ameliorates startup time. + timer t(500 ms, 500 ms) + state count: int = 1 + reaction(t) -> out {= + if (self->count % 4 == 0) { + // Be slow. + lf_sleep(MSEC(300)); + } + lf_set(out, self->count++); + =} +} + +reactor Watcher { + input in: int + output out: int + state count: int = 1 + logical action a(500 ms) + + watchdog dog(750 ms) {= + instant_t p = lf_time_physical_elapsed(); + lf_print("******** Watchdog timed out at elapsed physical time: " PRINTF_TIME, p); + =} + + reaction(in) -> dog, out {= + // Reset the watchdog. The next event is expected in 500 ms. + // This watchdog will trigger if the event does not arrive within 750 ms from now, + // or is more than 250 ms late. + lf_watchdog_start(dog, 0); + lf_print("Watchdog started at physical time " PRINTF_TIME, lf_time_physical_elapsed()); + lf_print("Will expire at " PRINTF_TIME, lf_time_logical_elapsed() + MSEC(750)); + lf_set(out, in->value); + self->count++; + =} deadline (200 ms) {= + // This input is more than 200 ms late. It must have been from the slow cycles. + lf_print("Watcher received late input %d. Ignoring it.", in->value); + =} + + reaction(dog) -> a {= + // Note that this reaction will trigger at the earliest available tag, which + // will be one microstep later than the most recent input or watchdog violation. + lf_print("******** Watchdog triggered. Scheduling output for next logical time."); + // Use a logical action so that the logical time of the output aligns. + lf_schedule(a, 0); + =} + + reaction(a) -> out, dog {= + lf_print("******** Backup output being produced."); + lf_set(out, self->count++); + // Start another watchdog cycle in case the very next input is also delayed. + lf_watchdog_start(dog, 0); + lf_print("Watchdog started at physical time " PRINTF_TIME, lf_time_physical_elapsed()); + lf_print("Will expire at " PRINTF_TIME, lf_time_logical_elapsed() + MSEC(750)); + =} + + reaction(shutdown) -> dog {= + lf_watchdog_stop(dog); + =} +} + +reactor Checker { + input in: int + state count: int = 1 + reaction(in) {= + lf_print("Checker received %d at logical time " PRINTF_TIME + " and physical time " PRINTF_TIME, in->value, + lf_time_logical_elapsed(), + lf_time_physical_elapsed()); + if (in->value != self->count) { + lf_print_error_and_exit("Expected %d", self->count); + } + self->count++; + =} + reaction(shutdown) {= + if (self->count < 10) { + lf_print_error_and_exit("Received %d inputs. Expected at least 10.", self->count); + } + =} +} + +federated reactor { + + s = new SometimesSlowSource() + w = new Watcher() + c = new Checker() + + s.out -> w.in + w.out -> c.in +} diff --git a/examples/C/src/watchdog/img/Watchdog.png b/examples/C/src/watchdog/img/Watchdog.png new file mode 100644 index 0000000000000000000000000000000000000000..3bb720f593ef06a98f2696756e90440d12b83f60 GIT binary patch literal 13111 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 Tl_l^(42GJLmLf{tJox_uZkIS$ literal 0 HcmV?d00001 From 4209c4f6baaa1ed688135a1f006845c70e2f5006 Mon Sep 17 00:00:00 2001 From: "Edward A. Lee" Date: Thu, 11 Jan 2024 12:59:15 -0800 Subject: [PATCH 2/2] Format --- examples/C/src/watchdog/Watchdog.lf | 43 ++++++++++++++--------------- 1 file changed, 21 insertions(+), 22 deletions(-) diff --git a/examples/C/src/watchdog/Watchdog.lf b/examples/C/src/watchdog/Watchdog.lf index 581b17df..8d0db5ef 100644 --- a/examples/C/src/watchdog/Watchdog.lf +++ b/examples/C/src/watchdog/Watchdog.lf @@ -1,21 +1,19 @@ /** * @brief Demonstration of watchdogs in LF. - * - * This program has a periodic source that triggers events every 500 ms, - * but where every fourth event is delayed before being delivered to the - * downstream Watcher. This delay models either communication or - * computation time. - * - * The Watcher has a deadline of 200 ms. It wants to see events within - * 200 ms of their logical time, but, because of the delay every fourth event, - * the deadline will be violated. The deadline violation handler is invoked - * in this case, but it is only invoked after the event arrives, which is late. - * What if we need to react to the deadline violation sooner, e.g. in order to - * drive an actuator? - * - * To handle this, the Watcher includes watchdog named "dog" that triggers if - * any input event is more than 250 ms late. - * + * + * This program has a periodic source that triggers events every 500 ms, but where every fourth + * event is delayed before being delivered to the downstream Watcher. This delay models either + * communication or computation time. + * + * The Watcher has a deadline of 200 ms. It wants to see events within 200 ms of their logical time, + * but, because of the delay every fourth event, the deadline will be violated. The deadline + * violation handler is invoked in this case, but it is only invoked after the event arrives, which + * is late. What if we need to react to the deadline violation sooner, e.g. in order to drive an + * actuator? + * + * To handle this, the Watcher includes watchdog named "dog" that triggers if any input event is + * more than 250 ms late. + * * @author Benjamin Asch * @author Edward A. Lee */ @@ -25,9 +23,9 @@ target C { reactor SometimesSlowSource { output out: int - // Offset ameliorates startup time. - timer t(500 ms, 500 ms) + timer t(500 ms, 500 ms) // Offset ameliorates startup time. state count: int = 1 + reaction(t) -> out {= if (self->count % 4 == 0) { // Be slow. @@ -35,7 +33,7 @@ reactor SometimesSlowSource { } lf_set(out, self->count++); =} -} +} reactor Watcher { input in: int @@ -57,7 +55,7 @@ reactor Watcher { lf_print("Will expire at " PRINTF_TIME, lf_time_logical_elapsed() + MSEC(750)); lf_set(out, in->value); self->count++; - =} deadline (200 ms) {= + =} deadline(200 ms) {= // This input is more than 200 ms late. It must have been from the slow cycles. lf_print("Watcher received late input %d. Ignoring it.", in->value); =} @@ -69,7 +67,7 @@ reactor Watcher { // Use a logical action so that the logical time of the output aligns. lf_schedule(a, 0); =} - + reaction(a) -> out, dog {= lf_print("******** Backup output being produced."); lf_set(out, self->count++); @@ -87,6 +85,7 @@ reactor Watcher { reactor Checker { input in: int state count: int = 1 + reaction(in) {= lf_print("Checker received %d at logical time " PRINTF_TIME " and physical time " PRINTF_TIME, in->value, @@ -97,6 +96,7 @@ reactor Checker { } self->count++; =} + reaction(shutdown) {= if (self->count < 10) { lf_print_error_and_exit("Received %d inputs. Expected at least 10.", self->count); @@ -105,7 +105,6 @@ reactor Checker { } federated reactor { - s = new SometimesSlowSource() w = new Watcher() c = new Checker()