馃 meltybrain avocado
0

Configure Feed

Select the types of activity you want to include in your feed.

1#include "head_led.h" 2#include "hw_pins.h" 3#include "hardware/gpio.h" 4#include <math.h> 5 6/* Tunables. */ 7#define SPIN_OMEGA_MIN 10.0f /* rad/s; below this the robot is "idle" */ 8#define STROBE_WINDOW 0.35f /* rad (~20 deg) total width of the dot */ 9#define REF_HEADING 0.0f /* heading at which the dot appears */ 10#define STALE_US 200000u /* no estimate for this long => idle */ 11#define IDLE_BLINK_US 250000u /* idle heartbeat half-period (2 Hz) */ 12 13static float s_heading; 14static float s_omega; 15static uint32_t s_update_us; 16static bool s_have; 17 18void head_led_init(void) { 19 gpio_init(PIN_HEAD_LED); 20 gpio_set_dir(PIN_HEAD_LED, GPIO_OUT); 21 gpio_put(PIN_HEAD_LED, 0); 22 s_have = false; 23} 24 25void head_led_on_estimate(const heading_estimate_t *est, uint32_t now_us) { 26 s_heading = est->heading; 27 s_omega = est->omega; 28 s_update_us = now_us; 29 s_have = true; 30} 31 32static float wrap_pi(float a) { 33 const float pi = (float)M_PI; 34 while (a >= pi) a -= 2.0f * pi; 35 while (a < -pi) a += 2.0f * pi; 36 return a; 37} 38 39void head_led_tick(uint32_t now_us) { 40 bool stale = !s_have || (now_us - s_update_us) > STALE_US; 41 42 if (!stale && fabsf(s_omega) > SPIN_OMEGA_MIN) { 43 /* Extrapolate heading to "now" so the dot stays put between the 44 * (slower) estimate updates, then light the LED within a small 45 * angular window around the reference heading. */ 46 float dt = (float)(now_us - s_update_us) * 1e-6f; 47 float err = wrap_pi(s_heading + s_omega * dt - REF_HEADING); 48 gpio_put(PIN_HEAD_LED, fabsf(err) < (STROBE_WINDOW * 0.5f)); 49 } else { 50 /* Idle heartbeat. */ 51 gpio_put(PIN_HEAD_LED, ((now_us / IDLE_BLINK_US) & 1u) == 0u); 52 } 53}