Skip to content

Commit

Permalink
Update the Watchdog example
Browse files Browse the repository at this point in the history
  • Loading branch information
edwardalee committed Jul 9, 2024
1 parent 598df88 commit 2135607
Show file tree
Hide file tree
Showing 2 changed files with 31 additions and 28 deletions.
59 changes: 31 additions & 28 deletions examples/C/src/watchdog/Watchdog.lf
Original file line number Diff line number Diff line change
@@ -1,18 +1,23 @@
/**
* @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.
* This program has a periodic source that sends events every 500 ms, but where every fourth event
* is delayed 300ms in physical time 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?
* The Watcher has a deadline of 250 ms. It wants to see events within 250 ms of their logical time,
* but, because of the delay every fourth event, the deadline will be violated by those events. The
* deadline violation handler is invoked in this case, but it is only invoked after the event
* arrives, which is more than 800 ms in physical time after the previous input. What if this input
* never arrives or we need to react to the deadline violation sooner, e.g. in order to drive an
* actuator? This program ensures that the Watcher will produce an output no later than about 750 ms
* in physical time after the previous output. The logical time of the output will be offset by 250
* ms.
*
* To handle this, the Watcher includes watchdog named "dog" that triggers if any input event is
* more than 250 ms late.
* To handle this, the Watcher includes watchdog named `dog` that triggers if 750 ms have elapsed in
* physical time since the last input. When the watchdog triggers, it prints a message and produces
* an output immediately, which is 750 ms in logical time (and roughly the same in physical time)
* after the previous output.
*
* @author Benjamin Asch
* @author Edward A. Lee
Expand All @@ -39,42 +44,40 @@ reactor Watcher {
input in: int
output out: int
state count: int = 1
logical action a(500 ms)

watchdog dog(750 ms) {=
watchdog dog(0 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);
// (is more than 250 ms late).
lf_watchdog_start(dog, MSEC(750));
lf_print("Watcher received input %d. Count: %d. Logical time: " PRINTF_TIME,
in->value, self->count, lf_time_logical_elapsed());
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_print("Will expire at physical time " 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.
=} deadline(250 ms) {=
// This input is more than 250 ms late. It must have been from the slow cycles.
lf_print("Watcher received late input %d. Ignoring it.", in->value);
=}

reaction(dog) -> a {=
reaction(dog) -> out, dog {=
// 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.");
// will be one microstep later than the most recent input.
tag_t tag = lf_tag();
instant_t start = lf_time_start();
lf_print("******** Watchdog triggered reaction at " PRINTF_TAG ". Producing backup output %d." PRINTF_TIME,
tag.time - start, tag.microstep, self->count);
lf_set(out, self->count++);
// Start another watchdog cycle in case the very next input is also delayed.
lf_watchdog_start(dog, 0);
lf_watchdog_start(dog, MSEC(500));
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_print("Will expire at physical time " PRINTF_TIME, lf_time_logical_elapsed() + MSEC(500));
=}

reaction(shutdown) -> dog {=
Expand Down
Binary file modified examples/C/src/watchdog/img/Watchdog.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.

0 comments on commit 2135607

Please sign in to comment.