Skip to content

Commit 1200a51

Browse files
committed
optimize spike
1 parent e1b2ae6 commit 1200a51

1 file changed

Lines changed: 20 additions & 16 deletions

File tree

pybricks/experimental/odometry.c

Lines changed: 20 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,9 @@
1212
#include <pbio/servo.h>
1313
#include "pybricks/experimental/odometry.h"
1414

15+
// THE LIFELINE: Bring in the Pybricks background task runner!
16+
extern bool pbio_os_run_processes_once(void);
17+
1518
// Hardware acceleration for the Spike Prime (FPU + RAM execution)
1619
#if defined(__ARM_ARCH_7M__) || defined(__ARM_ARCH_7EM__)
1720
#define ACCEL_RAM __attribute__((section(".data"), noinline))
@@ -42,13 +45,10 @@ mp_obj_t calculate_odometry(int num_iters, float wheel_circ, float axle_track, m
4245
float ry = 0.0f;
4346
float rh = 0.0f;
4447

45-
// THE MAGIC: Extract the raw Pybricks hardware struct from the Python object.
46-
// This entirely removes the Python interpreter from the loop.
4748
pbio_servo_t *srv_r = ((pb_type_Motor_obj_t *)MP_OBJ_TO_PTR(right_motor_obj))->srv;
4849
pbio_servo_t *srv_l = ((pb_type_Motor_obj_t *)MP_OBJ_TO_PTR(left_motor_obj))->srv;
4950

5051
int32_t last_r, last_l, unused_rate;
51-
// Direct memory read to initialize
5252
pbio_servo_get_state_user(srv_r, &last_r, &unused_rate);
5353
pbio_servo_get_state_user(srv_l, &last_l, &unused_rate);
5454

@@ -57,30 +57,34 @@ mp_obj_t calculate_odometry(int num_iters, float wheel_circ, float axle_track, m
5757
for (int i = 0; i < num_iters; i++) {
5858
int32_t cur_r, cur_l;
5959

60-
// 1. Direct memory read (Instantaneous, 0 Python overhead)
60+
// 1. Instant Memory read
6161
pbio_servo_get_state_user(srv_r, &cur_r, &unused_rate);
6262
pbio_servo_get_state_user(srv_l, &cur_l, &unused_rate);
6363

64-
// 2. FPU Delta Math
65-
float dR = (float)(cur_r - last_r) * deg_to_mm;
66-
float dL = (float)(cur_l - last_l) * deg_to_mm;
67-
float dD = (dR + dL) * 0.5f;
68-
float dH = (dR - dL) * inv_axle_track;
64+
// 2. THE BYPASS: Only run heavy FPU math if the wheels physically moved!
65+
int32_t delta_r = cur_r - last_r;
66+
int32_t delta_l = cur_l - last_l;
67+
68+
if (delta_r != 0 || delta_l != 0) {
69+
float dR = (float)delta_r * deg_to_mm;
70+
float dL = (float)delta_l * deg_to_mm;
71+
float dD = (dR + dL) * 0.5f;
72+
float dH = (dR - dL) * inv_axle_track;
6973

70-
// 3. RK2 Integration
71-
if (dD != 0.0f || dH != 0.0f) {
7274
float avg_h = rh + (dH * 0.5f);
7375
rx += dD * fast_sin_internal(avg_h + 1.5707963f); // cos
7476
ry += dD * fast_sin_internal(avg_h); // sin
7577
rh += dH;
76-
}
7778

78-
last_r = cur_r;
79-
last_l = cur_l;
79+
last_r = cur_r;
80+
last_l = cur_l;
81+
}
8082

81-
// 4. Polling (bitwise check is faster than modulo)
82-
if ((i & 0x3FF) == 0) {
83+
// 3. THE LIFELINE: Pump the Pybricks OS so the motors actually drive
84+
// (Bitwise & is a lightning-fast way to do % 256)
85+
if ((i & 0xFF) == 0) {
8386
mp_handle_pending(true);
87+
while (pbio_os_run_processes_once()) {}
8488
}
8589
}
8690

0 commit comments

Comments
 (0)