60 changes: 60 additions & 0 deletions sw/airborne/c++.cpp
@@ -0,0 +1,60 @@
/*
* Copyright (C) 2019 Freek van Tienen <freek.v.tienen@gmail.com>
*
* This file is part of paparazzi.
*
* paparazzi is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2, or (at your option)
* any later version.
*
* paparazzi is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with paparazzi; see the file COPYING. If not, see
* <http://www.gnu.org/licenses/>.
*/
#include <stdlib.h>

/**
* Replace new and delete operators of C++
*/

void * operator new(size_t size)
{
if (size < 1) {
size = 1;
}
return(calloc(size, 1));
}

void operator delete(void *p)
{
if (p) free(p);
}

void * operator new[](size_t size)
{
if (size < 1) {
size = 1;
}
return(calloc(size, 1));
}

void operator delete[](void * ptr)
{
if (ptr) free(ptr);
}

/*void operator delete(void* ptr, unsigned int size)
{
if (ptr) free(ptr);
}
void operator delete [](void* ptr, unsigned int size)
{
if (ptr) free(ptr);
}*/
23 changes: 0 additions & 23 deletions sw/airborne/firmwares/fixedwing/fixedwing_datalink.c
Expand Up @@ -47,19 +47,6 @@

#define MOfMM(_x) (((float)(_x))/1000.)

#if USE_JOYSTICK
#include "firmwares/fixedwing/stabilization/stabilization_attitude.h"
#include "autopilot.h"
uint8_t joystick_block;
#define JoystickHandeDatalink(_roll_int8, _pitch_int8, _throttle_int8) { \
if (autopilot_get_mode() == AP_MODE_AUTO2 && nav_block == joystick_block) { \
h_ctl_roll_setpoint = _roll_int8 * (AUTO1_MAX_ROLL / 0x7f); \
h_ctl_pitch_setpoint = _pitch_int8 * (AUTO1_MAX_PITCH / 0x7f); \
v_ctl_throttle_setpoint = (MAX_PPRZ/0x7f) * _throttle_int8; \
} \
}
#endif

void firmware_parse_msg(struct link_device *dev __attribute__((unused)), struct transport_tx *trans __attribute__((unused)), uint8_t *buf)
{
uint8_t msg_id = IdOfPprzMsg(buf);
Expand Down Expand Up @@ -152,16 +139,6 @@ void firmware_parse_msg(struct link_device *dev __attribute__((unused)), struct
break;
#endif /* HITL */

#if USE_JOYSTICK
case DL_JOYSTICK_RAW: {
if (DL_JOYSTICK_RAW_ac_id(buf) == AC_ID) {
JoystickHandeDatalink(DL_JOYSTICK_RAW_roll(buf),
DL_JOYSTICK_RAW_pitch(buf),
DL_JOYSTICK_RAW_throttle(buf));
}
}
break;
#endif // USE_JOYSTICK
default:
break;
}
Expand Down
6 changes: 0 additions & 6 deletions sw/airborne/firmwares/fixedwing/joystick.h

This file was deleted.

22 changes: 17 additions & 5 deletions sw/airborne/firmwares/fixedwing/main_chibios.c
Expand Up @@ -115,9 +115,7 @@ int main(void)
#endif

// Main loop, do nothing
while (TRUE) {
chThdSleepMilliseconds(1000);
}
chThdSleep(TIME_INFINITE);
return 0;
}

Expand All @@ -134,7 +132,14 @@ static void thd_ap(void *arg)
while (!chThdShouldTerminateX()) {
Ap(handle_periodic_tasks);
Ap(event_task);
chThdSleepMicroseconds(500);
// In tick mode, the minimum step is 1e6 / CH_CFG_ST_FREQUENCY
// which means that whatever happens, if we do a sleep of this
// time step, the next wakeup will be "aligned" and we won't see
// jitter. The polling on event will also be as fast as possible
// Be careful that in tick-less mode, it will be required to use
// the chThdSleepUntil function with a correct computation of the
// wakeup time, in particular roll-over should be check.
chThdSleepMicroseconds(1000000 / CH_CFG_ST_FREQUENCY);
}

chThdExit(0);
Expand All @@ -153,7 +158,14 @@ static void thd_fbw(void *arg)
while (!chThdShouldTerminateX()) {
Fbw(handle_periodic_tasks);
Fbw(event_task);
chThdSleepMicroseconds(500);
// In tick mode, the minimum step is 1e6 / CH_CFG_ST_FREQUENCY
// which means that whatever happens, if we do a sleep of this
// time step, the next wakeup will be "aligned" and we won't see
// jitter. The polling on event will also be as fast as possible
// Be careful that in tick-less mode, it will be required to use
// the chThdSleepUntil function with a correct computation of the
// wakeup time, in particular roll-over should be check.
chThdSleepMicroseconds(1000000 / CH_CFG_ST_FREQUENCY);
}

chThdExit(0);
Expand Down
7 changes: 7 additions & 0 deletions sw/airborne/firmwares/rotorcraft/guidance/guidance_h.h
Expand Up @@ -27,6 +27,9 @@
#ifndef GUIDANCE_H_H
#define GUIDANCE_H_H

#ifdef __cplusplus
extern "C" {
#endif

#include "math/pprz_algebra_int.h"
#include "math/pprz_algebra_float.h"
Expand Down Expand Up @@ -191,4 +194,8 @@ static inline void guidance_h_SetTau(float tau)
gh_set_tau(tau);
}

#ifdef __cplusplus
}
#endif

#endif /* GUIDANCE_H_H */
13 changes: 9 additions & 4 deletions sw/airborne/firmwares/rotorcraft/main_chibios.c
Expand Up @@ -63,9 +63,7 @@ int main(void)
apThdPtr = chThdCreateStatic(wa_thd_ap, sizeof(wa_thd_ap), NORMALPRIO, thd_ap, NULL);

// Main loop, do nothing
while (TRUE) {
chThdSleepMilliseconds(1000);
}
chThdSleep(TIME_INFINITE);
return 0;
}

Expand All @@ -82,7 +80,14 @@ static void thd_ap(void *arg)
while (!chThdShouldTerminateX()) {
handle_periodic_tasks();
main_event();
chThdSleepMicroseconds(500);
// In tick mode, the minimum step is 1e6 / CH_CFG_ST_FREQUENCY
// which means that whatever happens, if we do a sleep of this
// time step, the next wakeup will be "aligned" and we won't see
// jitter. The polling on event will also be as fast as possible
// Be careful that in tick-less mode, it will be required to use
// the chThdSleepUntil function with a correct computation of the
// wakeup time, in particular roll-over should be check.
chThdSleepMicroseconds(1000000 / CH_CFG_ST_FREQUENCY);
}

chThdExit(0);
Expand Down
Expand Up @@ -27,6 +27,10 @@
#ifndef STABILIZATION_ATTITUDE_H
#define STABILIZATION_ATTITUDE_H

#ifdef __cplusplus
extern "C" {
#endif

#include "firmwares/rotorcraft/stabilization.h"
#include "math/pprz_algebra_int.h"
#include STABILIZATION_ATTITUDE_TYPE_H
Expand All @@ -39,5 +43,8 @@ extern void stabilization_attitude_set_rpy_setpoint_i(struct Int32Eulers *rpy);
extern void stabilization_attitude_set_earth_cmd_i(struct Int32Vect2 *cmd, int32_t heading);
extern void stabilization_attitude_run(bool in_flight);

#ifdef __cplusplus
}
#endif

#endif /* STABILIZATION_ATTITUDE_H */
14 changes: 14 additions & 0 deletions sw/airborne/math/pprz_isa.h
Expand Up @@ -62,6 +62,8 @@ extern "C" {
#define PPRZ_ISA_AIR_GAS_CONSTANT (PPRZ_ISA_GAS_CONSTANT/PPRZ_ISA_MOLAR_MASS)
/** standard air density in kg/m^3 */
#define PPRZ_ISA_AIR_DENSITY 1.225
/** absolute null in celcius */
#define PPRZ_ISA_ABS_NULL -273.15

static const float PPRZ_ISA_M_OF_P_CONST = (PPRZ_ISA_AIR_GAS_CONSTANT *PPRZ_ISA_SEA_LEVEL_TEMP / PPRZ_ISA_GRAVITY);

Expand Down Expand Up @@ -181,6 +183,18 @@ static inline float pprz_isa_temperature_of_altitude(float alt)
return PPRZ_ISA_SEA_LEVEL_TEMP - PPRZ_ISA_TEMP_LAPS_RATE * alt;
}

/**
* Get the air density (rho) from a given pressure and temperature
*
* @param pressure current pressure in Pascal (Pa)
* @param temp temperature in celcius
* @return air density rho
*/
static inline float pprz_isa_density_of_pressure(float pressure, float temp)
{
return pressure * (1.0f / (PPRZ_ISA_AIR_GAS_CONSTANT * (temp - PPRZ_ISA_ABS_NULL)));
}

#ifdef __cplusplus
} /* extern "C" */
#endif
Expand Down
64 changes: 64 additions & 0 deletions sw/airborne/modules/actuators/actuators_dshot.h
@@ -0,0 +1,64 @@
/*
* Copyright (C) 2018 Gautier Hattenberger <gautier.hattenberger@enac.fr>
*
* This file is part of paparazzi
*
* paparazzi is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2, or (at your option)
* any later version.
*
* paparazzi is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with paparazzi; see the file COPYING. If not, see
* <http://www.gnu.org/licenses/>.
*/

/**
* @file "modules/actuators/actuators_dshot.h"
* @author Gautier Hattenberger
* Driver for DSHOT speed controller protocol
*/

#ifndef ACTUATORS_DSHOT_H
#define ACTUATORS_DSHOT_H

#include "std.h"
#include "modules/actuators/actuators_dshot_arch.h"

/** In normal DSHOT, first 48 values are special commands
* this offset allow to use 0 as the no-throttle command
* This should not be changed unless you know what you are doing
*/
#ifndef ACTUATORS_DSHOT_OFFSET
#define ACTUATORS_DSHOT_OFFSET 48
#endif

/** Maxnum number of DSHOT commands
* This should be large enough for max applications
*/
#ifndef ACTUATORS_DSHOT_NB
#define ACTUATORS_DSHOT_NB 8
#endif

extern uint16_t actuators_dshot_values[ACTUATORS_DSHOT_NB];

/** Arch dependent init
*/
extern void actuators_dshot_arch_init(void);
extern void actuators_dshot_arch_commit(void);

/* Actuator macros */
#define ActuatorDShotSet(_i, _v) { \
if (_v == 0) { actuators_dshot_values[_i] = 0; } \
else { actuators_dshot_values[_i] = _v + ACTUATORS_DSHOT_OFFSET; } \
}
#define ActuatorsDShotInit() actuators_dshot_arch_init()
#define ActuatorsDShotCommit() actuators_dshot_arch_commit()

#endif

2 changes: 1 addition & 1 deletion sw/airborne/modules/air_data/air_data.c
Expand Up @@ -109,7 +109,7 @@ PRINT_CONFIG_MSG("USE_AIRSPEED_AIR_DATA automatically set to TRUE")
static uint8_t baro_health_counter;


static void pressure_abs_cb(uint8_t __attribute__((unused)) sender_id, float pressure)
static void pressure_abs_cb(uint8_t __attribute__((unused)) sender_id, uint32_t __attribute__((unused)) stamp, float pressure)
{
air_data.pressure = pressure;

Expand Down
4 changes: 2 additions & 2 deletions sw/airborne/modules/ctrl/optical_flow_landing.c
Expand Up @@ -166,7 +166,7 @@ static void send_divergence(struct transport_tx *trans, struct link_device *dev)

/// Function definitions
/// Callback function of the ground altitude
void vertical_ctrl_agl_cb(uint8_t sender_id, float distance);
void vertical_ctrl_agl_cb(uint8_t sender_id, uint32_t stamp, float distance);
// Callback function of the optical flow estimate:
void vertical_ctrl_optical_flow_cb(uint8_t sender_id, uint32_t stamp, int16_t flow_x,
int16_t flow_y, int16_t flow_der_x, int16_t flow_der_y, float quality, float size_divergence);
Expand Down Expand Up @@ -592,7 +592,7 @@ void update_errors(float err, float dt)
}

// Reading from "sensors":
void vertical_ctrl_agl_cb(uint8_t sender_id UNUSED, float distance)
void vertical_ctrl_agl_cb(uint8_t sender_id UNUSED, __attribute__((unused)) uint32_t stamp, float distance)
{
of_landing_ctrl.agl = distance;
}
Expand Down
4 changes: 2 additions & 2 deletions sw/airborne/modules/ctrl/vertical_ctrl_module_demo.c
Expand Up @@ -48,7 +48,7 @@ PRINT_CONFIG_VAR(VERTICAL_CTRL_MODULE_AGL_ID)
static abi_event agl_ev; ///< The altitude ABI event

/// Callback function of the ground altitude
static void vertical_ctrl_agl_cb(uint8_t sender_id __attribute__((unused)), float distance);
static void vertical_ctrl_agl_cb(uint8_t sender_id, uint32_t stamp, float distance);

struct VerticalCtrlDemo v_ctrl;

Expand Down Expand Up @@ -85,7 +85,7 @@ void vertical_ctrl_module_run(bool in_flight)
}
}

static void vertical_ctrl_agl_cb(uint8_t sender_id, float distance)
static void vertical_ctrl_agl_cb(__attribute__((unused)) uint8_t sender_id, __attribute__((unused)) uint32_t stamp, float distance)
{
v_ctrl.agl = distance;
}
Expand Down
2 changes: 1 addition & 1 deletion sw/airborne/modules/ins/ins_mekf_wind_wrapper.c
Expand Up @@ -210,7 +210,7 @@ static abi_event geo_mag_ev;
static abi_event gps_ev;


static void baro_cb(uint8_t __attribute__((unused)) sender_id, float pressure)
static void baro_cb(uint8_t __attribute__((unused)) sender_id, __attribute__((unused)) uint32_t stamp, float pressure)
{
static float ins_qfe = PPRZ_ISA_SEA_LEVEL_PRESSURE;
static float alpha = 10.0f;
Expand Down
2 changes: 1 addition & 1 deletion sw/airborne/modules/ins/ins_skeleton.c
Expand Up @@ -190,7 +190,7 @@ static void ins_ned_to_state(void)
* ABI callback functions
**********************************************************/

static void baro_cb(uint8_t __attribute__((unused)) sender_id, float pressure)
static void baro_cb(uint8_t __attribute__((unused)) sender_id, __attribute__((unused)) uint32_t stamp, float pressure)
{
/* call module implementation */
ins_module_update_baro(pressure);
Expand Down
52 changes: 52 additions & 0 deletions sw/airborne/modules/joystick/joystick.c
@@ -0,0 +1,52 @@
/*
* Copyright (C) 2019 Gautier Hattenberger <gautier.hattenberger@enac.fr>
*
* This file is part of paparazzi
*
* paparazzi is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2, or (at your option)
* any later version.
*
* paparazzi is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with paparazzi; see the file COPYING. If not, see
* <http://www.gnu.org/licenses/>.
*/
/**
* @file "modules/joystick/joystick.c"
* @author Gautier Hattenberger
* Handle JOYSTICK_RAW messages
*/

#include "modules/joystick/joystick.h"
#include "subsystems/datalink/datalink.h"
#include "subsystems/abi.h"
#include "pprzlink/dl_protocol.h"
#include "generated/airframe.h"

struct Joystick joystick;

void joystick_init(void)
{
joystick.roll = 0;
joystick.pitch = 0;
joystick.yaw = 0;
joystick.throttle = 0;
}

void joystick_parse(void)
{
if (DL_JOYSTICK_RAW_ac_id(dl_buffer) == AC_ID) {
joystick.roll = DL_JOYSTICK_RAW_roll(dl_buffer);
joystick.pitch = DL_JOYSTICK_RAW_pitch(dl_buffer);
joystick.yaw = DL_JOYSTICK_RAW_yaw(dl_buffer);
joystick.throttle = DL_JOYSTICK_RAW_throttle(dl_buffer);
AbiSendMsgJOYSTICK(JOYSTICK_ID, joystick.roll, joystick.pitch, joystick.yaw, joystick.throttle);
}
}

55 changes: 55 additions & 0 deletions sw/airborne/modules/joystick/joystick.h
@@ -0,0 +1,55 @@
/*
* Copyright (C) 2019 Gautier Hattenberger <gautier.hattenberger@enac.fr>
*
* This file is part of paparazzi
*
* paparazzi is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2, or (at your option)
* any later version.
*
* paparazzi is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with paparazzi; see the file COPYING. If not, see
* <http://www.gnu.org/licenses/>.
*/
/**
* @file "modules/joystick/joystick.h"
* @author Gautier Hattenberger
* Handle JOYSTICK_RAW messages
*/

#ifndef JOYSTICK_H
#define JOYSTICK_H

#include "std.h"

/**
* Joystick structure
*/
struct Joystick {
int32_t roll; ///< roll command
int32_t pitch; ///< pitch command
int32_t yaw; ///< yaw command
int32_t throttle; ///< throttle command
};

extern struct Joystick joystick;

/**
* Init function
*/
extern void joystick_init(void);

/**
* JOYSTICK_RAW message parser
* if valid, send a JOYSTICK ABI message
*/
extern void joystick_parse(void);

#endif

6 changes: 4 additions & 2 deletions sw/airborne/modules/lidar/lidar_lite.c
Expand Up @@ -137,8 +137,9 @@ void lidar_lite_periodic(void)
}
}
break;
case LIDAR_LITE_PARSE:
case LIDAR_LITE_PARSE: {
// filter data
uint32_t now_ts = get_sys_time_usec();
lidar_lite.distance_raw = update_median_filter_i(
&lidar_lite_filter,
(uint32_t)((lidar_lite.trans.buf[0] << 8) | lidar_lite.trans.buf[1]));
Expand All @@ -154,12 +155,13 @@ void lidar_lite_periodic(void)

// send message (if requested)
if (lidar_lite.update_agl) {
AbiSendMsgAGL(AGL_LIDAR_LITE_ID, lidar_lite.distance);
AbiSendMsgAGL(AGL_LIDAR_LITE_ID, now_ts, lidar_lite.distance);
}

// increment status
lidar_lite.status = LIDAR_LITE_INIT_RANGING;
break;
}
default:
break;
}
Expand Down
6 changes: 4 additions & 2 deletions sw/airborne/modules/lidar/lidar_sf11.c
Expand Up @@ -97,9 +97,10 @@ void lidar_sf11_periodic(void)
lidar_sf11.trans.buf[0] = 0; // set tx to zero
i2c_transceive(&LIDAR_SF11_I2C_DEV, &lidar_sf11.trans, lidar_sf11.addr, 1, 2);
break;
case LIDAR_SF11_READ_OK:
case LIDAR_SF11_READ_OK: {
// process results
// filter data
uint32_t now_ts = get_sys_time_usec();
lidar_sf11.distance_raw = update_median_filter_i(
&lidar_sf11_filter,
(uint32_t)((lidar_sf11.trans.buf[0] << 8) | lidar_sf11.trans.buf[1]));
Expand All @@ -115,12 +116,13 @@ void lidar_sf11_periodic(void)

// send message (if requested)
if (lidar_sf11.update_agl) {
AbiSendMsgAGL(AGL_LIDAR_SF11_ID, lidar_sf11.distance);
AbiSendMsgAGL(AGL_LIDAR_SF11_ID, now_ts, lidar_sf11.distance);
}

// reset status
lidar_sf11.status = LIDAR_SF11_REQ_READ;
break;
}
default:
break;
}
Expand Down
173 changes: 173 additions & 0 deletions sw/airborne/modules/lidar/tfmini.c
@@ -0,0 +1,173 @@
/*
* Copyright (C) 2019 Freek van Tienen <freek.v.tienen@gmail.com>
*
* This file is part of paparazzi.
*
* paparazzi is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2, or (at your option)
* any later version.
*
* paparazzi is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with paparazzi; see the file COPYING. If not, write to
* the Free Software Foundation, 59 Temple Place - Suite 330,
* Boston, MA 02111-1307, USA.
*
*/

/** @file modules/lidar/tfmini.c
* @brief driver for the TFMini lidar
*
*/
#include "tfmini.h"
#include "mcu_periph/uart.h"
#include "subsystems/abi.h"

// State interface for rotation compensation
#include "state.h"

// Messages
#include "pprzlink/messages.h"
#include "subsystems/datalink/downlink.h"

struct TFMini tfmini = {
.parse_status = TFMINI_INITIALIZE
};

static void tfmini_parse(uint8_t byte);

#if PERIODIC_TELEMETRY
#include "subsystems/datalink/telemetry.h"

/**
* Downlink message lidar
*/
static void tfmini_send_lidar(struct transport_tx *trans, struct link_device *dev)
{
pprz_msg_send_LIDAR(trans, dev, AC_ID,
&tfmini.distance,
&tfmini.mode,
&tfmini.parse_status);
}

#endif

/**
* Initialization function
*/
void tfmini_init(void)
{
tfmini.device = &((TFMINI_PORT).device);

tfmini.update_agl = USE_TFMINI_AGL;
tfmini.compensate_rotation = TFMINI_COMPENSATE_ROTATION;

tfmini.strength = 0;
tfmini.distance = 0;
tfmini.parse_status = TFMINI_PARSE_HEAD;

#if PERIODIC_TELEMETRY
register_periodic_telemetry(DefaultPeriodic, PPRZ_MSG_ID_LIDAR, tfmini_send_lidar);
#endif
}

/**
* Lidar event function
* Receive bytes from the UART port and parse them
*/
void tfmini_event(void)
{
while (tfmini.parse_status != TFMINI_INITIALIZE && tfmini.device->char_available(tfmini.device->periph)) {
tfmini_parse(tfmini.device->get_byte(tfmini.device->periph));
}
}

/**
* Parse the lidar bytes 1 by 1
*/
static void tfmini_parse(uint8_t byte)
{
switch (tfmini.parse_status) {
case TFMINI_INITIALIZE:
break;
case TFMINI_PARSE_HEAD:
if (byte == 0x59) {
tfmini.parse_crc = byte;
tfmini.parse_status++;
}
break;
case TFMINI_PARSE_HEAD2:
if (byte == 0x59) {
tfmini.parse_crc += byte;
tfmini.parse_status++;
} else {
tfmini.parse_status = TFMINI_PARSE_HEAD;
}
break;

case TFMINI_PARSE_DIST_L:
tfmini.raw_dist = byte;
tfmini.parse_crc += byte;
tfmini.parse_status++;
break;
case TFMINI_PARSE_DIST_H:
tfmini.raw_dist |= (byte << 8);
tfmini.parse_crc += byte;
tfmini.parse_status++;
break;

case TFMINI_PARSE_STRENGTH_L:
tfmini.raw_strength = byte;
tfmini.parse_crc += byte;
tfmini.parse_status++;
break;
case TFMINI_PARSE_STRENGTH_H:
tfmini.raw_strength |= (byte << 8);
tfmini.parse_crc += byte;
tfmini.parse_status++;
break;

case TFMINI_PARSE_MODE:
tfmini.raw_mode = byte;
tfmini.parse_crc += byte;
tfmini.parse_status++;
break;
case TFMINI_PARSE_BYTE7:
tfmini.parse_crc += byte;
tfmini.parse_status++;
break;

case TFMINI_PARSE_CHECKSUM:
// When the CRC matches
if (tfmini.parse_crc == byte) {
tfmini.distance = tfmini.raw_dist / 100.f;
tfmini.strength = tfmini.raw_strength;
tfmini.mode = tfmini.raw_mode;

// When the distance is valid
if (tfmini.distance != 0xFFFF) {
// compensate AGL measurement for body rotation
if (tfmini.compensate_rotation) {
float phi = stateGetNedToBodyEulers_f()->phi;
float theta = stateGetNedToBodyEulers_f()->theta;
float gain = (float)fabs((double)(cosf(phi) * cosf(theta)));
tfmini.distance = tfmini.distance / gain;
}

// send message (if requested)
if (tfmini.update_agl) {
AbiSendMsgAGL(AGL_LIDAR_TFMINI_ID, tfmini.distance);
}
}
}

// Start reading again
tfmini.parse_status = TFMINI_PARSE_HEAD;
break;
}
}
68 changes: 68 additions & 0 deletions sw/airborne/modules/lidar/tfmini.h
@@ -0,0 +1,68 @@
/*
* Copyright (C) 2019 Freek van Tienen <freek.v.tienen@gmail.com>
*
* This file is part of paparazzi.
*
* paparazzi is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2, or (at your option)
* any later version.
*
* paparazzi is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with paparazzi; see the file COPYING. If not, write to
* the Free Software Foundation, 59 Temple Place - Suite 330,
* Boston, MA 02111-1307, USA.
*
*/

/** @file modules/lidar/tfmini.h
* @brief driver for the TFMini lidar
*
*/
#ifndef LIDAR_TFMINI_H
#define LIDAR_TFMINI_H

#include "std.h"
#include "mcu_periph/i2c.h"

enum TFMiniParseStatus {
TFMINI_INITIALIZE,
TFMINI_PARSE_HEAD,
TFMINI_PARSE_HEAD2,
TFMINI_PARSE_DIST_L,
TFMINI_PARSE_DIST_H,
TFMINI_PARSE_STRENGTH_L,
TFMINI_PARSE_STRENGTH_H,
TFMINI_PARSE_MODE,
TFMINI_PARSE_BYTE7,
TFMINI_PARSE_CHECKSUM
};

struct TFMini {
struct link_device *device;
enum TFMiniParseStatus parse_status;
uint8_t parse_crc;
uint16_t raw_dist;
uint16_t raw_strength;
uint8_t raw_mode;

uint16_t strength;
float distance; // [m]
uint8_t mode;
bool update_agl;
bool compensate_rotation;
};

extern struct TFMini tfmini;

extern void tfmini_init(void);
extern void tfmini_event(void);
extern void tfmini_downlink(void);

#endif /* LIDAR_TFMINI_H */

3 changes: 2 additions & 1 deletion sw/airborne/modules/meteo/meteo_stick.c
Expand Up @@ -396,9 +396,10 @@ void meteo_stick_event(void)
#ifdef MS_PRESSURE_SLAVE_IDX
// send absolute pressure data over ABI as soon as available
if (meteo_stick.pressure.data_available) {
uint32_t now_ts = get_sys_time_usec();
meteo_stick.current_pressure = get_pressure(meteo_stick.pressure.data);
#if USE_MS_PRESSURE
AbiSendMsgBARO_ABS(METEO_STICK_SENDER_ID, meteo_stick.current_pressure);
AbiSendMsgBARO_ABS(METEO_STICK_SENDER_ID, now_ts, meteo_stick.current_pressure);
#endif
meteo_stick.pressure.data_available = false;
}
Expand Down
3 changes: 2 additions & 1 deletion sw/airborne/modules/optical_flow/px4flow.c
Expand Up @@ -79,6 +79,7 @@ static void decode_optical_flow_msg(struct mavlink_message *msg __attribute__((u
{
static float quality = 0;
static float noise = 0;
uint32_t now_ts = get_sys_time_usec();
quality = ((float)optical_flow.quality) / 255.0;
noise = px4flow_stddev + (1 - quality) * px4flow_stddev * 10;
noise = noise * noise; // square the noise to get variance of the measurement
Expand Down Expand Up @@ -107,7 +108,7 @@ static void decode_optical_flow_msg(struct mavlink_message *msg __attribute__((u
if (px4flow_update_agl) {
// positive distance means it's known/valid
if (optical_flow.ground_distance > 0) {
AbiSendMsgAGL(AGL_SONAR_PX4FLOW_ID, optical_flow.ground_distance);
AbiSendMsgAGL(AGL_SONAR_PX4FLOW_ID, now_ts, optical_flow.ground_distance);
}
}
}
Expand Down
3 changes: 2 additions & 1 deletion sw/airborne/modules/optical_flow/px4flow_i2c.c
Expand Up @@ -66,6 +66,7 @@ static inline void px4flow_i2c_frame_cb(void)
{
static float quality = 0;
static float noise = 0;
uint32_t now_ts = get_sys_time_usec();
quality = ((float)px4flow.i2c_frame.qual) / 255.0;
noise = px4flow.stddev + (1 - quality) * px4flow.stddev * 10;
noise = noise * noise; // square the noise to get variance of the measurement
Expand Down Expand Up @@ -112,7 +113,7 @@ static inline void px4flow_i2c_frame_cb(void)
}

if (px4flow.update_agl) {
AbiSendMsgAGL(AGL_SONAR_PX4FLOW_ID, ground_distance_float);
AbiSendMsgAGL(AGL_SONAR_PX4FLOW_ID, now_ts, ground_distance_float);
}
}

Expand Down
3 changes: 2 additions & 1 deletion sw/airborne/modules/range_finder/laser_range_array.c
Expand Up @@ -83,6 +83,7 @@ static void laser_range_array_parse_msg(void)
// Get Time of Flight laser range sensor ring messages
switch (msg_id) {
case DL_IMCU_REMOTE_GROUND: {
uint32_t now_ts = get_sys_time_usec();
uint8_t id = DL_IMCU_REMOTE_GROUND_id(lra_msg_buf);

if (id < LASER_RANGE_ARRAY_NUM_SENSORS) {
Expand All @@ -92,7 +93,7 @@ static void laser_range_array_parse_msg(void)
laser_range_array_orientations[id*2 + 1]);

if (id == agl_id && range > 1e-5 && range < VL53L0_MAX_VAL) {
AbiSendMsgAGL(AGL_VL53L0_LASER_ARRAY_ID, range);
AbiSendMsgAGL(AGL_VL53L0_LASER_ARRAY_ID, now_ts, range);
}
}
break;
Expand Down
3 changes: 2 additions & 1 deletion sw/airborne/modules/range_finder/teraranger_one.c
Expand Up @@ -125,7 +125,8 @@ void teraranger_event(void)
teraranger.dist = (float)teraranger.raw / 1000.f + teraranger.offset;
teraranger.data_available = true;
#if USE_TERARANGER_ONE_AGL
AbiSendMsgAGL(AGL_TERARANGER_ONE_ID, teraranger.dist);
uint32_t now_ts = get_sys_time_usec();
AbiSendMsgAGL(AGL_TERARANGER_ONE_ID, now_ts, teraranger.dist);
#endif
} else {
// data are not valid any more
Expand Down
3 changes: 2 additions & 1 deletion sw/airborne/modules/sensors/baro_MS5534A.c
Expand Up @@ -267,13 +267,14 @@ void baro_MS5534A_event(void)
spi_message_received = false;
baro_MS5534A_event_task();
if (baro_MS5534A_available) {
uint32_t now_ts = get_sys_time_usec();
baro_MS5534A_available = false;
baro_MS5534A_z = ground_alt + ((float)baro_MS5534A_ground_pressure - baro_MS5534A_pressure) * 0.084;
#if SENSO_SYNC_SEND
DOWNLINK_SEND_BARO_MS5534A(DefaultChannel, DefaultDevice, &baro_MS5534A_pressure, &baro_MS5534A_temp, &baro_MS5534A_z);
#endif
float pressure = (float)baro_MS5534A_pressure;
AbiSendMsgBARO_ABS(BARO_MS5534A_SENDER_ID, pressure);
AbiSendMsgBARO_ABS(BARO_MS5534A_SENDER_ID, now_ts, pressure);
}
}
}
4 changes: 3 additions & 1 deletion sw/airborne/modules/sensors/baro_amsys.c
Expand Up @@ -160,6 +160,8 @@ void baro_amsys_read_event(void)
// Continue only if a new altimeter value was received
//if (baro_amsys_valid && GpsFixValid()) {
if (baro_amsys_valid) {
uint32_t now_ts = get_sys_time_usec();

//Cut RAW Min and Max
if (pBaroRaw < BARO_AMSYS_OFFSET_MIN) {
pBaroRaw = BARO_AMSYS_OFFSET_MIN;
Expand All @@ -172,7 +174,7 @@ void baro_amsys_read_event(void)
baro_amsys_p = (float)(pBaroRaw - BARO_AMSYS_OFFSET_MIN) * BARO_AMSYS_MAX_PRESSURE / (float)(
BARO_AMSYS_OFFSET_MAX - BARO_AMSYS_OFFSET_MIN);
// Send pressure over ABI
AbiSendMsgBARO_ABS(BARO_AMSYS_SENDER_ID, baro_amsys_p);
AbiSendMsgBARO_ABS(BARO_AMSYS_SENDER_ID, now_ts, baro_amsys_p);
// compute altitude localy
if (!baro_amsys_offset_init) {
--baro_amsys_cnt;
Expand Down
4 changes: 2 additions & 2 deletions sw/airborne/modules/sensors/baro_bmp.c
Expand Up @@ -84,13 +84,13 @@ void baro_bmp_event(void)
bmp085_event(&baro_bmp);

if (baro_bmp.data_available) {

uint32_t now_ts = get_sys_time_usec();
float tmp = baro_bmp.pressure / 101325.0; // pressure at sea level
tmp = pow(tmp, 0.190295);
baro_bmp_alt = 44330 * (1.0 - tmp);

float pressure = (float)baro_bmp.pressure;
AbiSendMsgBARO_ABS(BARO_BMP_SENDER_ID, pressure);
AbiSendMsgBARO_ABS(BARO_BMP_SENDER_ID, now_ts, pressure);
float temp = baro_bmp.temperature / 10.0f;
AbiSendMsgTEMPERATURE(BARO_BOARD_SENDER_ID, temp);
baro_bmp.data_available = false;
Expand Down
3 changes: 2 additions & 1 deletion sw/airborne/modules/sensors/baro_ets.c
Expand Up @@ -186,8 +186,9 @@ void baro_ets_read_event(void)
if (baro_ets_offset_init) {
baro_ets_altitude = ground_alt + BARO_ETS_ALT_SCALE * (float)(baro_ets_offset - baro_ets_adc);
// New value available
uint32_t now_ts = get_sys_time_usec();
float pressure = BARO_ETS_SCALE * (float) baro_ets_adc + BARO_ETS_PRESSURE_OFFSET;
AbiSendMsgBARO_ABS(BARO_ETS_SENDER_ID, pressure);
AbiSendMsgBARO_ABS(BARO_ETS_SENDER_ID, now_ts, pressure);
#ifdef BARO_ETS_SYNC_SEND
DOWNLINK_SEND_BARO_ETS(DefaultChannel, DefaultDevice, &baro_ets_adc, &baro_ets_offset, &baro_ets_altitude);
#endif
Expand Down
3 changes: 2 additions & 1 deletion sw/airborne/modules/sensors/baro_hca.c
Expand Up @@ -97,8 +97,9 @@ void baro_hca_read_event(void)
pBaroRaw = BARO_HCA_MAX_OUT;
}

uint32_t now_ts = get_sys_time_usec();
float pressure = BARO_HCA_SCALE * (float)pBaroRaw + BARO_HCA_PRESSURE_OFFSET;
AbiSendMsgBARO_ABS(BARO_HCA_SENDER_ID, pressure);
AbiSendMsgBARO_ABS(BARO_HCA_SENDER_ID, now_ts, pressure);
}
baro_hca_i2c_trans.status = I2CTransDone;

Expand Down
3 changes: 2 additions & 1 deletion sw/airborne/modules/sensors/baro_mpl3115.c
Expand Up @@ -63,10 +63,11 @@ void baro_mpl3115_read_event(void)
{
mpl3115_event(&baro_mpl);
if (baro_mpl.data_available) {
uint32_t now_ts = get_sys_time_usec();
float pressure = (float)baro_mpl.pressure / (1 << 2);
AbiSendMsgBARO_ABS(BARO_MPL3115_SENDER_ID, pressure);
float temp = (float)baro_mpl.pressure / 16.0f;
AbiSendMsgTEMPERATURE(BARO_MPL3115_SENDER_ID, temp);
AbiSendMsgTEMPERATURE(BARO_MPL3115_SENDER_ID, now_ts, temp);
#ifdef SENSOR_SYNC_SEND
DOWNLINK_SEND_MPL3115_BARO(DefaultChannel, DefaultDevice, &baro_mpl.pressure, &baro_mpl.temperature, &baro_mpl.alt);
#endif
Expand Down
3 changes: 2 additions & 1 deletion sw/airborne/modules/sensors/baro_ms5611_i2c.c
Expand Up @@ -93,8 +93,9 @@ void baro_ms5611_event(void)
ms5611_i2c_event(&baro_ms5611);

if (baro_ms5611.data_available) {
uint32_t now_ts = get_sys_time_usec();
float pressure = (float)baro_ms5611.data.pressure;
AbiSendMsgBARO_ABS(BARO_MS5611_SENDER_ID, pressure);
AbiSendMsgBARO_ABS(BARO_MS5611_SENDER_ID, now_ts, pressure);
float temp = baro_ms5611.data.temperature / 100.0f;
AbiSendMsgTEMPERATURE(BARO_MS5611_SENDER_ID, temp);
baro_ms5611.data_available = false;
Expand Down
3 changes: 2 additions & 1 deletion sw/airborne/modules/sensors/baro_ms5611_spi.c
Expand Up @@ -93,8 +93,9 @@ void baro_ms5611_event(void)
ms5611_spi_event(&baro_ms5611);

if (baro_ms5611.data_available) {
uint32_t now_ts = get_sys_time_usec();
float pressure = (float)baro_ms5611.data.pressure;
AbiSendMsgBARO_ABS(BARO_MS5611_SENDER_ID, pressure);
AbiSendMsgBARO_ABS(BARO_MS5611_SENDER_ID, now_ts, pressure);
float temp = baro_ms5611.data.temperature / 100.0f;
AbiSendMsgTEMPERATURE(BARO_MS5611_SENDER_ID, temp);
baro_ms5611.data_available = false;
Expand Down
3 changes: 2 additions & 1 deletion sw/airborne/modules/sensors/baro_scp.c
Expand Up @@ -188,8 +188,9 @@ static void baro_scp_read(void)
void baro_scp_event(void)
{
if (baro_scp_available == TRUE) {
uint32_t now_ts = get_sys_time_usec();
float pressure = (float)baro_scp_pressure;
AbiSendMsgBARO_ABS(BARO_SCP_SENDER_ID, pressure);
AbiSendMsgBARO_ABS(BARO_SCP_SENDER_ID, now_ts, pressure);
#ifdef SENSOR_SYNC_SEND
DOWNLINK_SEND_SCP_STATUS(DefaultChannel, DefaultDevice, &baro_scp_pressure, &baro_scp_temperature);
#endif
Expand Down
3 changes: 2 additions & 1 deletion sw/airborne/modules/sensors/baro_scp_i2c.c
Expand Up @@ -101,8 +101,9 @@ void baro_scp_event(void)
baro_scp_pressure |= scp_trans.buf[1];
baro_scp_pressure *= 25;

uint32_t now_ts = get_sys_time_usec();
float pressure = (float) baro_scp_pressure;
AbiSendMsgBARO_ABS(BARO_SCP_SENDER_ID, pressure);
AbiSendMsgBARO_ABS(BARO_SCP_SENDER_ID, now_ts, pressure);
#ifdef SENSOR_SYNC_SEND
DOWNLINK_SEND_SCP_STATUS(DefaultChannel, DefaultDevice, &baro_scp_pressure, &baro_scp_temperature);
#endif
Expand Down
3 changes: 2 additions & 1 deletion sw/airborne/modules/sensors/baro_sim.c
Expand Up @@ -38,6 +38,7 @@ void baro_sim_init(void)

void baro_sim_periodic(void)
{
uint32_t now_ts = get_sys_time_usec();
float pressure = pprz_isa_pressure_of_altitude(gps.hmsl / 1000.0);
AbiSendMsgBARO_ABS(BARO_SIM_SENDER_ID, pressure);
AbiSendMsgBARO_ABS(BARO_SIM_SENDER_ID, now_ts, pressure);
}
3 changes: 2 additions & 1 deletion sw/airborne/modules/sensors/mag_pitot_uart.c
Expand Up @@ -100,10 +100,11 @@ static inline void mag_pitot_parse_msg(void)

/* Got a barometer message */
case DL_IMCU_REMOTE_BARO: {
uint32_t now_ts = get_sys_time_usec();
float pitot_stat = DL_IMCU_REMOTE_BARO_pitot_stat(mp_msg_buf);
float pitot_temp = DL_IMCU_REMOTE_BARO_pitot_temp(mp_msg_buf);

AbiSendMsgBARO_ABS(IMU_MAG_PITOT_ID, pitot_stat);
AbiSendMsgBARO_ABS(IMU_MAG_PITOT_ID, now_ts, pitot_stat);
AbiSendMsgTEMPERATURE(IMU_MAG_PITOT_ID, pitot_temp);
break;
}
Expand Down
4 changes: 2 additions & 2 deletions sw/airborne/modules/sonar/agl_dist.c
Expand Up @@ -51,7 +51,7 @@ float agl_measurement_time;

abi_event agl_ev;

static void agl_cb(uint8_t sender_id, float distance);
static void agl_cb(uint8_t sender_id, uint32_t stamp, float distance);

void agl_dist_init(void)
{
Expand All @@ -64,7 +64,7 @@ void agl_dist_init(void)
AbiBindMsgAGL(AGL_DIST_ID, &agl_ev, agl_cb);
}

static void agl_cb(uint8_t __attribute__((unused)) sender_id, float distance)
static void agl_cb(uint8_t __attribute__((unused)) sender_id, uint32_t __attribute__((unused)) stamp, float distance)
{
if (distance < AGL_DIST_MAX_RANGE && distance > AGL_DIST_MIN_RANGE) {
agl_dist_value = distance;
Expand Down
3 changes: 2 additions & 1 deletion sw/airborne/modules/sonar/sonar_adc.c
Expand Up @@ -76,7 +76,8 @@ void sonar_adc_read(void)
#endif // SITL

// Send ABI message
AbiSendMsgAGL(AGL_SONAR_ADC_ID, sonar_adc.distance);
uint32_t now_ts = get_sys_time_usec();
AbiSendMsgAGL(AGL_SONAR_ADC_ID, now_ts, sonar_adc.distance);

#ifdef SENSOR_SYNC_SEND_SONAR
// Send Telemetry report
Expand Down
3 changes: 2 additions & 1 deletion sw/airborne/modules/sonar/sonar_bebop.c
Expand Up @@ -210,7 +210,8 @@ void *sonar_bebop_read(void *data __attribute__((unused)))
#endif // SITL
// Send ABI message
AbiSendMsgAGL(AGL_SONAR_ADC_ID, sonar_bebop.distance);
uint32_t now_ts = get_sys_time_usec();
AbiSendMsgAGL(AGL_SONAR_ADC_ID, now_ts, sonar_bebop.distance);
#ifdef SENSOR_SYNC_SEND_SONAR
// Send Telemetry report
DOWNLINK_SEND_SONAR(DefaultChannel, DefaultDevice, &sonar_bebop.meas, &sonar_bebop.distance);
Expand Down
13 changes: 13 additions & 0 deletions sw/airborne/pprz_syscalls.c
Expand Up @@ -151,6 +151,13 @@ int _isatty_r(struct _reent *r, int fd)

/***************************************************************************/

__attribute__((used))
void _fini(void) {
return;
}

/***************************************************************************/

__attribute__((used))
pid_t _getpid(void)
{
Expand All @@ -169,6 +176,12 @@ void _exit(int i) {

void _kill(void) {}

/***************************************************************************/

void *__dso_handle;
void __cxa_pure_virtual(void);
void __cxa_pure_virtual() { while (1); } //TODO: Handle properly, maybe generate a traceback

#pragma GCC diagnostic pop

/*** EOF ***/
11 changes: 11 additions & 0 deletions sw/airborne/subsystems/abi_sender_ids.h
Expand Up @@ -157,6 +157,10 @@
#define AGL_RAY_SENSOR_GAZEBO_ID 10
#endif

#ifndef AGL_LIDAR_TFMINI_ID
#define AGL_LIDAR_TFMINI_ID 11
#endif

/*
* IDs of magnetometer sensors (including IMUs with mag)
*/
Expand Down Expand Up @@ -421,4 +425,11 @@
#define DETECT_GATE_ABI_ID 33
#endif

/*
* JOYSTICK message (used for payload or control, but not as a RC)
*/
#ifndef JOYSTICK_ID
#define JOYSTICK_ID 1
#endif

#endif /* ABI_SENDER_IDS_H */
33 changes: 33 additions & 0 deletions sw/airborne/subsystems/actuators/actuators_dshot.h
@@ -0,0 +1,33 @@
/*
* Copyright (C) 2018 Gautier Hattenberger <gautier.hattenberger@enac.fr>
*
* This file is part of paparazzi
*
* paparazzi is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2, or (at your option)
* any later version.
*
* paparazzi is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with paparazzi; see the file COPYING. If not, see
* <http://www.gnu.org/licenses/>.
*/

/**
* @file "subsystems/actuators/actuators_dshot.h"
* @author Gautier Hattenberger
* dummy file for airframe generator (driver section)
*/

#ifndef SUB_ACTUATORS_DSHOT_H
#define SUB_ACTUATORS_DSHOT_H

#include "modules/actuators/actuators_dshot.h"

#endif

8 changes: 8 additions & 0 deletions sw/airborne/subsystems/datalink/telemetry_common.h
Expand Up @@ -29,6 +29,10 @@
#ifndef TELEMETRY_COMMON_H
#define TELEMETRY_COMMON_H

#ifdef __cplusplus
extern "C" {
#endif

#include <inttypes.h>
#include "std.h"
#include "pprzlink/pprzlink_device.h"
Expand Down Expand Up @@ -83,5 +87,9 @@ static inline int8_t register_periodic_telemetry(struct periodic_telemetry *_pt
extern void periodic_telemetry_err_report(uint8_t _process, uint8_t _mode, uint8_t _id);
#endif

#ifdef __cplusplus
}
#endif

#endif /* TELEMETRY_COMMON_H */

2 changes: 2 additions & 0 deletions sw/airborne/subsystems/gps.h
Expand Up @@ -92,6 +92,8 @@ struct GpsState {
uint16_t speed_3d; ///< norm of 3d speed in cm/s
int32_t course; ///< GPS course over ground in rad*1e7, [0, 2*Pi]*1e7 (CW/north)
uint32_t pacc; ///< position accuracy in cm
uint32_t hacc; ///< horizontal accuracy in cm
uint32_t vacc; ///< vertical accuracy in cm
uint32_t sacc; ///< speed accuracy in cm/s
uint32_t cacc; ///< course accuracy in rad*1e7
uint16_t pdop; ///< position dilution of precision scaled by 100
Expand Down
2 changes: 2 additions & 0 deletions sw/airborne/subsystems/gps/gps_ubx.c
Expand Up @@ -155,6 +155,8 @@ void gps_ubx_read_message(void)
gps_ubx.state.lla_pos.lat = UBX_NAV_POSLLH_LAT(gps_ubx.msg_buf);
gps_ubx.state.lla_pos.lon = UBX_NAV_POSLLH_LON(gps_ubx.msg_buf);
gps_ubx.state.lla_pos.alt = UBX_NAV_POSLLH_HEIGHT(gps_ubx.msg_buf);
gps_ubx.state.hacc = UBX_NAV_POSLLH_Hacc(gps_ubx.msg_buf);
gps_ubx.state.vacc = UBX_NAV_POSLLH_Vacc(gps_ubx.msg_buf);
SetBit(gps_ubx.state.valid_fields, GPS_VALID_POS_LLA_BIT);
gps_ubx.state.hmsl = UBX_NAV_POSLLH_HMSL(gps_ubx.msg_buf);
SetBit(gps_ubx.state.valid_fields, GPS_VALID_HMSL_BIT);
Expand Down
2 changes: 1 addition & 1 deletion sw/airborne/subsystems/ins/ins_alt_float.c
Expand Up @@ -355,7 +355,7 @@ static void alt_kalman(float z_meas, float dt)
}

#if USE_BAROMETER
static void baro_cb(uint8_t __attribute__((unused)) sender_id, float pressure)
static void baro_cb(uint8_t __attribute__((unused)) sender_id, __attribute__((unused)) uint32_t stamp, float pressure)
{
ins_alt_float_update_baro(pressure);
}
Expand Down
498 changes: 498 additions & 0 deletions sw/airborne/subsystems/ins/ins_ekf2.cpp

Large diffs are not rendered by default.

45 changes: 45 additions & 0 deletions sw/airborne/subsystems/ins/ins_ekf2.h
@@ -0,0 +1,45 @@
/*
* Copyright (C) 2016 Freek van Tienen <freek.v.tienen@gmail.com>
*
* This file is part of paparazzi.
*
* paparazzi is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2, or (at your option)
* any later version.
*
* paparazzi is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with paparazzi; see the file COPYING. If not, write to
* the Free Software Foundation, 59 Temple Place - Suite 330,
* Boston, MA 02111-1307, USA.
*/

/**
* @file subsystems/ins/ins_ekf2.h
*
* INS based in the EKF2 of PX4
*
*/

#ifndef INS_EKF2_H
#define INS_EKF2_H

#ifdef __cplusplus
extern "C" {
#endif

#include "subsystems/ins.h"

extern void ins_ekf2_init(void);
extern void ins_ekf2_update(void);

#ifdef __cplusplus
}
#endif

#endif /* INS_EKF2_H */
2 changes: 1 addition & 1 deletion sw/airborne/subsystems/ins/ins_float_invariant_wrapper.c
Expand Up @@ -111,7 +111,7 @@ static abi_event body_to_imu_ev;
static abi_event geo_mag_ev;
static abi_event gps_ev;

static void baro_cb(uint8_t __attribute__((unused)) sender_id, float pressure)
static void baro_cb(uint8_t __attribute__((unused)) sender_id, __attribute__((unused)) uint32_t stamp, float pressure)
{
ins_float_invariant_update_baro(pressure);
}
Expand Down
6 changes: 3 additions & 3 deletions sw/airborne/subsystems/ins/ins_int.c
Expand Up @@ -117,7 +117,7 @@ PRINT_CONFIG_MSG("USE_INS_NAV_INIT defaulting to TRUE")
#endif
PRINT_CONFIG_VAR(INS_INT_BARO_ID)
abi_event baro_ev;
static void baro_cb(uint8_t sender_id, float pressure);
static void baro_cb(uint8_t sender_id, uint32_t stamp, float pressure);

/** ABI binding for IMU data.
* Used accel ABI messages.
Expand Down Expand Up @@ -334,7 +334,7 @@ void ins_int_propagate(struct Int32Vect3 *accel, float dt)
}
}

static void baro_cb(uint8_t __attribute__((unused)) sender_id, float pressure)
static void baro_cb(uint8_t __attribute__((unused)) sender_id, __attribute__((unused)) uint32_t stamp, float pressure)
{
if (pressure < 1.f)
{
Expand Down Expand Up @@ -476,7 +476,7 @@ void ins_int_update_gps(struct GpsState *gps_s __attribute__((unused))) {}
* This is only used with the extended version of the vertical float filter
*/
#if USE_VFF_EXTENDED
static void agl_cb(uint8_t __attribute__((unused)) sender_id, float distance) {
static void agl_cb(uint8_t __attribute__((unused)) sender_id, __attribute__((unused)) uint32_t stamp, float distance) {
if (distance <= 0 || !(ins_int.baro_initialized)) {
return;
}
Expand Down
2 changes: 1 addition & 1 deletion sw/airborne/test/test_baro_board.c
Expand Up @@ -99,7 +99,7 @@ int main(void)
return 0;
}

static void pressure_abs_cb(uint8_t __attribute__((unused)) sender_id, float pressure)
static void pressure_abs_cb(uint8_t __attribute__((unused)) sender_id, __attribute__((unused)) uint32_t stamp, float pressure)
{
float p = pressure;
float foo = 42.;
Expand Down
4 changes: 3 additions & 1 deletion sw/ext/Makefile
Expand Up @@ -33,7 +33,7 @@ EXT_DIR=$(PAPARAZZI_SRC)/sw/ext
include $(PAPARAZZI_SRC)/conf/Makefile.arm-embedded-toolchain


all: libopencm3 luftboot chibios fatfs libsbp mavlink TRICAL hacl-c key_generator rustlink
all: libopencm3 luftboot chibios fatfs libsbp mavlink TRICAL hacl-c key_generator rustlink ecl

# update (and init if needed) all submodules
update_submodules:
Expand Down Expand Up @@ -77,6 +77,8 @@ TRICAL: TRICAL.update

fatfs: fatfs.update

ecl: ecl.update

mavlink: mavlink.update mavlink.build

mavlink.build:
Expand Down
1 change: 1 addition & 0 deletions sw/ext/ecl
Submodule ecl added at e40409
1 change: 1 addition & 0 deletions sw/ext/matrix
Submodule matrix added at 6b0777
2 changes: 1 addition & 1 deletion sw/ext/pprzlink
6 changes: 6 additions & 0 deletions sw/ground_segment/python/matlab2pprz/README.md
@@ -0,0 +1,6 @@
matlab2pprz.py is a bridge between Natnet (Optitrack interface), Simulink (using UDP send and receive blocks) and Paparazzi (using Ivy)

example of Simulink model: https://github.com/enacuavlab/vto-tools/tree/master/Matlab/Simulink

example of command to start the script: ./matlab2pprz.py -ac 211 211 5005 -sp 9090 -ns 192.168.1.230 -v

149 changes: 149 additions & 0 deletions sw/ground_segment/python/matlab2pprz/matlab2pprz.py
@@ -0,0 +1,149 @@
#!/usr/bin/env python3
#
# Copyright (C) 2019 Gautier Hattenberger <gautier.hattenberger@enac.fr>
#
# This file is part of paparazzi.
#
# paparazzi is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2, or (at your option)
# any later version.
#
# paparazzi is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with paparazzi; see the file COPYING. If not, see
# <http://www.gnu.org/licenses/>.
#

'''
Forward rigid body positions and orientation from Natnet to Matlab/Simulink
via UDP ports and receive commands that are forwarded over Ivy
'''

from __future__ import print_function

import sys
from os import path, getenv
from time import time, sleep
import argparse
import math
import socket
import struct

# if PAPARAZZI_HOME not set, then assume the tree containing this
# file is a reasonable substitute
PPRZ_HOME = getenv("PAPARAZZI_HOME", path.normpath(path.join(path.dirname(path.abspath(__file__)), '../../../../')))
sys.path.append(PPRZ_HOME + "/var/lib/python")
sys.path.append(PPRZ_HOME + "/sw/ground_segment/python/natnet3.x")

from NatNetClient import NatNetClient

from pprzlink.ivy import IvyMessagesInterface
from pprzlink.message import PprzMessage

# parse args
parser = argparse.ArgumentParser(formatter_class=argparse.ArgumentDefaultsHelpFormatter)
parser.add_argument('-ac', action='append', nargs=3,
metavar=('rigid_id','ac_id','udp_out'), help='tuple of rigid body, A/C id and UDP output port to Simulink (multiple possible)')
parser.add_argument('-b', '--ivy_bus', dest='ivy_bus', help="Ivy bus address and port")
parser.add_argument('-ns', '--natnet_server', dest='natnet_server', default="127.0.0.1", help="NatNet server IP address")
parser.add_argument('-m', '--multicast_addr', dest='multicast', default="239.255.42.99", help="NatNet server multicast address")
parser.add_argument('-dp', '--data_port', dest='data_port', type=int, default=1511, help="NatNet server data socket UDP port")
parser.add_argument('-cp', '--command_port', dest='command_port', type=int, default=1510, help="NatNet server command socket UDP port")
parser.add_argument('-ss', '--simulink_server', dest='simulink_server', default="127.0.0.1", help="Simulink server IP address")
parser.add_argument('-sp', '--simulink_in_port', dest='simulink_in_port', default=9090, help="Simulink input port")
parser.add_argument('-v', '--verbose', dest='verbose', action='store_true', help="display debug messages")
args = parser.parse_args()

if args.ac is None:
print("At least one pair of rigid boby / AC id must be declared")
exit()

# dictionary of ID associations
id_dict = { v[0]: {'ac_id':v[1], 'udp_out':v[2]} for v in args.ac }

# start ivy interface
if args.ivy_bus is not None:
ivy = IvyMessagesInterface("matlab2pprz", ivy_bus=args.ivy_bus)
else:
ivy = IvyMessagesInterface("matlab2pprz")
# prepare Ivy message
ivy_msg = PprzMessage("datalink", "JOYSTICK_RAW")

# start socket for communication with Matlab/Simulink
try:
sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
sock.setsockopt(socket.SOL_SOCKET, socket.SO_BROADCAST, 1)
sock.settimeout(2.0)
sock.bind(('0.0.0.0', args.simulink_in_port)) # FIXME one port for all or one for each ?
except OSError:
print("Error: unable to open socket")


def receiveRigidBodyList( rigidBodyList, stamp ):
for (body_id, pos, quat, valid) in rigidBodyList:
if not valid:
# skip if rigid body is not valid
continue

i = str(body_id)
if i not in id_dict.keys():
# unknown A/C ID
continue
ac_id = id_dict[i]['ac_id']
port = int(id_dict[i]['udp_out'])

# data array = pos + quat
data = pos + quat

msg = ac_id+" "+format(stamp,"+0.5f")+" "+" ".join(format(x,"+0.4f") for x in data)
if args.verbose:
print('sending to simulink ({},{}): {}'.format(args.simulink_server, port, msg))

bindata = struct.pack('<fffffffff',float(ac_id),stamp,pos[0],pos[1],pos[2],quat[0],quat[1],quat[2],quat[3])
sock.sendto(bindata,(args.simulink_server,port))

natnet = NatNetClient(
server=args.natnet_server,
rigidBodyListListener=receiveRigidBodyList,
dataPort=args.data_port,
commandPort=args.command_port)

def sendCommandMsg(cmd):
# decode 5 int16 (short) and send other Ivy
bindata = struct.unpack('<hhhhh',cmd)
ivy_msg['ac_id'] = bindata[0]
ivy_msg['roll'] = bindata[1]
ivy_msg['pitch'] = bindata[2]
ivy_msg['yaw'] = bindata[3]
ivy_msg['throttle'] = bindata[4]
ivy.send(ivy_msg)

print("Starting Natnet3.x/Ivy to Matlab/Simulink bridge between %s and %s" % (args.natnet_server, args.simulink_server))
try:
# Start up the streaming client.
# This will run perpetually, and operate on a separate thread.
natnet.run()
while True:
try:
(cmd, address) = sock.recvfrom(10) # receiving 5 int16 (id, roll, pitch, yaw, thrust)
if len(cmd) == 10: # something to send
sendCommandMsg(cmd)
except socket.timeout:
pass
except (KeyboardInterrupt, SystemExit):
print("Shutting down socket, ivy and natnet interfaces...")
natnet.stop()
ivy.shutdown()
sock.close()
except OSError:
print("Natnet connection error")
natnet.stop()
ivy.stop()
sock.close()
exit(-1)

6 changes: 4 additions & 2 deletions sw/simulator/nps/nps_autopilot_fixedwing.c
Expand Up @@ -128,8 +128,9 @@ void nps_autopilot_run_step(double time)
}

if (nps_sensors_baro_available()) {
uint32_t now_ts = get_sys_time_usec();
float pressure = (float) sensors.baro.value;
AbiSendMsgBARO_ABS(BARO_SIM_SENDER_ID, pressure);
AbiSendMsgBARO_ABS(BARO_SIM_SENDER_ID, now_ts, pressure);
Fbw(event_task);
Ap(event_task);
}
Expand All @@ -154,8 +155,9 @@ void nps_autopilot_run_step(double time)

#if USE_SONAR
if (nps_sensors_sonar_available()) {
uint32_t now_ts = get_sys_time_usec();
float dist = (float) sensors.sonar.value;
AbiSendMsgAGL(AGL_SONAR_NPS_ID, dist);
AbiSendMsgAGL(AGL_SONAR_NPS_ID, now_ts, dist);

#ifdef SENSOR_SYNC_SEND_SONAR
uint16_t foo = 0;
Expand Down
8 changes: 6 additions & 2 deletions sw/simulator/nps/nps_autopilot_rotorcraft.c
Expand Up @@ -113,8 +113,9 @@ void nps_autopilot_run_step(double time)
}

if (nps_sensors_baro_available()) {
uint32_t now_ts = get_sys_time_usec();
float pressure = (float) sensors.baro.value;
AbiSendMsgBARO_ABS(BARO_SIM_SENDER_ID, pressure);
AbiSendMsgBARO_ABS(BARO_SIM_SENDER_ID, now_ts, pressure);
main_event();
}

Expand All @@ -130,8 +131,11 @@ void nps_autopilot_run_step(double time)

#if USE_SONAR
if (nps_sensors_sonar_available()) {
uint32_t now_ts = get_sys_time_usec();
float dist = (float) sensors.sonar.value;
AbiSendMsgAGL(AGL_SONAR_NPS_ID, dist);
if (dist >= 0.0) {
AbiSendMsgAGL(AGL_SONAR_NPS_ID, now_ts, dist);
}

#ifdef SENSOR_SYNC_SEND_SONAR
uint16_t foo = 0;
Expand Down
48 changes: 45 additions & 3 deletions sw/simulator/nps/nps_fdm_gazebo.cpp
Expand Up @@ -121,6 +121,8 @@ static void gazebo_read_range_sensors(void);

#endif

std::shared_ptr<gazebo::sensors::SonarSensor> sonar = NULL;

/// Holds all necessary NPS FDM state information
struct NpsFdm fdm;

Expand Down Expand Up @@ -328,6 +330,14 @@ static void init_gazebo(void)
string gazebodir = pprz_home + gazebo_home;
cout << "Gazebo directory: " << gazebodir << endl;

if (getenv("ROS_MASTER_URI")) {
// Launch with ROS support
cout << "Add ROS plugins... ";
gazebo::addPlugin("libgazebo_ros_paths_plugin.so");
gazebo::addPlugin("libgazebo_ros_api_plugin.so");
cout << "ok" << endl;
}

if (!gazebo::setupServer(0, NULL)) {
cout << "Failed to start Gazebo, exiting." << endl;
std::exit(-1);
Expand Down Expand Up @@ -431,10 +441,34 @@ static void init_gazebo(void)
gazebo::runWorld(world, 1);
cout << "Sensors initialized..." << endl;

// activate collision sensor
// Find sensors
// Contact sensor
gazebo::sensors::SensorManager *mgr = gazebo::sensors::SensorManager::Instance();
ct = static_pointer_cast < gazebo::sensors::ContactSensor > (mgr->GetSensor("contactsensor"));
ct->SetActive(true);
// Sonar
sonar = static_pointer_cast<gazebo::sensors::SonarSensor>(mgr->GetSensor("sonarsensor"));
if(sonar) {
cout << "Found sonar" << endl;
}

gazebo::physics::LinkPtr link = model->GetLink("sonar");
if (link) {
// Get a pointer to the sensor using its full name
if (link->GetSensorCount() != 1) {
cout << "ERROR: Link '" << link->GetName()
<< "' should only contain 1 sensor!" << endl;
} else {
string name = link->GetSensorName(0);
sonar = static_pointer_cast< gazebo::sensors::SonarSensor > (mgr->GetSensor(name));
if (!sonar) {
cout << "ERROR: Could not get pointer to '" << name << "'!" << endl;
} else {
// Activate sensor
sonar->SetActive(true);
}
}
}

// Overwrite motor directions as defined by motor_mixing
#ifdef MOTOR_MIXING_YAW_COEF
Expand Down Expand Up @@ -498,7 +532,14 @@ static void gazebo_read(void)
fdm.lla_pos_pprz = fdm.lla_pos; // Don't really care...
fdm.lla_pos_geod = fdm.lla_pos;
fdm.lla_pos_geoc = fdm.lla_pos;
fdm.agl = pose.Pos().Z(); // TODO Measure with sensor

if(sonar) {
double agl = sonar->Range();
if (agl > sonar->RangeMax()) agl = -1.0;
fdm.agl = agl;
} else {
fdm.agl = pose.Pos().Z(); // TODO Measure with sensor
}

/* velocity */
fdm.ecef_ecef_vel = to_pprz_ecef(sphere->VelocityTransform(vel, gazebo::common::SphericalCoordinates::LOCAL,
Expand Down Expand Up @@ -908,10 +949,11 @@ static void gazebo_read_range_sensors(void)
range_orientation[i * 2 + 1]);

if (i == ray_sensor_agl_index) {
uint32_t now_ts = get_sys_time_usec();
float agl = rays[i].sensor->Range(0);
// Down range sensor as agl
if (agl > 1e-5 && !isinf(agl)) {
AbiSendMsgAGL(AGL_RAY_SENSOR_GAZEBO_ID, agl);
AbiSendMsgAGL(AGL_RAY_SENSOR_GAZEBO_ID, now_ts, agl);
}
}
rays[i].last_measurement_time = rays[i].sensor->LastMeasurementTime();
Expand Down
15 changes: 15 additions & 0 deletions sw/tools/gzserver_ros_launcher.sh
@@ -0,0 +1,15 @@
#!/bin/sh
# This script sets up environment variables for gazebo_ros

# Paparazzi paths
export GAZEBO_MODEL_PATH="$PAPARAZZI_HOME/conf/simulator/gazebo/models:$GAZEBO_MODEL_PATH"
export GAZEBO_MODEL_PATH="$PAPARAZZI_HOME/sw/ext/tudelft_gazebo_models/models:$GAZEBO_MODEL_PATH"

# ROS and Gazebo defaults
ROS_SETUP=`locate --regex 'ros/[a-z]*/setup.sh$'`
GAZEBO_SETUP=`locate --regex 'gazebo/setup.sh$'`
. $ROS_SETUP
. $GAZEBO_SETUP

# Launch NPS-Gazebo
exec $PAPARAZZI_HOME/sw/simulator/pprzsim-launch $@