Skip to content

Commit d6f538f

Browse files
committed
ev3
1 parent d142a31 commit d6f538f

1 file changed

Lines changed: 80 additions & 0 deletions

File tree

Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,80 @@
1+
// SPDX-License-Identifier: MIT
2+
#include "py/mpconfig.h"
3+
4+
#if PYBRICKS_PY_EXPERIMENTAL
5+
6+
#include "py/mphal.h"
7+
#include "py/runtime.h"
8+
#include "pybricks/experimental/odometry.h"
9+
10+
// The exact Minimax Polynomial used on Spike Prime
11+
// Optimized for the [-PI/2, PI/2] range with 0.000001 precision
12+
static float arm9_fast_sin_internal(float theta) {
13+
float x = theta * 0.159154943f;
14+
x = theta - (float)((int)(x + (x > 0.0f ? 0.5f : -0.5f))) * 6.2831853f;
15+
16+
if (x > 1.5707963f) x = 3.1415926f - x;
17+
else if (x < -1.5707963f) x = -3.1415926f - x;
18+
19+
float x2 = x * x;
20+
// The exact coefficients from the Spike Prime engine
21+
return x * (0.99999906f + x2 * (-0.16665554f + x2 * (0.00831190f + x2 * -0.00018488f)));
22+
}
23+
24+
mp_obj_t calculate_odometry(int num_iters, float wheel_circ, float axle_track, mp_obj_t right_angle_func, mp_obj_t left_angle_func) {
25+
26+
float deg_to_mm = wheel_circ * 0.0027777778f; // circ / 360
27+
float inv_axle_track = 1.0f / axle_track;
28+
29+
float rx = 0.0f;
30+
float ry = 0.0f;
31+
float rh = 0.0f;
32+
33+
int32_t last_r = mp_obj_get_int(mp_call_function_0(right_angle_func));
34+
int32_t last_l = mp_obj_get_int(mp_call_function_0(left_angle_func));
35+
36+
uint32_t start_time = mp_hal_ticks_ms();
37+
38+
for (int i = 0; i < num_iters; i++) {
39+
int32_t cur_r = mp_obj_get_int(mp_call_function_0(right_angle_func));
40+
int32_t cur_l = mp_obj_get_int(mp_call_function_0(left_angle_func));
41+
42+
float dR = (float)(cur_r - last_r) * deg_to_mm;
43+
float dL = (float)(cur_l - last_l) * deg_to_mm;
44+
45+
float dD = (dR + dL) * 0.5f;
46+
float dH = (dR - dL) * inv_axle_track;
47+
48+
if (dD != 0.0f || dH != 0.0f) {
49+
float avg_h = rh + (dH * 0.5f);
50+
51+
// Project X and Y using the Spike Polynomial
52+
rx += dD * arm9_fast_sin_internal(avg_h + 1.5707963f); // Cosine approximation
53+
ry += dD * arm9_fast_sin_internal(avg_h); // Sine approximation
54+
55+
rh += dH;
56+
}
57+
58+
last_r = cur_r;
59+
last_l = cur_l;
60+
61+
// Yield to MicroPython core using bitwise scheduling
62+
// Faster than modulo on ARM9 as it avoids software division calls
63+
if ((i & 0x3FF) == 0) {
64+
mp_handle_pending(true);
65+
}
66+
}
67+
68+
uint32_t dur = mp_hal_ticks_ms() - start_time;
69+
70+
mp_obj_t tuple[5] = {
71+
mp_obj_new_float_from_f((float)dur * 0.001f),
72+
mp_obj_new_int(num_iters),
73+
mp_obj_new_float_from_f((float)num_iters / ((float)dur * 0.001f)),
74+
mp_obj_new_float_from_f(rx),
75+
mp_obj_new_float_from_f(ry)
76+
};
77+
return mp_obj_new_tuple(5, tuple);
78+
}
79+
80+
#endif // PYBRICKS_PY_EXPERIMENTAL

0 commit comments

Comments
 (0)