Spaces:
Running
Running
Added antenna movement
Browse files
reachy_f1_commentator/src/motion_controller.py
CHANGED
|
@@ -216,7 +216,7 @@ class GestureLibrary:
|
|
| 216 |
"""Library of predefined gestures for F1 commentary.
|
| 217 |
|
| 218 |
Each gesture is defined as a sequence of movements using the 6-DOF
|
| 219 |
-
neck capabilities (pitch, yaw, roll, x, y, z).
|
| 220 |
|
| 221 |
Validates: Requirements 7.3, 7.4, 7.5, 7.6
|
| 222 |
"""
|
|
@@ -225,58 +225,59 @@ class GestureLibrary:
|
|
| 225 |
GESTURES = {
|
| 226 |
Gesture.NEUTRAL: GestureSequence(
|
| 227 |
movements=[
|
| 228 |
-
{"pitch": 0, "yaw": 0, "roll": 0, "x": 0, "y": 0, "z": 0,
|
|
|
|
| 229 |
],
|
| 230 |
total_duration=1.0
|
| 231 |
),
|
| 232 |
|
| 233 |
Gesture.NOD: GestureSequence(
|
| 234 |
movements=[
|
| 235 |
-
{"pitch": 10, "yaw": 0, "roll": 0, "duration": 0.3},
|
| 236 |
-
{"pitch": -5, "yaw": 0, "roll": 0, "duration": 0.3},
|
| 237 |
-
{"pitch": 0, "yaw": 0, "roll": 0, "duration": 0.3}
|
| 238 |
],
|
| 239 |
total_duration=0.9
|
| 240 |
),
|
| 241 |
|
| 242 |
Gesture.TURN_LEFT: GestureSequence(
|
| 243 |
movements=[
|
| 244 |
-
{"pitch": 0, "yaw": -30, "roll": 0, "duration": 0.5},
|
| 245 |
-
{"pitch": 0, "yaw": 0, "roll": 0, "duration": 0.5}
|
| 246 |
],
|
| 247 |
total_duration=1.0
|
| 248 |
),
|
| 249 |
|
| 250 |
Gesture.TURN_RIGHT: GestureSequence(
|
| 251 |
movements=[
|
| 252 |
-
{"pitch": 0, "yaw": 30, "roll": 0, "duration": 0.5},
|
| 253 |
-
{"pitch": 0, "yaw": 0, "roll": 0, "duration": 0.5}
|
| 254 |
],
|
| 255 |
total_duration=1.0
|
| 256 |
),
|
| 257 |
|
| 258 |
Gesture.EXCITED: GestureSequence(
|
| 259 |
movements=[
|
| 260 |
-
# Quick forward lean with look up
|
| 261 |
-
{"pitch": 15, "yaw": 5, "roll": 0, "z": 10, "duration": 0.3},
|
| 262 |
-
# Slight turn left
|
| 263 |
-
{"pitch": 10, "yaw": -10, "roll": 0, "z": 10, "duration": 0.3},
|
| 264 |
-
# Slight turn right
|
| 265 |
-
{"pitch": 10, "yaw": 10, "roll": 0, "z": 10, "duration": 0.3},
|
| 266 |
# Return to neutral
|
| 267 |
-
{"pitch": 0, "yaw": 0, "roll": 0, "z": 0, "duration": 0.4}
|
| 268 |
],
|
| 269 |
total_duration=1.3
|
| 270 |
),
|
| 271 |
|
| 272 |
Gesture.CONCERNED: GestureSequence(
|
| 273 |
movements=[
|
| 274 |
-
# Slow tilt left with slight down look
|
| 275 |
-
{"pitch": -5, "yaw": 0, "roll": -15, "duration": 0.6},
|
| 276 |
# Hold position
|
| 277 |
-
{"pitch": -5, "yaw": 0, "roll": -15, "duration": 0.4},
|
| 278 |
# Return to neutral slowly
|
| 279 |
-
{"pitch": 0, "yaw": 0, "roll": 0, "duration": 0.6}
|
| 280 |
],
|
| 281 |
total_duration=1.6
|
| 282 |
),
|
|
@@ -411,13 +412,18 @@ class MotionController:
|
|
| 411 |
z = movement.get("z", 0)
|
| 412 |
duration = movement.get("duration", 1.0)
|
| 413 |
|
|
|
|
|
|
|
|
|
|
|
|
|
| 414 |
# Apply speed limiting (Requirement 7.8)
|
| 415 |
duration = self._apply_speed_limit(pitch, yaw, roll, duration)
|
| 416 |
|
| 417 |
-
# Execute movement
|
| 418 |
success = self.reachy.move_head(
|
| 419 |
x=x, y=y, z=z,
|
| 420 |
roll=roll, pitch=pitch, yaw=yaw,
|
|
|
|
| 421 |
duration=duration,
|
| 422 |
method="minjerk"
|
| 423 |
)
|
|
|
|
| 216 |
"""Library of predefined gestures for F1 commentary.
|
| 217 |
|
| 218 |
Each gesture is defined as a sequence of movements using the 6-DOF
|
| 219 |
+
neck capabilities (pitch, yaw, roll, x, y, z) plus 2 antenna DOF.
|
| 220 |
|
| 221 |
Validates: Requirements 7.3, 7.4, 7.5, 7.6
|
| 222 |
"""
|
|
|
|
| 225 |
GESTURES = {
|
| 226 |
Gesture.NEUTRAL: GestureSequence(
|
| 227 |
movements=[
|
| 228 |
+
{"pitch": 0, "yaw": 0, "roll": 0, "x": 0, "y": 0, "z": 0,
|
| 229 |
+
"antennas": [0, 0], "duration": 1.0}
|
| 230 |
],
|
| 231 |
total_duration=1.0
|
| 232 |
),
|
| 233 |
|
| 234 |
Gesture.NOD: GestureSequence(
|
| 235 |
movements=[
|
| 236 |
+
{"pitch": 10, "yaw": 0, "roll": 0, "antennas": [10, 10], "duration": 0.3},
|
| 237 |
+
{"pitch": -5, "yaw": 0, "roll": 0, "antennas": [-5, -5], "duration": 0.3},
|
| 238 |
+
{"pitch": 0, "yaw": 0, "roll": 0, "antennas": [0, 0], "duration": 0.3}
|
| 239 |
],
|
| 240 |
total_duration=0.9
|
| 241 |
),
|
| 242 |
|
| 243 |
Gesture.TURN_LEFT: GestureSequence(
|
| 244 |
movements=[
|
| 245 |
+
{"pitch": 0, "yaw": -30, "roll": 0, "antennas": [-15, 5], "duration": 0.5},
|
| 246 |
+
{"pitch": 0, "yaw": 0, "roll": 0, "antennas": [0, 0], "duration": 0.5}
|
| 247 |
],
|
| 248 |
total_duration=1.0
|
| 249 |
),
|
| 250 |
|
| 251 |
Gesture.TURN_RIGHT: GestureSequence(
|
| 252 |
movements=[
|
| 253 |
+
{"pitch": 0, "yaw": 30, "roll": 0, "antennas": [5, -15], "duration": 0.5},
|
| 254 |
+
{"pitch": 0, "yaw": 0, "roll": 0, "antennas": [0, 0], "duration": 0.5}
|
| 255 |
],
|
| 256 |
total_duration=1.0
|
| 257 |
),
|
| 258 |
|
| 259 |
Gesture.EXCITED: GestureSequence(
|
| 260 |
movements=[
|
| 261 |
+
# Quick forward lean with look up and antennas up
|
| 262 |
+
{"pitch": 15, "yaw": 5, "roll": 0, "z": 10, "antennas": [30, 30], "duration": 0.3},
|
| 263 |
+
# Slight turn left with asymmetric antennas
|
| 264 |
+
{"pitch": 10, "yaw": -10, "roll": 0, "z": 10, "antennas": [35, 25], "duration": 0.3},
|
| 265 |
+
# Slight turn right with asymmetric antennas
|
| 266 |
+
{"pitch": 10, "yaw": 10, "roll": 0, "z": 10, "antennas": [25, 35], "duration": 0.3},
|
| 267 |
# Return to neutral
|
| 268 |
+
{"pitch": 0, "yaw": 0, "roll": 0, "z": 0, "antennas": [0, 0], "duration": 0.4}
|
| 269 |
],
|
| 270 |
total_duration=1.3
|
| 271 |
),
|
| 272 |
|
| 273 |
Gesture.CONCERNED: GestureSequence(
|
| 274 |
movements=[
|
| 275 |
+
# Slow tilt left with slight down look and drooping antennas
|
| 276 |
+
{"pitch": -5, "yaw": 0, "roll": -15, "antennas": [-20, -20], "duration": 0.6},
|
| 277 |
# Hold position
|
| 278 |
+
{"pitch": -5, "yaw": 0, "roll": -15, "antennas": [-20, -20], "duration": 0.4},
|
| 279 |
# Return to neutral slowly
|
| 280 |
+
{"pitch": 0, "yaw": 0, "roll": 0, "antennas": [0, 0], "duration": 0.6}
|
| 281 |
],
|
| 282 |
total_duration=1.6
|
| 283 |
),
|
|
|
|
| 412 |
z = movement.get("z", 0)
|
| 413 |
duration = movement.get("duration", 1.0)
|
| 414 |
|
| 415 |
+
# Extract antenna positions (in degrees, will be converted to radians)
|
| 416 |
+
antenna_angles = movement.get("antennas", [0, 0])
|
| 417 |
+
antennas = np.deg2rad(antenna_angles)
|
| 418 |
+
|
| 419 |
# Apply speed limiting (Requirement 7.8)
|
| 420 |
duration = self._apply_speed_limit(pitch, yaw, roll, duration)
|
| 421 |
|
| 422 |
+
# Execute movement with antennas
|
| 423 |
success = self.reachy.move_head(
|
| 424 |
x=x, y=y, z=z,
|
| 425 |
roll=roll, pitch=pitch, yaw=yaw,
|
| 426 |
+
antennas=antennas,
|
| 427 |
duration=duration,
|
| 428 |
method="minjerk"
|
| 429 |
)
|