Spaces:
Running
Running
Oliver Nitsche Claude Sonnet 4.6 commited on
Commit ·
1f086bc
1
Parent(s): 2fda523
Align motion API with AGENTS.md recommendations
Browse files- Use goto_target() directly for the WAKING look (recommended primary API),
with body_yaw=None to leave body position unchanged after wake_up()
- Replace set_target(head=_look_direction(...)) with look_at_world(duration=0)
in the ACTIVE scan loop; duration=0 calls set_target() internally
- Remove hand-rolled _look_direction() helper that duplicated SDK rotation logic
- Drop scipy dependency (only used by _look_direction)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- pyproject.toml +0 -1
- recognizer/main.py +3 -25
pyproject.toml
CHANGED
|
@@ -13,7 +13,6 @@ dependencies = [
|
|
| 13 |
"reachy-mini",
|
| 14 |
"onnxruntime",
|
| 15 |
"opencv-python-headless",
|
| 16 |
-
"scipy",
|
| 17 |
]
|
| 18 |
keywords = ["reachy-mini-app", "reachy-mini"]
|
| 19 |
|
|
|
|
| 13 |
"reachy-mini",
|
| 14 |
"onnxruntime",
|
| 15 |
"opencv-python-headless",
|
|
|
|
| 16 |
]
|
| 17 |
keywords = ["reachy-mini-app", "reachy-mini"]
|
| 18 |
|
recognizer/main.py
CHANGED
|
@@ -107,7 +107,8 @@ class Recognizer(ReachyMiniApp):
|
|
| 107 |
|
| 108 |
# Look toward the sound: DoA 0=left π/2=front π=right → world-y
|
| 109 |
y = math.sin(doa_angle - math.pi / 2) * 0.6
|
| 110 |
-
reachy_mini.look_at_world(1.0, y, 0.0,
|
|
|
|
| 111 |
|
| 112 |
active_start = time.time()
|
| 113 |
scan_t0 = active_start
|
|
@@ -125,9 +126,7 @@ class Recognizer(ReachyMiniApp):
|
|
| 125 |
# Gentle head scan so the robot looks alive while waiting
|
| 126 |
elapsed = now - scan_t0
|
| 127 |
y_scan = math.sin(2 * math.pi * 0.15 * elapsed) * SCAN_AMPLITUDE
|
| 128 |
-
reachy_mini.
|
| 129 |
-
head=_look_direction(1.0, y_scan, 0.0)
|
| 130 |
-
)
|
| 131 |
|
| 132 |
# Throttled face recognition
|
| 133 |
if now - last_face_check >= FACE_INTERVAL:
|
|
@@ -183,27 +182,6 @@ class Recognizer(ReachyMiniApp):
|
|
| 183 |
reachy_mini.goto_sleep()
|
| 184 |
|
| 185 |
|
| 186 |
-
def _look_direction(x: float, y: float, z: float) -> np.ndarray:
|
| 187 |
-
"""Return a 4×4 head-pose matrix that points the head toward (x, y, z)."""
|
| 188 |
-
from scipy.spatial.transform import Rotation as R
|
| 189 |
-
|
| 190 |
-
target = np.array([x, y, z], dtype=float)
|
| 191 |
-
target /= np.linalg.norm(target)
|
| 192 |
-
forward = np.array([1.0, 0.0, 0.0])
|
| 193 |
-
|
| 194 |
-
axis = np.cross(forward, target)
|
| 195 |
-
axis_norm = np.linalg.norm(axis)
|
| 196 |
-
if axis_norm < 1e-8:
|
| 197 |
-
rot_mat = np.eye(3) if np.dot(forward, target) > 0 else R.from_euler("y", 180, degrees=True).as_matrix()
|
| 198 |
-
else:
|
| 199 |
-
angle = np.arccos(np.clip(np.dot(forward, target), -1.0, 1.0))
|
| 200 |
-
rot_mat = R.from_rotvec(angle * axis / axis_norm).as_matrix()
|
| 201 |
-
|
| 202 |
-
pose = np.eye(4)
|
| 203 |
-
pose[:3, :3] = rot_mat
|
| 204 |
-
return pose
|
| 205 |
-
|
| 206 |
-
|
| 207 |
if __name__ == "__main__":
|
| 208 |
app = Recognizer()
|
| 209 |
try:
|
|
|
|
| 107 |
|
| 108 |
# Look toward the sound: DoA 0=left π/2=front π=right → world-y
|
| 109 |
y = math.sin(doa_angle - math.pi / 2) * 0.6
|
| 110 |
+
head_pose = reachy_mini.look_at_world(1.0, y, 0.0, perform_movement=False)
|
| 111 |
+
reachy_mini.goto_target(head=head_pose, duration=0.5, body_yaw=None)
|
| 112 |
|
| 113 |
active_start = time.time()
|
| 114 |
scan_t0 = active_start
|
|
|
|
| 126 |
# Gentle head scan so the robot looks alive while waiting
|
| 127 |
elapsed = now - scan_t0
|
| 128 |
y_scan = math.sin(2 * math.pi * 0.15 * elapsed) * SCAN_AMPLITUDE
|
| 129 |
+
reachy_mini.look_at_world(1.0, y_scan, 0.0, duration=0)
|
|
|
|
|
|
|
| 130 |
|
| 131 |
# Throttled face recognition
|
| 132 |
if now - last_face_check >= FACE_INTERVAL:
|
|
|
|
| 182 |
reachy_mini.goto_sleep()
|
| 183 |
|
| 184 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 185 |
if __name__ == "__main__":
|
| 186 |
app = Recognizer()
|
| 187 |
try:
|