Calypso Module 12: Time
Independent Timer RulesIndependent timer rules are not indented, so they don't depend on a parent rule. They run all the time, and their action is taken whenever the timer expires. Then, on the next rule cycle, the timer starts again. Independent timers can be used in multiple ways, such as to provide repeated actions, to implement a countdown clock or stopwatch, or to provide a timeout/escape mechanism.
1. Repeated ActionsIf we want Cozmo to say "play with me" every 10 seconds, we can use a timer rule to do that:
We can make the behavior more interesting by giving the "say" tile a list of phrases, each on a separate line in the dialog box. Cozmo will choose a phrase at random each time. Similarly, here's a rule that will make a character change color every 2 seconds:
2. Countdown Clock or Visible StopwatchA 1 second timer can be used to implement a countdown clock or stopwatch. Here's a game where the player has to drive Cozmo to a cube within 15 seconds to win. The red score acts as a countdown clock, keeping track of the time and adding tension to the game play. If the red score reaches 0 before a cube has been bumped, the player loses.
Notice that the first line of the program initializes the red score to 15. This is an example of the "Set the Table" idiom. But here we don't need to switch pages; instead we use a "once" tile so the rule will only run on the first rule cycle. The "Visible Stopwatch" idiom is similar to Countdown Timer, except we are counting up instead of down. This can be used for games where the player wants to keep track of their best time over multiple runs. For example, suppose we want to see how long it takes to get Cozmo to bump all three cubes when they are placed on an obstacle course. We can put the Visible Stopwatch rule on page 1, and switch to page 2 when we want to freeze the stopwatch so the player can read their score.
3. Timeout Escape: Don't Stay Too LongSometimes we want Cozmo to wait for an event to occur, such as a cube becoming visible. If it doesn't occur, Cozmo will be stuck waiting forever unless we include a timeout escape that switches to another page. This idiom is called "Don't Stay Too Long". Here's an example. Cozmo says "Show me a cube" and waits until a cube is visible in the camera frame. If he sees a cube, he switches to page 2. But if he has to wait more than 25 seconds, he says "You took too long" and switches to page 3 instead.
Here is the state machine diagram:
The normal path through the program is from page 1 to page 2. If Cozmo sees a cube within 25 seconds he will take that path. But he won't be stuck waiting for a cube forever. The timer provides an alternate way to leave page 1. This "timeout" path to page 3 will be taken if 25 seconds elapse without seeing a cube.
4. Extended Duration ActionsExtended duration actions such as "move" or "turn" require multiple rule cycles to get anything done,. Since "WHEN timer" is only true for one rule cycle, a timer rule can't be used to trigger these actions. The following rule does not wait 10 seconds and then drive forward forever:
Won't work!The right way for a timer to trigger an extended duration action is to switch pages, like this:
5. Fixed-Duration Continuous ActionsFixed-duration continuous actions are a variant of the timeout escape paradigm. We can begin a continuous action that normally runs forever, and use a timer to terminate it by switching pages. An example is conducting some limited exploration using "move wander". Suppose we want to have cubes in the world map, and if we don't find them, we want to wander around for a certain interval and then go back to page 1 and consider what we found. We can do this by using a timer to escape the wandering behavior. Note that "move wander" can't be tied to the timer rule. It is a top level rule that runs independently. The timer limits wandering by leaving the page.
6. Timer ResetSwitching pages resets any timers, even if we're switching from a page to itself. Here's a little game where you have to press the A button at least once every 5 seconds to reset the timer. If you don't reset it, you will lose.
7. Interaction With the 3rd and 5th LawsWhen a timer expires and any associated action succeeds, the rules indented below that timer rule can run; this is the Fourth Law. The indented rules are subject to the same laws, which leads to the following interesting example for making a character repeatedly glow red, then green, then blue:
The first time the timer expires, the "glow me red" rule runs. Two seconds later the timer expires again. Now the "glow me green" rule can run, and it does. According to the 5th law, this enables the "glow me blue" rule to run, and it does, but the glow me blue action is overridden by the preceding rule's "glow me green" action, in accordance with the Third Law. The "glow me red" rule's action is overridden by "glow me green" rule for the same reason. The second time the timer expires, the character is glowing green. The "glow me blue" rule can run, and it does. The "glow me red" rule can also run but its action is again overridden. The third time the timer expires, the character is glowing blue, so the only rule that can run is the "glow me red" rule, and the cycle repeats.
Dependent Timer RulesDependent timer rules have the timer indented under another rule, so the timer only starts to run when the parent rule's WHEN condition is true and its action succeeds. The parent's WHEN condition must remain true on every rule cycle until the timer expires; otherwise the timer will be reset. The main use of dependent timers is to test for an enduring condition.
1. Test for Enduring ConditionSuppose we want to require the user to hold down the A button for 3 seconds in order to switch to another page. When the button is pressed, the indented timer rule should start the timer running. As long as the button remains pressed, the timer keeps running, and when it expires, the page swith occurs. If the button is released before the timer expires, the timer rule stops running. Pressing the button again will cause the time to start afresh.
Here's another example of this idea. This time we'll use the gamepad A button to glow a cube green for 3 seconds. The condition of being green triggers a dependent timer that will eventually shut off the glow.
2. Timers are momentary, not enduringWhile a timer is running it is not considered to be "true", so any rules indented beneath it cannot run. Thus, you cannot use a timer as the parent rule to test for an enduring condition. Suppose we want the robot to complain whenever it goes 10 seconds without seeing a cube. The following program will not work as intended:
Will not work!What the above rules do is check every 10 seconds for the camera image to have no cubes in it. There is no measurement of how long the cube has been missing. If the cube disappeared one second before the timer expired, this rule would complain, although it should be silent. The correct solution is to have the timer rule depend on the visibility check instead of the other way around:
Now the timer starts when there is no cube in the camera frame, and only if this condition persists for 10 seconds will the timer have a chance to expire and trigger the "say" action, as we intended.
Advanced Timer ConceptsTimers are a fairly sophisticated concept because of their interaction with other rules and the changing state of the world. Below are some interesting observations about how timers work:
The "Once" Tile Cannot Be Used With A Timer."Once" allows an action to be performed only once while the rule's WHEN condition remains true. The "once" flag is reset when the condition becomes false, so the next time the condition becomes true the action will be performed again. "Once" cannot be used with a timer, because timer conditions are never true for more than a single rule cycle. Thus, the "once" flag will always be reset immediately. In effect, the "once" tile is meaningless in this context. The following code will say "banana" over and over, not just once:
If our intention is for the entire rule to only run once, the easiest solution is to use use a page switch to prevent the timer from restarting:
Timers Don't NestIt is not possible to nest one timer inside another. Again, the reason is that timer predicates are only true for an instant, so any timer nested inside a parent timer rule would be reset on the very next rule cycle. Suppose that every 8 seconds we want cube 1 to flash red for two seconds. The following code will not work:
Will not work!When the first rule glows the cube red, the second timer will start to run, but it will be reset on the next rule cycle, so the timer will never get a chance to expire. One way to implement this behavior correctly is with a state machine. We stay in the "glow red" state for two seconds and then switch to the "glow none" state for 6 seconds, for a total period of 8 seconds.
But it is also possible to implement this behavior in a single page by using the cube's color to trigger a dependent timer. This is another example of testing for an enduring condition:
Note that the second timer's period must be 8 seconds, not 6 seconds, because now the timers are running independently.
Random IntervalsCharacters can seem less robotic if they have some variablity in their timing. This can be done with the random tile. The following rule makes Cozmo say "knock-knock" every 5 to 8 seconds. Tiles appearing to the right of a "random" tile are added up to produce a sume N, and then "random" picks a random value from 0 to (and including) N
Is time purely a WHEN-side concept?In the Calypso language, time-related tiles appear only on the WHEN side of a rule. We have the "timer" predicate tile, and various "seconds" tiles for specifying a duration. Time is never mentioned on the DO side of a rule. Does it have to be this way? Can you think of ways we might use "seconds" with a DO side action?
Review and DiscoveryDo the
Next ModuleIn the next module you'll learn how logical operations are represented in Calypso.
Back to Calypso Curriculum overview.
Copyright © 2018 Visionary Machines LLC.