Skip to content

Commit f11aae4

Browse files
committed
spike opt
1 parent d6f538f commit f11aae4

1 file changed

Lines changed: 88 additions & 0 deletions

File tree

Lines changed: 88 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,88 @@
1+
// SPDX-License-Identifier: MIT
2+
#include "py/mpconfig.h"
3+
4+
#if PYBRICKS_PY_EXPERIMENTAL
5+
#if defined(__ARM_ARCH_7M__) || defined(__ARM_ARCH_7EM__)
6+
7+
#include "py/mphal.h"
8+
#include "py/runtime.h"
9+
#include <math.h>
10+
#include "pybricks/experimental/odometry.h"
11+
12+
// Force the math functions into RAM for zero-wait-state execution
13+
#define ACCEL_RAM __attribute__((section(".data"), noinline))
14+
15+
// High-speed Minimax Polynomial for Sine/Cosine
16+
// This replaces the heavy math.h calls with raw FPU instructions
17+
ACCEL_RAM static float fast_sin_internal(float theta) {
18+
float x = theta * 0.159154943f;
19+
x = theta - (float)((int)(x + (x > 0.0f ? 0.5f : -0.5f))) * 6.2831853f;
20+
21+
if (x > 1.5707963f) x = 3.1415926f - x;
22+
else if (x < -1.5707963f) x = -3.1415926f - x;
23+
24+
float x2 = x * x;
25+
return x * (0.99999906f + x2 * (-0.16665554f + x2 * (0.00831190f + x2 * -0.00018488f)));
26+
}
27+
28+
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) {
29+
30+
// Pre-calculate kinematic constants
31+
float deg_to_mm = wheel_circ * 0.0027777778f; // (circ / 360)
32+
float inv_axle_track = 1.0f / axle_track;
33+
34+
// Robot state
35+
float rx = 0.0f;
36+
float ry = 0.0f;
37+
float rh = 0.0f;
38+
39+
// Initial sensor grab
40+
int32_t last_r = mp_obj_get_int(mp_call_function_0(right_angle_func));
41+
int32_t last_l = mp_obj_get_int(mp_call_function_0(left_angle_func));
42+
43+
uint32_t start_time = mp_hal_ticks_ms();
44+
45+
for (int i = 0; i < num_iters; i++) {
46+
// 1. Fetch encoder data (The primary Spike bottleneck)
47+
int32_t cur_r = mp_obj_get_int(mp_call_function_0(right_angle_func));
48+
int32_t cur_l = mp_obj_get_int(mp_call_function_0(left_angle_func));
49+
50+
// 2. Delta math
51+
float dR = (float)(cur_r - last_r) * deg_to_mm;
52+
float dL = (float)(cur_l - last_l) * deg_to_mm;
53+
float dD = (dR + dL) * 0.5f;
54+
float dH = (dR - dL) * inv_axle_track;
55+
56+
// 3. RK2 Midpoint Integration
57+
if (dD != 0.0f || dH != 0.0f) {
58+
float avg_h = rh + (dH * 0.5f);
59+
rx += dD * fast_sin_internal(avg_h + 1.5707963f); // cos
60+
ry += dD * fast_sin_internal(avg_h); // sin
61+
rh += dH;
62+
}
63+
64+
last_r = cur_r;
65+
last_l = cur_l;
66+
67+
// 4. Housekeeping (Polled, not delayed)
68+
// Checking every 1024 iterations (bitwise & is faster than % on M4)
69+
if ((i & 0x3FF) == 0) {
70+
mp_handle_pending(true);
71+
}
72+
}
73+
74+
uint32_t dur = mp_hal_ticks_ms() - start_time;
75+
76+
// Packaging results for Python
77+
mp_obj_t tuple[5] = {
78+
mp_obj_new_float_from_f((float)dur * 0.001f),
79+
mp_obj_new_int(num_iters),
80+
mp_obj_new_float_from_f((float)num_iters / ((float)dur * 0.001f)),
81+
mp_obj_new_float_from_f(rx),
82+
mp_obj_new_float_from_f(ry)
83+
};
84+
return mp_obj_new_tuple(5, tuple);
85+
}
86+
87+
#endif
88+
#endif

0 commit comments

Comments
 (0)