@@ -31,53 +31,51 @@ ACCEL_RAM static float fast_sin_internal(float theta) {
3131}
3232
3333// -----------------------------------------------------------------------------
34- // High-Speed API Odometry
34+ // High-Speed API Odometry (Pure Encoders, No Gyro)
3535// -----------------------------------------------------------------------------
3636static mp_obj_t experimental_odometry_benchmark (size_t n_args , const mp_obj_t * args ) {
3737 int num_iters = mp_obj_get_int (args [0 ]);
3838 float wheel_circ = mp_obj_get_float (args [1 ]);
39+ float axle_track = mp_obj_get_float (args [2 ]); // Added so we can do wheel math
3940
40- // THE CORRECT WAY: Receive the bound MicroPython methods (e.g. motor.angle)
41- mp_obj_t right_angle_func = args [2 ];
42- mp_obj_t left_angle_func = args [3 ];
43- mp_obj_t db_heading_func = args [4 ];
41+ // Receive the bound MicroPython methods for the motors
42+ mp_obj_t right_angle_func = args [3 ];
43+ mp_obj_t left_angle_func = args [4 ];
4444
4545 float deg_to_mm = wheel_circ / 360.0f ;
4646 float robot_x = 0.0f , robot_y = 0.0f ;
47+ float current_heading_rad = 0.0f ;
4748
48- // Call the functions safely via the MicroPython VM dispatcher to get initial state
49+ // motor.angle() safely returns an integer
4950 int32_t last_r_deg = mp_obj_get_int (mp_call_function_0 (right_angle_func ));
5051 int32_t last_l_deg = mp_obj_get_int (mp_call_function_0 (left_angle_func ));
51- int32_t last_heading_deg = mp_obj_get_int (mp_call_function_0 (db_heading_func ));
52-
53- float last_r_mm = (float )last_r_deg * deg_to_mm ;
54- float last_l_mm = (float )last_l_deg * deg_to_mm ;
55- float last_lin = (last_l_mm + last_r_mm ) / 2.0f ;
5652
5753 uint32_t start_time = mp_hal_ticks_ms ();
5854
5955 for (int i = 0 ; i < num_iters ; i ++ ) {
60- // Execute the hardware read securely.
61- // This resolves to the internal Pybricks C-function automatically.
6256 int32_t cur_r_deg = mp_obj_get_int (mp_call_function_0 (right_angle_func ));
6357 int32_t cur_l_deg = mp_obj_get_int (mp_call_function_0 (left_angle_func ));
64- int32_t cur_heading_deg = mp_obj_get_int (mp_call_function_0 (db_heading_func ));
65-
66- float cur_r_mm = (float )cur_r_deg * deg_to_mm ;
67- float cur_l_mm = (float )cur_l_deg * deg_to_mm ;
68- float cur_lin = (cur_l_mm + cur_r_mm ) / 2.0f ;
69-
70- float linear_delta = cur_lin - last_lin ;
71- float heading_delta = (float )(cur_heading_deg - last_heading_deg );
7258
73- if (fabsf (linear_delta ) > 0.0001f ) {
74- float avg_h_rad = ((float )last_heading_deg + (heading_delta / 2.0f )) * 0.01745329f ;
75- robot_x += linear_delta * fast_sin_internal (avg_h_rad + 1.5707963f );
76- robot_y += linear_delta * fast_sin_internal (avg_h_rad );
59+ // Calculate distance traveled by each wheel in this specific loop step
60+ float delta_r_mm = (float )(cur_r_deg - last_r_deg ) * deg_to_mm ;
61+ float delta_l_mm = (float )(cur_l_deg - last_l_deg ) * deg_to_mm ;
62+
63+ // Kinematics: Center distance and heading change
64+ float linear_delta = (delta_r_mm + delta_l_mm ) / 2.0f ;
65+ float heading_delta_rad = (delta_r_mm - delta_l_mm ) / axle_track ;
66+
67+ if (fabsf (linear_delta ) > 0.0001f || fabsf (heading_delta_rad ) > 0.0001f ) {
68+ // Arc integration: use the average heading during the movement step
69+ float avg_h_rad = current_heading_rad + (heading_delta_rad / 2.0f );
70+
71+ robot_x += linear_delta * fast_sin_internal (avg_h_rad + 1.5707963f ); // cos
72+ robot_y += linear_delta * fast_sin_internal (avg_h_rad ); // sin
73+
74+ current_heading_rad += heading_delta_rad ;
7775 }
7876
79- last_lin = cur_lin ;
80- last_heading_deg = cur_heading_deg ;
77+ last_r_deg = cur_r_deg ;
78+ last_l_deg = cur_l_deg ;
8179
8280 // Yield for system stability
8381 if ((i % 2000 ) == 0 ) {
0 commit comments