Paparazzi UAS v7.0_unstable
Paparazzi is a free software Unmanned Aircraft System.
All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Modules Pages
nps_hitl_sensors.c
Go to the documentation of this file.
1/*
2 * Copyright (C) 2009 Antoine Drouin <poinix@gmail.com>
3 * Copyright (C) 2012 The Paparazzi Team
4 * Copyright (C) 2016 Michal Podhradsky <http://github.com/podhrmic>
5 * Copyright (C) 2023 Gautier Hattenberger <gautier.hattenberger@enac.fr>
6 *
7 * This file is part of paparazzi.
8 *
9 * paparazzi is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; either version 2, or (at your option)
12 * any later version.
13 *
14 * paparazzi is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
18 *
19 * You should have received a copy of the GNU General Public License
20 * along with paparazzi; see the file COPYING. If not, write to
21 * the Free Software Foundation, 59 Temple Place - Suite 330,
22 * Boston, MA 02111-1307, USA.
23 */
24
25#include "nps_ins.h"
26#include <sys/time.h>
27#include "nps_fdm.h"
28#include <time.h>
29#include <stdio.h>
30#include <stdlib.h>
31#include <string.h>
32#include <errno.h>
33#include <unistd.h>
34#include <fcntl.h>
35#include <sys/poll.h>
36#include "nps_sensors.h"
37#include "nps_main.h"
38#include "paparazzi.h"
39#include "pprzlink/messages.h"
40#include "pprzlink/dl_protocol.h"
41#include "pprzlink/pprzlink_device.h"
42#include "pprzlink/pprz_transport.h"
44
45#ifndef AP_DEV
46#warning "[hitl] Please define AP_DEV in your airframe file"
47#define AP_DEV "/dev/ttyUSB0"
48#endif
49#ifndef AP_BAUD
50#define AP_BAUD B921600
51PRINT_CONFIG_MSG_VALUE("[hitl] Using default baudrate for AP_DEV (B921600)", AP_BAUD)
52#endif
53
54#define NPS_HITL_DEBUG 0
55#if NPS_HITL_DEBUG
56#define DEBUG_PRINT printf
57#else
58#define DEBUG_PRINT(...) {}
59#endif
60
61void *nps_sensors_loop(void *data __attribute__((unused)));
62void *nps_ap_data_loop(void *data __attribute__((unused)));
63pthread_t th_sensors; // send sensors to AP
64pthread_t th_ap_data; // receive commands from AP
65
66/* implement pprzlink_device interface */
67#define PPRZLINK_BUFFER_SIZE 256
84
85static struct linkdev dev;
86
87static int check_free_space(struct linkdev *d, long *fd __attribute__((unused)), uint16_t len)
88{
90 return space >= len ? space : 0;
91}
92
93static void put_byte(struct linkdev *d, long fd __attribute__((unused)), uint8_t data)
94{
95 d->tx_buf[d->tx_idx++] = data;
96}
97
98static void put_buffer(struct linkdev *d, long fd __attribute__((unused)), const uint8_t *data, uint16_t len)
99{
100 memcpy(&(d->tx_buf[d->tx_idx]), data, len);
101 d->tx_idx += len;
102}
103
104static void send_message(struct linkdev *d, long fd __attribute__((unused)))
105{
106 int ret = 0;
107 do {
108 ret = write((int)(d->port->fd), d->tx_buf, d->tx_idx);
109 } while (ret < 1 && errno == EAGAIN); //FIXME: max retry
110 if (ret < 1) {
111 DEBUG_PRINT("[hitl] put_byte: write failed [%d: %s]\n", ret, strerror(errno));
112 }
113 d->tx_idx = 0;
114}
115
116static uint8_t getch(struct linkdev *d)
117{
118 // this function should only be called when bytes are available
119 unsigned char c = 'B';
120 ssize_t ret = 0;
121 ret = read(d->port->fd, &c, 1);
122 if (ret > 0) {
123 d->rx_buf[d->rx_idx] = c;
124 if (d->rx_idx < PPRZLINK_BUFFER_SIZE) {
125 d->rx_idx++;
126 } else {
127 DEBUG_PRINT("[hitl] rx buffer overflow\n");
128 }
129 } else {
130 DEBUG_PRINT("[hitl] rx read error\n");
131 }
132 return c;
133}
134
135static int char_available(struct linkdev *d)
136{
137 int ret = poll(d->fds, 1, 1000);
138 if (ret > 0) {
139 if (d->fds[0].revents & POLLHUP) {
140 printf("[hitl] lost connection. Exiting\n");
141 exit(1);
142 }
143 if (d->fds[0].revents & POLLIN) {
144 return true;
145 }
146 } else if (ret == -1) {
147 DEBUG_PRINT("[hitl] poll failed\n");
148 }
149 return false;
150}
151
153
155{
158
159 dev.device.periph = (void *) (&dev);
160 dev.device.check_free_space = (check_free_space_t) check_free_space;
161 dev.device.put_byte = (put_byte_t) put_byte;
162 dev.device.put_buffer = (put_buffer_t) put_buffer;
163 dev.device.send_message = (send_message_t) send_message;
164 dev.device.char_available = (char_available_t) char_available;
165 dev.device.get_byte = (get_byte_t) getch;
167
168 // open serial port
171 if (ret != 0) {
172 printf("[hitl] Error opening %s code %d\n", AP_DEV, ret);
174 }
175
176 // poll
177 if (dev.port != NULL) {
178 dev.fds[0].fd = dev.port->fd;
179 dev.fds[0].events = POLLIN;
180 }
181}
182
183void *nps_sensors_loop(void *data __attribute__((unused)))
184{
185 struct timespec requestStart;
186 struct timespec requestEnd;
187 struct timespec waitFor;
188 long int period_ns = (1. / PERIODIC_FREQUENCY) * 1000000000L; // thread period in nanoseconds
189 long int task_ns = 0; // time it took to finish the task in nanoseconds
190
191 while (TRUE) {
192 // lock mutex
194
195 // start timing
197
198 uint8_t id = AC_ID;
199
201 float gx = (float)sensors.gyro.value.x;
202 float gy = (float)sensors.gyro.value.y;
203 float gz = (float)sensors.gyro.value.z;
204 float ax = (float)sensors.accel.value.x;
205 float ay = (float)sensors.accel.value.y;
206 float az = (float)sensors.accel.value.z;
207 float mx = (float)sensors.mag.value.x;
208 float my = (float)sensors.mag.value.y;
209 float mz = (float)sensors.mag.value.z;
210 uint8_t id = AC_ID;
212 &gx, &gy, &gz,
213 &ax, &ay, &az,
214 &mx, &my, &mz,
215 &id);
216 }
217
219 float gps_lat = (float)DegOfRad(sensors.gps.lla_pos.lat);
220 float gps_lon = (float)DegOfRad(sensors.gps.lla_pos.lon);
221 float gps_alt = (float)sensors.gps.lla_pos.alt;
222 float gps_hmsl = (float)sensors.gps.hmsl;
223 float gps_vx = (float)sensors.gps.ecef_vel.x;
224 float gps_vy = (float)sensors.gps.ecef_vel.y;
225 float gps_vz = (float)sensors.gps.ecef_vel.z;
227 uint8_t gps_fix = 3; // GPS fix
230 &gps_vx, &gps_vy, &gps_vz,
231 &gps_time, &gps_fix, &id);
232 }
233
235 float baro = -1.f;
236 float airspeed = -1.f;
237 float aoa = 0.f;
238 float sideslip = 0.f;
241 baro = (float) sensors.baro.value;
242 }
245 airspeed = (float) sensors.airspeed.value;
246 }
249 aoa = (float) sensors.aoa.value;
250 }
253 sideslip = (float) sensors.sideslip.value;
254 }
255 if (air_data_flag != 0) {
257 &baro, &airspeed, &aoa, &sideslip, &air_data_flag, &id);
258 }
259
260 // unlock mutex
262
264
265 // Calculate time it took
266 task_ns = (requestEnd.tv_sec - requestStart.tv_sec) * 1000000000L + (requestEnd.tv_nsec - requestStart.tv_nsec);
267
268 // task took less than one period, sleep for the rest of time
269 if (task_ns < period_ns) {
270 waitFor.tv_sec = 0;
271 waitFor.tv_nsec = period_ns - task_ns;
273 } else {
274 // task took longer than the period
275#ifdef PRINT_TIME
276 printf("SENSORS: task took longer than one period, exactly %f [ms], but the period is %f [ms]\n",
277 (double)task_ns / 1E6, (double)period_ns / 1E6);
278#endif
279 }
280 }
281 return(NULL);
282}
283
284void *nps_ap_data_loop(void *data __attribute__((unused)))
285{
286 struct timespec waitFor;
287
289 bool msg_available = false;
290
291 bool first_command = true;
292
293 uint8_t cmd_len = 0;
295
296 while (TRUE) {
297
299 if (msg_available) {
300 // reset rx index to zero for next message
301 dev.rx_idx = 0;
302 //Parse message
305
306 if (sender_id != AC_ID) {
307 printf("[hitl] receiving message from wrong id (%d)\n", sender_id);
308 return(NULL); // wrong A/C ?
309 }
310 /* parse telemetry messages coming from the correct AC_ID */
311 switch (msg_id) {
312 case DL_COMMANDS:
313 // parse commands message
317 // update commands
318 for (uint8_t i = 0; i < NPS_COMMANDS_NB; i++) {
320 }
321 // hack: invert pitch to fit most JSBSim models
323 if (first_command) {
324 printf("[hitl] receiving COMMANDS message\n");
325 first_command = false;
326 }
328 break;
329 case DL_MOTOR_MIXING:
330 // parse actuarors message
332 // check for out-of-bounds access
333 if (cmd_len > NPS_COMMANDS_NB) {
335 }
338 // update commands
339 for (uint8_t i = 0; i < NPS_COMMANDS_NB; i++) {
341 }
342 if (first_command) {
343 printf("[hitl] receiving MOTOR_MIXING message\n");
344 first_command = false;
345 }
347 break;
348 default:
349 break;
350 }
351
352 msg_available = false;
353 }
354
355 // wait before next loop
356 waitFor.tv_sec = 0;
357 waitFor.tv_nsec = 1000;
359
360 }
361 return(NULL);
362}
363
364
#define sensors(...)
uint16_t foo
Definition main_demo5.c:58
struct NpsAutopilot nps_autopilot
#ifndef NPS_NO_MOTOR_MIXING #include "modules/actuators/motor_mixing.h"
double commands[NPS_COMMANDS_NB]
#define NPS_COMMANDS_NB
Number of commands sent to the FDM of NPS.
uint8_t rx_buf[PPRZLINK_BUFFER_SIZE]
Receive buffer.
static void put_buffer(struct linkdev *d, long fd, const uint8_t *data, uint16_t len)
void * nps_sensors_loop(void *data)
uint8_t tx_buf[PPRZLINK_BUFFER_SIZE]
Transmit buffer.
#define AP_DEV
pthread_t th_ap_data
static void send_message(struct linkdev *d, long fd)
#define PPRZLINK_BUFFER_SIZE
struct SerialPort * port
Serial port.
static struct linkdev dev
struct link_device device
Generic device interface.
void * nps_ap_data_loop(void *data)
static int char_available(struct linkdev *d)
#define DEBUG_PRINT(...)
uint16_t rx_idx
void nps_hitl_impl_init(void)
END pprzlink_dev.
pthread_t th_sensors
uint16_t tx_idx
#define AP_BAUD
static uint8_t getch(struct linkdev *d)
static int check_free_space(struct linkdev *d, long *fd, uint16_t len)
struct pprz_transport pprz_tp
transport
struct pollfd fds[1]
static void put_byte(struct linkdev *d, long fd, uint8_t data)
#define clock_get_current_time(_x)
Definition nps_main.h:17
struct NpsMain nps_main
double sim_time
Definition nps_main.h:57
pthread_mutex_t fdm_mutex
bool nps_sensors_airspeed_available(void)
Definition nps_sensors.c:85
bool nps_sensors_gps_available(void)
Definition nps_sensors.c:67
bool nps_sensors_sideslip_available(void)
bool nps_sensors_aoa_available(void)
bool nps_sensors_baro_available(void)
Definition nps_sensors.c:58
bool nps_sensors_gyro_available(void)
Definition nps_sensors.c:40
int16_t pprz_t
Definition paparazzi.h:6
#define MAX_PPRZ
Definition paparazzi.h:8
int fd
Definition serial.c:26
void serial_port_free(struct SerialPort *me)
Definition serial_port.c:80
int serial_port_open_raw(struct SerialPort *me, const char *device, speed_t speed)
struct SerialPort * serial_port_new(void)
Definition serial_port.c:74
#define TRUE
Definition std.h:4
char cmd_buf[64]
unsigned short uint16_t
Typedef defining 16 bit unsigned short type.
short int16_t
Typedef defining 16 bit short type.
unsigned char uint8_t
Typedef defining 8 bit unsigned char type.