robot-face

Preview of the facial-animation library for a 0.96″ 128×64 OLED. The frame is computed by the js/robot-face.js module, the twin of the C component that draws the same face on the device. Eye shape is set by two numbers, valence and arousal; emotion traits, overlays and motion are layered on top.

All faces at once

Every activity and every emotion on its own screen, each with its own seed. Click a screen to show that face on the large module.

Now: Neutral SSD1306 · 30 fps · 1024 bytes per frame · full frame ≈31 ms over I²C at 300 kHz

Emotions: set by an LLM emoji

Each emotion is a point on the V–A plane plus its own recognizable trait: eye shape, overlay or motion. An LLM emits an emoji and the server maps it to an emotion name. Emotions tagged rude are for a rude character only: the server leaves them out of a friendly robot's emoji list.

States: from the protocol

The robot switches states itself on protocol messages; the trigger message is shown under each button. Listening, Thinking and Error temporarily replace the emotion with their own face, Speaking adds a mouth over the emotion, Idle brings the emotion back.

Activities: a life of its own while idle

An activity shows only in Idle: its own face, prop and gaze. Listening, Thinking, Speaking and Error hide it; “No activity” brings the emotion back. On a device the activities can be chosen by a server on a schedule.

Emotion plane V–A

Drag the point. Horizontal is valence, vertical is arousal. The face is a bilinear blend of four corner faces: P(V, A) = P₀ + V·EV + A·EA + V·A·EVA. Angry and sad lids, heavy sleepy lids and the smiling eyes are enabled through max(0, …), only in their own quadrant.

negativepositiveactivesleepy angerdelightgloomcontentment

Layers

Overlays are sprites drawn over the eyes. Picking an emotion sets its own; after that you can change them.
Motion of the whole face. “By V–A” derives breathing, bouncing and trembling from the point position.

Conversation over the protocol

The emotion arrives in the emotion field together with a sentence. The device attaches it as a marker in the audio queue, and the face changes when that sentence starts playing.

    Own life: schedule demo

    Example schedule a server could run (accelerated). After a conversation: 2 min of the base face. By day an activity runs 1–5 min, then 1–3 min of the base face; the next activity is chosen at random by weight and never repeats the previous one. At night the robot sleeps with a dimmed screen; in the morning it returns to the base face and the daytime schedule.

      Firmware parameters

      Current eye targets. All model numbers live in presets/face.json, from which both the firmware and this module are built.