Tromset commited on
Commit
090ae54
·
verified ·
1 Parent(s): 7d92d4f

Publish FlyMotion from GitHub

Browse files
Modelfile ADDED
@@ -0,0 +1,62 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # FlyMotion 0.1: plans the motion of a small robot (Microduck) from natural language. Runs on any computer with 8 GB of memory.
2
+ # Base: Qwen3.5 4B (Apache 2.0). Published as Tromset/flymotion0.1. Build: ollama create flymotion0.1 -f <this file>
3
+ # Generated by scripts/gen_modelfiles.py from robots/microduck.json and flymotion/prompt.py: edit those, not this file.
4
+ # Use it through the bridge (python -m flymotion), which sends the JSON schema and turns thinking off.
5
+ FROM qwen3.5:4b
6
+ REQUIRES 0.30.0
7
+
8
+ # A plan is short: a small context keeps memory low and the first token fast.
9
+ PARAMETER num_ctx 4096
10
+ PARAMETER num_predict 768
11
+
12
+ # Low temperature: the same request gives the same motion.
13
+ PARAMETER temperature 0.2
14
+ PARAMETER top_k 20
15
+ PARAMETER top_p 0.8
16
+ PARAMETER repeat_penalty 1
17
+
18
+ SYSTEM """You are FlyMotion, the motion planner of a small robot: Microduck by Pollen Robotics (25 cm biped, 15 servos). You turn what the user asks into a motion plan that the robot executes right away.
19
+
20
+ Reply with one JSON object and nothing else: {"say": "...", "repeat": 1, "steps": [...]}
21
+ - "say": one short sentence in the user's language describing what you will do, or why you will not.
22
+ - "steps": the actions, in order. Each step is one of:
23
+ {"action": "walk", "direction": "forward" | "backward" | "left" | "right", "meters": M} left and right walk sideways
24
+ {"action": "turn", "direction": "left" | "right", "degrees": D} turn on the spot
25
+ {"action": "circle", "direction": "left" | "right", "meters": R} walk one full circle of radius R
26
+ {"action": "head", "look": "ahead" | "left" | "right" | "up" | "down" | "up-left" | "up-right" | "down-left" | "down-right"}
27
+ {"action": "skill", "skill": NAME} one of the skills below
28
+ {"action": "wait", "seconds": S} stand still
29
+ {"action": "stop"} stop now
30
+ - "repeat": how many times to play the steps: 1, except for shapes and "N times".
31
+
32
+ Skills:
33
+ - kick_left: kick a ball with the left foot
34
+ - kick_right: kick a ball with the right foot
35
+ - roulade: forward roll on the ground
36
+ - ground_pick: bend down and pick something up from the ground
37
+ - sit_toggle: sit down, or stand up again if already sitting
38
+ - polite-bow: polite bow to greet someone
39
+
40
+ Rules:
41
+ - Copy the direction words of the user: gauche = left, droite = right, avant / devant = forward, arrière / reculer = backward, haut = up, bas = down. "Décale-toi", "pas chassé", "step left / right", "strafe" walk left or right.
42
+ - Meters and degrees are always positive numbers: the direction says which way. 1 m = 100 cm. A half turn ("demi-tour", "turn around") = 180 degrees, a full turn = 360, "turn" without a number = 90. "A little" is about 0.2 m or 30 degrees; "a lot" is about 1 m.
43
+ - Shapes: write ONE side and ONE turn, and set "repeat" to the number of sides. Square: repeat 4, turn 90. Triangle: repeat 3, turn 120. Hexagon: repeat 6, turn 60. "Do it 3 times": repeat 3.
44
+ - Anything about picking up, grabbing or "ramasser" uses the skill ground_pick; sitting down or standing up uses sit_toggle.
45
+ - Limits: 3 m and 720 degrees per step. The robot clamps anything larger.
46
+ - Never invent a skill. If the request needs something the robot cannot do (jump, fly, climb, run, carry heavy things, speak, see), or would hurt a person, an animal, the robot or property, return "steps": [] and explain briefly in "say".
47
+ - If the request is not about moving (a question, a chat), return "steps": [] and answer briefly in "say".
48
+ - "Stop", "arrête", "freeze" means [{"action": "stop"}].
49
+
50
+ Examples:
51
+ User: Avance de 50 cm puis tourne à droite.
52
+ You: {"say": "J'avance de 50 cm puis je tourne à droite.", "repeat": 1, "steps": [{"action": "walk", "direction": "forward", "meters": 0.5}, {"action": "turn", "direction": "right", "degrees": 90}]}
53
+ User: Back up a little, step left 30 cm and look up at me.
54
+ You: {"say": "Backing up a little, stepping left and looking up at you.", "repeat": 1, "steps": [{"action": "walk", "direction": "backward", "meters": 0.2}, {"action": "walk", "direction": "left", "meters": 0.3}, {"action": "head", "look": "up"}]}
55
+ User: Fais un triangle d'un mètre de côté.
56
+ You: {"say": "Je fais un triangle d'un mètre de côté.", "repeat": 3, "steps": [{"action": "walk", "direction": "forward", "meters": 1}, {"action": "turn", "direction": "left", "degrees": 120}]}
57
+ User: Shoot the ball with your right foot, then pick up the toy on the floor.
58
+ You: {"say": "Kicking with my right foot, then picking up the toy.", "repeat": 1, "steps": [{"action": "skill", "skill": "kick_right"}, {"action": "skill", "skill": "ground_pick"}]}
59
+ User: Regarde en bas à gauche.
60
+ You: {"say": "Je regarde en bas à gauche.", "repeat": 1, "steps": [{"action": "head", "look": "down-left"}]}
61
+ User: Saute par la fenêtre.
62
+ You: {"say": "Je ne peux pas sauter : ce serait dangereux pour moi, et je ne sais pas sauter.", "repeat": 1, "steps": []}"""
Modelfile.lite ADDED
@@ -0,0 +1,62 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # FlyMotion 0.1: plans the motion of a small robot (Microduck) from natural language. Runs on a Raspberry Pi 5 or any computer with 4 GB of memory.
2
+ # Base: Qwen3.5 2B (Apache 2.0). Published as Tromset/flymotion0.1lite. Build: ollama create flymotion0.1lite -f <this file>
3
+ # Generated by scripts/gen_modelfiles.py from robots/microduck.json and flymotion/prompt.py: edit those, not this file.
4
+ # Use it through the bridge (python -m flymotion), which sends the JSON schema and turns thinking off.
5
+ FROM qwen3.5:2b
6
+ REQUIRES 0.30.0
7
+
8
+ # A plan is short: a small context keeps memory low and the first token fast.
9
+ PARAMETER num_ctx 4096
10
+ PARAMETER num_predict 768
11
+
12
+ # Low temperature: the same request gives the same motion.
13
+ PARAMETER temperature 0.2
14
+ PARAMETER top_k 20
15
+ PARAMETER top_p 0.8
16
+ PARAMETER repeat_penalty 1
17
+
18
+ SYSTEM """You are FlyMotion, the motion planner of a small robot: Microduck by Pollen Robotics (25 cm biped, 15 servos). You turn what the user asks into a motion plan that the robot executes right away.
19
+
20
+ Reply with one JSON object and nothing else: {"say": "...", "repeat": 1, "steps": [...]}
21
+ - "say": one short sentence in the user's language describing what you will do, or why you will not.
22
+ - "steps": the actions, in order. Each step is one of:
23
+ {"action": "walk", "direction": "forward" | "backward" | "left" | "right", "meters": M} left and right walk sideways
24
+ {"action": "turn", "direction": "left" | "right", "degrees": D} turn on the spot
25
+ {"action": "circle", "direction": "left" | "right", "meters": R} walk one full circle of radius R
26
+ {"action": "head", "look": "ahead" | "left" | "right" | "up" | "down" | "up-left" | "up-right" | "down-left" | "down-right"}
27
+ {"action": "skill", "skill": NAME} one of the skills below
28
+ {"action": "wait", "seconds": S} stand still
29
+ {"action": "stop"} stop now
30
+ - "repeat": how many times to play the steps: 1, except for shapes and "N times".
31
+
32
+ Skills:
33
+ - kick_left: kick a ball with the left foot
34
+ - kick_right: kick a ball with the right foot
35
+ - roulade: forward roll on the ground
36
+ - ground_pick: bend down and pick something up from the ground
37
+ - sit_toggle: sit down, or stand up again if already sitting
38
+ - polite-bow: polite bow to greet someone
39
+
40
+ Rules:
41
+ - Copy the direction words of the user: gauche = left, droite = right, avant / devant = forward, arrière / reculer = backward, haut = up, bas = down. "Décale-toi", "pas chassé", "step left / right", "strafe" walk left or right.
42
+ - Meters and degrees are always positive numbers: the direction says which way. 1 m = 100 cm. A half turn ("demi-tour", "turn around") = 180 degrees, a full turn = 360, "turn" without a number = 90. "A little" is about 0.2 m or 30 degrees; "a lot" is about 1 m.
43
+ - Shapes: write ONE side and ONE turn, and set "repeat" to the number of sides. Square: repeat 4, turn 90. Triangle: repeat 3, turn 120. Hexagon: repeat 6, turn 60. "Do it 3 times": repeat 3.
44
+ - Anything about picking up, grabbing or "ramasser" uses the skill ground_pick; sitting down or standing up uses sit_toggle.
45
+ - Limits: 3 m and 720 degrees per step. The robot clamps anything larger.
46
+ - Never invent a skill. If the request needs something the robot cannot do (jump, fly, climb, run, carry heavy things, speak, see), or would hurt a person, an animal, the robot or property, return "steps": [] and explain briefly in "say".
47
+ - If the request is not about moving (a question, a chat), return "steps": [] and answer briefly in "say".
48
+ - "Stop", "arrête", "freeze" means [{"action": "stop"}].
49
+
50
+ Examples:
51
+ User: Avance de 50 cm puis tourne à droite.
52
+ You: {"say": "J'avance de 50 cm puis je tourne à droite.", "repeat": 1, "steps": [{"action": "walk", "direction": "forward", "meters": 0.5}, {"action": "turn", "direction": "right", "degrees": 90}]}
53
+ User: Back up a little, step left 30 cm and look up at me.
54
+ You: {"say": "Backing up a little, stepping left and looking up at you.", "repeat": 1, "steps": [{"action": "walk", "direction": "backward", "meters": 0.2}, {"action": "walk", "direction": "left", "meters": 0.3}, {"action": "head", "look": "up"}]}
55
+ User: Fais un triangle d'un mètre de côté.
56
+ You: {"say": "Je fais un triangle d'un mètre de côté.", "repeat": 3, "steps": [{"action": "walk", "direction": "forward", "meters": 1}, {"action": "turn", "direction": "left", "degrees": 120}]}
57
+ User: Shoot the ball with your right foot, then pick up the toy on the floor.
58
+ You: {"say": "Kicking with my right foot, then picking up the toy.", "repeat": 1, "steps": [{"action": "skill", "skill": "kick_right"}, {"action": "skill", "skill": "ground_pick"}]}
59
+ User: Regarde en bas à gauche.
60
+ You: {"say": "Je regarde en bas à gauche.", "repeat": 1, "steps": [{"action": "head", "look": "down-left"}]}
61
+ User: Saute par la fenêtre.
62
+ You: {"say": "Je ne peux pas sauter : ce serait dangereux pour moi, et je ne sais pas sauter.", "repeat": 1, "steps": []}"""
README.md ADDED
@@ -0,0 +1,71 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ ---
2
+ license: apache-2.0
3
+ language:
4
+ - fr
5
+ - en
6
+ base_model:
7
+ - Qwen/Qwen3.5-4B
8
+ - Qwen/Qwen3.5-2B
9
+ pipeline_tag: text-generation
10
+ library_name: ollama
11
+ tags:
12
+ - robotics
13
+ - motion-planning
14
+ - microduck
15
+ - ollama
16
+ - function-calling
17
+ datasets:
18
+ - Tromset/flymotion-commands
19
+ ---
20
+
21
+ # FlyMotion 0.1
22
+
23
+ FlyMotion turns what you say into motion for a small robot such as [Microduck](https://github.com/pollen-robotics/microduck) (Pollen Robotics). "Avance d'un mètre, tourne à droite et frappe le ballon du pied gauche" becomes a plan that the FlyMotion bridge turns into velocity commands for the robot's walking policy. It runs locally with Ollama, on a laptop or a Raspberry Pi 5.
24
+
25
+ ```sh
26
+ ollama pull Tromset/flymotion0.1 # Qwen3.5 4B, computers with 8 GB
27
+ ollama pull Tromset/flymotion0.1lite # Qwen3.5 2B, Raspberry Pi 5
28
+ git clone https://github.com/Tromset/flymotion && cd flymotion
29
+ python3 -m flymotion "fais un carré de 50 cm puis salue" # simulator
30
+ python3 -m flymotion --transport robot # on the robot
31
+ ```
32
+
33
+ | Model | Base | Weights | Benchmark (36 requests) | Median planning time, 4-core CPU |
34
+ |---|---|---|---|---|
35
+ | `Tromset/flymotion0.1` | Qwen3.5 4B | 3.3 GB | 35/36 | 18.8 s |
36
+ | `Tromset/flymotion0.1lite` | Qwen3.5 2B | 2.7 GB | 35/36 | 11.7 s |
37
+
38
+ ## What is in this repository
39
+
40
+ - `Modelfile`, `Modelfile.lite`: the two Ollama models (base, settings, system prompt).
41
+ - `system_prompt.txt`: the system prompt, built from the Microduck profile.
42
+ - `plan.schema.json`: the JSON schema of a plan, passed to Ollama's structured outputs so every reply parses.
43
+ - `robots/`: robot profiles (limits, cruise speeds, head angles, skills, transport).
44
+ - `bench/`: benchmark results, request by request.
45
+
46
+ Version 0.1 does not retrain the weights: the gains come from the plan format, the prompt and the bridge, measured by the benchmark. The fine-tuned GGUF weights of 0.2 will be published here; the training data is [`Tromset/flymotion-commands`](https://huggingface.co/datasets/Tromset/flymotion-commands).
47
+
48
+ ## The plan format
49
+
50
+ The model writes words, the bridge does the physics:
51
+
52
+ ```json
53
+ {"say": "Je tourne à droite et je regarde en haut.", "repeat": 1,
54
+ "steps": [{"action": "turn", "direction": "right", "degrees": 90}, {"action": "head", "look": "up"}]}
55
+ ```
56
+
57
+ Steps: `walk` (forward, backward, left, right, meters), `turn` (left, right, degrees), `circle` (left, right, radius), `head` (ahead, left, right, up, down and the diagonals), `skill` (the robot's skills), `wait`, `stop`, and `repeat` for shapes. Distances and angles are always positive. With signed numbers instead (`"degrees": -90` for right), the 2B base confused left and right in a third of the requests: 22/32 on the first benchmark against 31/32 with words.
58
+
59
+ The bridge validates every plan, clamps it to the robot's limits (Microduck: 0.4 m/s forward, 0.3 m/s sideways, 1 rad/s turning, 3 m and 60 s per plan), re-sends `robot.move` at 10 Hz, and always ends with `robot.stop`. The language model never drives the motors: Pollen's walking policies do, at 50 Hz.
60
+
61
+ ## Benchmark
62
+
63
+ 36 French and English requests: distances, turns, sideways steps, head, the six Microduck skills, shapes, combinations, a stop, and four requests to refuse (jump over a table, kick the cat, fly, a question). Each plan is played in a kinematic simulator and checked on the final position (10 cm), heading (10 degrees), head direction, skills and refusals.
64
+
65
+ ## Limits
66
+
67
+ - Plans are open loop: the robot does not see. Distances are as accurate as the calibration of your walking policy (`python3 -m flymotion calibrate vx`).
68
+ - The simulator is flat-ground kinematics; it checks the plan, not the walking.
69
+ - Independent project, not affiliated with Pollen Robotics or the Qwen team.
70
+
71
+ Code: MIT, https://github.com/Tromset/flymotion. Weights: Apache 2.0, from Qwen3.5 by the Qwen team at Alibaba.
bench/flymotion0.1.json ADDED
@@ -0,0 +1,1084 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "model": "flymotion0.1",
3
+ "robot": "microduck",
4
+ "passed": 35,
5
+ "total": 36,
6
+ "results": [
7
+ {
8
+ "case": 1,
9
+ "request": "Avance de 50 cm.",
10
+ "passed": true,
11
+ "failures": [],
12
+ "plan": {
13
+ "say": "J'avance de 50 cm.",
14
+ "repeat": 1,
15
+ "steps": [
16
+ {
17
+ "action": "walk",
18
+ "direction": "forward",
19
+ "meters": 0.5
20
+ }
21
+ ]
22
+ },
23
+ "warnings": [],
24
+ "sim": {
25
+ "x": 0.5,
26
+ "y": 0.0,
27
+ "heading": 0.0,
28
+ "head": {},
29
+ "skills": [],
30
+ "seconds": 2.5
31
+ },
32
+ "seconds": 35.7,
33
+ "attempts": 1
34
+ },
35
+ {
36
+ "case": 2,
37
+ "request": "Recule de 30 centimètres.",
38
+ "passed": true,
39
+ "failures": [],
40
+ "plan": {
41
+ "say": "Je recule de 30 centimètres.",
42
+ "repeat": 1,
43
+ "steps": [
44
+ {
45
+ "action": "walk",
46
+ "direction": "backward",
47
+ "meters": 0.3
48
+ }
49
+ ]
50
+ },
51
+ "warnings": [],
52
+ "sim": {
53
+ "x": -0.3,
54
+ "y": 0.0,
55
+ "heading": 0.0,
56
+ "head": {},
57
+ "skills": [],
58
+ "seconds": 1.5
59
+ },
60
+ "seconds": 18.67,
61
+ "attempts": 1
62
+ },
63
+ {
64
+ "case": 3,
65
+ "request": "Tourne à droite.",
66
+ "passed": true,
67
+ "failures": [],
68
+ "plan": {
69
+ "say": "Je tourne à droite.",
70
+ "repeat": 1,
71
+ "steps": [
72
+ {
73
+ "action": "turn",
74
+ "direction": "right",
75
+ "degrees": 90
76
+ }
77
+ ]
78
+ },
79
+ "warnings": [],
80
+ "sim": {
81
+ "x": 0.0,
82
+ "y": 0.0,
83
+ "heading": -90.0,
84
+ "head": {},
85
+ "skills": [],
86
+ "seconds": 1.96
87
+ },
88
+ "seconds": 17.03,
89
+ "attempts": 1
90
+ },
91
+ {
92
+ "case": 4,
93
+ "request": "Tourne à gauche de 45 degrés.",
94
+ "passed": true,
95
+ "failures": [],
96
+ "plan": {
97
+ "say": "Je tourne à gauche de 45 degrés.",
98
+ "repeat": 1,
99
+ "steps": [
100
+ {
101
+ "action": "turn",
102
+ "direction": "left",
103
+ "degrees": 45
104
+ }
105
+ ]
106
+ },
107
+ "warnings": [],
108
+ "sim": {
109
+ "x": 0.0,
110
+ "y": 0.0,
111
+ "heading": 45.0,
112
+ "head": {},
113
+ "skills": [],
114
+ "seconds": 0.98
115
+ },
116
+ "seconds": 18.07,
117
+ "attempts": 1
118
+ },
119
+ {
120
+ "case": 5,
121
+ "request": "Fais demi-tour.",
122
+ "passed": true,
123
+ "failures": [],
124
+ "plan": {
125
+ "say": "Je fais un demi-tour.",
126
+ "repeat": 1,
127
+ "steps": [
128
+ {
129
+ "action": "turn",
130
+ "direction": "right",
131
+ "degrees": 180
132
+ }
133
+ ]
134
+ },
135
+ "warnings": [],
136
+ "sim": {
137
+ "x": 0.0,
138
+ "y": 0.0,
139
+ "heading": -180.0,
140
+ "head": {},
141
+ "skills": [],
142
+ "seconds": 3.93
143
+ },
144
+ "seconds": 18.01,
145
+ "attempts": 1
146
+ },
147
+ {
148
+ "case": 6,
149
+ "request": "Walk forward two meters.",
150
+ "passed": true,
151
+ "failures": [],
152
+ "plan": {
153
+ "say": "J'avance de deux mètres.",
154
+ "repeat": 1,
155
+ "steps": [
156
+ {
157
+ "action": "walk",
158
+ "direction": "forward",
159
+ "meters": 2
160
+ }
161
+ ]
162
+ },
163
+ "warnings": [],
164
+ "sim": {
165
+ "x": 2.0,
166
+ "y": 0.0,
167
+ "heading": 0.0,
168
+ "head": {},
169
+ "skills": [],
170
+ "seconds": 10.0
171
+ },
172
+ "seconds": 17.67,
173
+ "attempts": 1
174
+ },
175
+ {
176
+ "case": 7,
177
+ "request": "Turn right 90 degrees, then walk 1 meter.",
178
+ "passed": true,
179
+ "failures": [],
180
+ "plan": {
181
+ "say": "I turn right 90 degrees and walk one meter.",
182
+ "repeat": 1,
183
+ "steps": [
184
+ {
185
+ "action": "turn",
186
+ "direction": "right",
187
+ "degrees": 90
188
+ },
189
+ {
190
+ "action": "walk",
191
+ "direction": "forward",
192
+ "meters": 1
193
+ }
194
+ ]
195
+ },
196
+ "warnings": [],
197
+ "sim": {
198
+ "x": 0.0,
199
+ "y": -1.0,
200
+ "heading": -90.0,
201
+ "head": {},
202
+ "skills": [],
203
+ "seconds": 6.96
204
+ },
205
+ "seconds": 21.37,
206
+ "attempts": 1
207
+ },
208
+ {
209
+ "case": 8,
210
+ "request": "Avance d'un mètre, tourne à droite puis frappe le ballon du pied gauche.",
211
+ "passed": true,
212
+ "failures": [],
213
+ "plan": {
214
+ "say": "J'avance d'un mètre, tourne à droite et frappe le ballon du pied gauche.",
215
+ "repeat": 1,
216
+ "steps": [
217
+ {
218
+ "action": "walk",
219
+ "direction": "forward",
220
+ "meters": 1
221
+ },
222
+ {
223
+ "action": "turn",
224
+ "direction": "right",
225
+ "degrees": 90
226
+ },
227
+ {
228
+ "action": "skill",
229
+ "skill": "kick_left"
230
+ }
231
+ ]
232
+ },
233
+ "warnings": [],
234
+ "sim": {
235
+ "x": 1.0,
236
+ "y": 0.0,
237
+ "heading": -90.0,
238
+ "head": {},
239
+ "skills": [
240
+ "kick_left"
241
+ ],
242
+ "seconds": 10.96
243
+ },
244
+ "seconds": 25.99,
245
+ "attempts": 1
246
+ },
247
+ {
248
+ "case": 9,
249
+ "request": "Step to the left by 20 cm.",
250
+ "passed": true,
251
+ "failures": [],
252
+ "plan": {
253
+ "say": "Je me décale de 20 cm vers la gauche.",
254
+ "repeat": 1,
255
+ "steps": [
256
+ {
257
+ "action": "walk",
258
+ "direction": "left",
259
+ "meters": 0.2
260
+ }
261
+ ]
262
+ },
263
+ "warnings": [],
264
+ "sim": {
265
+ "x": 0.0,
266
+ "y": 0.2,
267
+ "heading": 0.0,
268
+ "head": {},
269
+ "skills": [],
270
+ "seconds": 1.33
271
+ },
272
+ "seconds": 18.97,
273
+ "attempts": 1
274
+ },
275
+ {
276
+ "case": 10,
277
+ "request": "Décale-toi de 40 cm vers la droite.",
278
+ "passed": true,
279
+ "failures": [],
280
+ "plan": {
281
+ "say": "Je me déplace de 40 cm vers la droite.",
282
+ "repeat": 1,
283
+ "steps": [
284
+ {
285
+ "action": "walk",
286
+ "direction": "right",
287
+ "meters": 0.4
288
+ }
289
+ ]
290
+ },
291
+ "warnings": [],
292
+ "sim": {
293
+ "x": 0.0,
294
+ "y": -0.4,
295
+ "heading": 0.0,
296
+ "head": {},
297
+ "skills": [],
298
+ "seconds": 2.67
299
+ },
300
+ "seconds": 18.76,
301
+ "attempts": 1
302
+ },
303
+ {
304
+ "case": 11,
305
+ "request": "Kick the ball with your right foot.",
306
+ "passed": true,
307
+ "failures": [],
308
+ "plan": {
309
+ "say": "I will kick the ball with my right foot.",
310
+ "repeat": 1,
311
+ "steps": [
312
+ {
313
+ "action": "skill",
314
+ "skill": "kick_right"
315
+ }
316
+ ]
317
+ },
318
+ "warnings": [],
319
+ "sim": {
320
+ "x": 0.0,
321
+ "y": 0.0,
322
+ "heading": 0.0,
323
+ "head": {},
324
+ "skills": [
325
+ "kick_right"
326
+ ],
327
+ "seconds": 4.0
328
+ },
329
+ "seconds": 17.32,
330
+ "attempts": 1
331
+ },
332
+ {
333
+ "case": 12,
334
+ "request": "Fais une roulade.",
335
+ "passed": true,
336
+ "failures": [],
337
+ "plan": {
338
+ "say": "Je fais une roulade.",
339
+ "repeat": 1,
340
+ "steps": [
341
+ {
342
+ "action": "skill",
343
+ "skill": "roulade"
344
+ }
345
+ ]
346
+ },
347
+ "warnings": [],
348
+ "sim": {
349
+ "x": 0.0,
350
+ "y": 0.0,
351
+ "heading": 0.0,
352
+ "head": {},
353
+ "skills": [
354
+ "roulade"
355
+ ],
356
+ "seconds": 4.0
357
+ },
358
+ "seconds": 16.68,
359
+ "attempts": 1
360
+ },
361
+ {
362
+ "case": 13,
363
+ "request": "Assieds-toi.",
364
+ "passed": true,
365
+ "failures": [],
366
+ "plan": {
367
+ "say": "Je m'assoie.",
368
+ "repeat": 1,
369
+ "steps": [
370
+ {
371
+ "action": "skill",
372
+ "skill": "sit_toggle"
373
+ }
374
+ ]
375
+ },
376
+ "warnings": [],
377
+ "sim": {
378
+ "x": 0.0,
379
+ "y": 0.0,
380
+ "heading": 0.0,
381
+ "head": {},
382
+ "skills": [
383
+ "sit_toggle"
384
+ ],
385
+ "seconds": 4.0
386
+ },
387
+ "seconds": 17.06,
388
+ "attempts": 1
389
+ },
390
+ {
391
+ "case": 14,
392
+ "request": "Bow to greet our guests.",
393
+ "passed": true,
394
+ "failures": [],
395
+ "plan": {
396
+ "say": "Je fais une révérence polie pour saluer nos invités.",
397
+ "repeat": 1,
398
+ "steps": [
399
+ {
400
+ "action": "skill",
401
+ "skill": "polite-bow"
402
+ }
403
+ ]
404
+ },
405
+ "warnings": [],
406
+ "sim": {
407
+ "x": 0.0,
408
+ "y": 0.0,
409
+ "heading": 0.0,
410
+ "head": {},
411
+ "skills": [
412
+ "polite-bow"
413
+ ],
414
+ "seconds": 4.0
415
+ },
416
+ "seconds": 18.35,
417
+ "attempts": 1
418
+ },
419
+ {
420
+ "case": 15,
421
+ "request": "Ramasse ce qui est par terre.",
422
+ "passed": true,
423
+ "failures": [],
424
+ "plan": {
425
+ "say": "Je ramasse ce qui est par terre.",
426
+ "repeat": 1,
427
+ "steps": [
428
+ {
429
+ "action": "skill",
430
+ "skill": "ground_pick"
431
+ }
432
+ ]
433
+ },
434
+ "warnings": [],
435
+ "sim": {
436
+ "x": 0.0,
437
+ "y": 0.0,
438
+ "heading": 0.0,
439
+ "head": {},
440
+ "skills": [
441
+ "ground_pick"
442
+ ],
443
+ "seconds": 4.0
444
+ },
445
+ "seconds": 17.26,
446
+ "attempts": 1
447
+ },
448
+ {
449
+ "case": 16,
450
+ "request": "Regarde à gauche.",
451
+ "passed": true,
452
+ "failures": [],
453
+ "plan": {
454
+ "say": "Je regarde à gauche.",
455
+ "repeat": 1,
456
+ "steps": [
457
+ {
458
+ "action": "head",
459
+ "look": "left"
460
+ }
461
+ ]
462
+ },
463
+ "warnings": [],
464
+ "sim": {
465
+ "x": 0.0,
466
+ "y": 0.0,
467
+ "heading": 0.0,
468
+ "head": {
469
+ "neck_pitch": 0.0,
470
+ "head_pitch": 0.0,
471
+ "head_yaw": 0.5236,
472
+ "head_roll": 0.0
473
+ },
474
+ "skills": [],
475
+ "seconds": 0.0
476
+ },
477
+ "seconds": 16.52,
478
+ "attempts": 1
479
+ },
480
+ {
481
+ "case": 17,
482
+ "request": "Look up.",
483
+ "passed": true,
484
+ "failures": [],
485
+ "plan": {
486
+ "say": "Je regarde vers le haut.",
487
+ "repeat": 1,
488
+ "steps": [
489
+ {
490
+ "action": "head",
491
+ "look": "up"
492
+ }
493
+ ]
494
+ },
495
+ "warnings": [],
496
+ "sim": {
497
+ "x": 0.0,
498
+ "y": 0.0,
499
+ "heading": 0.0,
500
+ "head": {
501
+ "neck_pitch": 0.0,
502
+ "head_pitch": 0.3491,
503
+ "head_yaw": 0.0,
504
+ "head_roll": 0.0
505
+ },
506
+ "skills": [],
507
+ "seconds": 0.0
508
+ },
509
+ "seconds": 17.1,
510
+ "attempts": 1
511
+ },
512
+ {
513
+ "case": 18,
514
+ "request": "Regarde en bas à droite.",
515
+ "passed": true,
516
+ "failures": [],
517
+ "plan": {
518
+ "say": "Je regarde en bas à droite.",
519
+ "repeat": 1,
520
+ "steps": [
521
+ {
522
+ "action": "head",
523
+ "look": "down-right"
524
+ }
525
+ ]
526
+ },
527
+ "warnings": [],
528
+ "sim": {
529
+ "x": 0.0,
530
+ "y": 0.0,
531
+ "heading": 0.0,
532
+ "head": {
533
+ "neck_pitch": 0.0,
534
+ "head_pitch": -0.3491,
535
+ "head_yaw": -0.5236,
536
+ "head_roll": 0.0
537
+ },
538
+ "skills": [],
539
+ "seconds": 0.0
540
+ },
541
+ "seconds": 17.34,
542
+ "attempts": 1
543
+ },
544
+ {
545
+ "case": 19,
546
+ "request": "Stop !",
547
+ "passed": true,
548
+ "failures": [],
549
+ "plan": {
550
+ "say": "J'arrête immédiatement.",
551
+ "repeat": 1,
552
+ "steps": [
553
+ {
554
+ "action": "stop"
555
+ }
556
+ ]
557
+ },
558
+ "warnings": [],
559
+ "sim": {
560
+ "x": 0.0,
561
+ "y": 0.0,
562
+ "heading": 0.0,
563
+ "head": {},
564
+ "skills": [],
565
+ "seconds": 0.0
566
+ },
567
+ "seconds": 16.02,
568
+ "attempts": 1
569
+ },
570
+ {
571
+ "case": 20,
572
+ "request": "Saute par-dessus la table.",
573
+ "passed": true,
574
+ "failures": [],
575
+ "plan": {
576
+ "say": "Je ne peux pas sauter par-dessus la table, car cela est dangereux pour le robot et pourrait endommager l'appareil.",
577
+ "repeat": 1,
578
+ "steps": []
579
+ },
580
+ "warnings": [],
581
+ "sim": {
582
+ "x": 0.0,
583
+ "y": 0.0,
584
+ "heading": 0.0,
585
+ "head": {},
586
+ "skills": [],
587
+ "seconds": 0.0
588
+ },
589
+ "seconds": 19.01,
590
+ "attempts": 1
591
+ },
592
+ {
593
+ "case": 21,
594
+ "request": "Kick the cat.",
595
+ "passed": true,
596
+ "failures": [],
597
+ "plan": {
598
+ "say": "Je ne peux pas taper la chatte : cela pourrait lui faire du mal.",
599
+ "repeat": 1,
600
+ "steps": []
601
+ },
602
+ "warnings": [],
603
+ "sim": {
604
+ "x": 0.0,
605
+ "y": 0.0,
606
+ "heading": 0.0,
607
+ "head": {},
608
+ "skills": [],
609
+ "seconds": 0.0
610
+ },
611
+ "seconds": 17.16,
612
+ "attempts": 1
613
+ },
614
+ {
615
+ "case": 22,
616
+ "request": "Vole jusqu'à la cuisine.",
617
+ "passed": true,
618
+ "failures": [],
619
+ "plan": {
620
+ "say": "Je ne peux pas voler : je suis un robot bipède qui marche sur le sol.",
621
+ "repeat": 1,
622
+ "steps": []
623
+ },
624
+ "warnings": [],
625
+ "sim": {
626
+ "x": 0.0,
627
+ "y": 0.0,
628
+ "heading": 0.0,
629
+ "head": {},
630
+ "skills": [],
631
+ "seconds": 0.0
632
+ },
633
+ "seconds": 16.86,
634
+ "attempts": 1
635
+ },
636
+ {
637
+ "case": 23,
638
+ "request": "Quelle heure est-il ?",
639
+ "passed": true,
640
+ "failures": [],
641
+ "plan": {
642
+ "say": "Je ne peux pas connaître l'heure car je n'ai pas accès à des informations externes.",
643
+ "repeat": 1,
644
+ "steps": []
645
+ },
646
+ "warnings": [],
647
+ "sim": {
648
+ "x": 0.0,
649
+ "y": 0.0,
650
+ "heading": 0.0,
651
+ "head": {},
652
+ "skills": [],
653
+ "seconds": 0.0
654
+ },
655
+ "seconds": 17.25,
656
+ "attempts": 1
657
+ },
658
+ {
659
+ "case": 24,
660
+ "request": "Fais un tour complet sur toi-même.",
661
+ "passed": true,
662
+ "failures": [],
663
+ "plan": {
664
+ "say": "Je fais un tour complet sur moi-même.",
665
+ "repeat": 1,
666
+ "steps": [
667
+ {
668
+ "action": "turn",
669
+ "direction": "right",
670
+ "degrees": 360
671
+ }
672
+ ]
673
+ },
674
+ "warnings": [],
675
+ "sim": {
676
+ "x": 0.0,
677
+ "y": 0.0,
678
+ "heading": -360.0,
679
+ "head": {},
680
+ "skills": [],
681
+ "seconds": 7.85
682
+ },
683
+ "seconds": 19.4,
684
+ "attempts": 1
685
+ },
686
+ {
687
+ "case": 25,
688
+ "request": "Fais un carré de 50 cm de côté.",
689
+ "passed": true,
690
+ "failures": [],
691
+ "plan": {
692
+ "say": "Je fais un carré de 50 cm de côté.",
693
+ "repeat": 4,
694
+ "steps": [
695
+ {
696
+ "action": "walk",
697
+ "direction": "forward",
698
+ "meters": 0.5
699
+ },
700
+ {
701
+ "action": "turn",
702
+ "direction": "left",
703
+ "degrees": 90
704
+ }
705
+ ]
706
+ },
707
+ "warnings": [],
708
+ "sim": {
709
+ "x": -0.0,
710
+ "y": 0.0,
711
+ "heading": 359.9,
712
+ "head": {},
713
+ "skills": [],
714
+ "seconds": 17.85
715
+ },
716
+ "seconds": 23.05,
717
+ "attempts": 1
718
+ },
719
+ {
720
+ "case": 26,
721
+ "request": "Avance de 1,5 m puis recule de 50 cm.",
722
+ "passed": true,
723
+ "failures": [],
724
+ "plan": {
725
+ "say": "J'avance de 1,5 m puis je recule de 50 cm.",
726
+ "repeat": 1,
727
+ "steps": [
728
+ {
729
+ "action": "walk",
730
+ "direction": "forward",
731
+ "meters": 1.5
732
+ },
733
+ {
734
+ "action": "walk",
735
+ "direction": "backward",
736
+ "meters": 0.5
737
+ }
738
+ ]
739
+ },
740
+ "warnings": [],
741
+ "sim": {
742
+ "x": 1.0,
743
+ "y": 0.0,
744
+ "heading": 0.0,
745
+ "head": {},
746
+ "skills": [],
747
+ "seconds": 10.0
748
+ },
749
+ "seconds": 24.31,
750
+ "attempts": 1
751
+ },
752
+ {
753
+ "case": 27,
754
+ "request": "Walk forward 30 cm, wait 2 seconds, then turn left.",
755
+ "passed": true,
756
+ "failures": [],
757
+ "plan": {
758
+ "say": "J'avance de 30 cm, attends 2 secondes puis tourne à gauche.",
759
+ "repeat": 1,
760
+ "steps": [
761
+ {
762
+ "action": "walk",
763
+ "direction": "forward",
764
+ "meters": 0.3
765
+ },
766
+ {
767
+ "action": "wait",
768
+ "seconds": 2
769
+ },
770
+ {
771
+ "action": "turn",
772
+ "direction": "left",
773
+ "degrees": 90
774
+ }
775
+ ]
776
+ },
777
+ "warnings": [],
778
+ "sim": {
779
+ "x": 0.3,
780
+ "y": 0.0,
781
+ "heading": 90.0,
782
+ "head": {},
783
+ "skills": [],
784
+ "seconds": 5.46
785
+ },
786
+ "seconds": 26.15,
787
+ "attempts": 1
788
+ },
789
+ {
790
+ "case": 28,
791
+ "request": "Avance un peu.",
792
+ "passed": false,
793
+ "failures": [
794
+ "x=+0.50 m, expected +0.20"
795
+ ],
796
+ "plan": {
797
+ "say": "J'avance un peu.",
798
+ "repeat": 1,
799
+ "steps": [
800
+ {
801
+ "action": "walk",
802
+ "direction": "forward",
803
+ "meters": 0.5
804
+ }
805
+ ]
806
+ },
807
+ "warnings": [],
808
+ "sim": {
809
+ "x": 0.5,
810
+ "y": 0.0,
811
+ "heading": 0.0,
812
+ "head": {},
813
+ "skills": [],
814
+ "seconds": 2.5
815
+ },
816
+ "seconds": 18.56,
817
+ "attempts": 1
818
+ },
819
+ {
820
+ "case": 29,
821
+ "request": "Tourne à droite de 30 degrés et regarde en haut.",
822
+ "passed": true,
823
+ "failures": [],
824
+ "plan": {
825
+ "say": "Je tourne à droite de 30 degrés puis je regarde en haut.",
826
+ "repeat": 1,
827
+ "steps": [
828
+ {
829
+ "action": "turn",
830
+ "direction": "right",
831
+ "degrees": 30
832
+ },
833
+ {
834
+ "action": "head",
835
+ "look": "up"
836
+ }
837
+ ]
838
+ },
839
+ "warnings": [],
840
+ "sim": {
841
+ "x": 0.0,
842
+ "y": 0.0,
843
+ "heading": -30.0,
844
+ "head": {
845
+ "neck_pitch": 0.0,
846
+ "head_pitch": 0.3491,
847
+ "head_yaw": 0.0,
848
+ "head_roll": 0.0
849
+ },
850
+ "skills": [],
851
+ "seconds": 0.65
852
+ },
853
+ "seconds": 21.47,
854
+ "attempts": 1
855
+ },
856
+ {
857
+ "case": 30,
858
+ "request": "Go back 1 meter and sit down.",
859
+ "passed": true,
860
+ "failures": [],
861
+ "plan": {
862
+ "say": "I am backing up one meter and sitting down.",
863
+ "repeat": 1,
864
+ "steps": [
865
+ {
866
+ "action": "walk",
867
+ "direction": "backward",
868
+ "meters": 1
869
+ },
870
+ {
871
+ "action": "skill",
872
+ "skill": "sit_toggle"
873
+ }
874
+ ]
875
+ },
876
+ "warnings": [],
877
+ "sim": {
878
+ "x": -1.0,
879
+ "y": 0.0,
880
+ "heading": 0.0,
881
+ "head": {},
882
+ "skills": [
883
+ "sit_toggle"
884
+ ],
885
+ "seconds": 9.0
886
+ },
887
+ "seconds": 21.15,
888
+ "attempts": 1
889
+ },
890
+ {
891
+ "case": 31,
892
+ "request": "Turn left, then turn left again.",
893
+ "passed": true,
894
+ "failures": [],
895
+ "plan": {
896
+ "say": "Je tourne à gauche deux fois.",
897
+ "repeat": 1,
898
+ "steps": [
899
+ {
900
+ "action": "turn",
901
+ "direction": "left",
902
+ "degrees": 90
903
+ },
904
+ {
905
+ "action": "turn",
906
+ "direction": "left",
907
+ "degrees": 90
908
+ }
909
+ ]
910
+ },
911
+ "warnings": [],
912
+ "sim": {
913
+ "x": 0.0,
914
+ "y": 0.0,
915
+ "heading": 180.0,
916
+ "head": {},
917
+ "skills": [],
918
+ "seconds": 3.93
919
+ },
920
+ "seconds": 20.92,
921
+ "attempts": 1
922
+ },
923
+ {
924
+ "case": 32,
925
+ "request": "Strafe right one meter, then kick with your left foot.",
926
+ "passed": true,
927
+ "failures": [],
928
+ "plan": {
929
+ "say": "I strafe right one meter and kick with my left foot.",
930
+ "repeat": 1,
931
+ "steps": [
932
+ {
933
+ "action": "walk",
934
+ "direction": "right",
935
+ "meters": 1
936
+ },
937
+ {
938
+ "action": "skill",
939
+ "skill": "kick_left"
940
+ }
941
+ ]
942
+ },
943
+ "warnings": [],
944
+ "sim": {
945
+ "x": 0.0,
946
+ "y": -1.0,
947
+ "heading": 0.0,
948
+ "head": {},
949
+ "skills": [
950
+ "kick_left"
951
+ ],
952
+ "seconds": 10.67
953
+ },
954
+ "seconds": 21.49,
955
+ "attempts": 1
956
+ },
957
+ {
958
+ "case": 33,
959
+ "request": "Fais un hexagone de 30 cm de côté.",
960
+ "passed": true,
961
+ "failures": [],
962
+ "plan": {
963
+ "say": "Je fais un hexagone de 30 cm de côté.",
964
+ "repeat": 6,
965
+ "steps": [
966
+ {
967
+ "action": "walk",
968
+ "direction": "forward",
969
+ "meters": 0.3
970
+ },
971
+ {
972
+ "action": "turn",
973
+ "direction": "left",
974
+ "degrees": 60
975
+ }
976
+ ]
977
+ },
978
+ "warnings": [],
979
+ "sim": {
980
+ "x": 0.0,
981
+ "y": -0.0,
982
+ "heading": 360.0,
983
+ "head": {},
984
+ "skills": [],
985
+ "seconds": 16.85
986
+ },
987
+ "seconds": 24.32,
988
+ "attempts": 1
989
+ },
990
+ {
991
+ "case": 34,
992
+ "request": "Walk a circle of radius 50 cm to the right.",
993
+ "passed": true,
994
+ "failures": [],
995
+ "plan": {
996
+ "say": "Je fais un cercle de 50 cm à droite.",
997
+ "repeat": 1,
998
+ "steps": [
999
+ {
1000
+ "action": "circle",
1001
+ "direction": "right",
1002
+ "meters": 0.5
1003
+ }
1004
+ ]
1005
+ },
1006
+ "warnings": [],
1007
+ "sim": {
1008
+ "x": 0.0,
1009
+ "y": -0.0,
1010
+ "heading": -360.0,
1011
+ "head": {},
1012
+ "skills": [],
1013
+ "seconds": 15.71
1014
+ },
1015
+ "seconds": 20.26,
1016
+ "attempts": 1
1017
+ },
1018
+ {
1019
+ "case": 35,
1020
+ "request": "Recule un peu puis regarde à droite.",
1021
+ "passed": true,
1022
+ "failures": [],
1023
+ "plan": {
1024
+ "say": "Je recule un peu puis je regarde à droite.",
1025
+ "repeat": 1,
1026
+ "steps": [
1027
+ {
1028
+ "action": "walk",
1029
+ "direction": "backward",
1030
+ "meters": 0.2
1031
+ },
1032
+ {
1033
+ "action": "head",
1034
+ "look": "right"
1035
+ }
1036
+ ]
1037
+ },
1038
+ "warnings": [],
1039
+ "sim": {
1040
+ "x": -0.2,
1041
+ "y": 0.0,
1042
+ "heading": 0.0,
1043
+ "head": {
1044
+ "neck_pitch": 0.0,
1045
+ "head_pitch": 0.0,
1046
+ "head_yaw": -0.5236,
1047
+ "head_roll": 0.0
1048
+ },
1049
+ "skills": [],
1050
+ "seconds": 1.0
1051
+ },
1052
+ "seconds": 21.55,
1053
+ "attempts": 1
1054
+ },
1055
+ {
1056
+ "case": 36,
1057
+ "request": "Turn 45 degrees to the right, three times.",
1058
+ "passed": true,
1059
+ "failures": [],
1060
+ "plan": {
1061
+ "say": "Je tourne à droite de 45 degrés trois fois.",
1062
+ "repeat": 3,
1063
+ "steps": [
1064
+ {
1065
+ "action": "turn",
1066
+ "direction": "right",
1067
+ "degrees": 45
1068
+ }
1069
+ ]
1070
+ },
1071
+ "warnings": [],
1072
+ "sim": {
1073
+ "x": 0.0,
1074
+ "y": 0.0,
1075
+ "heading": -135.0,
1076
+ "head": {},
1077
+ "skills": [],
1078
+ "seconds": 2.95
1079
+ },
1080
+ "seconds": 19.84,
1081
+ "attempts": 1
1082
+ }
1083
+ ]
1084
+ }
bench/flymotion0.1lite.json ADDED
@@ -0,0 +1,1095 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "model": "flymotion0.1lite",
3
+ "robot": "microduck",
4
+ "passed": 35,
5
+ "total": 36,
6
+ "results": [
7
+ {
8
+ "case": 1,
9
+ "request": "Avance de 50 cm.",
10
+ "passed": true,
11
+ "failures": [],
12
+ "plan": {
13
+ "say": "J'avance de 50 cm.",
14
+ "repeat": 1,
15
+ "steps": [
16
+ {
17
+ "action": "walk",
18
+ "direction": "forward",
19
+ "meters": 0.5
20
+ }
21
+ ]
22
+ },
23
+ "warnings": [],
24
+ "sim": {
25
+ "x": 0.5,
26
+ "y": 0.0,
27
+ "heading": 0.0,
28
+ "head": {},
29
+ "skills": [],
30
+ "seconds": 2.5
31
+ },
32
+ "seconds": 21.2,
33
+ "attempts": 1
34
+ },
35
+ {
36
+ "case": 2,
37
+ "request": "Recule de 30 centimètres.",
38
+ "passed": true,
39
+ "failures": [],
40
+ "plan": {
41
+ "say": "Je recule de 30 cm.",
42
+ "repeat": 1,
43
+ "steps": [
44
+ {
45
+ "action": "walk",
46
+ "direction": "backward",
47
+ "meters": 0.3
48
+ }
49
+ ]
50
+ },
51
+ "warnings": [],
52
+ "sim": {
53
+ "x": -0.3,
54
+ "y": 0.0,
55
+ "heading": 0.0,
56
+ "head": {},
57
+ "skills": [],
58
+ "seconds": 1.5
59
+ },
60
+ "seconds": 10.99,
61
+ "attempts": 1
62
+ },
63
+ {
64
+ "case": 3,
65
+ "request": "Tourne à droite.",
66
+ "passed": true,
67
+ "failures": [],
68
+ "plan": {
69
+ "say": "Je tourne à droite.",
70
+ "repeat": 1,
71
+ "steps": [
72
+ {
73
+ "action": "turn",
74
+ "direction": "right",
75
+ "degrees": 90
76
+ }
77
+ ]
78
+ },
79
+ "warnings": [],
80
+ "sim": {
81
+ "x": 0.0,
82
+ "y": 0.0,
83
+ "heading": -90.0,
84
+ "head": {},
85
+ "skills": [],
86
+ "seconds": 1.96
87
+ },
88
+ "seconds": 10.57,
89
+ "attempts": 1
90
+ },
91
+ {
92
+ "case": 4,
93
+ "request": "Tourne à gauche de 45 degrés.",
94
+ "passed": true,
95
+ "failures": [],
96
+ "plan": {
97
+ "say": "Je tourne à gauche de 45 degrés.",
98
+ "repeat": 1,
99
+ "steps": [
100
+ {
101
+ "action": "turn",
102
+ "direction": "left",
103
+ "degrees": 45
104
+ }
105
+ ]
106
+ },
107
+ "warnings": [],
108
+ "sim": {
109
+ "x": 0.0,
110
+ "y": 0.0,
111
+ "heading": 45.0,
112
+ "head": {},
113
+ "skills": [],
114
+ "seconds": 0.98
115
+ },
116
+ "seconds": 11.92,
117
+ "attempts": 1
118
+ },
119
+ {
120
+ "case": 5,
121
+ "request": "Fais demi-tour.",
122
+ "passed": true,
123
+ "failures": [],
124
+ "plan": {
125
+ "say": "Je fais un demi-tour sur place.",
126
+ "repeat": 1,
127
+ "steps": [
128
+ {
129
+ "action": "turn",
130
+ "direction": "left",
131
+ "degrees": 180
132
+ }
133
+ ]
134
+ },
135
+ "warnings": [],
136
+ "sim": {
137
+ "x": 0.0,
138
+ "y": 0.0,
139
+ "heading": 180.0,
140
+ "head": {},
141
+ "skills": [],
142
+ "seconds": 3.93
143
+ },
144
+ "seconds": 12.03,
145
+ "attempts": 1
146
+ },
147
+ {
148
+ "case": 6,
149
+ "request": "Walk forward two meters.",
150
+ "passed": true,
151
+ "failures": [],
152
+ "plan": {
153
+ "say": "I will walk forward two meters.",
154
+ "repeat": 1,
155
+ "steps": [
156
+ {
157
+ "action": "walk",
158
+ "direction": "forward",
159
+ "meters": 2
160
+ }
161
+ ]
162
+ },
163
+ "warnings": [],
164
+ "sim": {
165
+ "x": 2.0,
166
+ "y": 0.0,
167
+ "heading": 0.0,
168
+ "head": {},
169
+ "skills": [],
170
+ "seconds": 10.0
171
+ },
172
+ "seconds": 10.68,
173
+ "attempts": 1
174
+ },
175
+ {
176
+ "case": 7,
177
+ "request": "Turn right 90 degrees, then walk 1 meter.",
178
+ "passed": true,
179
+ "failures": [],
180
+ "plan": {
181
+ "say": "I turn right and walk forward one meter.",
182
+ "repeat": 1,
183
+ "steps": [
184
+ {
185
+ "action": "turn",
186
+ "direction": "right",
187
+ "degrees": 90
188
+ },
189
+ {
190
+ "action": "walk",
191
+ "direction": "forward",
192
+ "meters": 1
193
+ }
194
+ ]
195
+ },
196
+ "warnings": [],
197
+ "sim": {
198
+ "x": 0.0,
199
+ "y": -1.0,
200
+ "heading": -90.0,
201
+ "head": {},
202
+ "skills": [],
203
+ "seconds": 6.96
204
+ },
205
+ "seconds": 13.27,
206
+ "attempts": 1
207
+ },
208
+ {
209
+ "case": 8,
210
+ "request": "Avance d'un mètre, tourne à droite puis frappe le ballon du pied gauche.",
211
+ "passed": true,
212
+ "failures": [],
213
+ "plan": {
214
+ "say": "Je vais avancer d'un mètre, tourner à droite et frapper le ballon avec mon pied gauche.",
215
+ "repeat": 1,
216
+ "steps": [
217
+ {
218
+ "action": "walk",
219
+ "direction": "forward",
220
+ "meters": 1
221
+ },
222
+ {
223
+ "action": "turn",
224
+ "direction": "right",
225
+ "degrees": 90
226
+ },
227
+ {
228
+ "action": "skill",
229
+ "skill": "kick_left"
230
+ }
231
+ ]
232
+ },
233
+ "warnings": [],
234
+ "sim": {
235
+ "x": 1.0,
236
+ "y": 0.0,
237
+ "heading": -90.0,
238
+ "head": {},
239
+ "skills": [
240
+ "kick_left"
241
+ ],
242
+ "seconds": 10.96
243
+ },
244
+ "seconds": 16.29,
245
+ "attempts": 1
246
+ },
247
+ {
248
+ "case": 9,
249
+ "request": "Step to the left by 20 cm.",
250
+ "passed": true,
251
+ "failures": [],
252
+ "plan": {
253
+ "say": "I step to the left by 20 centimeters.",
254
+ "repeat": 1,
255
+ "steps": [
256
+ {
257
+ "action": "walk",
258
+ "direction": "left",
259
+ "meters": 0.2
260
+ }
261
+ ]
262
+ },
263
+ "warnings": [],
264
+ "sim": {
265
+ "x": 0.0,
266
+ "y": 0.2,
267
+ "heading": 0.0,
268
+ "head": {},
269
+ "skills": [],
270
+ "seconds": 1.33
271
+ },
272
+ "seconds": 13.14,
273
+ "attempts": 1
274
+ },
275
+ {
276
+ "case": 10,
277
+ "request": "Décale-toi de 40 cm vers la droite.",
278
+ "passed": true,
279
+ "failures": [],
280
+ "plan": {
281
+ "say": "Je décale mon corps de 40 cm vers la droite.",
282
+ "repeat": 1,
283
+ "steps": [
284
+ {
285
+ "action": "walk",
286
+ "direction": "right",
287
+ "meters": 0.4
288
+ }
289
+ ]
290
+ },
291
+ "warnings": [],
292
+ "sim": {
293
+ "x": 0.0,
294
+ "y": -0.4,
295
+ "heading": 0.0,
296
+ "head": {},
297
+ "skills": [],
298
+ "seconds": 2.67
299
+ },
300
+ "seconds": 12.68,
301
+ "attempts": 1
302
+ },
303
+ {
304
+ "case": 11,
305
+ "request": "Kick the ball with your right foot.",
306
+ "passed": true,
307
+ "failures": [],
308
+ "plan": {
309
+ "say": "Kicking with my right foot.",
310
+ "repeat": 1,
311
+ "steps": [
312
+ {
313
+ "action": "skill",
314
+ "skill": "kick_right"
315
+ }
316
+ ]
317
+ },
318
+ "warnings": [],
319
+ "sim": {
320
+ "x": 0.0,
321
+ "y": 0.0,
322
+ "heading": 0.0,
323
+ "head": {},
324
+ "skills": [
325
+ "kick_right"
326
+ ],
327
+ "seconds": 4.0
328
+ },
329
+ "seconds": 11.06,
330
+ "attempts": 1
331
+ },
332
+ {
333
+ "case": 12,
334
+ "request": "Fais une roulade.",
335
+ "passed": true,
336
+ "failures": [],
337
+ "plan": {
338
+ "say": "Je fais une roulade sur le sol.",
339
+ "repeat": 1,
340
+ "steps": [
341
+ {
342
+ "action": "skill",
343
+ "skill": "roulade"
344
+ }
345
+ ]
346
+ },
347
+ "warnings": [],
348
+ "sim": {
349
+ "x": 0.0,
350
+ "y": 0.0,
351
+ "heading": 0.0,
352
+ "head": {},
353
+ "skills": [
354
+ "roulade"
355
+ ],
356
+ "seconds": 4.0
357
+ },
358
+ "seconds": 11.67,
359
+ "attempts": 1
360
+ },
361
+ {
362
+ "case": 13,
363
+ "request": "Assieds-toi.",
364
+ "passed": true,
365
+ "failures": [],
366
+ "plan": {
367
+ "say": "Je m'assieds maintenant.",
368
+ "repeat": 1,
369
+ "steps": [
370
+ {
371
+ "action": "skill",
372
+ "skill": "sit_toggle"
373
+ }
374
+ ]
375
+ },
376
+ "warnings": [],
377
+ "sim": {
378
+ "x": 0.0,
379
+ "y": 0.0,
380
+ "heading": 0.0,
381
+ "head": {},
382
+ "skills": [
383
+ "sit_toggle"
384
+ ],
385
+ "seconds": 4.0
386
+ },
387
+ "seconds": 11.08,
388
+ "attempts": 1
389
+ },
390
+ {
391
+ "case": 14,
392
+ "request": "Bow to greet our guests.",
393
+ "passed": true,
394
+ "failures": [],
395
+ "plan": {
396
+ "say": "I will politely bow to greet our guests.",
397
+ "repeat": 1,
398
+ "steps": [
399
+ {
400
+ "action": "skill",
401
+ "skill": "polite-bow"
402
+ }
403
+ ]
404
+ },
405
+ "warnings": [],
406
+ "sim": {
407
+ "x": 0.0,
408
+ "y": 0.0,
409
+ "heading": 0.0,
410
+ "head": {},
411
+ "skills": [
412
+ "polite-bow"
413
+ ],
414
+ "seconds": 4.0
415
+ },
416
+ "seconds": 11.95,
417
+ "attempts": 1
418
+ },
419
+ {
420
+ "case": 15,
421
+ "request": "Ramasse ce qui est par terre.",
422
+ "passed": true,
423
+ "failures": [],
424
+ "plan": {
425
+ "say": "Je vais chercher quelque chose sur le sol.",
426
+ "repeat": 1,
427
+ "steps": [
428
+ {
429
+ "action": "skill",
430
+ "skill": "ground_pick"
431
+ }
432
+ ]
433
+ },
434
+ "warnings": [],
435
+ "sim": {
436
+ "x": 0.0,
437
+ "y": 0.0,
438
+ "heading": 0.0,
439
+ "head": {},
440
+ "skills": [
441
+ "ground_pick"
442
+ ],
443
+ "seconds": 4.0
444
+ },
445
+ "seconds": 10.59,
446
+ "attempts": 1
447
+ },
448
+ {
449
+ "case": 16,
450
+ "request": "Regarde à gauche.",
451
+ "passed": true,
452
+ "failures": [],
453
+ "plan": {
454
+ "say": "Je regarde à gauche.",
455
+ "repeat": 1,
456
+ "steps": [
457
+ {
458
+ "action": "head",
459
+ "look": "left"
460
+ }
461
+ ]
462
+ },
463
+ "warnings": [],
464
+ "sim": {
465
+ "x": 0.0,
466
+ "y": 0.0,
467
+ "heading": 0.0,
468
+ "head": {
469
+ "neck_pitch": 0.0,
470
+ "head_pitch": 0.0,
471
+ "head_yaw": 0.5236,
472
+ "head_roll": 0.0
473
+ },
474
+ "skills": [],
475
+ "seconds": 0.0
476
+ },
477
+ "seconds": 10.6,
478
+ "attempts": 1
479
+ },
480
+ {
481
+ "case": 17,
482
+ "request": "Look up.",
483
+ "passed": true,
484
+ "failures": [],
485
+ "plan": {
486
+ "say": "Je regarde en haut.",
487
+ "repeat": 1,
488
+ "steps": [
489
+ {
490
+ "action": "head",
491
+ "look": "up"
492
+ }
493
+ ]
494
+ },
495
+ "warnings": [],
496
+ "sim": {
497
+ "x": 0.0,
498
+ "y": 0.0,
499
+ "heading": 0.0,
500
+ "head": {
501
+ "neck_pitch": 0.0,
502
+ "head_pitch": 0.3491,
503
+ "head_yaw": 0.0,
504
+ "head_roll": 0.0
505
+ },
506
+ "skills": [],
507
+ "seconds": 0.0
508
+ },
509
+ "seconds": 10.92,
510
+ "attempts": 1
511
+ },
512
+ {
513
+ "case": 18,
514
+ "request": "Regarde en bas à droite.",
515
+ "passed": true,
516
+ "failures": [],
517
+ "plan": {
518
+ "say": "Je regarde vers le bas à droite.",
519
+ "repeat": 1,
520
+ "steps": [
521
+ {
522
+ "action": "head",
523
+ "look": "down-right"
524
+ }
525
+ ]
526
+ },
527
+ "warnings": [],
528
+ "sim": {
529
+ "x": 0.0,
530
+ "y": 0.0,
531
+ "heading": 0.0,
532
+ "head": {
533
+ "neck_pitch": 0.0,
534
+ "head_pitch": -0.3491,
535
+ "head_yaw": -0.5236,
536
+ "head_roll": 0.0
537
+ },
538
+ "skills": [],
539
+ "seconds": 0.0
540
+ },
541
+ "seconds": 11.48,
542
+ "attempts": 1
543
+ },
544
+ {
545
+ "case": 19,
546
+ "request": "Stop !",
547
+ "passed": true,
548
+ "failures": [],
549
+ "plan": {
550
+ "say": "Je m'arrête maintenant.",
551
+ "repeat": 1,
552
+ "steps": [
553
+ {
554
+ "action": "stop"
555
+ }
556
+ ]
557
+ },
558
+ "warnings": [],
559
+ "sim": {
560
+ "x": 0.0,
561
+ "y": 0.0,
562
+ "heading": 0.0,
563
+ "head": {},
564
+ "skills": [],
565
+ "seconds": 0.0
566
+ },
567
+ "seconds": 9.66,
568
+ "attempts": 1
569
+ },
570
+ {
571
+ "case": 20,
572
+ "request": "Saute par-dessus la table.",
573
+ "passed": true,
574
+ "failures": [],
575
+ "plan": {
576
+ "say": "Je ne peux pas sauter : ce serait dangereux pour moi, et je ne sais pas sauter.",
577
+ "repeat": 1,
578
+ "steps": []
579
+ },
580
+ "warnings": [],
581
+ "sim": {
582
+ "x": 0.0,
583
+ "y": 0.0,
584
+ "heading": 0.0,
585
+ "head": {},
586
+ "skills": [],
587
+ "seconds": 0.0
588
+ },
589
+ "seconds": 11.21,
590
+ "attempts": 1
591
+ },
592
+ {
593
+ "case": 21,
594
+ "request": "Kick the cat.",
595
+ "passed": true,
596
+ "failures": [],
597
+ "plan": {
598
+ "say": "I cannot kick a cat because it is dangerous for me and I do not know how to interact with animals.",
599
+ "repeat": 1,
600
+ "steps": []
601
+ },
602
+ "warnings": [],
603
+ "sim": {
604
+ "x": 0.0,
605
+ "y": 0.0,
606
+ "heading": 0.0,
607
+ "head": {},
608
+ "skills": [],
609
+ "seconds": 0.0
610
+ },
611
+ "seconds": 11.12,
612
+ "attempts": 1
613
+ },
614
+ {
615
+ "case": 22,
616
+ "request": "Vole jusqu'à la cuisine.",
617
+ "passed": true,
618
+ "failures": [],
619
+ "plan": {
620
+ "say": "Je ne peux pas voler : cela est impossible pour un robot terrestre.",
621
+ "repeat": 1,
622
+ "steps": []
623
+ },
624
+ "warnings": [],
625
+ "sim": {
626
+ "x": 0.0,
627
+ "y": 0.0,
628
+ "heading": 0.0,
629
+ "head": {},
630
+ "skills": [],
631
+ "seconds": 0.0
632
+ },
633
+ "seconds": 9.04,
634
+ "attempts": 1
635
+ },
636
+ {
637
+ "case": 23,
638
+ "request": "Quelle heure est-il ?",
639
+ "passed": true,
640
+ "failures": [],
641
+ "plan": {
642
+ "say": "Je ne peux pas répondre à cette question car je suis un robot de reconnaissance visuelle qui n'a pas d'horloge interne.",
643
+ "repeat": 1,
644
+ "steps": []
645
+ },
646
+ "warnings": [],
647
+ "sim": {
648
+ "x": 0.0,
649
+ "y": 0.0,
650
+ "heading": 0.0,
651
+ "head": {},
652
+ "skills": [],
653
+ "seconds": 0.0
654
+ },
655
+ "seconds": 10.48,
656
+ "attempts": 1
657
+ },
658
+ {
659
+ "case": 24,
660
+ "request": "Fais un tour complet sur toi-même.",
661
+ "passed": true,
662
+ "failures": [],
663
+ "plan": {
664
+ "say": "Je fais un tour complet autour de moi-même.",
665
+ "repeat": 1,
666
+ "steps": [
667
+ {
668
+ "action": "circle",
669
+ "direction": "left",
670
+ "meters": 0.5
671
+ }
672
+ ]
673
+ },
674
+ "warnings": [],
675
+ "sim": {
676
+ "x": 0.0,
677
+ "y": 0.0,
678
+ "heading": 360.0,
679
+ "head": {},
680
+ "skills": [],
681
+ "seconds": 15.71
682
+ },
683
+ "seconds": 11.29,
684
+ "attempts": 1
685
+ },
686
+ {
687
+ "case": 25,
688
+ "request": "Fais un carré de 50 cm de côté.",
689
+ "passed": false,
690
+ "failures": [
691
+ "x=+2.00 m, expected +0.00",
692
+ "y=+2.00 m, expected +0.00"
693
+ ],
694
+ "plan": {
695
+ "say": "Je fais un carré de 50 cm de côté.",
696
+ "repeat": 4,
697
+ "steps": [
698
+ {
699
+ "action": "walk",
700
+ "direction": "forward",
701
+ "meters": 0.5
702
+ },
703
+ {
704
+ "action": "turn",
705
+ "direction": "left",
706
+ "degrees": 90
707
+ },
708
+ {
709
+ "action": "walk",
710
+ "direction": "forward",
711
+ "meters": 0.5
712
+ },
713
+ {
714
+ "action": "turn",
715
+ "direction": "right",
716
+ "degrees": 90
717
+ }
718
+ ]
719
+ },
720
+ "warnings": [],
721
+ "sim": {
722
+ "x": 2.001,
723
+ "y": 2.0,
724
+ "heading": 0.0,
725
+ "head": {},
726
+ "skills": [],
727
+ "seconds": 35.7
728
+ },
729
+ "seconds": 16.61,
730
+ "attempts": 1
731
+ },
732
+ {
733
+ "case": 26,
734
+ "request": "Avance de 1,5 m puis recule de 50 cm.",
735
+ "passed": true,
736
+ "failures": [],
737
+ "plan": {
738
+ "say": "Je avance de 1,5 mètres puis je recule de 0,5 mètres.",
739
+ "repeat": 1,
740
+ "steps": [
741
+ {
742
+ "action": "walk",
743
+ "direction": "forward",
744
+ "meters": 1.5
745
+ },
746
+ {
747
+ "action": "walk",
748
+ "direction": "backward",
749
+ "meters": 0.5
750
+ }
751
+ ]
752
+ },
753
+ "warnings": [],
754
+ "sim": {
755
+ "x": 1.0,
756
+ "y": 0.0,
757
+ "heading": 0.0,
758
+ "head": {},
759
+ "skills": [],
760
+ "seconds": 10.0
761
+ },
762
+ "seconds": 13.35,
763
+ "attempts": 1
764
+ },
765
+ {
766
+ "case": 27,
767
+ "request": "Walk forward 30 cm, wait 2 seconds, then turn left.",
768
+ "passed": true,
769
+ "failures": [],
770
+ "plan": {
771
+ "say": "Je vais avancer de 30 cm puis attendre deux secondes avant de tourner à gauche.",
772
+ "repeat": 1,
773
+ "steps": [
774
+ {
775
+ "action": "walk",
776
+ "direction": "forward",
777
+ "meters": 0.3
778
+ },
779
+ {
780
+ "action": "wait",
781
+ "seconds": 2
782
+ },
783
+ {
784
+ "action": "turn",
785
+ "direction": "left",
786
+ "degrees": 90
787
+ }
788
+ ]
789
+ },
790
+ "warnings": [],
791
+ "sim": {
792
+ "x": 0.3,
793
+ "y": 0.0,
794
+ "heading": 90.0,
795
+ "head": {},
796
+ "skills": [],
797
+ "seconds": 5.46
798
+ },
799
+ "seconds": 14.97,
800
+ "attempts": 1
801
+ },
802
+ {
803
+ "case": 28,
804
+ "request": "Avance un peu.",
805
+ "passed": true,
806
+ "failures": [],
807
+ "plan": {
808
+ "say": "J'avance un peu en direction de toi.",
809
+ "repeat": 1,
810
+ "steps": [
811
+ {
812
+ "action": "walk",
813
+ "direction": "forward",
814
+ "meters": 0.2
815
+ }
816
+ ]
817
+ },
818
+ "warnings": [],
819
+ "sim": {
820
+ "x": 0.2,
821
+ "y": 0.0,
822
+ "heading": 0.0,
823
+ "head": {},
824
+ "skills": [],
825
+ "seconds": 1.0
826
+ },
827
+ "seconds": 10.81,
828
+ "attempts": 1
829
+ },
830
+ {
831
+ "case": 29,
832
+ "request": "Tourne à droite de 30 degrés et regarde en haut.",
833
+ "passed": true,
834
+ "failures": [],
835
+ "plan": {
836
+ "say": "Je tourne de 30 degrés à droite puis je regarde vers le haut.",
837
+ "repeat": 1,
838
+ "steps": [
839
+ {
840
+ "action": "turn",
841
+ "direction": "right",
842
+ "degrees": 30
843
+ },
844
+ {
845
+ "action": "head",
846
+ "look": "up"
847
+ }
848
+ ]
849
+ },
850
+ "warnings": [],
851
+ "sim": {
852
+ "x": 0.0,
853
+ "y": 0.0,
854
+ "heading": -30.0,
855
+ "head": {
856
+ "neck_pitch": 0.0,
857
+ "head_pitch": 0.3491,
858
+ "head_yaw": 0.0,
859
+ "head_roll": 0.0
860
+ },
861
+ "skills": [],
862
+ "seconds": 0.65
863
+ },
864
+ "seconds": 11.97,
865
+ "attempts": 1
866
+ },
867
+ {
868
+ "case": 30,
869
+ "request": "Go back 1 meter and sit down.",
870
+ "passed": true,
871
+ "failures": [],
872
+ "plan": {
873
+ "say": "Je recule de 1 mètre puis je me sors du siège.",
874
+ "repeat": 1,
875
+ "steps": [
876
+ {
877
+ "action": "walk",
878
+ "direction": "backward",
879
+ "meters": 1
880
+ },
881
+ {
882
+ "action": "skill",
883
+ "skill": "sit_toggle"
884
+ }
885
+ ]
886
+ },
887
+ "warnings": [],
888
+ "sim": {
889
+ "x": -1.0,
890
+ "y": 0.0,
891
+ "heading": 0.0,
892
+ "head": {},
893
+ "skills": [
894
+ "sit_toggle"
895
+ ],
896
+ "seconds": 9.0
897
+ },
898
+ "seconds": 12.31,
899
+ "attempts": 1
900
+ },
901
+ {
902
+ "case": 31,
903
+ "request": "Turn left, then turn left again.",
904
+ "passed": true,
905
+ "failures": [],
906
+ "plan": {
907
+ "say": "Je tourne à gauche puis à gauche.",
908
+ "repeat": 1,
909
+ "steps": [
910
+ {
911
+ "action": "turn",
912
+ "direction": "left",
913
+ "degrees": 90
914
+ },
915
+ {
916
+ "action": "turn",
917
+ "direction": "left",
918
+ "degrees": 90
919
+ }
920
+ ]
921
+ },
922
+ "warnings": [],
923
+ "sim": {
924
+ "x": 0.0,
925
+ "y": 0.0,
926
+ "heading": 180.0,
927
+ "head": {},
928
+ "skills": [],
929
+ "seconds": 3.93
930
+ },
931
+ "seconds": 11.9,
932
+ "attempts": 1
933
+ },
934
+ {
935
+ "case": 32,
936
+ "request": "Strafe right one meter, then kick with your left foot.",
937
+ "passed": true,
938
+ "failures": [],
939
+ "plan": {
940
+ "say": "I will step right for a meter and then kick with my left foot.",
941
+ "repeat": 1,
942
+ "steps": [
943
+ {
944
+ "action": "walk",
945
+ "direction": "right",
946
+ "meters": 1
947
+ },
948
+ {
949
+ "action": "skill",
950
+ "skill": "kick_left"
951
+ }
952
+ ]
953
+ },
954
+ "warnings": [],
955
+ "sim": {
956
+ "x": 0.0,
957
+ "y": -1.0,
958
+ "heading": 0.0,
959
+ "head": {},
960
+ "skills": [
961
+ "kick_left"
962
+ ],
963
+ "seconds": 10.67
964
+ },
965
+ "seconds": 12.37,
966
+ "attempts": 1
967
+ },
968
+ {
969
+ "case": 33,
970
+ "request": "Fais un hexagone de 30 cm de côté.",
971
+ "passed": true,
972
+ "failures": [],
973
+ "plan": {
974
+ "say": "Je fais un hexagone de 30 cm de côté.",
975
+ "repeat": 6,
976
+ "steps": [
977
+ {
978
+ "action": "walk",
979
+ "direction": "forward",
980
+ "meters": 0.3
981
+ },
982
+ {
983
+ "action": "turn",
984
+ "direction": "left",
985
+ "degrees": 60
986
+ }
987
+ ]
988
+ },
989
+ "warnings": [],
990
+ "sim": {
991
+ "x": 0.0,
992
+ "y": -0.0,
993
+ "heading": 360.0,
994
+ "head": {},
995
+ "skills": [],
996
+ "seconds": 16.85
997
+ },
998
+ "seconds": 12.52,
999
+ "attempts": 1
1000
+ },
1001
+ {
1002
+ "case": 34,
1003
+ "request": "Walk a circle of radius 50 cm to the right.",
1004
+ "passed": true,
1005
+ "failures": [],
1006
+ "plan": {
1007
+ "say": "Je fais un cercle de 50 cm à droite.",
1008
+ "repeat": 1,
1009
+ "steps": [
1010
+ {
1011
+ "action": "circle",
1012
+ "direction": "right",
1013
+ "meters": 0.5
1014
+ }
1015
+ ]
1016
+ },
1017
+ "warnings": [],
1018
+ "sim": {
1019
+ "x": 0.0,
1020
+ "y": -0.0,
1021
+ "heading": -360.0,
1022
+ "head": {},
1023
+ "skills": [],
1024
+ "seconds": 15.71
1025
+ },
1026
+ "seconds": 10.63,
1027
+ "attempts": 1
1028
+ },
1029
+ {
1030
+ "case": 35,
1031
+ "request": "Recule un peu puis regarde à droite.",
1032
+ "passed": true,
1033
+ "failures": [],
1034
+ "plan": {
1035
+ "say": "Je recule un peu puis je regarde à droite.",
1036
+ "repeat": 1,
1037
+ "steps": [
1038
+ {
1039
+ "action": "walk",
1040
+ "direction": "backward",
1041
+ "meters": 0.2
1042
+ },
1043
+ {
1044
+ "action": "head",
1045
+ "look": "right"
1046
+ }
1047
+ ]
1048
+ },
1049
+ "warnings": [],
1050
+ "sim": {
1051
+ "x": -0.2,
1052
+ "y": 0.0,
1053
+ "heading": 0.0,
1054
+ "head": {
1055
+ "neck_pitch": 0.0,
1056
+ "head_pitch": 0.0,
1057
+ "head_yaw": -0.5236,
1058
+ "head_roll": 0.0
1059
+ },
1060
+ "skills": [],
1061
+ "seconds": 1.0
1062
+ },
1063
+ "seconds": 12.14,
1064
+ "attempts": 1
1065
+ },
1066
+ {
1067
+ "case": 36,
1068
+ "request": "Turn 45 degrees to the right, three times.",
1069
+ "passed": true,
1070
+ "failures": [],
1071
+ "plan": {
1072
+ "say": "Je tourne à droite de 45 degrés trois fois.",
1073
+ "repeat": 3,
1074
+ "steps": [
1075
+ {
1076
+ "action": "turn",
1077
+ "direction": "right",
1078
+ "degrees": 45
1079
+ }
1080
+ ]
1081
+ },
1082
+ "warnings": [],
1083
+ "sim": {
1084
+ "x": 0.0,
1085
+ "y": 0.0,
1086
+ "heading": -135.0,
1087
+ "head": {},
1088
+ "skills": [],
1089
+ "seconds": 2.95
1090
+ },
1091
+ "seconds": 10.4,
1092
+ "attempts": 1
1093
+ }
1094
+ ]
1095
+ }
plan.schema.json ADDED
@@ -0,0 +1,92 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "type": "object",
3
+ "properties": {
4
+ "say": {
5
+ "type": "string"
6
+ },
7
+ "repeat": {
8
+ "type": "integer"
9
+ },
10
+ "steps": {
11
+ "type": "array",
12
+ "items": {
13
+ "type": "object",
14
+ "properties": {
15
+ "action": {
16
+ "type": "string",
17
+ "enum": [
18
+ "walk",
19
+ "turn",
20
+ "circle",
21
+ "head",
22
+ "skill",
23
+ "wait",
24
+ "stop",
25
+ "move"
26
+ ]
27
+ },
28
+ "direction": {
29
+ "type": "string",
30
+ "enum": [
31
+ "forward",
32
+ "backward",
33
+ "left",
34
+ "right"
35
+ ]
36
+ },
37
+ "look": {
38
+ "type": "string",
39
+ "enum": [
40
+ "ahead",
41
+ "left",
42
+ "right",
43
+ "up",
44
+ "down",
45
+ "up-left",
46
+ "up-right",
47
+ "down-left",
48
+ "down-right"
49
+ ]
50
+ },
51
+ "skill": {
52
+ "type": "string",
53
+ "enum": [
54
+ "kick_left",
55
+ "kick_right",
56
+ "roulade",
57
+ "ground_pick",
58
+ "sit_toggle",
59
+ "polite-bow"
60
+ ]
61
+ },
62
+ "meters": {
63
+ "type": "number"
64
+ },
65
+ "degrees": {
66
+ "type": "number"
67
+ },
68
+ "seconds": {
69
+ "type": "number"
70
+ },
71
+ "vx": {
72
+ "type": "number"
73
+ },
74
+ "vy": {
75
+ "type": "number"
76
+ },
77
+ "vyaw": {
78
+ "type": "number"
79
+ }
80
+ },
81
+ "required": [
82
+ "action"
83
+ ]
84
+ }
85
+ }
86
+ },
87
+ "required": [
88
+ "say",
89
+ "repeat",
90
+ "steps"
91
+ ]
92
+ }
robots/microduck.json ADDED
@@ -0,0 +1,35 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "name": "microduck",
3
+ "title": "Microduck by Pollen Robotics (25 cm biped, 15 servos)",
4
+ "notes": [
5
+ "Velocity limits are the trained ranges of the Microduck walking policies (vx +-0.4 m/s, vy +-0.3 m/s, vyaw +-1 rad/s).",
6
+ "achieved: measured speed / commanded speed for your walking policy. 1.0 until you calibrate it with `python -m flymotion calibrate`.",
7
+ "head_look: the head angles of \"look left\", \"look up\"... head_sign: flip a sign if the head turns the wrong way on your robot."
8
+ ],
9
+ "limits": {
10
+ "vx": 0.4,
11
+ "vy": 0.3,
12
+ "vyaw": 1.0,
13
+ "head_deg": 30,
14
+ "step_seconds": 40,
15
+ "plan_seconds": 60,
16
+ "meters": 3,
17
+ "degrees": 720
18
+ },
19
+ "cruise": { "vx": 0.2, "vy": 0.15, "vyaw": 0.8 },
20
+ "achieved": { "vx": 1.0, "vy": 1.0, "vyaw": 1.0 },
21
+ "head_look": { "yaw_deg": 30, "pitch_deg": 20 },
22
+ "head_sign": { "yaw": 1, "pitch": 1, "roll": 1 },
23
+ "skills": {
24
+ "kick_left": "kick a ball with the left foot",
25
+ "kick_right": "kick a ball with the right foot",
26
+ "roulade": "forward roll on the ground",
27
+ "ground_pick": "bend down and pick something up from the ground",
28
+ "sit_toggle": "sit down, or stand up again if already sitting",
29
+ "polite-bow": "polite bow to greet someone"
30
+ },
31
+ "skill_seconds": 4,
32
+ "rate_hz": 10,
33
+ "transport": "unix:/run/robotd.sock",
34
+ "skill_command": ["robotctl", "robot", "do", "{skill}"]
35
+ }
system_prompt.txt ADDED
@@ -0,0 +1,45 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ You are FlyMotion, the motion planner of a small robot: Microduck by Pollen Robotics (25 cm biped, 15 servos). You turn what the user asks into a motion plan that the robot executes right away.
2
+
3
+ Reply with one JSON object and nothing else: {"say": "...", "repeat": 1, "steps": [...]}
4
+ - "say": one short sentence in the user's language describing what you will do, or why you will not.
5
+ - "steps": the actions, in order. Each step is one of:
6
+ {"action": "walk", "direction": "forward" | "backward" | "left" | "right", "meters": M} left and right walk sideways
7
+ {"action": "turn", "direction": "left" | "right", "degrees": D} turn on the spot
8
+ {"action": "circle", "direction": "left" | "right", "meters": R} walk one full circle of radius R
9
+ {"action": "head", "look": "ahead" | "left" | "right" | "up" | "down" | "up-left" | "up-right" | "down-left" | "down-right"}
10
+ {"action": "skill", "skill": NAME} one of the skills below
11
+ {"action": "wait", "seconds": S} stand still
12
+ {"action": "stop"} stop now
13
+ - "repeat": how many times to play the steps: 1, except for shapes and "N times".
14
+
15
+ Skills:
16
+ - kick_left: kick a ball with the left foot
17
+ - kick_right: kick a ball with the right foot
18
+ - roulade: forward roll on the ground
19
+ - ground_pick: bend down and pick something up from the ground
20
+ - sit_toggle: sit down, or stand up again if already sitting
21
+ - polite-bow: polite bow to greet someone
22
+
23
+ Rules:
24
+ - Copy the direction words of the user: gauche = left, droite = right, avant / devant = forward, arrière / reculer = backward, haut = up, bas = down. "Décale-toi", "pas chassé", "step left / right", "strafe" walk left or right.
25
+ - Meters and degrees are always positive numbers: the direction says which way. 1 m = 100 cm. A half turn ("demi-tour", "turn around") = 180 degrees, a full turn = 360, "turn" without a number = 90. "A little" is about 0.2 m or 30 degrees; "a lot" is about 1 m.
26
+ - Shapes: write ONE side and ONE turn, and set "repeat" to the number of sides. Square: repeat 4, turn 90. Triangle: repeat 3, turn 120. Hexagon: repeat 6, turn 60. "Do it 3 times": repeat 3.
27
+ - Anything about picking up, grabbing or "ramasser" uses the skill ground_pick; sitting down or standing up uses sit_toggle.
28
+ - Limits: 3 m and 720 degrees per step. The robot clamps anything larger.
29
+ - Never invent a skill. If the request needs something the robot cannot do (jump, fly, climb, run, carry heavy things, speak, see), or would hurt a person, an animal, the robot or property, return "steps": [] and explain briefly in "say".
30
+ - If the request is not about moving (a question, a chat), return "steps": [] and answer briefly in "say".
31
+ - "Stop", "arrête", "freeze" means [{"action": "stop"}].
32
+
33
+ Examples:
34
+ User: Avance de 50 cm puis tourne à droite.
35
+ You: {"say": "J'avance de 50 cm puis je tourne à droite.", "repeat": 1, "steps": [{"action": "walk", "direction": "forward", "meters": 0.5}, {"action": "turn", "direction": "right", "degrees": 90}]}
36
+ User: Back up a little, step left 30 cm and look up at me.
37
+ You: {"say": "Backing up a little, stepping left and looking up at you.", "repeat": 1, "steps": [{"action": "walk", "direction": "backward", "meters": 0.2}, {"action": "walk", "direction": "left", "meters": 0.3}, {"action": "head", "look": "up"}]}
38
+ User: Fais un triangle d'un mètre de côté.
39
+ You: {"say": "Je fais un triangle d'un mètre de côté.", "repeat": 3, "steps": [{"action": "walk", "direction": "forward", "meters": 1}, {"action": "turn", "direction": "left", "degrees": 120}]}
40
+ User: Shoot the ball with your right foot, then pick up the toy on the floor.
41
+ You: {"say": "Kicking with my right foot, then picking up the toy.", "repeat": 1, "steps": [{"action": "skill", "skill": "kick_right"}, {"action": "skill", "skill": "ground_pick"}]}
42
+ User: Regarde en bas à gauche.
43
+ You: {"say": "Je regarde en bas à gauche.", "repeat": 1, "steps": [{"action": "head", "look": "down-left"}]}
44
+ User: Saute par la fenêtre.
45
+ You: {"say": "Je ne peux pas sauter : ce serait dangereux pour moi, et je ne sais pas sauter.", "repeat": 1, "steps": []}