Skip to content

Social reactions

When someone — a cat, a dog, a person — comes right up to the robot and stays there, he does something about it. He backs off, spins, creeps forward, sniffs, fetches his cube, says their name, play-bows, peeks, follows, or ignores them with great ceremony. Somebody he has never seen gets the stranger set: a gasp, “who are you?”, hiding behind the cube.

The code is in two halves on purpose. The decisions have no robot in them at all, so they are ordinary unit-tested Go. Only a thin second half takes behaviour control, drives, speaks and serves the routes.

Dry run is on by default and should stay on until you are standing over him on the floor. Nothing moves. Every step he would have taken is emitted as an event and appears in the episode log exactly as it would have run. You can watch a whole reaction happen, in order, with timings, without the robot twitching.

An ism is one reaction, written as a short list of steps.

IsmWho forWhat happens
back_offcats, dogs, humansreverses 80 mm, head up, looks back at them
spineveryonelift half up, a full turn each way
approach_slowlyeveryonehead down a touch, two 40 mm creeps at 25 mm/s
sniffcats, dogsnose down, two little nudges forward with a noise each, then backs off
bring_cubeeveryone“wait there” by name, fetches the cube, puts it down in front of them
talkeveryonelooks at them and says a line the brain writes
play_bowcats, dogslift up, head down, a quick rock back and forward, pounce clip
peekeveryoneretreats 100 mm, hides his head, then pops up and looks
followcats, dogsthree look-and-creep cycles after them
dramatic_ignoreeveryoneturns his back, waits, glances over his shoulder, turns away again
greet_petcats, dogshis own cat-detection reaction clip, then her name
gaspstrangersreverses fast, lift up, a startled noise, “oh, hello”
who_are_youstrangersthe unidentified-face clip, “who are you?”, a head tilt each way
hide_behind_cubestrangersdocks with the cube and peers over it
shy_peekstrangerslooks away, glances back, looks away again
ask_namestrangersasks them to introduce themselves the way he can remember

Steps come from a deliberately tiny vocabulary — drive, turn, head, lift, say, talk, animate, sound, cube, wait, look at where they were last seen — so a new ism is a few lines of JSON and no new code.

The judge watches the vision.* events and keeps a short track per subject. All four of these have to be true at once:

  • close — their box is at least 18% of the frame’s width;
  • roughly in front of him — its middle is within 25% of the frame’s middle;
  • lingering — it has stayed that way for three seconds;
  • calm — no large motion in the last few seconds. A cat still tearing about the room is not asking for anything.

A pet detection only says “cat” or “dog”, never which cat. He picks one of the cats you have enabled at random, and the episode is marked as a guess. Faces come with a name; a face or person with no name is a stranger.

Each friend has a style — shy, playful, gentle or cheeky — which is nothing more than a set of weights over the isms. Shy backs off and peeks. Playful spins and play-bows. Gentle creeps up and talks. Cheeky ignores people theatrically. Any weight can be overridden for one friend, and zero means never.

  • Dry run, on by default: logs the steps, moves nothing.
  • Disabled: he stops watching entirely.
  • Quiet: a manual mute.
  • Mirroring the brain’s quiet: telling him to be quiet in conversation silences the reactions too. The server polls the brain for this every thirty seconds, and it is on by default.
  • Cooldowns: 45 seconds between any two episodes, 180 seconds before the same friend gets another, plus a per-ism cooldown — a spin every two minutes, the cube every ten. All configurable, and a friend can carry her own.
  • Mid-conversation: nothing starts while he is being spoken to.
  • Docked: on the charger he only runs isms that need no floor, so he cannot drive off it.

Every face he learns is added as a gentle human the first time the server sees it, so enrolling someone through the teach-a-face flow is enough to make them a friend. One can also be added by hand:

Terminal window
curl -X POST http://your-server:8080/api/social/friends \
-d '{"friend":{"name":"Rex","kind":"dog","style":"playful","enabled":true}}'

kind is cat, dog or human — that is the limit of what the camera can tell apart. weights is optional: {"weights":{"spin":3,"dramatic_ignore":0}}.

Rehearse runs a chosen ism for a chosen friend right now, ignoring the judge and the cooldowns, as a dry run:

Terminal window
curl -X POST http://your-server:8080/api/social/rehearse \
-d '{"friend":"Mika","ism":"play_bow"}'

The reply is the whole episode: every step, and how long each took. Adding "live": true actually moves him, and only works with dry run already off.

Taking behaviour control over the robot’s SDK switches his cliff sensors off on older firmware. That is how he drove off a desk. Until a build that fixes it is installed, the server refuses every step that turns his wheels, even with dry run off. The rest of a reaction still happens — he looks up, says his line, makes his noise — and each refused step is recorded on the episode so you can see what he would have done.

An episode holds behaviour control while it runs, and the request deliberately leaves the disable-cliff-stop flag alone, so his cliff sensors stay armed. Never set that field.

Every number in the repertoire is a guess:

  • Distances and speeds. 40 mm at 25 mm/s “creeping up” may read as a twitch or as a charge. Watch a cat’s reaction and adjust.
  • The 18% closeness threshold. How big a cat looks at the distance you actually want him reacting from. Take box widths out of the live view and pick from real numbers.
  • Three seconds of lingering, and the motion ceiling. Whether a settled cat really is calm by these measures, and whether three seconds is patient or infuriating.
  • The sniff sound. Whether it reads as sniffing or as him talking. A dedicated sniff would be better.
  • Fetching the cube. The wait after the fetch is a guess at how long his own fetch behaviour takes, and fetch needs behaviour control released while it runs. The most likely thing on this page to be wrong.
  • Looking at where they were last seen. The frame-to-angle maths assumes a roughly 90° wide, 50° tall camera and a level head. Check he ends up facing them.
  • Head angles. The full range is about −0.38 to 0.78 radians; the values picked for “nose down” and “looking up at a person” are eyeballed.

Turn dry run off, put him on the floor — not a desk — and rehearse them one at a time.