Skip to content

Commit 55a0b6e

Browse files
committed
odo test
1 parent 8d511e5 commit 55a0b6e

1 file changed

Lines changed: 55 additions & 49 deletions

File tree

pybricks/experimental/pb_module_experimental.c

Lines changed: 55 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -10,11 +10,6 @@
1010
#include "py/runtime.h"
1111
#include <math.h>
1212

13-
// Direct Hardware Access Headers
14-
#include <pbio/tacho.h>
15-
#include <pbio/port.h>
16-
17-
// Architecture Detection & Optimization Macros
1813
#if defined(__ARM_ARCH_7M__) || defined(__ARM_ARCH_7EM__)
1914
#define IS_CORTEX_M 1
2015
#define ACCEL_RAM __attribute__((section(".data"), noinline))
@@ -30,9 +25,8 @@ static const float HALF_PI_F = 1.570796326794896f;
3025
static const float INV_TWO_PI_F = 0.159154943091895f;
3126

3227
// -----------------------------------------------------------------------------
33-
// Core Math Engines
28+
// Core Math Engine (Lasse Schlör Absolute Error Optimized)
3429
// -----------------------------------------------------------------------------
35-
3630
ACCEL_RAM static float fast_sin_internal(float theta) {
3731
float x = theta * INV_TWO_PI_F;
3832
x = theta - (float)((int)(x + (x > 0 ? 0.5f : -0.5f))) * TWO_PI_F;
@@ -41,68 +35,79 @@ ACCEL_RAM static float fast_sin_internal(float theta) {
4135
else if (x < -HALF_PI_F) { x = -PI_F - x; }
4236

4337
float x2 = x * x;
44-
float res;
45-
4638
#if IS_CORTEX_M
47-
res = -0.0001848814f;
39+
float res = -0.0001848814f;
4840
res = 0.0083119000f + (x2 * res);
4941
res = -0.1666555409f + (x2 * res);
50-
res = 1.0f + (x2 * res); // Note: 1.0f is faster for absolute error Minimax
42+
return x * (0.9999990609f + (x2 * res));
5143
#else
52-
res = 0.9999990609f + x2 * (-0.1666555409f + x2 * (0.0083119000f + x2 * -0.0001848814f));
44+
return x * (0.9999990609f + x2 * (-0.1666555409f + x2 * (0.0083119000f + x2 * -0.0001848814f)));
5345
#endif
54-
55-
return x * res;
46+
}
47+
48+
// Helper to safely unpack hardware values regardless of Pybricks version
49+
static float get_float_from_obj(mp_obj_t obj) {
50+
if (MP_OBJ_IS_SMALL_INT(obj)) {
51+
return (float)MP_OBJ_SMALL_INT_VALUE(obj);
52+
} else if (mp_obj_is_type(obj, &mp_type_float)) {
53+
return mp_obj_get_float(obj);
54+
} else {
55+
return (float)mp_obj_get_int(obj);
56+
}
5657
}
5758

5859
// -----------------------------------------------------------------------------
59-
// Hardware Benchmarks
60+
// The "No-Tax" Odometry Benchmark
6061
// -----------------------------------------------------------------------------
61-
62-
static mp_obj_t experimental_odometry_benchmark(mp_obj_t num_iters_in, mp_obj_t wheel_circ_in) {
63-
int num_iters = mp_obj_get_int(num_iters_in);
64-
float wheel_circ = mp_obj_get_float(wheel_circ_in);
65-
float deg_to_mm = wheel_circ / 360.0f;
66-
67-
float robot_x = 0.0f, robot_y = 0.0f;
68-
int32_t last_left = 0, last_right = 0;
69-
float heading = 0.0f;
62+
static mp_obj_t experimental_odometry_benchmark(size_t n_args, const mp_obj_t *args) {
63+
// 1. Unpack Python Arguments
64+
int num_iters = mp_obj_get_int(args[0]);
65+
float wheel_circ = get_float_from_obj(args[1]);
66+
mp_obj_t right_angle_func = args[2];
67+
mp_obj_t left_angle_func = args[3];
68+
mp_obj_t db_angle_func = args[4];
69+
70+
float deg_to_mm = wheel_circ / 720.0f;
7071

71-
// FIX 1: Updated to pbio_tacho_get_angle
72-
pbio_tacho_get_angle(pbio_tacho_get_tacho(PBIO_PORT_ID_A), &last_left);
73-
pbio_tacho_get_angle(pbio_tacho_get_tacho(PBIO_PORT_ID_D), &last_right);
72+
// State variables
73+
float robot_x = 0.0f, robot_y = 0.0f;
74+
float last_linear = 0.0f;
75+
float last_heading = 0.0f;
7476

7577
uint32_t start_time = mp_hal_ticks_ms();
7678

79+
// 2. The Core High-Speed C Loop
7780
for (int i = 0; i < num_iters; i++) {
78-
int32_t cur_left, cur_right;
79-
pbio_tacho_get_angle(pbio_tacho_get_tacho(PBIO_PORT_ID_A), &cur_left);
80-
pbio_tacho_get_angle(pbio_tacho_get_tacho(PBIO_PORT_ID_D), &cur_right);
81-
82-
float d_left = (float)(cur_left - last_left) * deg_to_mm;
83-
float d_right = (float)(cur_right - last_right) * deg_to_mm;
84-
float linear_delta = (d_left + d_right) / 2.0f;
85-
float heading_delta = (d_right - d_left) / 96.0f; // Axle track 96mm
86-
87-
if (fabsf(linear_delta) > 0.0001f) {
88-
float avg_h = heading + (heading_delta / 2.0f);
89-
robot_x += linear_delta * fast_sin_internal(avg_h + HALF_PI_F);
90-
robot_y += linear_delta * fast_sin_internal(avg_h);
81+
82+
// Execute the exact same hardware getters as your Python script
83+
float right_angle = get_float_from_obj(mp_call_function_0(right_angle_func));
84+
float left_angle = get_float_from_obj(mp_call_function_0(left_angle_func));
85+
float robot_heading = get_float_from_obj(mp_call_function_0(db_angle_func));
86+
87+
// Exactly mirroring your Python math logic
88+
float current_linear = (right_angle + left_angle) * deg_to_mm;
89+
float linear = current_linear - last_linear;
90+
float heading_difference = robot_heading - last_heading;
91+
92+
last_linear = current_linear;
93+
last_heading = robot_heading;
94+
95+
if (fabsf(linear) > 0.0f) {
96+
float avg_heading_deg = last_heading - (heading_difference / 2.0f);
97+
float avg_heading_rad = avg_heading_deg * 0.0174532925f; // DEG_TO_RAD
98+
99+
robot_x += linear * fast_sin_internal(avg_heading_rad + HALF_PI_F); // cos
100+
robot_y += linear * fast_sin_internal(avg_heading_rad); // sin
91101
}
92102

93-
heading += heading_delta;
94-
last_left = cur_left;
95-
last_right = cur_right;
96-
97-
// FIX 2 & 3: Semicolon and proper event polling for Pybricks bricks
98-
if ((i % 1000) == 0) {
99-
mp_handle_pending(true);
100-
}
103+
// Safety: Prevent watchdog timeouts during massive loops
104+
if ((i % 1000) == 0) { mp_handle_pending(true); }
101105
}
102106

103107
uint32_t duration_ms = mp_hal_ticks_ms() - start_time;
104108
float duration = (float)duration_ms / 1000.0f;
105109

110+
// 3. Return Results Tuple
106111
mp_obj_t tuple[5] = {
107112
mp_obj_new_float_from_f(duration),
108113
mp_obj_new_int(num_iters),
@@ -112,7 +117,8 @@ static mp_obj_t experimental_odometry_benchmark(mp_obj_t num_iters_in, mp_obj_t
112117
};
113118
return mp_obj_new_tuple(5, tuple);
114119
}
115-
static MP_DEFINE_CONST_FUN_OBJ_2(experimental_odometry_benchmark_obj, experimental_odometry_benchmark);
120+
// Define function accepting 5 arguments
121+
static MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(experimental_odometry_benchmark_obj, 5, 5, experimental_odometry_benchmark);
116122

117123
// Module Globals
118124
static const mp_rom_map_elem_t experimental_globals_table[] = {

0 commit comments

Comments
 (0)