Paparazzi UAS v7.0_unstable
Paparazzi is a free software Unmanned Aircraft System.
Loading...
Searching...
No Matches
rover_obstacles.c
Go to the documentation of this file.
1/*
2 * Copyright (C) 2025 Alejandro Rochas <alrochas@ucm.es>
3 *
4 * This file is part of paparazzi.
5 *
6 * paparazzi is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2, or (at your option)
9 * any later version.
10 *
11 * paparazzi is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with paparazzi; see the file COPYING. If not, write to
18 * the Free Software Foundation, 59 Temple Place - Suite 330,
19 * Boston, MA 02111-1307, USA.
20 *
21 */
22
29// Depends of tfmini lidar(could be replaced by other lidar)
30
31#include "rover_obstacles.h"
33
35#include "state.h"
36
38
39
40// Probability Map
41#define P_FREE 0.4 // cell observed as free (negative log-odds)
42#define P_OCC 0.7 // cell observed as occupied (positive log-odds)
43#define L_MIN -127 // minimum saturation
44#define L_MAX 127 // maximum saturation
45#define L0 0 // initial value (unknown)
46#define P_T 0.95 // Threshold to consider a cell occupied/free
47
48#define SCALE 20.0f // scaling of log-odds float to int8_t --> With 20, max prob 0.995
49
50
51// Abi call
52#ifndef OBSTACLES_RECEIVE_ID
53#define OBSTACLES_RECEIVE_ID ABI_BROADCAST
54#endif
55
56
57#define DECAY_INTERVAL 5000 // ms for obstacle probability to decay
58#define DECAY 5 // Decay per second
59static uint32_t last_s = 0;
60
61
62#include "modules/core/abi.h"
64static void lidar_cb(uint8_t sender_id, uint32_t stamp, float distance, float angle);
65float max_distance = 5;
66
67
68// Global variables (to avoid recalculating log all the time)
69static float POCC = 0;
70static float PFREE = 0;
71static float PT = 0;
72
74
76uint8_t grid_block_size = GRID_BLOCK_SIZE; // This is only used in CBF
77
78
79#if PERIODIC_TELEMETRY
80static void send_obstacle_grid(struct transport_tx *trans, struct link_device *dev)
81{
82 // Send all cols from obstacle_grid.now_row in a cyclic pattern
92
94}
107#endif
108
110{
111
112 int i, j;
113 for (i = 0; i < N_ROW_GRID; i++) {
114 for (j = 0; j < N_COL_GRID; j++) {
115 obstacle_grid.world[i][j] = L0;
116 }
117 }
118 // Rows in X, cols in Y
126
127#if PERIODIC_TELEMETRY
129#endif
131
132}
133
134// Same as init_grid but with 4 waypoints (you can give the 4 wp in any order,
135// but you need to have them in the correct order in the flightplan for painting the border in the GCS).
137{
142
143 obstacle_grid.xmin = xmin;
144 obstacle_grid.xmax = xmax;
145 obstacle_grid.ymin = ymin;
146 obstacle_grid.ymax = ymax;
147
148 obstacle_grid.dx = (xmax - xmin) / ((float)N_COL_GRID);
149 obstacle_grid.dy = (ymax - ymin) / ((float)N_ROW_GRID);
150
153
158
160
161#if PERIODIC_TELEMETRY
163#endif
164
166
167 // Send the message to the GCS
178 );
179}
180
181
182void obtain_cell_xy(float px, float py, int *cell_x, int *cell_y)
183{
184
185 // Must be >= 0, xmin <= px <= xmax
186 // ymin <= py <= ymax
187 *cell_x = (int)((px - obstacle_grid.xmin) / obstacle_grid.dx); // Like floor
189
190 *cell_x = (*cell_x >= 0) ? *cell_x : 0;
191 *cell_y = (*cell_y >= 0) ? *cell_y : 0;
192}
193
194void fill_cell(float px, float py)
195{
196
197 int cx, cy;
198 obtain_cell_xy(px, py, &cx, &cy);
199 obstacle_grid.world[cy][cx] = 1; // Row, col
200
201}
202
203void fill_bayesian_cell(float px, float py)
204{
205
206 if (!obstacle_grid.is_ready) { return; }
207
208 int cx, cy;
209 obtain_cell_xy(px, py, &cx, &cy);
210
211 // Gets the cell where the rover is
212 int rx, ry;
213 struct EnuCoor_f rover_pos;
216
217 update_line_bayes(rx, ry, cx, cy); // Free between rover and obstacle
218 compute_cell_bayes(cx, cy, true); // Ocupied at the last point
219}
220
221// Fills the free cells when there is no lidar measurement
222void fill_free_cells(float lidar, float angle)
223{
224 if (!obstacle_grid.is_ready) { return; }
225
226 // Gets the cell where the rover is
227 int rx, ry;
228 struct EnuCoor_f rover_pos;
232 return;
233 }
234
235 // If there is no lidar measurement, mark cells as free
236 if (lidar == 0.0f) {
237 // Calculates the fictitious obstacle
238 int cx, cy;
239 float theta = stateGetNedToBodyEulers_f()->psi;
240 float corrected_angle = M_PI / 2 - angle * M_PI / 180 - theta;
241
242 float px = rover_pos.x + (max_distance * cosf(corrected_angle));
243 float py = rover_pos.y + (max_distance * sinf(corrected_angle));
244
245 obtain_cell_xy(px, py, &cx, &cy);
246
247 update_line_bayes(rx, ry, cx, cy); // Free between rover and obstacle
248 return;
249 } else {
250 compute_cell_bayes(rx, ry, false); // Free at the end point
251 }
252}
253
254
255// Function for the map to forget the obstacles
257{
259
260 if (now_s > (last_s + DECAY_INTERVAL)) {
261 last_s = now_s;
262 for (int y = 0; y < N_ROW_GRID; y++) {
263 for (int x = 0; x < N_COL_GRID; x++) {
265 if (*cell == 0) {
266 continue;
267 } else if (*cell > 0) {
268 int updated = (*cell > obstacle_grid.map.decay) ? *cell - obstacle_grid.map.decay : 0;
269 update_cell(x, y, updated);
270 } else if (*cell < 0) {
271 int updated = (*cell < - obstacle_grid.map.decay) ? *cell + obstacle_grid.map.decay : 0;
272 update_cell(x, y, updated);
273 }
274 }
275 }
276 }
277}
278
279
280
281/*******************************************************************************
282 * *
283 * Aux functions *
284 * *
285 ******************************************************************************/
286
287
288// Bresenham algorithm
289void update_line_bayes(int x0, int y0, int x1, int y1)
290{
291 int dx = abs(x1 - x0), sx = x0 < x1 ? 1 : -1;
292 int dy = -abs(y1 - y0), sy = y0 < y1 ? 1 : -1;
293 int err = dx + dy;
294
295 while (1) {
296 if (x0 == x1 && y0 == y1) { break; }
297 compute_cell_bayes(x0, y0, false); // Libre
298 int e2 = 2 * err;
299 if (e2 >= dy) { err += dy; x0 += sx; }
300 if (e2 <= dx) { err += dx; y0 += sy; }
301 }
302}
303
304
305// Decide to send the cell (0 unknown, 1 occupied, 2 free)
306void update_cell(int x, int y, int new_value)
307{
308
311
312 uint8_t old_state = (old_value > LT) ? 1 : (old_value < -LT) ? 2 : 0;
313 uint8_t new_state = (new_value > LT) ? 1 : (new_value < -LT) ? 2 : 0;
314 obstacle_grid.map.LT = LT; // For the GCS
315
317
318 if (old_state != new_state) {
320 // printf("Cell (%d, %d) updated from %d to %d (delta: %d)\n", x, y, old_value, *cell, delta);
321 }
322}
323
324
325void compute_cell_bayes(int x, int y, bool is_occupied)
326{
328 return;
329 }
331
332 check_probs();
333
334 int delta = is_occupied ? LOCC : LFREE;
335 int updated = *cell + delta;
336 if (updated > L_MAX) { updated = L_MAX; }
337 if (updated < L_MIN) { updated = L_MIN; }
338
339 update_cell(x, y, updated);
340}
341
342
343//int8_t *LOCC, int8_t *LFREE, int8_t *LT
344void check_probs(void)
345{
346
347 if ((obstacle_grid.map.occ != POCC) || (obstacle_grid.map.free != PFREE)) {
352 // printf("LOCC: %d, LFREE: %d\n", *LOCC, *LFREE);
353 }
354
355 if (obstacle_grid.map.threshold != PT) {
358 }
359}
360
361
362
363/*******************************************************************************
364 * *
365 * Testing functions *
366 * *
367 ******************************************************************************/
368
369
370void ins_update_lidar(float distance, float angle)
371{
372
374 return;
375 }
376
379 }
380
381 // In case there is real measured for the Lidar
382 if (distance == 0.0) {
383 return;
384 }
385
386 // Everything is in ENU
389
390
391 float theta = stateGetNedToBodyEulers_f()->psi;
392 float corrected_angle = M_PI / 2 - angle * M_PI / 180 - theta;
393
394 struct FloatVect2 obstacle = {0.0, 0.0};
395 obstacle.x = x_rover + (distance * cosf(corrected_angle));
396 obstacle.y = y_rover + (distance * sinf(corrected_angle));
397
398 // Fill the grid
399#ifdef USE_GRID
401#endif
402
403}
404
405
406
408 uint32_t stamp __attribute__((unused)),
409 float distance, float angle)
410{
411 ins_update_lidar(distance, angle);
412}
Main include for ABI (AirBorneInterface).
Event structure to store callbacks in a linked list.
Definition abi_common.h:67
uint32_t get_sys_time_msec(void)
Get the time in milliseconds since startup.
#define WaypointX(_wp)
Definition common_nav.h:45
#define WaypointY(_wp)
Definition common_nav.h:46
float psi
in radians
double y
in meters
double x
in meters
static struct FloatEulers * stateGetNedToBodyEulers_f(void)
Get vehicle body attitude euler angles (float).
Definition state.h:1306
static bool stateIsLocalCoordinateValid(void)
Test if local coordinates are valid.
Definition state.h:613
static struct EnuCoor_f * stateGetPositionEnu_f(void)
Get position in local ENU coordinates (float).
Definition state.h:848
void convert_walls_to_ltp(void)
struct WallSystem wall_system
uint16_t foo
Definition main_demo5.c:58
static struct EnuCoor_d rover_pos
Physical model structures.
Paparazzi floating point math for geodetic calculations.
float y
in meters
float x
in meters
vector in East North Up coordinates Units: meters
Rover navigation functions.
#define L_MIN
static float PFREE
#define P_OCC
#define SCALE
static void send_grid_init(struct transport_tx *trans, struct link_device *dev)
static void lidar_cb(uint8_t sender_id, uint32_t stamp, float distance, float angle)
void obtain_cell_xy(float px, float py, int *cell_x, int *cell_y)
static float POCC
static void send_obstacle_grid(struct transport_tx *trans, struct link_device *dev)
void fill_bayesian_cell(float px, float py)
static int8_t LOCC
static int8_t LT
world_grid obstacle_grid
void check_probs(void)
#define DECAY_INTERVAL
void init_grid_4(uint8_t wp1, uint8_t wp2, uint8_t wp3, uint8_t wp4)
void ins_update_lidar(float distance, float angle)
#define OBSTACLES_RECEIVE_ID
static int8_t LFREE
#define DECAY
void fill_free_cells(float lidar, float angle)
#define P_T
void update_cell(int x, int y, int new_value)
#define L_MAX
void compute_cell_bayes(int x, int y, bool is_occupied)
#define L0
void decay_map()
static abi_event lidar_ev
static float PT
float max_distance
uint8_t grid_block_size
void init_grid(uint8_t pa, uint8_t pb)
void fill_cell(float px, float py)
void update_line_bayes(int x0, int y0, int x1, int y1)
#define P_FREE
static uint32_t last_s
bayesian_map map
int8_t world[N_ROW_GRID][N_COL_GRID]
#define N_COL_GRID
#define GRID_BLOCK_SIZE
#define N_ROW_GRID
uint16_t now_row
API to get/set the generic vehicle states.
static const struct usb_device_descriptor dev
Definition usb_ser_hw.c:74
int16_t register_periodic_telemetry(struct periodic_telemetry *_pt, uint16_t _id, telemetry_cb _cb)
Register a telemetry callback function.
Definition telemetry.c:51
Periodic telemetry system header (includes downlink utility and generated code).
#define DefaultPeriodic
Set default periodic telemetry.
Definition telemetry.h:66
unsigned int uint32_t
Typedef defining 32 bit unsigned int type.
unsigned char uint8_t
Typedef defining 8 bit unsigned char type.
signed char int8_t
Typedef defining 8 bit char type.