Manipulate the rules in Kuri’s rules engine to enable, modify or disable Kuri behaviors
Much of Kuri’s behavior is driven by a rules engine. The rules engine takes inputs, called triggers
, and information about Kuri’s current state, defined by properties
, and decides what task
Kuri should do next.
Consider the following rule:
{
"trigger": "tap touch",
"match": ["prop.task == 'choreo_dance'"],
"task": "stop",
"priority": 3,
"description": "Stops Pancake Robot when touched"
},
This says that when Kuri is tapped on the head, and Kuri is in the choreo_dance state (playing Pancake Robot), she should stop dancing and playing the song.
tick
which fires once a secondcreating-animations
Task Priority vs Rule Priority:
Each task has a priority. This represents how important the Task is, with lower numbers being more important. Each rule also has a priority. A rule will only execute if the current task’s priority is >= the rule priority. This is an easy way to build a hierarchy of behavior, so that, for instance, being picked up prevents lots of rules from firing.
The priority levels currently in use are:
Less commonly used rule fields:
The following is a list of properties. Each property is a function on an object of type Robot.
Property | Returns | Description |
---|---|---|
autonomous_wander_allowed | boolean | True if Kuri is allowed to wander based on schedule, battery level, etc |
battery | integer | battery percent charged |
configured | boolean | True unless the robot has just been reset |
docked | boolean | True if the robot is touching the charge contacts |
in_brickish_onboarding | boolean | True before the first head touch in onboarding |
in_override_mode | boolean | True if Kuri Live Override mode is active |
in_tour | boolean | True during onboarding and remapping sessions |
lost | boolean | True when localization is poor |
mapping | boolean | True during onboarding and remapping sessions when actively mapping |
move_dock_waiting | boolean | Internal for relocate dock flow |
moving_dock | boolean | Internal for relocate dock flow |
num_waypoints | integer | The number of user-saved places |
on_pedestal | boolean | True if the robots wheels are dropped and it is charging (like on a demo pedestal) |
playing_media | boolean | True if bluetooth audio or the internal player is active |
reaper_busy | boolean | True during shutdown and reset |
setting_auto_dance | boolean | Returns the user setting for allowing dance |
should_stay_put | boolean | True if the user has said “stay put” or if music is playing |
slam_can_accept | boolean | Internal for mapping flows |
power_critical | boolean | The battery is below 15% |
wander_allowed | boolean | There are enough places to wander to (>= 2), mapping not active, and not lost |
wander_supported | boolean | There are enough places to wanter to |
wants_to_dance | boolean | True if music is playing that Kuri detects a beat for |
Triggers are sent programatically by calling the trigger method on the Robot object. The signature is:
def trigger(self, trigger, params)
Trigger name | Description | Parameters | |
---|---|---|---|
app_command | Command from the app | input, name of the command | |
battery critical | Robot battery has dropped below 15% | ||
bluetooth timeout | Bluetooth connection has timed out | ||
boredom finished | The boredom animation has finished. Any reaction X triggers ‘X finished’ when it finishes | ||
dock resume | Resumes docking after interruption | ||
docked | Robot has just contacted the dock | ||
enter override | Kuri Live has entered override | ||
exit override | Kuri Live has exited override or disconnected | ||
hey kuri | Wake word heard | ||
hold touch | A sustained touch on the head | ||
hold touch end | A lift after a sustained touch | ||
ifttt_trigger | From IFTTT multiple goal system | type is animation or navigation, navigation also contains the waypoint | |
lost faces | Kuri has stopped seeing faces | ||
map status change | The map has changed | ||
nav resume | Resume navigation after an interruption | ||
paired and connected device | Bluetooth device paired from the pairing state | ||
paired new device | New blueooth device paired from the pairing state | ||
pickup | Robot has been picked up | ||
putdown | Robot has been put down | ||
reboot robot | Robot has received the reboot command | ||
reset robot | Robot has received factory reset | ||
saw cat | Kuri has detected a cat | ||
saw dog | Kuri has detected a dog | ||
saw face | Kuri has detected a face | ||
start_dance | Kuri is starting to dance to Bluetooth audio | ||
stop_dance | Kuri is stopping dancing | ||
tap touch | A quick touch on the head (triggers on lift) | ||
tick | Triggers once a second | ||
tickle touch | A touch alternating multiple head sensors | ||
tickle touch end | The lift for the above touch | ||
voice error | An error talking to SoundHound has occurred | ||
voice interaction | SoundHound response | input: the voice command, can also contain waypoint information | |
wander | Kuri is deciding whether to autonomously wander | ||
wheels_request | The app is trying to drive the robot |
Tasks are functions on the Robot object. The signature of a task is:
def a_task(self, trigger, params, reaction)
Trigger is a tuple (trigger_name, trigger_params_dict)
. Triggers can be sent in by publishing a Command.msg to the /triggers topic. The name
parameter becomes the trigger_name
and the params
key-value pairs become the entries in trigger_params_dict
.
Params is a dictionary of task parameters, defined by the task_params
field in the rule entry.
Reaction is the name of the reaction to play, see Creating New Animations
The description for all the existing tasks can be found in the rules file itself.
The rules file lives at /opt/gizmo/share/gizmo/configs/robot.json
For an example project involving modifying the rules file see Making Kuri play with your kitties