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