1010#include "py/runtime.h"
1111#include <math.h>
1212
13- // Adjusted include paths to match Pybricks build system search paths
14- #include "pybricks/pupdevices.h"
15- #include "pybricks/robotics.h"
1613#include <pbio/tacho.h>
14+ #include <pbio/drivebase.h>
1715
1816#if defined(__ARM_ARCH_7M__ ) || defined(__ARM_ARCH_7EM__ )
1917 #define IS_CORTEX_M 1
2321 #define ACCEL_RAM
2422#endif
2523
26- // Constants
2724static const float PI_F = 3.141592653589793f ;
2825static const float TWO_PI_F = 6.283185307179586f ;
2926static const float HALF_PI_F = 1.570796326794896f ;
3027static const float INV_TWO_PI_F = 0.159154943091895f ;
3128
3229// -----------------------------------------------------------------------------
33- // Core Math Engine (Lasse Schlör Absolute Error Optimized)
30+ // Core Math Engine
3431// -----------------------------------------------------------------------------
3532ACCEL_RAM static float fast_sin_internal (float theta ) {
3633 float x = theta * INV_TWO_PI_F ;
3734 x = theta - (float )((int )(x + (x > 0 ? 0.5f : -0.5f ))) * TWO_PI_F ;
38-
3935 if (x > HALF_PI_F ) {
4036 x = PI_F - x ;
4137 } else if (x < - HALF_PI_F ) {
4238 x = - PI_F - x ;
4339 }
44-
4540 float x2 = x * x ;
4641 #if IS_CORTEX_M
4742 float res = -0.0001848814f ;
@@ -53,67 +48,67 @@ ACCEL_RAM static float fast_sin_internal(float theta) {
5348 #endif
5449}
5550
56- // Helper to safely unpack hardware values
57- static float get_float_from_obj (mp_obj_t obj ) {
58- if (MP_OBJ_IS_SMALL_INT (obj )) {
59- return (float )MP_OBJ_SMALL_INT_VALUE (obj );
60- } else if (mp_obj_is_type (obj , & mp_type_float )) {
61- return mp_obj_get_float (obj );
62- } else {
63- return (float )mp_obj_get_int (obj );
64- }
65- }
66-
6751// -----------------------------------------------------------------------------
68- // The " Bare Metal" Odometry Benchmark
52+ // High-Speed Bare Metal Odometry
6953// -----------------------------------------------------------------------------
7054static mp_obj_t experimental_odometry_benchmark (size_t n_args , const mp_obj_t * args ) {
7155 int num_iters = mp_obj_get_int (args [0 ]);
72- float wheel_circ = get_float_from_obj (args [1 ]);
56+ float wheel_circ = mp_obj_get_float (args [1 ]);
7357
74- // Unpack as pointers to Pybricks objects
75- // Note: We use the generic object pointer then cast to access members
76- pb_type_Motor_obj_t * right_motor = (pb_type_Motor_obj_t * )MP_OBJ_TO_PTR (args [2 ]);
77- pb_type_Motor_obj_t * left_motor = (pb_type_Motor_obj_t * )MP_OBJ_TO_PTR (args [3 ]);
78- pb_type_DriveBase_obj_t * db = (pb_type_DriveBase_obj_t * )MP_OBJ_TO_PTR (args [4 ]);
58+ // We use the raw PBIO Port IDs directly to avoid struct-naming conflicts
59+ // Assuming Port A = Left, Port D = Right (Standard EV3/Spike setup)
60+ pbio_tacho_t * tacho_l = pbio_tacho_get_tacho (PBIO_PORT_ID_A );
61+ pbio_tacho_t * tacho_r = pbio_tacho_get_tacho (PBIO_PORT_ID_D );
62+
63+ // Grab the global DriveBase pointer
64+ pbio_drivebase_t * db ;
65+ pbio_drivebase_get_drivebase (& db );
7966
8067 float deg_to_mm = wheel_circ / 720.0f ;
8168 float robot_x = 0.0f , robot_y = 0.0f ;
82- float last_linear = 0.0f , last_heading = 0.0f ;
69+
70+ pbio_angle_t ang_l , ang_r ;
71+ pbio_tacho_get_angle (tacho_l , & ang_l );
72+ pbio_tacho_get_angle (tacho_r , & ang_r );
73+
74+ float last_lin = (float )ang_l .rotations * 360.0f + (float )ang_l .millidegrees / 1000.0f +
75+ (float )ang_r .rotations * 360.0f + (float )ang_r .millidegrees / 1000.0f ;
76+ last_lin *= deg_to_mm ;
77+
78+ int32_t h_mdeg ;
79+ pbio_drivebase_get_state (db , NULL , NULL , & h_mdeg , NULL );
80+ float last_heading = (float )h_mdeg / 1000.0f ;
8381
8482 uint32_t start_time = mp_hal_ticks_ms ();
8583
8684 for (int i = 0 ; i < num_iters ; i ++ ) {
87- int32_t r_ang , l_ang ;
88- pbio_tacho_get_angle (right_motor -> tacho , & r_ang );
89- pbio_tacho_get_angle (left_motor -> tacho , & l_ang );
90-
91- // Heading access: On many Pybricks versions, it's inside a state struct
92- // We use the getter to be safe across EV3/Spike builds
93- float robot_heading = pbio_drivebase_get_heading (db -> db );
85+ pbio_tacho_get_angle (tacho_l , & ang_l );
86+ pbio_tacho_get_angle (tacho_r , & ang_r );
87+ pbio_drivebase_get_state (db , NULL , NULL , & h_mdeg , NULL );
9488
95- float current_linear = (float )( r_ang + l_ang ) * deg_to_mm ;
96- float linear = current_linear - last_linear ;
97- float heading_difference = robot_heading - last_heading ;
89+ float cur_lin = (( float )ang_l . rotations * 360.0f + ( float ) ang_l . millidegrees / 1000.0f +
90+ ( float ) ang_r . rotations * 360.0f + ( float ) ang_r . millidegrees / 1000.0f ) * deg_to_mm ;
91+ float cur_heading = ( float ) h_mdeg / 1000.0f ;
9892
99- last_linear = current_linear ;
100- last_heading = robot_heading ;
93+ float linear_delta = cur_lin - last_lin ;
94+ float heading_delta = cur_heading - last_heading ;
10195
102- if (fabsf (linear ) > 0.0f ) {
103- float avg_heading_deg = last_heading - (heading_difference / 2.0f );
104- float avg_heading_rad = avg_heading_deg * 0.0174532925f ;
105-
106- robot_x += linear * fast_sin_internal (avg_heading_rad + HALF_PI_F );
107- robot_y += linear * fast_sin_internal (avg_heading_rad );
96+ if (fabsf (linear_delta ) > 0.001f ) {
97+ float avg_h_rad = (last_heading + (heading_delta / 2.0f )) * 0.01745329f ;
98+ robot_x += linear_delta * fast_sin_internal (avg_h_rad + HALF_PI_F );
99+ robot_y += linear_delta * fast_sin_internal (avg_h_rad );
108100 }
109101
102+ last_lin = cur_lin ;
103+ last_heading = cur_heading ;
104+
110105 if ((i % 1000 ) == 0 ) {
111106 mp_handle_pending (true);
112107 }
113108 }
114109
115- uint32_t duration_ms = mp_hal_ticks_ms () - start_time ;
116- float duration = (float )duration_ms / 1000.0f ;
110+ uint32_t dur = mp_hal_ticks_ms () - start_time ;
111+ float duration = (float )dur / 1000.0f ;
117112
118113 mp_obj_t tuple [5 ] = {
119114 mp_obj_new_float_from_f (duration ),
@@ -125,7 +120,7 @@ static mp_obj_t experimental_odometry_benchmark(size_t n_args, const mp_obj_t *a
125120 return mp_obj_new_tuple (5 , tuple );
126121}
127122
128- static MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN (experimental_odometry_benchmark_obj , 5 , 5 , experimental_odometry_benchmark ) ;
123+ static MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN (experimental_odometry_benchmark_obj , 2 , 2 , experimental_odometry_benchmark ) ;
129124
130125static const mp_rom_map_elem_t experimental_globals_table [] = {
131126 { MP_ROM_QSTR (MP_QSTR___name__ ), MP_ROM_QSTR (MP_QSTR_experimental ) },
0 commit comments