Skip to content

Commit 93184b5

Browse files
committed
restructure please compile
1 parent d110f7d commit 93184b5

5 files changed

Lines changed: 78 additions & 109 deletions

File tree

bricks/_common/mphalport.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
// Bring in our background hook
2121
#if PYBRICKS_PY_EXPERIMENTAL
2222
extern void pb_background_odometry_update(void);
23+
extern void pb_background_pursuit_update(void); // Add this
2324
#endif
2425

2526
// Core delay function that does an efficient sleep and may switch thread context.
@@ -37,6 +38,7 @@ void mp_hal_delay_ms(mp_uint_t Delay) {
3738
// ---> EXPERIMENTAL ODOMETRY HOOK <---
3839
#if PYBRICKS_PY_EXPERIMENTAL
3940
pb_background_odometry_update();
41+
pb_background_pursuit_update();
4042
#endif
4143

4244
} while (pbdrv_clock_get_ms() - start < Delay);
Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,4 @@
11
# Always compile the shared Python wrapper
22
PYBRICKS_SRC_C += pybricks/experimental/pb_module_experimental.c
3+
PYBRICKS_SRC_C += pybricks/experimental/odometry.c
34

4-
# Routing logic based on PLATFORM
5-
ifeq ($(PLATFORM), $(filter $(PLATFORM), prime_hub essential_hub technic_hub))
6-
PYBRICKS_SRC_C += pybricks/experimental/odometry_cortexm4.c
7-
else ifeq ($(PLATFORM), ev3dev)
8-
PYBRICKS_SRC_C += pybricks/experimental/odometry_arm9.c
9-
endif

pybricks/experimental/odometry.c

Lines changed: 62 additions & 82 deletions
Original file line numberDiff line numberDiff line change
@@ -7,60 +7,33 @@
77
#include "py/runtime.h"
88
#include <math.h>
99

10-
// Core Pybricks headers for bare-metal hardware access
1110
#include <pybricks/common.h>
1211
#include <pbio/servo.h>
1312
#include "pybricks/experimental/odometry.h"
13+
#include "pybricks/experimental/platform_math.h"
1414

15-
// Hardware acceleration for the Spike Prime
16-
#if defined(__ARM_ARCH_7M__) || defined(__ARM_ARCH_7EM__)
17-
#define ACCEL_RAM __attribute__((section(".data"), noinline))
18-
#else
19-
#define ACCEL_RAM
20-
#endif
21-
22-
ACCEL_RAM static float fast_sin_internal(float theta) {
23-
float x = theta * 0.159154943f;
24-
x = theta - (float)((int)(x + (x > 0.00f ? 0.5f : -0.5f))) * 6.2831853f;
25-
26-
if (x > 1.5707963f) {
27-
x = 3.1415926f - x;
28-
} else if (x < -1.5707963f) {
29-
x = -3.1415926f - x;
30-
}
31-
32-
float x2 = x * x;
33-
return x * (0.99999906f + x2 * (-0.16665554f + x2 * (0.00831190f + x2 * -0.00018488f)));
34-
}
35-
36-
ACCEL_RAM static float fast_cos_internal(float theta) {
37-
return fast_sin_internal(theta + 1.57079633f);
38-
}
15+
// Hardware Pointers
16+
static pbio_servo_t *left_servo_ptr = NULL;
17+
static pbio_servo_t *right_servo_ptr = NULL;
3918

40-
// ---------------------------------------------------------
41-
// BACKGROUND ODOMETRY STATE MACHINE
42-
// ---------------------------------------------------------
19+
// Odometry State
4320
volatile bool odom_running = false;
4421
volatile uint32_t last_odom_time_ms = 0;
45-
46-
volatile float global_x = 0.0f;
47-
volatile float global_y = 0.0f;
48-
volatile float global_h = 0.0f;
49-
50-
volatile int32_t last_left_angle = 0;
51-
volatile int32_t last_right_angle = 0;
52-
22+
volatile float global_x = 0.0f, global_y = 0.0f, global_h = 0.0f;
23+
volatile int32_t last_left_angle = 0, last_right_angle = 0;
5324
float odom_deg_to_mm = 1.0f;
5425
float odom_inv_track = 1.0f;
5526

56-
pbio_servo_t *left_servo_ptr = NULL;
57-
pbio_servo_t *right_servo_ptr = NULL;
27+
// Pursuit State
28+
volatile bool pursuit_running = false;
29+
volatile float p_target_x = 0.0f, p_target_y = 0.0f, p_target_speed = 0.0f;
30+
volatile float p_stop_threshold_sq = 400.0f;
31+
32+
// --- Background Updates ---
5833

59-
// This is the hook that will run continuously in the OS background
6034
void pb_background_odometry_update(void) {
6135
if (!odom_running) return;
6236

63-
// Throttle to 200Hz (5ms) to prevent starving the motor controllers
6437
uint32_t now = mp_hal_ticks_ms();
6538
if (now - last_odom_time_ms < 5) return;
6639
last_odom_time_ms = now;
@@ -75,86 +48,93 @@ void pb_background_odometry_update(void) {
7548
if (delta_l != 0 || delta_r != 0) {
7649
float dL = (float)delta_l * odom_deg_to_mm;
7750
float dR = (float)delta_r * odom_deg_to_mm;
78-
7951
float dD = (dR + dL) * 0.5f;
8052
float dH = (dR - dL) * odom_inv_track;
8153
float avg_h = global_h + (dH * 0.5f);
8254

83-
global_x += dD * fast_cos_internal(avg_h);
84-
global_y += dD * fast_sin_internal(avg_h);
55+
global_x += dD * pb_fast_cos(avg_h);
56+
global_y += dD * pb_fast_sin(avg_h);
8557
global_h += dH;
8658

8759
last_left_angle = cur_l;
8860
last_right_angle = cur_r;
8961
}
9062
}
9163

92-
// Python API: experimental.start_odometry(left_motor, right_motor, circ, track, x, y, h)
64+
void pb_background_pursuit_update(void) {
65+
if (!pursuit_running || !left_servo_ptr || !right_servo_ptr) return;
66+
67+
float x_dif = p_target_x - global_x;
68+
float y_dif = p_target_y - global_y;
69+
float dist_sq = (x_dif * x_dif) + (y_dif * y_dif);
70+
71+
if (dist_sq < p_stop_threshold_sq) {
72+
pursuit_running = false;
73+
pbio_servo_stop(left_servo_ptr, PBIO_CONTROL_STOP_BRAKE);
74+
pbio_servo_stop(right_servo_ptr, PBIO_CONTROL_STOP_BRAKE);
75+
return;
76+
}
77+
78+
float relative_y = (y_dif * pb_fast_cos(global_h)) - (x_dif * pb_fast_sin(global_h));
79+
float m_left = 1.0f, m_right = 1.0f;
80+
81+
if (relative_y > 0.001f || relative_y < -0.001f) {
82+
float radius = -(dist_sq / (2.0f * relative_y));
83+
float two_r = 2.0f * radius;
84+
float track = 1.0f / odom_inv_track;
85+
m_right = two_r / (two_r + track);
86+
m_left = two_r / (two_r - track);
87+
}
88+
89+
pbio_servo_run_velocity(left_servo_ptr, (int32_t)(p_target_speed * m_left));
90+
pbio_servo_run_velocity(right_servo_ptr, (int32_t)(p_target_speed * m_right));
91+
}
92+
93+
// --- MicroPython API ---
94+
9395
mp_obj_t experimental_start_odometry(size_t n_args, const mp_obj_t *args) {
9496
left_servo_ptr = ((pb_type_Motor_obj_t *)MP_OBJ_TO_PTR(args[0]))->srv;
9597
right_servo_ptr = ((pb_type_Motor_obj_t *)MP_OBJ_TO_PTR(args[1]))->srv;
96-
9798
odom_deg_to_mm = mp_obj_get_float(args[2]) / 360.0f;
9899
odom_inv_track = 1.0f / mp_obj_get_float(args[3]);
99-
100100
global_x = mp_obj_get_float(args[4]);
101101
global_y = mp_obj_get_float(args[5]);
102102
global_h = mp_obj_get_float(args[6]);
103103

104104
int32_t unused_rate;
105105
pbio_servo_get_state_user(left_servo_ptr, (int32_t*)&last_left_angle, &unused_rate);
106106
pbio_servo_get_state_user(right_servo_ptr, (int32_t*)&last_right_angle, &unused_rate);
107-
108107
odom_running = true;
109108
return mp_const_none;
110109
}
111110

112-
// Python API: experimental.get_odometry() -> (x, y, h)
113111
mp_obj_t experimental_get_odometry(void) {
114-
mp_obj_t tuple[3] = {
115-
mp_obj_new_float_from_f(global_x),
116-
mp_obj_new_float_from_f(global_y),
117-
mp_obj_new_float_from_f(global_h)
118-
};
112+
mp_obj_t tuple[3] = { mp_obj_new_float_from_f(global_x), mp_obj_new_float_from_f(global_y), mp_obj_new_float_from_f(global_h) };
119113
return mp_obj_new_tuple(3, tuple);
120114
}
121115

122-
// Python API: experimental.stop_odometry()
123116
mp_obj_t experimental_stop_odometry(void) {
124117
odom_running = false;
125118
return mp_const_none;
126119
}
127120

128-
// ---------------------------------------------------------
129-
// PURE PURSUIT (Unchanged)
130-
// ---------------------------------------------------------
131-
mp_obj_t get_pure_pursuit_multipliers(float tx, float ty, float rx_pos, float ry_pos, float rh_ang, float track) {
132-
float x_dif = tx - rx_pos;
133-
float y_dif = ty - ry_pos;
134-
135-
float cos_h = fast_cos_internal(rh_ang);
136-
float sin_h = fast_sin_internal(rh_ang);
137-
138-
float relative_y = (y_dif * cos_h) - (x_dif * sin_h);
139-
140-
float m_left = 1.0f;
141-
float m_right = 1.0f;
142-
143-
float abs_rel_y = relative_y < 0.0f ? -relative_y : relative_y;
121+
mp_obj_t experimental_start_pursuit(size_t n_args, const mp_obj_t *args) {
122+
p_target_x = mp_obj_get_float(args[0]);
123+
p_target_y = mp_obj_get_float(args[1]);
124+
p_target_speed = mp_obj_get_float(args[2]);
125+
float thresh = mp_obj_get_float(args[3]);
126+
p_stop_threshold_sq = thresh * thresh;
127+
pursuit_running = true;
128+
return mp_const_none;
129+
}
144130

145-
if (abs_rel_y > 0.001f) {
146-
float dist_sq = (x_dif * x_dif) + (y_dif * y_dif);
147-
float radius = -(dist_sq / (2.0f * relative_y));
148-
float two_r = 2.0f * radius;
149-
m_right = two_r / (two_r + track);
150-
m_left = two_r / (two_r - track);
131+
mp_obj_t experimental_stop_pursuit(void) {
132+
pursuit_running = false;
133+
if (left_servo_ptr && right_servo_ptr) {
134+
pbio_servo_stop(left_servo_ptr, PBIO_CONTROL_STOP_BRAKE);
135+
pbio_servo_stop(right_servo_ptr, PBIO_CONTROL_STOP_BRAKE);
151136
}
152-
153-
mp_obj_t tuple[2] = {
154-
mp_obj_new_float_from_f(m_left),
155-
mp_obj_new_float_from_f(m_right)
156-
};
157-
return mp_obj_new_tuple(2, tuple);
137+
return mp_const_none;
158138
}
159139

160140
#endif

pybricks/experimental/odometry.h

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,8 @@
33

44
#include "py/obj.h"
55

6-
// The signature must use float to match the core and avoid double-promotion errors
7-
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);
6+
// Background update hooks
7+
void pb_background_odometry_update(void);
8+
void pb_background_pursuit_update(void);
89

9-
#endif // PYBRICKS_EXPERIMENTAL_ODOMETRY_H
10+
#endif

pybricks/experimental/pb_module_experimental.c

Lines changed: 9 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -4,36 +4,27 @@
44

55
#if PYBRICKS_PY_EXPERIMENTAL
66

7-
// Forward declare the C functions from odometry.c
7+
// Forward declarations
88
extern mp_obj_t experimental_start_odometry(size_t n_args, const mp_obj_t *args);
99
extern mp_obj_t experimental_get_odometry(void);
1010
extern mp_obj_t experimental_stop_odometry(void);
11-
extern mp_obj_t get_pure_pursuit_multipliers(float tx, float ty, float rx_pos, float ry_pos, float rh_ang, float track);
11+
extern mp_obj_t experimental_start_pursuit(size_t n_args, const mp_obj_t *args);
12+
extern mp_obj_t experimental_stop_pursuit(void);
1213

13-
// Wrap them for MicroPython
14+
// Object definitions
1415
static MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(experimental_start_odometry_obj, 7, 7, experimental_start_odometry);
1516
static MP_DEFINE_CONST_FUN_OBJ_0(experimental_get_odometry_obj, experimental_get_odometry);
1617
static MP_DEFINE_CONST_FUN_OBJ_0(experimental_stop_odometry_obj, experimental_stop_odometry);
18+
static MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(experimental_start_pursuit_obj, 4, 4, experimental_start_pursuit);
19+
static MP_DEFINE_CONST_FUN_OBJ_0(experimental_stop_pursuit_obj, experimental_stop_pursuit);
1720

18-
static mp_obj_t experimental_pure_pursuit_logic(size_t n_args, const mp_obj_t *args) {
19-
return get_pure_pursuit_multipliers(
20-
mp_obj_get_float(args[0]),
21-
mp_obj_get_float(args[1]),
22-
mp_obj_get_float(args[2]),
23-
mp_obj_get_float(args[3]),
24-
mp_obj_get_float(args[4]),
25-
mp_obj_get_float(args[5])
26-
);
27-
}
28-
static MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(experimental_pure_pursuit_logic_obj, 6, 6, experimental_pure_pursuit_logic);
29-
30-
// Register the module functions
3121
const mp_rom_map_elem_t pb_module_experimental_globals_table[] = {
3222
{ MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_experimental) },
3323
{ MP_ROM_QSTR(MP_QSTR_start_odometry), MP_ROM_PTR(&experimental_start_odometry_obj) },
3424
{ MP_ROM_QSTR(MP_QSTR_get_odometry), MP_ROM_PTR(&experimental_get_odometry_obj) },
3525
{ MP_ROM_QSTR(MP_QSTR_stop_odometry), MP_ROM_PTR(&experimental_stop_odometry_obj) },
36-
{ MP_ROM_QSTR(MP_QSTR_pure_pursuit_logic),MP_ROM_PTR(&experimental_pure_pursuit_logic_obj) },
26+
{ MP_ROM_QSTR(MP_QSTR_start_pursuit), MP_ROM_PTR(&experimental_start_pursuit_obj) },
27+
{ MP_ROM_QSTR(MP_QSTR_stop_pursuit), MP_ROM_PTR(&experimental_stop_pursuit_obj) },
3728
};
3829
MP_DEFINE_CONST_DICT(pb_module_experimental_globals, pb_module_experimental_globals_table);
3930

@@ -42,4 +33,4 @@ const mp_obj_module_t pb_module_experimental = {
4233
.globals = (mp_obj_dict_t *)&pb_module_experimental_globals,
4334
};
4435

45-
#endif // PYBRICKS_PY_EXPERIMENTAL
36+
#endif

0 commit comments

Comments
 (0)