1313#include <pbio/tacho.h>
1414#include <pbio/drivebase.h>
1515
16- #if defined(__ARM_ARCH_7M__ ) || defined(__ARM_ARCH_7EM__ )
17- #define IS_CORTEX_M 1
18- #define ACCEL_RAM __attribute__((section(".data"), noinline))
19- #else
20- #define IS_CORTEX_M 0
21- #define ACCEL_RAM
22- #endif
23-
24- // Manually defining internal structures to bypass "Unknown Type" errors.
25- // This matches the memory layout used in Spike and EV3 firmware.
26- typedef struct _pb_type_Motor_obj_t {
27- mp_obj_base_t base ;
28- pbio_tacho_t * tacho ;
29- } pb_type_Motor_obj_t ;
30-
31- typedef struct _pb_type_DriveBase_obj_t {
32- mp_obj_base_t base ;
33- pbio_drivebase_t * db ;
34- } pb_type_DriveBase_obj_t ;
16+ // These headers contain the "Getters" we need
17+ #include "pybricks/pupdevices.h"
18+ #include "pybricks/robotics.h"
3519
3620// -----------------------------------------------------------------------------
37- // Core Math Engine (MiniMax Polynomial Sine)
21+ // Core Math Engine
3822// -----------------------------------------------------------------------------
39- ACCEL_RAM static float fast_sin_internal (float theta ) {
40- float x = theta * 0.159154943f ; // INV_TWO_PI
41- x = theta - (float )((int )(x + (x > 0 ? 0.5f : -0.5f ))) * 6.2831853f ; // TWO_PI
42- if (x > 1.5707963f ) x = 3.1415926f - x ; // HALF_PI, PI
23+ static float fast_sin_internal (float theta ) {
24+ float x = theta * 0.159154943f ;
25+ x = theta - (float )((int )(x + (x > 0 ? 0.5f : -0.5f ))) * 6.2831853f ;
26+ if (x > 1.5707963f ) x = 3.1415926f - x ;
4327 else if (x < -1.5707963f ) x = -3.1415926f - x ;
4428 float x2 = x * x ;
4529 return x * (0.99999906f + x2 * (-0.16665554f + x2 * (0.00831190f + x2 * -0.00018488f )));
4630}
4731
4832// -----------------------------------------------------------------------------
49- // High-Speed Direct-Tacho Odometry
33+ // High-Speed API-Based Odometry
5034// -----------------------------------------------------------------------------
5135static mp_obj_t experimental_odometry_benchmark (size_t n_args , const mp_obj_t * args ) {
5236 int num_iters = mp_obj_get_int (args [0 ]);
5337 float wheel_circ = mp_obj_get_float (args [1 ]);
5438
55- // Cast raw Python objects to our manual C-struct definitions
56- pb_type_Motor_obj_t * right_motor = (pb_type_Motor_obj_t * )MP_OBJ_TO_PTR (args [2 ]);
57- pb_type_Motor_obj_t * left_motor = (pb_type_Motor_obj_t * )MP_OBJ_TO_PTR (args [3 ]);
58- pb_type_DriveBase_obj_t * db_obj = (pb_type_DriveBase_obj_t * )MP_OBJ_TO_PTR (args [4 ]);
39+ // Use the OFFICIAL Pybricks getters to retrieve the C-pointers.
40+ // This is the "Nuclear" fix: it works regardless of struct padding.
41+ pbio_tacho_t * right_tacho = pb_type_Motor_get_tacho (args [2 ]);
42+ pbio_tacho_t * left_tacho = pb_type_Motor_get_tacho (args [3 ]);
43+ pbio_drivebase_t * db = pb_type_drivebase_get_drivebase (args [4 ]);
5944
6045 float deg_to_mm = wheel_circ / 360.0f ;
6146 float robot_x = 0.0f , robot_y = 0.0f ;
6247
6348 pbio_angle_t ang_l , ang_r ;
6449 int32_t h_mdeg ;
6550
66- // Initial state
67- pbio_tacho_get_angle (left_motor -> tacho , & ang_l );
68- pbio_tacho_get_angle (right_motor -> tacho , & ang_r );
69- pbio_drivebase_get_state_user (db_obj -> db , NULL , NULL , & h_mdeg , NULL );
51+ // Capture initial state
52+ pbio_tacho_get_angle (left_tacho , & ang_l );
53+ pbio_tacho_get_angle (right_tacho , & ang_r );
54+ pbio_drivebase_get_state_user (db , NULL , NULL , & h_mdeg , NULL );
7055
7156 float last_l_mm = ((float )ang_l .rotations * 360.0f + (float )ang_l .millidegrees / 1000.0f ) * deg_to_mm ;
7257 float last_r_mm = ((float )ang_r .rotations * 360.0f + (float )ang_r .millidegrees / 1000.0f ) * deg_to_mm ;
@@ -76,10 +61,9 @@ static mp_obj_t experimental_odometry_benchmark(size_t n_args, const mp_obj_t *a
7661 uint32_t start_time = mp_hal_ticks_ms ();
7762
7863 for (int i = 0 ; i < num_iters ; i ++ ) {
79- // Direct Hardware Access
80- pbio_tacho_get_angle (left_motor -> tacho , & ang_l );
81- pbio_tacho_get_angle (right_motor -> tacho , & ang_r );
82- pbio_drivebase_get_state_user (db_obj -> db , NULL , NULL , & h_mdeg , NULL );
64+ pbio_tacho_get_angle (left_tacho , & ang_l );
65+ pbio_tacho_get_angle (right_tacho , & ang_r );
66+ pbio_drivebase_get_state_user (db , NULL , NULL , & h_mdeg , NULL );
8367
8468 float cur_l_mm = ((float )ang_l .rotations * 360.0f + (float )ang_l .millidegrees / 1000.0f ) * deg_to_mm ;
8569 float cur_r_mm = ((float )ang_r .rotations * 360.0f + (float )ang_r .millidegrees / 1000.0f ) * deg_to_mm ;
@@ -91,14 +75,14 @@ static mp_obj_t experimental_odometry_benchmark(size_t n_args, const mp_obj_t *a
9175
9276 if (fabsf (linear_delta ) > 0.0001f ) {
9377 float avg_h_rad = (last_heading + (heading_delta / 2.0f )) * 0.01745329f ;
94- robot_x += linear_delta * fast_sin_internal (avg_h_rad + 1.5707963f ); // cos
95- robot_y += linear_delta * fast_sin_internal (avg_h_rad ); // sin
78+ robot_x += linear_delta * fast_sin_internal (avg_h_rad + 1.5707963f );
79+ robot_y += linear_delta * fast_sin_internal (avg_h_rad );
9680 }
9781
9882 last_lin = cur_lin ;
9983 last_heading = cur_heading ;
10084
101- // Yield to hub system every 2000 loops
85+ // Yield for stability
10286 if ((i % 2000 ) == 0 ) {
10387 mp_handle_pending (true);
10488 mp_hal_delay_ms (1 );
0 commit comments