| import { Matrix4 } from "three"; |
| import { interpolateTarget } from "../reachy/reachyKinematics.js"; |
|
|
| export const EMOTIONS = Object.freeze({ |
| joy: { sentence: "Oh, you're happy! Me too!", motion: "cheerful1" }, |
| sadness: { sentence: "Oh, you're sad! Me too!", motion: "sad1" }, |
| |
| |
| anger: { sentence: "Oh, you're angry! Me too!", motion: "reprimand2" }, |
| }); |
|
|
| const matrixFromRows = (rows) => new Matrix4().set(...rows.flat()); |
|
|
| export async function loadReachyEmotion(name) { |
| const response = await fetch(`./robot/reachy/emotions/${name}.json`); |
| if (!response.ok) throw new Error(`Unable to load Reachy emotion ${name}`); |
| const source = await response.json(); |
| const frames = source.time.map((time, i) => { |
| const frame = source.set_target_data[i]; |
| return { time, target: { head: matrixFromRows(frame.head), antennas: [...frame.antennas], bodyYaw: frame.body_yaw } }; |
| }); |
| const duration = frames.at(-1)?.time ?? 0; |
| return { |
| duration, |
| sample(seconds) { |
| if (!frames.length) throw new Error(`Empty Reachy emotion ${name}`); |
| if (seconds <= frames[0].time) return frames[0].target; |
| if (seconds >= duration) return frames.at(-1).target; |
| let hi = 1; |
| while (hi < frames.length && frames[hi].time < seconds) hi++; |
| const a = frames[hi - 1], b = frames[hi]; |
| return interpolateTarget(a.target, b.target, (seconds - a.time) / (b.time - a.time)); |
| }, |
| }; |
| } |
|
|