feat(detect): make detection thresholds runtime-tunable via BLE SET / INI
Replace 11 compile-time THR_* #defines with runtime float globals (g_thr_grass_roi, g_thr_*_collision, g_thr_*_alert) defined in stdc_post_process.c and exposed via extern in the header. - ini/host_stream.ini: add [detect] section with integer promille values - kp_firmware.c: read [detect] section at startup, log initial values - event_recorder.c: add 11 BLE SET handlers (THR_GRASS_ROI, THR_PERSON/CAR/TREE/BUNKER/POND_COL, THR_PERSON/CAR/TREE/BUNKER/POND_ALT) each with range validation (1-1000), runtime update, and INI persistence - app_header_init.c: rename log field mov= to moving= for clarity
This commit is contained in:
parent
174200eb03
commit
b2321fcdca
@ -34,7 +34,6 @@
|
||||
#define STDC_WARNING_SECONDS 2.0f
|
||||
#define STDC_MOTION_THRESHOLD 3.0f
|
||||
#define STDC_TREE_GROWTH_THR 0.05f
|
||||
#define THR_GRASS_ROI 0.75f /* grass ratio in forward ROI */
|
||||
#define THR_CAR_GLOBAL 0.05f
|
||||
#define THR_PERSON_GLOBAL 0.01f
|
||||
#define THR_GREENERY_GLOBAL 0.20f
|
||||
@ -48,18 +47,20 @@
|
||||
#define COL_ROI_TOP 0.25f
|
||||
#define COL_ROI_BOTTOM 0.70f
|
||||
|
||||
#define THR_PERSON_COLLISION 0.10f
|
||||
#define THR_CAR_COLLISION 0.20f
|
||||
#define THR_TREE_COLLISION 0.20f
|
||||
#define THR_BUNKER_COLLISION 0.20f
|
||||
#define THR_POND_COLLISION 0.20f
|
||||
|
||||
/* Alert ROI thresholds (left/right sides) — tuned independently from collision */
|
||||
#define THR_PERSON_ALERT 0.10f
|
||||
#define THR_CAR_ALERT 0.10f
|
||||
#define THR_TREE_ALERT 0.20f
|
||||
#define THR_BUNKER_ALERT 0.10f
|
||||
#define THR_POND_ALERT 0.10f
|
||||
/* Runtime-tunable detection thresholds (BLE SET / INI [detect] section).
|
||||
* Defined in stdc_post_process.c; set from kp_firmware.c at startup.
|
||||
* BLE format: SET THR_GRASS_ROI 750 (integer promille, /1000 = 0.750) */
|
||||
extern float g_thr_grass_roi;
|
||||
extern float g_thr_person_collision;
|
||||
extern float g_thr_car_collision;
|
||||
extern float g_thr_tree_collision;
|
||||
extern float g_thr_bunker_collision;
|
||||
extern float g_thr_pond_collision;
|
||||
extern float g_thr_person_alert;
|
||||
extern float g_thr_car_alert;
|
||||
extern float g_thr_tree_alert;
|
||||
extern float g_thr_bunker_alert;
|
||||
extern float g_thr_pond_alert;
|
||||
|
||||
/* Forward ROI trapezoid - from Python roi_pts */
|
||||
#define FWD_ROI_TOP_LEFT 0.45f
|
||||
|
||||
@ -115,3 +115,18 @@ can_id = 0x100 # 11-bit standard frame ID for outbound event fram
|
||||
speed_normal = 240 # CAN speed command: normal driving
|
||||
speed_alert = 35 # CAN speed command: slow/alert (person or obstacle detected)
|
||||
speed_stop = 10 # CAN speed command: stop/emergency
|
||||
|
||||
[detect]
|
||||
# Detection thresholds as integer promille (value × 1000).
|
||||
# BLE SET example: SET THR_GRASS_ROI 750 → 0.750
|
||||
thr_grass_roi = 800 # grass ratio in forward ROI → violation
|
||||
thr_person_col = 200 # person ratio in center ROI → collision
|
||||
thr_car_col = 200 # car ratio → collision
|
||||
thr_tree_col = 200 # tree ratio → collision
|
||||
thr_bunker_col = 200 # bunker ratio → collision
|
||||
thr_pond_col = 200 # pond ratio → collision
|
||||
thr_person_alt = 200 # person ratio in side ROI → alert
|
||||
thr_car_alt = 200 # car ratio → alert
|
||||
thr_tree_alt = 200 # tree ratio → alert
|
||||
thr_bunker_alt = 200 # bunker ratio → alert
|
||||
thr_pond_alt = 200 # pond ratio → alert
|
||||
|
||||
@ -531,7 +531,7 @@ int app_header_recv_inference(uint32_t buf_addr, bool *bl_run_next_inference)
|
||||
s_last_log = now;
|
||||
log_trim_if_needed(); /* keep /tmp/fw.log under LOG_MAX_BYTES */
|
||||
if (g_verbose_log) {
|
||||
printf("[STDC] frame=%u mov=%d diff=%.1f "
|
||||
printf("[STDC] frame=%u moving=%d diff=%.1f "
|
||||
"bunker=%.1f%% car=%.1f%% grass=%.1f%% greenery=%.1f%% "
|
||||
"person=%.1f%% pond=%.1f%% road=%.1f%% tree=%.1f%%\n",
|
||||
ana->frame_count, ana->is_moving, ana->motion_diff,
|
||||
|
||||
@ -44,7 +44,7 @@
|
||||
#include "bt_uart.h"
|
||||
#include "can_bus.h"
|
||||
#include "buzzer.h"
|
||||
#include "stdc_post_process.h" /* THR_*_COLLISION constants */
|
||||
#include "stdc_post_process.h" /* g_thr_* runtime threshold globals */
|
||||
|
||||
/* ── External (from kdp2_host_stream.c) ──────────────────────────────────── */
|
||||
extern VMF_VSRC_HANDLE_T *g_ptVsrcHandle;
|
||||
@ -895,6 +895,72 @@ static void handle_set_cmd(const char *cmd)
|
||||
persist_ini_int("verbose_log", v);
|
||||
snprintf(ack, sizeof(ack), "SET_ACK verbose_log=%d", v);
|
||||
|
||||
} else if (strcmp(key, "THR_GRASS_ROI") == 0) {
|
||||
if (val < 1 || val > 1000) { bt_uart_send_json("SET_NACK THR_GRASS_ROI OUT_OF_RANGE"); return; }
|
||||
g_thr_grass_roi = val / 1000.0f;
|
||||
persist_ini_int("thr_grass_roi", val);
|
||||
snprintf(ack, sizeof(ack), "SET_ACK thr_grass_roi=%.3f", g_thr_grass_roi);
|
||||
|
||||
} else if (strcmp(key, "THR_PERSON_COL") == 0) {
|
||||
if (val < 1 || val > 1000) { bt_uart_send_json("SET_NACK THR_PERSON_COL OUT_OF_RANGE"); return; }
|
||||
g_thr_person_collision = val / 1000.0f;
|
||||
persist_ini_int("thr_person_col", val);
|
||||
snprintf(ack, sizeof(ack), "SET_ACK thr_person_col=%.3f", g_thr_person_collision);
|
||||
|
||||
} else if (strcmp(key, "THR_CAR_COL") == 0) {
|
||||
if (val < 1 || val > 1000) { bt_uart_send_json("SET_NACK THR_CAR_COL OUT_OF_RANGE"); return; }
|
||||
g_thr_car_collision = val / 1000.0f;
|
||||
persist_ini_int("thr_car_col", val);
|
||||
snprintf(ack, sizeof(ack), "SET_ACK thr_car_col=%.3f", g_thr_car_collision);
|
||||
|
||||
} else if (strcmp(key, "THR_TREE_COL") == 0) {
|
||||
if (val < 1 || val > 1000) { bt_uart_send_json("SET_NACK THR_TREE_COL OUT_OF_RANGE"); return; }
|
||||
g_thr_tree_collision = val / 1000.0f;
|
||||
persist_ini_int("thr_tree_col", val);
|
||||
snprintf(ack, sizeof(ack), "SET_ACK thr_tree_col=%.3f", g_thr_tree_collision);
|
||||
|
||||
} else if (strcmp(key, "THR_BUNKER_COL") == 0) {
|
||||
if (val < 1 || val > 1000) { bt_uart_send_json("SET_NACK THR_BUNKER_COL OUT_OF_RANGE"); return; }
|
||||
g_thr_bunker_collision = val / 1000.0f;
|
||||
persist_ini_int("thr_bunker_col", val);
|
||||
snprintf(ack, sizeof(ack), "SET_ACK thr_bunker_col=%.3f", g_thr_bunker_collision);
|
||||
|
||||
} else if (strcmp(key, "THR_POND_COL") == 0) {
|
||||
if (val < 1 || val > 1000) { bt_uart_send_json("SET_NACK THR_POND_COL OUT_OF_RANGE"); return; }
|
||||
g_thr_pond_collision = val / 1000.0f;
|
||||
persist_ini_int("thr_pond_col", val);
|
||||
snprintf(ack, sizeof(ack), "SET_ACK thr_pond_col=%.3f", g_thr_pond_collision);
|
||||
|
||||
} else if (strcmp(key, "THR_PERSON_ALT") == 0) {
|
||||
if (val < 1 || val > 1000) { bt_uart_send_json("SET_NACK THR_PERSON_ALT OUT_OF_RANGE"); return; }
|
||||
g_thr_person_alert = val / 1000.0f;
|
||||
persist_ini_int("thr_person_alt", val);
|
||||
snprintf(ack, sizeof(ack), "SET_ACK thr_person_alt=%.3f", g_thr_person_alert);
|
||||
|
||||
} else if (strcmp(key, "THR_CAR_ALT") == 0) {
|
||||
if (val < 1 || val > 1000) { bt_uart_send_json("SET_NACK THR_CAR_ALT OUT_OF_RANGE"); return; }
|
||||
g_thr_car_alert = val / 1000.0f;
|
||||
persist_ini_int("thr_car_alt", val);
|
||||
snprintf(ack, sizeof(ack), "SET_ACK thr_car_alt=%.3f", g_thr_car_alert);
|
||||
|
||||
} else if (strcmp(key, "THR_TREE_ALT") == 0) {
|
||||
if (val < 1 || val > 1000) { bt_uart_send_json("SET_NACK THR_TREE_ALT OUT_OF_RANGE"); return; }
|
||||
g_thr_tree_alert = val / 1000.0f;
|
||||
persist_ini_int("thr_tree_alt", val);
|
||||
snprintf(ack, sizeof(ack), "SET_ACK thr_tree_alt=%.3f", g_thr_tree_alert);
|
||||
|
||||
} else if (strcmp(key, "THR_BUNKER_ALT") == 0) {
|
||||
if (val < 1 || val > 1000) { bt_uart_send_json("SET_NACK THR_BUNKER_ALT OUT_OF_RANGE"); return; }
|
||||
g_thr_bunker_alert = val / 1000.0f;
|
||||
persist_ini_int("thr_bunker_alt", val);
|
||||
snprintf(ack, sizeof(ack), "SET_ACK thr_bunker_alt=%.3f", g_thr_bunker_alert);
|
||||
|
||||
} else if (strcmp(key, "THR_POND_ALT") == 0) {
|
||||
if (val < 1 || val > 1000) { bt_uart_send_json("SET_NACK THR_POND_ALT OUT_OF_RANGE"); return; }
|
||||
g_thr_pond_alert = val / 1000.0f;
|
||||
persist_ini_int("thr_pond_alt", val);
|
||||
snprintf(ack, sizeof(ack), "SET_ACK thr_pond_alt=%.3f", g_thr_pond_alert);
|
||||
|
||||
} else {
|
||||
snprintf(ack, sizeof(ack), "SET_NACK UNKNOWN_KEY %.48s", key);
|
||||
bt_uart_send_json(ack);
|
||||
@ -1411,11 +1477,11 @@ void event_recorder_update(const stdc_analysis_t *ana)
|
||||
int col_now = ana->collision_risk;
|
||||
if (col_now != g_last_collision_warning) {
|
||||
const char *col_type = NULL;
|
||||
if (ana->col_person_ratio >= THR_PERSON_COLLISION) col_type = "person";
|
||||
else if (ana->col_car_ratio >= THR_CAR_COLLISION) col_type = "vehicle";
|
||||
else if (ana->col_tree_ratio >= THR_TREE_COLLISION) col_type = "tree";
|
||||
else if (ana->col_pond_ratio >= THR_POND_COLLISION) col_type = "water_hazard";
|
||||
else if (ana->col_bunker_ratio >= THR_BUNKER_COLLISION) col_type = "bush";
|
||||
if (ana->col_person_ratio >= g_thr_person_collision) col_type = "person";
|
||||
else if (ana->col_car_ratio >= g_thr_car_collision) col_type = "vehicle";
|
||||
else if (ana->col_tree_ratio >= g_thr_tree_collision) col_type = "tree";
|
||||
else if (ana->col_pond_ratio >= g_thr_pond_collision) col_type = "water_hazard";
|
||||
else if (ana->col_bunker_ratio >= g_thr_bunker_collision) col_type = "bush";
|
||||
fire_collision_warning(col_now, col_now ? col_type : NULL);
|
||||
g_last_collision_warning = col_now;
|
||||
}
|
||||
|
||||
@ -41,6 +41,7 @@
|
||||
#include "kdp2_host_stream.h"
|
||||
#include "fec_api.h"
|
||||
#include "event_recorder.h"
|
||||
#include "stdc_post_process.h"
|
||||
#include "bt_uart.h"
|
||||
#include "can_bus.h"
|
||||
#include "buzzer.h"
|
||||
@ -325,6 +326,25 @@ int loadConfig(HOST_STREAM_INIT_OPT_T* pHostStreamInit)
|
||||
ev_spd_normal, ev_spd_alert, ev_spd_stop);
|
||||
}
|
||||
|
||||
/* --- [detect] section: runtime-tunable detection thresholds --- */
|
||||
{
|
||||
g_thr_grass_roi = iniparser_getint(ini, "detect:thr_grass_roi", 750) / 1000.0f;
|
||||
g_thr_person_collision = iniparser_getint(ini, "detect:thr_person_col", 100) / 1000.0f;
|
||||
g_thr_car_collision = iniparser_getint(ini, "detect:thr_car_col", 200) / 1000.0f;
|
||||
g_thr_tree_collision = iniparser_getint(ini, "detect:thr_tree_col", 200) / 1000.0f;
|
||||
g_thr_bunker_collision = iniparser_getint(ini, "detect:thr_bunker_col", 200) / 1000.0f;
|
||||
g_thr_pond_collision = iniparser_getint(ini, "detect:thr_pond_col", 200) / 1000.0f;
|
||||
g_thr_person_alert = iniparser_getint(ini, "detect:thr_person_alt", 100) / 1000.0f;
|
||||
g_thr_car_alert = iniparser_getint(ini, "detect:thr_car_alt", 100) / 1000.0f;
|
||||
g_thr_tree_alert = iniparser_getint(ini, "detect:thr_tree_alt", 200) / 1000.0f;
|
||||
g_thr_bunker_alert = iniparser_getint(ini, "detect:thr_bunker_alt", 100) / 1000.0f;
|
||||
g_thr_pond_alert = iniparser_getint(ini, "detect:thr_pond_alt", 100) / 1000.0f;
|
||||
printf("[FW] detect thresholds: grass=%.3f p_col=%.3f c_col=%.3f t_col=%.3f"
|
||||
" p_alt=%.3f c_alt=%.3f\n",
|
||||
g_thr_grass_roi, g_thr_person_collision, g_thr_car_collision,
|
||||
g_thr_tree_collision, g_thr_person_alert, g_thr_car_alert);
|
||||
}
|
||||
|
||||
/* --- [can] section: MCP2515 CAN bus via J15 SPI connector --- */
|
||||
{
|
||||
int can_enable = iniparser_getint(ini, "can:enable", 0);
|
||||
|
||||
@ -16,6 +16,19 @@
|
||||
|
||||
extern unsigned int g_verbose_log;
|
||||
|
||||
/* Detection thresholds — runtime tunable via BLE SET / INI [detect] section */
|
||||
float g_thr_grass_roi = 0.75f;
|
||||
float g_thr_person_collision = 0.10f;
|
||||
float g_thr_car_collision = 0.20f;
|
||||
float g_thr_tree_collision = 0.20f;
|
||||
float g_thr_bunker_collision = 0.20f;
|
||||
float g_thr_pond_collision = 0.20f;
|
||||
float g_thr_person_alert = 0.10f;
|
||||
float g_thr_car_alert = 0.10f;
|
||||
float g_thr_tree_alert = 0.20f;
|
||||
float g_thr_bunker_alert = 0.10f;
|
||||
float g_thr_pond_alert = 0.10f;
|
||||
|
||||
typedef struct {
|
||||
uint8_t *prev_roi_luma;
|
||||
uint32_t prev_roi_capacity;
|
||||
@ -252,11 +265,11 @@ int stdc_post_process(int model_id, struct kdp_image_s *image_p)
|
||||
ana->left_type[0] = '\0';
|
||||
{
|
||||
struct { float ratio; float thr; const char *name; } lc[] = {
|
||||
{ ana->left_person_ratio, THR_PERSON_ALERT, "person" },
|
||||
{ ana->left_car_ratio, THR_CAR_ALERT, "vehicle" },
|
||||
{ ana->left_tree_ratio, THR_TREE_ALERT, "tree" },
|
||||
{ ana->left_pond_ratio, THR_POND_ALERT, "water_hazard" },
|
||||
{ ana->left_bunker_ratio, THR_BUNKER_ALERT, "bush" },
|
||||
{ ana->left_person_ratio, g_thr_person_alert, "person" },
|
||||
{ ana->left_car_ratio, g_thr_car_alert, "vehicle" },
|
||||
{ ana->left_tree_ratio, g_thr_tree_alert, "tree" },
|
||||
{ ana->left_pond_ratio, g_thr_pond_alert, "water_hazard" },
|
||||
{ ana->left_bunker_ratio, g_thr_bunker_alert, "bush" },
|
||||
};
|
||||
float best = 0.0f;
|
||||
for (int i = 0; i < 5; i++) {
|
||||
@ -275,11 +288,11 @@ int stdc_post_process(int model_id, struct kdp_image_s *image_p)
|
||||
ana->right_type[0] = '\0';
|
||||
{
|
||||
struct { float ratio; float thr; const char *name; } rc[] = {
|
||||
{ ana->right_person_ratio, THR_PERSON_ALERT, "person" },
|
||||
{ ana->right_car_ratio, THR_CAR_ALERT, "vehicle" },
|
||||
{ ana->right_tree_ratio, THR_TREE_ALERT, "tree" },
|
||||
{ ana->right_pond_ratio, THR_POND_ALERT, "water_hazard" },
|
||||
{ ana->right_bunker_ratio, THR_BUNKER_ALERT, "bush" },
|
||||
{ ana->right_person_ratio, g_thr_person_alert, "person" },
|
||||
{ ana->right_car_ratio, g_thr_car_alert, "vehicle" },
|
||||
{ ana->right_tree_ratio, g_thr_tree_alert, "tree" },
|
||||
{ ana->right_pond_ratio, g_thr_pond_alert, "water_hazard" },
|
||||
{ ana->right_bunker_ratio, g_thr_bunker_alert, "bush" },
|
||||
};
|
||||
float best = 0.0f;
|
||||
for (int i = 0; i < 5; i++) {
|
||||
@ -296,7 +309,7 @@ int stdc_post_process(int model_id, struct kdp_image_s *image_p)
|
||||
/* -------------------------------------------------------
|
||||
* 3. Warning flags
|
||||
* ------------------------------------------------------- */
|
||||
ana->on_grass = (ana->grass_roi_ratio > THR_GRASS_ROI) ? 1 : 0;
|
||||
ana->on_grass = (ana->grass_roi_ratio > g_thr_grass_roi) ? 1 : 0;
|
||||
if (ana->on_grass && ana->is_moving)
|
||||
g_stdc_state.consecutive_grass_frames++;
|
||||
else
|
||||
@ -313,11 +326,11 @@ int stdc_post_process(int model_id, struct kdp_image_s *image_p)
|
||||
ana->tree_approaching = (ana->tree_roi_growth > STDC_TREE_GROWTH_THR) ? 1 : 0;
|
||||
|
||||
ana->collision_risk = 0;
|
||||
if (ana->col_person_ratio >= THR_PERSON_COLLISION) ana->collision_risk = 1;
|
||||
if (ana->col_car_ratio >= THR_CAR_COLLISION) ana->collision_risk = 1;
|
||||
if (ana->col_tree_ratio >= THR_TREE_COLLISION) ana->collision_risk = 1;
|
||||
if (ana->col_bunker_ratio >= THR_BUNKER_COLLISION) ana->collision_risk = 1;
|
||||
if (ana->col_pond_ratio >= THR_POND_COLLISION) ana->collision_risk = 1;
|
||||
if (ana->col_person_ratio >= g_thr_person_collision) ana->collision_risk = 1;
|
||||
if (ana->col_car_ratio >= g_thr_car_collision) ana->collision_risk = 1;
|
||||
if (ana->col_tree_ratio >= g_thr_tree_collision) ana->collision_risk = 1;
|
||||
if (ana->col_bunker_ratio >= g_thr_bunker_collision) ana->collision_risk = 1;
|
||||
if (ana->col_pond_ratio >= g_thr_pond_collision) ana->collision_risk = 1;
|
||||
|
||||
/* -------------------------------------------------------
|
||||
* 4. Log summary (throttled to 1Hz, verbose_log only)
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user