Skip to content

Commit 8d511e5

Browse files
committed
odo test
1 parent d8c6a79 commit 8d511e5

1 file changed

Lines changed: 19 additions & 81 deletions

File tree

pybricks/experimental/pb_module_experimental.c

Lines changed: 19 additions & 81 deletions
Original file line numberDiff line numberDiff line change
@@ -18,12 +18,9 @@
1818
#if defined(__ARM_ARCH_7M__) || defined(__ARM_ARCH_7EM__)
1919
#define IS_CORTEX_M 1
2020
#define ACCEL_RAM __attribute__((section(".data"), noinline))
21-
#define DWT_CONTROL (*((volatile uint32_t*)0xE0001000))
22-
#define DWT_CYCCNT (*((volatile uint32_t*)0xE0001004))
23-
#define DEMCR (*((volatile uint32_t*)0xE000EDFC))
2421
#else
2522
#define IS_CORTEX_M 0
26-
#define ACCEL_RAM // EV3/Linux handles RAM loading automatically
23+
#define ACCEL_RAM
2724
#endif
2825

2926
// Constants
@@ -33,73 +30,35 @@ static const float HALF_PI_F = 1.570796326794896f;
3330
static const float INV_TWO_PI_F = 0.159154943091895f;
3431

3532
// -----------------------------------------------------------------------------
36-
// Core Math Engines (Lasse Schlör Absolute Error MiniMax Coefficients)
33+
// Core Math Engines
3734
// -----------------------------------------------------------------------------
3835

3936
ACCEL_RAM static float fast_sin_internal(float theta) {
40-
// 1. Precise Range Reduction to [-PI, PI]
4137
float x = theta * INV_TWO_PI_F;
4238
x = theta - (float)((int)(x + (x > 0 ? 0.5f : -0.5f))) * TWO_PI_F;
4339

44-
// 2. Quadrant folding to [-PI/2, PI/2]
4540
if (x > HALF_PI_F) { x = PI_F - x; }
4641
else if (x < -HALF_PI_F) { x = -PI_F - x; }
4742

4843
float x2 = x * x;
4944
float res;
5045

5146
#if IS_CORTEX_M
52-
// Spike Prime: Horner's Scheme for VMLA.F32 pipeline
5347
res = -0.0001848814f;
5448
res = 0.0083119000f + (x2 * res);
5549
res = -0.1666555409f + (x2 * res);
56-
res = 0.9999990609f + (x2 * res);
50+
res = 1.0f + (x2 * res); // Note: 1.0f is faster for absolute error Minimax
5751
#else
58-
// EV3: Minimized Absolute Error (~9.33e-7)
5952
res = 0.9999990609f + x2 * (-0.1666555409f + x2 * (0.0083119000f + x2 * -0.0001848814f));
6053
#endif
6154

6255
return x * res;
6356
}
6457

65-
ACCEL_RAM static float fast_atan2_internal(float y, float x) {
66-
if (x == 0.0f && y == 0.0f) return 0.0f;
67-
float abs_y = fabsf(y) + 1e-10f;
68-
float abs_x = fabsf(x);
69-
float angle;
70-
float r = (abs_x >= abs_y) ? (y / x) : (x / y);
71-
float den = 1.0f + (r * r * 0.28086f);
72-
float res_atan = r * (1.0f / den);
73-
74-
if (abs_x >= abs_y) {
75-
angle = res_atan;
76-
if (x < 0.0f) angle += (y >= 0.0f) ? PI_F : -PI_F;
77-
} else {
78-
angle = (y > 0.0f ? HALF_PI_F : -HALF_PI_F) - res_atan;
79-
}
80-
return angle;
81-
}
82-
8358
// -----------------------------------------------------------------------------
84-
// Python Wrappers & Hardware Benchmarks
59+
// Hardware Benchmarks
8560
// -----------------------------------------------------------------------------
8661

87-
static mp_obj_t experimental_sin(mp_obj_t theta_in) {
88-
return mp_obj_new_float_from_f(fast_sin_internal(mp_obj_get_float(theta_in)));
89-
}
90-
static MP_DEFINE_CONST_FUN_OBJ_1(experimental_sin_obj, experimental_sin);
91-
92-
static mp_obj_t experimental_cos(mp_obj_t theta_in) {
93-
return mp_obj_new_float_from_f(fast_sin_internal(mp_obj_get_float(theta_in) + HALF_PI_F));
94-
}
95-
static MP_DEFINE_CONST_FUN_OBJ_1(experimental_cos_obj, experimental_cos);
96-
97-
static mp_obj_t experimental_atan2(mp_obj_t y_in, mp_obj_t x_in) {
98-
return mp_obj_new_float_from_f(fast_atan2_internal(mp_obj_get_float(y_in), mp_obj_get_float(x_in)));
99-
}
100-
static MP_DEFINE_CONST_FUN_OBJ_2(experimental_atan2_obj, experimental_atan2);
101-
102-
// The NEW Hardware-Polling Odometry Benchmark
10362
static mp_obj_t experimental_odometry_benchmark(mp_obj_t num_iters_in, mp_obj_t wheel_circ_in) {
10463
int num_iters = mp_obj_get_int(num_iters_in);
10564
float wheel_circ = mp_obj_get_float(wheel_circ_in);
@@ -109,37 +68,40 @@ static mp_obj_t experimental_odometry_benchmark(mp_obj_t num_iters_in, mp_obj_t
10968
int32_t last_left = 0, last_right = 0;
11069
float heading = 0.0f;
11170

112-
// Initial fetch (Assuming Left=A, Right=D as per your robot)
113-
pbio_tacho_get_count(PBIO_PORT_ID_A, &last_left);
114-
pbio_tacho_get_count(PBIO_PORT_ID_D, &last_right);
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);
11574

11675
uint32_t start_time = mp_hal_ticks_ms();
11776

11877
for (int i = 0; i < num_iters; i++) {
11978
int32_t cur_left, cur_right;
120-
pbio_tacho_get_count(PBIO_PORT_ID_A, &cur_left);
121-
pbio_tacho_get_count(PBIO_PORT_ID_D, &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);
12281

12382
float d_left = (float)(cur_left - last_left) * deg_to_mm;
12483
float d_right = (float)(cur_right - last_right) * deg_to_mm;
12584
float linear_delta = (d_left + d_right) / 2.0f;
126-
float heading_delta = (d_right - d_left) / 96.0f; // 96mm axle track
85+
float heading_delta = (d_right - d_left) / 96.0f; // Axle track 96mm
12786

128-
if (fabsf(linear_delta) > 0.0f) {
87+
if (fabsf(linear_delta) > 0.0001f) {
12988
float avg_h = heading + (heading_delta / 2.0f);
130-
robot_x += linear_delta * fast_sin_internal(avg_h + HALF_PI_F); // Cos
131-
robot_y += linear_delta * fast_sin_internal(avg_h); // Sin
89+
robot_x += linear_delta * fast_sin_internal(avg_h + HALF_PI_F);
90+
robot_y += linear_delta * fast_sin_internal(avg_h);
13291
}
13392

13493
heading += heading_delta;
13594
last_left = cur_left;
13695
last_right = cur_right;
13796

138-
if ((i % 1000) == 0) { MICROPY_EVENT_POLL_HOOK }
97+
// FIX 2 & 3: Semicolon and proper event polling for Pybricks bricks
98+
if ((i % 1000) == 0) {
99+
mp_handle_pending(true);
100+
}
139101
}
140102

141103
uint32_t duration_ms = mp_hal_ticks_ms() - start_time;
142-
float duration = duration_ms / 1000.0f;
104+
float duration = (float)duration_ms / 1000.0f;
143105

144106
mp_obj_t tuple[5] = {
145107
mp_obj_new_float_from_f(duration),
@@ -152,33 +114,9 @@ static mp_obj_t experimental_odometry_benchmark(mp_obj_t num_iters_in, mp_obj_t
152114
}
153115
static MP_DEFINE_CONST_FUN_OBJ_2(experimental_odometry_benchmark_obj, experimental_odometry_benchmark);
154116

155-
// Original CPU-only benchmark for pure math testing
156-
static mp_obj_t experimental_benchmark_math(mp_obj_t seed_in) {
157-
float seed = mp_obj_get_float(seed_in);
158-
#if IS_CORTEX_M
159-
DEMCR |= 0x01000000; DWT_CONTROL |= 1;
160-
DWT_CYCCNT = 0;
161-
uint32_t start = DWT_CYCCNT;
162-
volatile float res = fast_sin_internal(seed);
163-
res = fast_sin_internal(res + 0.01f);
164-
__asm volatile ("dsb");
165-
return mp_obj_new_int((DWT_CYCCNT - start) / 2);
166-
#else
167-
uint32_t t0 = mp_hal_ticks_ms();
168-
volatile float res = seed;
169-
for(int i=0; i<50000; i++) { res = fast_sin_internal(res + 0.0001f); }
170-
return mp_obj_new_int(((mp_hal_ticks_ms() - t0) * 1000000) / 50000);
171-
#endif
172-
}
173-
static MP_DEFINE_CONST_FUN_OBJ_1(experimental_benchmark_math_obj, experimental_benchmark_math);
174-
175-
// Module Globals Table
117+
// Module Globals
176118
static const mp_rom_map_elem_t experimental_globals_table[] = {
177119
{ MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_experimental) },
178-
{ MP_ROM_QSTR(MP_QSTR_sin), MP_ROM_PTR(&experimental_sin_obj) },
179-
{ MP_ROM_QSTR(MP_QSTR_cos), MP_ROM_PTR(&experimental_cos_obj) },
180-
{ MP_ROM_QSTR(MP_QSTR_atan2), MP_ROM_PTR(&experimental_atan2_obj) },
181-
{ MP_ROM_QSTR(MP_QSTR_benchmark_math), MP_ROM_PTR(&experimental_benchmark_math_obj) },
182120
{ MP_ROM_QSTR(MP_QSTR_odometry_benchmark), MP_ROM_PTR(&experimental_odometry_benchmark_obj) },
183121
};
184122
static MP_DEFINE_CONST_DICT(pb_module_experimental_globals, experimental_globals_table);

0 commit comments

Comments
 (0)