1
0
mirror of https://bitbucket.org/librepilot/librepilot.git synced 2024-12-02 10:24:11 +01:00

Flight/AHRS Communications: Switch to Les' very nice UAVObject communication

scheme

git-svn-id: svn://svn.openpilot.org/OpenPilot/trunk@1835 ebee16cc-31ac-478f-84a7-5cbb03baadba
This commit is contained in:
peabody124 2010-10-02 02:17:18 +00:00 committed by peabody124
parent 62300c9682
commit ea3fb03c7f
24 changed files with 1233 additions and 4092 deletions

View File

@ -82,7 +82,10 @@ STMUSBDIR = $(STMLIBDIR)/STM32_USB-FS-Device_Driver
STMSPDSRCDIR = $(STMSPDDIR)/src STMSPDSRCDIR = $(STMSPDDIR)/src
STMSPDINCDIR = $(STMSPDDIR)/inc STMSPDINCDIR = $(STMSPDDIR)/inc
CMSISDIR = $(STMLIBDIR)/CMSIS/Core/CM3 CMSISDIR = $(STMLIBDIR)/CMSIS/Core/CM3
OPDIR = ../OpenPilot
OPUAVOBJ = $(OPDIR)/UAVObjects
OPUAVOBJINC = $(OPUAVOBJ)/inc
OPSYSINC = $(OPDIR)/System/inc
# List C source files here. (C dependencies are automatically generated.) # List C source files here. (C dependencies are automatically generated.)
# use file-extension c for "c-only"-files # use file-extension c for "c-only"-files
@ -91,8 +94,10 @@ CMSISDIR = $(STMLIBDIR)/CMSIS/Core/CM3
SRC = ahrs.c SRC = ahrs.c
SRC += pios_board.c SRC += pios_board.c
SRC += ahrs_adc.c SRC += ahrs_adc.c
SRC += ahrs_fsm.c
SRC += ahrs_timer.c SRC += ahrs_timer.c
SRC += $(FLIGHTLIB)/ahrs_spi_comm.c
SRC += $(FLIGHTLIB)/ahrs_comm_objects.c
SRC += $(FLIGHTLIB)/ahrs_spi_program_slave.c
SRC += insgps.c SRC += insgps.c
SRC += $(FLIGHTLIB)/CoordinateConversions.c SRC += $(FLIGHTLIB)/CoordinateConversions.c
@ -110,7 +115,6 @@ SRC += $(PIOSSTM32F10X)/pios_exti.c
## PIOS Hardware (Common) ## PIOS Hardware (Common)
SRC += $(PIOSCOMMON)/pios_com.c SRC += $(PIOSCOMMON)/pios_com.c
SRC += $(PIOSCOMMON)/pios_hmc5843.c SRC += $(PIOSCOMMON)/pios_hmc5843.c
SRC += $(PIOSCOMMON)/pios_opahrs_proto.c
SRC += $(PIOSCOMMON)/printf-stdarg.c SRC += $(PIOSCOMMON)/printf-stdarg.c
## CMSIS for STM32 ## CMSIS for STM32
@ -172,6 +176,7 @@ EXTRAINCDIRS += $(PIOSBOARDS)
EXTRAINCDIRS += $(STMSPDINCDIR) EXTRAINCDIRS += $(STMSPDINCDIR)
EXTRAINCDIRS += $(CMSISDIR) EXTRAINCDIRS += $(CMSISDIR)
EXTRAINCDIRS += $(AHRSINC) EXTRAINCDIRS += $(AHRSINC)
EXTRAINCDIRS += $(OPUAVOBJINC)
# List any extra directories to look for library files here. # List any extra directories to look for library files here.
# Also add directories where the linker should search for # Also add directories where the linker should search for
@ -216,6 +221,7 @@ DEBUGF = dwarf-2
CDEFS = -DSTM32F10X_$(MODEL) CDEFS = -DSTM32F10X_$(MODEL)
CDEFS += -DUSE_STDPERIPH_DRIVER CDEFS += -DUSE_STDPERIPH_DRIVER
CDEFS += -DUSE_$(BOARD) CDEFS += -DUSE_$(BOARD)
CDEFS += -DIN_AHRS
ifeq ($(USE_BOOTLOADER), YES) ifeq ($(USE_BOOTLOADER), YES)
CDEFS += -DUSE_BOOTLOADER CDEFS += -DUSE_BOOTLOADER
endif endif

View File

@ -36,9 +36,10 @@
#include "ahrs_adc.h" #include "ahrs_adc.h"
#include "ahrs_timer.h" #include "ahrs_timer.h"
#include "pios_opahrs_proto.h" #include "pios_opahrs_proto.h"
#include "ahrs_fsm.h" /* lfsm_state */ //#include "ahrs_fsm.h" /* lfsm_state */
#include "insgps.h" #include "insgps.h"
#include "CoordinateConversions.h" #include "CoordinateConversions.h"
#include "ahrs_spi_comm.h"
// For debugging the raw sensors // For debugging the raw sensors
//#define DUMP_RAW //#define DUMP_RAW
@ -156,6 +157,11 @@ void process_spi_request(void);
void downsample_data(void); void downsample_data(void);
void calibrate_sensors(void); void calibrate_sensors(void);
void reset_values(); void reset_values();
void send_calibration(void);
void altitude_callback(AhrsObjHandle obj);
void calibration_callback(AhrsObjHandle obj);
void gps_callback(AhrsObjHandle obj);
void settings_callback(AhrsObjHandle obj);
volatile uint32_t last_counter_idle_start = 0; volatile uint32_t last_counter_idle_start = 0;
volatile uint32_t last_counter_idle_end = 0; volatile uint32_t last_counter_idle_end = 0;
@ -171,14 +177,10 @@ uint32_t counter_val;
//! Filter coefficients used in decimation. Limited order so filter can't run between samples //! Filter coefficients used in decimation. Limited order so filter can't run between samples
int16_t fir_coeffs[50]; int16_t fir_coeffs[50];
//! Indicates the communications are requesting a calibration
uint8_t calibration_pending = FALSE;
//! The oversampling rate, ekf is 2k / this //! The oversampling rate, ekf is 2k / this
static uint8_t adc_oversampling = 25; static uint8_t adc_oversampling = 17;
//! Flag for OP to check if AHRS has been initialized yet
enum initialized_mode initialized = 0;
/** /**
* @} * @}
@ -214,19 +216,38 @@ int main()
/* Magnetic sensor system */ /* Magnetic sensor system */
PIOS_I2C_Init(); PIOS_I2C_Init();
PIOS_HMC5843_Init(); PIOS_HMC5843_Init();
// Get 3 ID bytes // Get 3 ID bytes
strcpy((char *)mag_data.id, "ZZZ"); strcpy((char *)mag_data.id, "ZZZ");
PIOS_HMC5843_ReadID(mag_data.id); PIOS_HMC5843_ReadID(mag_data.id);
#endif #endif
/* SPI link to master */ /* SPI link to master */
PIOS_SPI_Init(); // PIOS_SPI_Init();
lfsm_init(); // lfsm_init();
reset_values(); reset_values();
ahrs_state = AHRS_IDLE; ahrs_state = AHRS_IDLE;
AhrsInitComms();
ahrs_state = AHRS_IDLE;
while(!AhrsLinkReady()) {
AhrsPoll();
while(ahrs_state != AHRS_DATA_READY) ;
ahrs_state = AHRS_PROCESSING;
downsample_data();
ahrs_state = AHRS_IDLE;
if((total_conversion_blocks % 10) == 0)
PIOS_LED_Toggle(LED1);
}
/* we didn't connect the callbacks before because we have to wait
for all data to be up to date before doing anything*/
AHRSCalibrationConnectCallback(calibration_callback);
GPSPositionConnectCallback(gps_callback);
BaroAltitudeConnectCallback(altitude_callback);
AHRSSettingsConnectCallback(settings_callback);
calibration_callback(AHRSCalibrationHandle()); //force an update
/* Use simple averaging filter for now */ /* Use simple averaging filter for now */
for (int i = 0; i < adc_oversampling; i++) for (int i = 0; i < adc_oversampling; i++)
@ -235,12 +256,10 @@ int main()
INSGPSInit(); INSGPSInit();
while(initialized != AHRS_INITIALIZED)
process_spi_request();
#ifdef DUMP_RAW #ifdef DUMP_RAW
int previous_conversion; int previous_conversion;
while (1) { while (1) {
AhrsPoll();
int result; int result;
uint8_t framing[16] = uint8_t framing[16] =
{ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
@ -277,16 +296,21 @@ int main()
timer_start(); timer_start();
/******************* Main EKF loop ****************************/ /******************* Main EKF loop ****************************/
while (1) { while(1) {
AhrsPoll();
AhrsStatusData status;
AhrsStatusGet(&status);
status.CPULoad = ((float)running_counts /
(float)(idle_counts + running_counts)) * 100;
status.IdleTimePerCyle = idle_counts / (TIMER_RATE / 10000);
status.RunningTimePerCyle = running_counts / (TIMER_RATE / 10000);
status.DroppedUpdates = ekf_too_slow;
AhrsStatusSet(&status);
// Alive signal // Alive signal
if ((total_conversion_blocks % 100) == 0) if ((total_conversion_blocks % 100) == 0)
PIOS_LED_Toggle(LED1); PIOS_LED_Toggle(LED1);
if (calibration_pending) {
calibrate_sensors();
calibration_pending = FALSE;
}
#if defined(PIOS_INCLUDE_HMC5843) && defined(PIOS_INCLUDE_I2C) #if defined(PIOS_INCLUDE_HMC5843) && defined(PIOS_INCLUDE_I2C)
// Get magnetic readings // Get magnetic readings
if (PIOS_HMC5843_NewDataAvailable()) { if (PIOS_HMC5843_NewDataAvailable()) {
@ -296,6 +320,7 @@ int main()
mag_data.scaled.axis[2] = (mag_data.raw.axis[2] * mag_data.calibration.scale[2]) + mag_data.calibration.bias[2]; mag_data.scaled.axis[2] = (mag_data.raw.axis[2] * mag_data.calibration.scale[2]) + mag_data.calibration.bias[2];
mag_data.updated = 1; mag_data.updated = 1;
} }
#endif #endif
// Delay for valid data // Delay for valid data
@ -543,6 +568,30 @@ void downsample_data()
gyro_data.filtered.z += valid_data_buffer[5 + i * PIOS_ADC_NUM_PINS] * fir_coeffs[i]; gyro_data.filtered.z += valid_data_buffer[5 + i * PIOS_ADC_NUM_PINS] * fir_coeffs[i];
gyro_data.filtered.z /= fir_coeffs[adc_oversampling]; gyro_data.filtered.z /= fir_coeffs[adc_oversampling];
gyro_data.filtered.z = (gyro_data.filtered.z * gyro_data.calibration.scale[2]) + gyro_data.calibration.bias[2]; gyro_data.filtered.z = (gyro_data.filtered.z * gyro_data.calibration.scale[2]) + gyro_data.calibration.bias[2];
AttitudeRawData raw;
raw.gyros[0] = valid_data_buffer[1];
raw.gyros[1] = valid_data_buffer[3];
raw.gyros[2] = valid_data_buffer[5];
raw.gyros_filtered[0] = gyro_data.filtered.x;
raw.gyros_filtered[1] = gyro_data.filtered.y;
raw.gyros_filtered[2] = gyro_data.filtered.z;
raw.accels[0] = valid_data_buffer[2];
raw.accels[1] = valid_data_buffer[0];
raw.accels[2] = valid_data_buffer[4];
raw.accels_filtered[0] = accel_data.filtered.x;
raw.accels_filtered[1] = accel_data.filtered.y;
raw.accels_filtered[2] = accel_data.filtered.z;
raw.magnetometers[0] = mag_data.scaled.axis[0];
raw.magnetometers[1] = mag_data.scaled.axis[1];
raw.magnetometers[2] = mag_data.scaled.axis[2];
AttitudeRawSet(&raw);
} }
/** /**
@ -565,6 +614,7 @@ void calibrate_sensors()
float gyro_bias[3] = {0, 0, 0}; float gyro_bias[3] = {0, 0, 0};
float mag_bias[3] = {0, 0, 0}; float mag_bias[3] = {0, 0, 0};
for (i = 0, j = 0; i < NBIAS; i++) { for (i = 0, j = 0; i < NBIAS; i++) {
while (ahrs_state != AHRS_DATA_READY) ; while (ahrs_state != AHRS_DATA_READY) ;
ahrs_state = AHRS_PROCESSING; ahrs_state = AHRS_PROCESSING;
@ -589,7 +639,7 @@ void calibrate_sensors()
mag_bias[2] += mag_data.scaled.axis[2]; mag_bias[2] += mag_data.scaled.axis[2];
} }
#endif #endif
process_spi_request();
} }
mag_bias[0] /= j; mag_bias[0] /= j;
mag_bias[1] /= j; mag_bias[1] /= j;
@ -628,12 +678,16 @@ void calibrate_sensors()
mag_data.calibration.variance[2] += pow(mag_data.scaled.axis[2]-mag_bias[2],2); mag_data.calibration.variance[2] += pow(mag_data.scaled.axis[2]-mag_bias[2],2);
} }
#endif #endif
process_spi_request();
} }
mag_data.calibration.variance[0] /= j; mag_data.calibration.variance[0] /= j;
mag_data.calibration.variance[1] /= j; mag_data.calibration.variance[1] /= j;
mag_data.calibration.variance[2] /= j; mag_data.calibration.variance[2] /= j;
gyro_data.calibration.bias[0] -= gyro_bias[0];
gyro_data.calibration.bias[1] -= gyro_bias[1];
gyro_data.calibration.bias[2] -= gyro_bias[2];
} }
/** /**
@ -669,259 +723,131 @@ void reset_values() {
mag_data.calibration.variance[2] = 1; mag_data.calibration.variance[2] = 1;
} }
/**
* @addtogroup AHRS_SPI SPI Messaging
* @{
* @brief SPI protocol handling requests for data from OP mainboard
*/
static struct opahrs_msg_v1 link_tx_v1;
static struct opahrs_msg_v1 link_rx_v1;
static struct opahrs_msg_v1 user_rx_v1;
static struct opahrs_msg_v1 user_tx_v1;
void process_spi_request(void) void process_spi_request(void)
{ {
bool msg_to_process = FALSE; AttitudeActualData attitude;
attitude.q1 = attitude_data.quaternion.q1;
attitude.q2 = attitude_data.quaternion.q2;
attitude.q3 = attitude_data.quaternion.q3;
attitude.q4 = attitude_data.quaternion.q4;
float rpy[3];
Quaternion2RPY(&attitude_data.quaternion.q1, rpy);
attitude.Roll = rpy[0];
attitude.Pitch = rpy[1];
attitude.Yaw = rpy[2];
AttitudeActualSet(&attitude);
}
PIOS_IRQ_Disable(); void send_calibration(void)
/* Figure out if we're in an interesting stable state */ {
switch (lfsm_get_state()) { AHRSCalibrationData cal;
case LFSM_STATE_USER_BUSY: AHRSCalibrationGet(&cal);
msg_to_process = TRUE; for(int ct=0; ct<3; ct++)
break; {
case LFSM_STATE_INACTIVE: cal.accel_var[ct] = accel_data.calibration.variance[ct];
/* Queue up a receive buffer */ cal.gyro_bias[ct] = gyro_data.calibration.bias[ct];
lfsm_user_set_rx_v1(&user_rx_v1); cal.gyro_var[ct] = gyro_data.calibration.variance[ct];
lfsm_user_done(); cal.mag_var[ct] = mag_data.calibration.variance[ct];
break;
case LFSM_STATE_STOPPED:
/* Get things going */
lfsm_set_link_proto_v1(&link_tx_v1, &link_rx_v1);
break;
default:
/* Not a stable state */
break;
} }
PIOS_IRQ_Enable(); cal.measure_var = AHRSCALIBRATION_MEASURE_VAR_SET;
AHRSCalibrationSet(&cal);
}
if (!msg_to_process) { /**
/* Nothing to do */ * @brief AHRS calibration callback
*
* Called when the OP board sets the calibration
*/
void calibration_callback(AhrsObjHandle obj)
{
AHRSCalibrationData cal;
AHRSCalibrationGet(&cal);
if(cal.measure_var == AHRSCALIBRATION_MEASURE_VAR_SET){
for(int ct=0; ct<3; ct++)
{
accel_data.calibration.scale[ct] = cal.accel_scale[ct];
accel_data.calibration.bias[ct] = cal.accel_bias[ct];
accel_data.calibration.variance[ct] = cal.accel_var[ct];
gyro_data.calibration.scale[ct] = cal.gyro_scale[ct];
gyro_data.calibration.bias[ct] = cal.gyro_bias[ct];
gyro_data.calibration.variance[ct] = cal.gyro_var[ct];
mag_data.calibration.bias[ct] = cal.mag_bias[ct];
mag_data.calibration.scale[ct] = cal.mag_scale[ct];
mag_data.calibration.variance[ct] = cal.mag_var[ct];
}
}else if(cal.measure_var == AHRSCALIBRATION_MEASURE_VAR_MEASURE){
calibrate_sensors();
AHRSCalibrationData cal;
AHRSCalibrationGet(&cal);
cal.measure_var = AHRSCALIBRATION_MEASURE_VAR_SET;
AHRSCalibrationSet(&cal);
}else if(cal.measure_var == AHRSCALIBRATION_MEASURE_VAR_ECHO){
send_calibration();
}
}
void gps_callback(AhrsObjHandle obj)
{
GPSPositionData pos;
GPSPositionGet(&pos);
HomeLocationData home;
HomeLocationGet(&home);
if(home.Set == HOMELOCATION_SET_FALSE || home.Indoor == HOMELOCATION_INDOOR_TRUE) {
gps_data.NED[0] = 0;
gps_data.NED[1] = 0;
gps_data.NED[2] = 0;
gps_data.groundspeed = 0;
gps_data.heading = 0;
gps_data.quality = -1; // indicates indoor mode, high variance zeros update
gps_data.updated = true;
return; return;
} }
switch (user_rx_v1.payload.user.t) { if(pos.Status != GPSPOSITION_STATUS_FIX3D) //FIXME: Will this work? the old ahrs_comms does it differently.
case OPAHRS_MSG_V1_REQ_RESET: {
PIOS_DELAY_WaitmS(user_rx_v1.payload.user.v.req.reset. gps_data.quality = 0;
reset_delay_in_ms);
PIOS_SYS_Reset();
break;
case OPAHRS_MSG_V1_REQ_SERIAL:
opahrs_msg_v1_init_user_tx(&user_tx_v1,OPAHRS_MSG_V1_RSP_SERIAL);
PIOS_SYS_SerialNumberGet((char *) &(user_tx_v1.payload.user.v.rsp.
serial.serial_bcd));
lfsm_user_set_tx_v1(&user_tx_v1);
break;
case OPAHRS_MSG_V1_REQ_ALGORITHM:
opahrs_msg_v1_init_user_tx(&user_tx_v1,OPAHRS_MSG_V1_RSP_ALGORITHM);
ahrs_algorithm = user_rx_v1.payload.user.v.req.algorithm.algorithm;
lfsm_user_set_tx_v1(&user_tx_v1);
break;
case OPAHRS_MSG_V1_REQ_NORTH:
opahrs_msg_v1_init_user_tx(&user_tx_v1,OPAHRS_MSG_V1_RSP_NORTH);
INSSetMagNorth(user_rx_v1.payload.user.v.req.north.Be);
lfsm_user_set_tx_v1(&user_tx_v1);
break;
case OPAHRS_MSG_V1_REQ_CALIBRATION:
if (user_rx_v1.payload.user.v.req.calibration.
measure_var == AHRS_MEASURE) {
calibration_pending = TRUE;
} else if (user_rx_v1.payload.user.v.req.calibration.measure_var == AHRS_SET) {
// Set the accel calibration
accel_data.calibration.variance[0] = user_rx_v1.payload.user.v.req.calibration.accel_var[0];
accel_data.calibration.variance[1] = user_rx_v1.payload.user.v.req.calibration.accel_var[1];
accel_data.calibration.variance[2] = user_rx_v1.payload.user.v.req.calibration.accel_var[2];
accel_data.calibration.scale[0] = user_rx_v1.payload.user.v.req.calibration.accel_scale[0];
accel_data.calibration.scale[1] = user_rx_v1.payload.user.v.req.calibration.accel_scale[1];
accel_data.calibration.scale[2] = user_rx_v1.payload.user.v.req.calibration.accel_scale[2];
accel_data.calibration.bias[0] = user_rx_v1.payload.user.v.req.calibration.accel_bias[0];
accel_data.calibration.bias[1] = user_rx_v1.payload.user.v.req.calibration.accel_bias[1];
accel_data.calibration.bias[2] = user_rx_v1.payload.user.v.req.calibration.accel_bias[2];
// Set the gyro calibration
gyro_data.calibration.variance[0] = user_rx_v1.payload.user.v.req.calibration.gyro_var[0];
gyro_data.calibration.variance[1] = user_rx_v1.payload.user.v.req.calibration.gyro_var[1];
gyro_data.calibration.variance[2] = user_rx_v1.payload.user.v.req.calibration.gyro_var[2];
gyro_data.calibration.scale[0] = user_rx_v1.payload.user.v.req.calibration.gyro_scale[0];
gyro_data.calibration.scale[1] = user_rx_v1.payload.user.v.req.calibration.gyro_scale[1];
gyro_data.calibration.scale[2] = user_rx_v1.payload.user.v.req.calibration.gyro_scale[2];
gyro_data.calibration.bias[0] = user_rx_v1.payload.user.v.req.calibration.gyro_bias[0];
gyro_data.calibration.bias[1] = user_rx_v1.payload.user.v.req.calibration.gyro_bias[1];
gyro_data.calibration.bias[2] = user_rx_v1.payload.user.v.req.calibration.gyro_bias[2];
// Set the mag calibration
mag_data.calibration.variance[0] = user_rx_v1.payload.user.v.req.calibration.mag_var[0];
mag_data.calibration.variance[1] = user_rx_v1.payload.user.v.req.calibration.mag_var[1];
mag_data.calibration.variance[2] = user_rx_v1.payload.user.v.req.calibration.mag_var[2];
mag_data.calibration.scale[0] = user_rx_v1.payload.user.v.req.calibration.mag_scale[0];
mag_data.calibration.scale[1] = user_rx_v1.payload.user.v.req.calibration.mag_scale[1];
mag_data.calibration.scale[2] = user_rx_v1.payload.user.v.req.calibration.mag_scale[2];
mag_data.calibration.bias[0] = user_rx_v1.payload.user.v.req.calibration.mag_bias[0];
mag_data.calibration.bias[1] = user_rx_v1.payload.user.v.req.calibration.mag_bias[1];
mag_data.calibration.bias[2] = user_rx_v1.payload.user.v.req.calibration.mag_bias[2];
float zeros[3] = { 0, 0, 0 };
INSSetGyroBias(zeros); //gyro bias corrects in preprocessing
INSSetAccelVar(accel_data.calibration.variance);
INSSetGyroVar(gyro_data.calibration.variance);
float mag_var[3] = {mag_data.calibration.variance[1], mag_data.calibration.variance[0], mag_data.calibration.variance[2]};
INSSetMagVar(mag_var);
}
// echo back the values used
opahrs_msg_v1_init_user_tx(&user_tx_v1,
OPAHRS_MSG_V1_RSP_CALIBRATION);
user_tx_v1.payload.user.v.rsp.calibration.accel_var[0] = accel_data.calibration.variance[0];
user_tx_v1.payload.user.v.rsp.calibration.accel_var[1] = accel_data.calibration.variance[1];
user_tx_v1.payload.user.v.rsp.calibration.accel_var[2] = accel_data.calibration.variance[2];
user_tx_v1.payload.user.v.rsp.calibration.gyro_var[0] = gyro_data.calibration.variance[0];
user_tx_v1.payload.user.v.rsp.calibration.gyro_var[1] = gyro_data.calibration.variance[1];
user_tx_v1.payload.user.v.rsp.calibration.gyro_var[2] = gyro_data.calibration.variance[2];
user_tx_v1.payload.user.v.rsp.calibration.mag_var[0] = mag_data.calibration.variance[0];
user_tx_v1.payload.user.v.rsp.calibration.mag_var[1] = mag_data.calibration.variance[1];
user_tx_v1.payload.user.v.rsp.calibration.mag_var[2] = mag_data.calibration.variance[2];
lfsm_user_set_tx_v1(&user_tx_v1);
break;
case OPAHRS_MSG_V1_REQ_ATTITUDERAW:
opahrs_msg_v1_init_user_tx(&user_tx_v1,
OPAHRS_MSG_V1_RSP_ATTITUDERAW);
// Grab one sample from buffer to populate this
accel_data.raw.x = valid_data_buffer[0];
accel_data.raw.y = valid_data_buffer[2];
accel_data.raw.z = valid_data_buffer[4];
gyro_data.raw.x = valid_data_buffer[1];
gyro_data.raw.y = valid_data_buffer[3];
gyro_data.raw.z = valid_data_buffer[5];
gyro_data.temp.xy = valid_data_buffer[6];
gyro_data.temp.z = valid_data_buffer[7];
user_tx_v1.payload.user.v.rsp.attituderaw.mags.x =
mag_data.raw.axis[0];
user_tx_v1.payload.user.v.rsp.attituderaw.mags.y =
mag_data.raw.axis[1];
user_tx_v1.payload.user.v.rsp.attituderaw.mags.z =
mag_data.raw.axis[2];
user_tx_v1.payload.user.v.rsp.attituderaw.gyros.x =
gyro_data.raw.x;
user_tx_v1.payload.user.v.rsp.attituderaw.gyros.y =
gyro_data.raw.y;
user_tx_v1.payload.user.v.rsp.attituderaw.gyros.z =
gyro_data.raw.z;
user_tx_v1.payload.user.v.rsp.attituderaw.gyros_filtered.
x = gyro_data.filtered.x;
user_tx_v1.payload.user.v.rsp.attituderaw.gyros_filtered.
y = gyro_data.filtered.y;
user_tx_v1.payload.user.v.rsp.attituderaw.gyros_filtered.
z = gyro_data.filtered.z;
user_tx_v1.payload.user.v.rsp.attituderaw.gyros.xy_temp =
gyro_data.temp.xy;
user_tx_v1.payload.user.v.rsp.attituderaw.gyros.z_temp =
gyro_data.temp.z;
user_tx_v1.payload.user.v.rsp.attituderaw.accels.x =
accel_data.raw.x;
user_tx_v1.payload.user.v.rsp.attituderaw.accels.y =
accel_data.raw.y;
user_tx_v1.payload.user.v.rsp.attituderaw.accels.z =
accel_data.raw.z;
user_tx_v1.payload.user.v.rsp.attituderaw.accels_filtered.
x = accel_data.filtered.x;
user_tx_v1.payload.user.v.rsp.attituderaw.accels_filtered.
y = accel_data.filtered.y;
user_tx_v1.payload.user.v.rsp.attituderaw.accels_filtered.
z = accel_data.filtered.z;
lfsm_user_set_tx_v1(&user_tx_v1);
break;
case OPAHRS_MSG_V1_REQ_UPDATE:
// process incoming data
opahrs_msg_v1_init_user_tx(&user_tx_v1,
OPAHRS_MSG_V1_RSP_UPDATE);
if (user_rx_v1.payload.user.v.req.update.barometer.updated) {
altitude_data.altitude =
user_rx_v1.payload.user.v.req.update.barometer.
altitude;
altitude_data.updated =
user_rx_v1.payload.user.v.req.update.barometer.
updated;
}
if (user_rx_v1.payload.user.v.req.update.gps.updated) {
gps_data.updated = true; gps_data.updated = true;
gps_data.NED[0] = user_rx_v1.payload.user.v.req.update.gps.NED[0]; return;
gps_data.NED[1] = user_rx_v1.payload.user.v.req.update.gps.NED[1];
gps_data.NED[2] = user_rx_v1.payload.user.v.req.update.gps.NED[2];
gps_data.heading = user_rx_v1.payload.user.v.req.update.gps.heading;
gps_data.groundspeed = user_rx_v1.payload.user.v.req.update.gps.groundspeed;
gps_data.quality = user_rx_v1.payload.user.v.req.update.gps.quality;
}
// send out attitude/position estimate
user_tx_v1.payload.user.v.rsp.update.quaternion.q1 =
attitude_data.quaternion.q1;
user_tx_v1.payload.user.v.rsp.update.quaternion.q2 =
attitude_data.quaternion.q2;
user_tx_v1.payload.user.v.rsp.update.quaternion.q3 =
attitude_data.quaternion.q3;
user_tx_v1.payload.user.v.rsp.update.quaternion.q4 =
attitude_data.quaternion.q4;
// convert all to cm/s
user_tx_v1.payload.user.v.rsp.update.NED[0] = Nav.Pos[0]*100;
user_tx_v1.payload.user.v.rsp.update.NED[1] = Nav.Pos[1]*100;
user_tx_v1.payload.user.v.rsp.update.NED[2] = Nav.Pos[2]*100;
user_tx_v1.payload.user.v.rsp.update.Vel[0] = Nav.Vel[0]*100;
user_tx_v1.payload.user.v.rsp.update.Vel[1] = Nav.Vel[1]*100;
user_tx_v1.payload.user.v.rsp.update.Vel[2] = Nav.Vel[2]*100;
// compute the idle fraction
user_tx_v1.payload.user.v.rsp.update.load =
((float)running_counts /
(float)(idle_counts + running_counts)) * 100;
user_tx_v1.payload.user.v.rsp.update.idle_time =
idle_counts / (TIMER_RATE / 10000);
user_tx_v1.payload.user.v.rsp.update.run_time =
running_counts / (TIMER_RATE / 10000);
user_tx_v1.payload.user.v.rsp.update.dropped_updates =
ekf_too_slow;
lfsm_user_set_tx_v1(&user_tx_v1);
break;
case OPAHRS_MSG_V1_REQ_INITIALIZED:
// process incoming data
opahrs_msg_v1_init_user_tx(&user_tx_v1,OPAHRS_MSG_V1_RSP_INITIALIZED);
user_tx_v1.payload.user.v.rsp.initialized.initialized = initialized;
if(user_rx_v1.payload.user.v.req.initialized.initialized == AHRS_INITIALIZED)
initialized = AHRS_INITIALIZED;
else if(user_rx_v1.payload.user.v.req.initialized.initialized == AHRS_UNINITIALIZED)
initialized = AHRS_UNINITIALIZED;
lfsm_user_set_tx_v1(&user_tx_v1);
break;
default:
break;
} }
/* Finished processing the received message, requeue it */ double LLA[3] = {(double) pos.Latitude / 1e7, (double) pos.Longitude / 1e7, (double) (pos.GeoidSeparation + pos.Altitude)};
lfsm_user_set_rx_v1(&user_rx_v1); // convert from cm back to meters
lfsm_user_done(); double ECEF[3] = {(double) (home.ECEF[0] / 100), (double) (home.ECEF[1] / 100), (double) (home.ECEF[2] / 100)};
LLA2Base(LLA, ECEF, (float (*)[3]) home.RNE, gps_data.NED);
gps_data.heading = pos.Heading;
gps_data.groundspeed = pos.Groundspeed;
gps_data.quality = 1;
gps_data.updated = true;
} }
void altitude_callback(AhrsObjHandle obj)
{
BaroAltitudeData alt;
BaroAltitudeGet(&alt);
altitude_data.altitude = alt.Altitude;
altitude_data.updated = true;
}
void settings_callback(AhrsObjHandle obj)
{
AHRSSettingsData settings;
AHRSSettingsGet(&settings);
if(settings.Algorithm == AHRSSETTINGS_ALGORITHM_INSGPS)
{
ahrs_algorithm = INSGPS_Algo;
}else
{
ahrs_algorithm = SIMPLE_Algo;
}
}
/** /**
* @} * @}
*/ */

View File

@ -1,735 +0,0 @@
/**
******************************************************************************
* @addtogroup AHRS AHRS
* @brief The AHRS Modules perform
*
* @{
* @addtogroup AHRS_ADC AHRS ADC
* @brief Specialized ADC code for double buffered DMA for AHRS
* @{
*
*
* @file ahrs.c
* @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2010.
* @brief INSGPS Test Program
* @see The GNU Public License (GPL) Version 3
*
*****************************************************************************/
/*
* This program 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 3 of the License, or
* (at your option) any later version.
*
* This program 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 this program; if not, write to the Free Software Foundation, Inc.,
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include <stdint.h> /* uint*_t */
#include <stddef.h> /* NULL */
#include "ahrs_fsm.h"
#include "pios_opahrs_proto.h"
#include "pios.h"
struct lfsm_context {
enum lfsm_state curr_state;
enum opahrs_msg_link_state link_state;
enum opahrs_msg_type user_payload_type;
uint32_t user_payload_len;
uint32_t errors;
uint8_t *rx;
uint8_t *tx;
uint8_t *link_rx;
uint8_t *link_tx;
uint8_t *user_rx;
uint8_t *user_tx;
struct lfsm_link_stats stats;
};
static struct lfsm_context context = { 0 };
static void lfsm_update_link_tx(struct lfsm_context *context);
static void lfsm_init_rx(struct lfsm_context *context);
/*
*
* Link Finite State Machine
*
*/
struct lfsm_transition {
void (*entry_fn) (struct lfsm_context * context);
enum lfsm_state next_state[LFSM_EVENT_NUM_EVENTS];
};
static void go_faulted(struct lfsm_context *context);
static void go_stopped(struct lfsm_context *context);
static void go_stopping(struct lfsm_context *context);
static void go_inactive(struct lfsm_context *context);
static void go_user_busy(struct lfsm_context *context);
static void go_user_busy_rx_pending(struct lfsm_context *context);
static void go_user_busy_tx_pending(struct lfsm_context *context);
static void go_user_busy_rxtx_pending(struct lfsm_context *context);
static void go_user_rx_pending(struct lfsm_context *context);
static void go_user_tx_pending(struct lfsm_context *context);
static void go_user_rxtx_pending(struct lfsm_context *context);
static void go_user_rx_active(struct lfsm_context *context);
static void go_user_tx_active(struct lfsm_context *context);
static void go_user_rxtx_active(struct lfsm_context *context);
const static struct lfsm_transition lfsm_transitions[LFSM_STATE_NUM_STATES]
= {
[LFSM_STATE_FAULTED] = {
.entry_fn = go_faulted,
},
[LFSM_STATE_STOPPED] = {
.entry_fn = go_stopped,
.next_state = {
[LFSM_EVENT_INIT_LINK] =
LFSM_STATE_INACTIVE,
[LFSM_EVENT_RX_UNKNOWN] =
LFSM_STATE_STOPPED,
},
},
[LFSM_STATE_STOPPING] = {
.entry_fn = go_stopping,
.next_state = {
[LFSM_EVENT_RX_LINK] =
LFSM_STATE_STOPPED,
[LFSM_EVENT_RX_USER] =
LFSM_STATE_STOPPED,
[LFSM_EVENT_RX_UNKNOWN] =
LFSM_STATE_STOPPED,
},
},
[LFSM_STATE_INACTIVE] = {
.entry_fn = go_inactive,
.next_state = {
[LFSM_EVENT_STOP] =
LFSM_STATE_STOPPING,
[LFSM_EVENT_USER_SET_RX] =
LFSM_STATE_USER_BUSY_RX_PENDING,
[LFSM_EVENT_USER_SET_TX] =
LFSM_STATE_USER_BUSY_TX_PENDING,
[LFSM_EVENT_RX_LINK] =
LFSM_STATE_INACTIVE,
[LFSM_EVENT_RX_USER] =
LFSM_STATE_INACTIVE,
[LFSM_EVENT_RX_UNKNOWN] =
LFSM_STATE_INACTIVE,
},
},
[LFSM_STATE_USER_BUSY] = {
.entry_fn = go_user_busy,
.next_state = {
[LFSM_EVENT_STOP] =
LFSM_STATE_STOPPING,
[LFSM_EVENT_USER_SET_RX] =
LFSM_STATE_USER_BUSY_RX_PENDING,
[LFSM_EVENT_USER_SET_TX] =
LFSM_STATE_USER_BUSY_TX_PENDING,
[LFSM_EVENT_USER_DONE] =
LFSM_STATE_INACTIVE,
[LFSM_EVENT_RX_LINK] =
LFSM_STATE_USER_BUSY,
[LFSM_EVENT_RX_USER] =
LFSM_STATE_USER_BUSY,
[LFSM_EVENT_RX_UNKNOWN] =
LFSM_STATE_USER_BUSY,
},
},
[LFSM_STATE_USER_BUSY_RX_PENDING] = {
.entry_fn =
go_user_busy_rx_pending,
.next_state = {
[LFSM_EVENT_USER_SET_TX] = LFSM_STATE_USER_BUSY_RXTX_PENDING,
[LFSM_EVENT_USER_DONE] = LFSM_STATE_USER_RX_PENDING,
[LFSM_EVENT_RX_LINK] = LFSM_STATE_USER_BUSY_RX_PENDING,
[LFSM_EVENT_RX_USER] = LFSM_STATE_USER_BUSY_RX_PENDING,
[LFSM_EVENT_RX_UNKNOWN] = LFSM_STATE_USER_BUSY_RX_PENDING,
},
},
[LFSM_STATE_USER_BUSY_TX_PENDING] = {
.entry_fn =
go_user_busy_tx_pending,
.next_state = {
[LFSM_EVENT_USER_SET_RX] = LFSM_STATE_USER_BUSY_RXTX_PENDING,
[LFSM_EVENT_USER_DONE] = LFSM_STATE_USER_TX_PENDING,
[LFSM_EVENT_RX_LINK] = LFSM_STATE_USER_BUSY_TX_PENDING,
[LFSM_EVENT_RX_USER] = LFSM_STATE_USER_BUSY_TX_PENDING,
[LFSM_EVENT_RX_UNKNOWN] = LFSM_STATE_USER_BUSY_TX_PENDING,
},
},
[LFSM_STATE_USER_BUSY_RXTX_PENDING] = {
.entry_fn =
go_user_busy_rxtx_pending,
.next_state = {
[LFSM_EVENT_USER_DONE] = LFSM_STATE_USER_RXTX_PENDING,
[LFSM_EVENT_RX_LINK] = LFSM_STATE_USER_BUSY_RXTX_PENDING,
[LFSM_EVENT_RX_USER] = LFSM_STATE_USER_BUSY_RXTX_PENDING,
[LFSM_EVENT_RX_UNKNOWN] = LFSM_STATE_USER_BUSY_RXTX_PENDING,
},
},
[LFSM_STATE_USER_RX_PENDING] = {
.entry_fn = go_user_rx_pending,
.next_state = {
[LFSM_EVENT_RX_LINK]
=
LFSM_STATE_USER_RX_ACTIVE,
[LFSM_EVENT_RX_USER]
=
LFSM_STATE_USER_RX_ACTIVE,
[LFSM_EVENT_RX_UNKNOWN] = LFSM_STATE_USER_RX_ACTIVE,
},
},
[LFSM_STATE_USER_TX_PENDING] = {
.entry_fn = go_user_tx_pending,
.next_state = {
[LFSM_EVENT_RX_LINK]
=
LFSM_STATE_USER_TX_ACTIVE,
[LFSM_EVENT_RX_USER]
=
LFSM_STATE_USER_TX_ACTIVE,
[LFSM_EVENT_RX_UNKNOWN] = LFSM_STATE_USER_TX_ACTIVE,
},
},
[LFSM_STATE_USER_RXTX_PENDING] = {
.entry_fn = go_user_rxtx_pending,
.next_state = {
[LFSM_EVENT_RX_LINK] = LFSM_STATE_USER_RXTX_ACTIVE,
[LFSM_EVENT_RX_USER] = LFSM_STATE_USER_RXTX_ACTIVE,
[LFSM_EVENT_RX_UNKNOWN] = LFSM_STATE_USER_RXTX_ACTIVE,
},
},
[LFSM_STATE_USER_RX_ACTIVE] = {
.entry_fn = go_user_rx_active,
.next_state = {
[LFSM_EVENT_RX_LINK]
=
LFSM_STATE_USER_RX_ACTIVE,
[LFSM_EVENT_RX_USER]
=
LFSM_STATE_USER_BUSY,
[LFSM_EVENT_RX_UNKNOWN] = LFSM_STATE_USER_RX_ACTIVE,
},
},
[LFSM_STATE_USER_TX_ACTIVE] = {
.entry_fn = go_user_tx_active,
.next_state = {
[LFSM_EVENT_RX_LINK]
=
LFSM_STATE_INACTIVE,
[LFSM_EVENT_RX_USER]
=
LFSM_STATE_INACTIVE,
[LFSM_EVENT_RX_UNKNOWN] = LFSM_STATE_INACTIVE,
},
},
[LFSM_STATE_USER_RXTX_ACTIVE] = {
.entry_fn = go_user_rxtx_active,
.next_state = {
[LFSM_EVENT_RX_LINK] = LFSM_STATE_USER_RX_ACTIVE,
[LFSM_EVENT_RX_USER] = LFSM_STATE_USER_BUSY,
[LFSM_EVENT_RX_UNKNOWN] = LFSM_STATE_USER_RX_ACTIVE,
},
},
};
/*
* FSM State Entry Functions
*/
static void go_faulted(struct lfsm_context *context)
{
PIOS_DEBUG_Assert(0);
}
static void go_stopped(struct lfsm_context *context)
{
#if 0
PIOS_SPI_Stop(PIOS_SPI_OP);
#endif
}
static void go_stopping(struct lfsm_context *context)
{
context->link_tx = NULL;
context->tx = NULL;
}
static void go_inactive(struct lfsm_context *context)
{
context->link_state = OPAHRS_MSG_LINK_STATE_INACTIVE;
lfsm_update_link_tx(context);
context->user_rx = NULL;
context->user_tx = NULL;
context->rx = context->link_rx;
context->tx = context->link_tx;
lfsm_init_rx(context);
PIOS_SPI_TransferBlock(PIOS_SPI_OP, context->tx, context->rx,
context->user_payload_len,
lfsm_irq_callback);
}
static void go_user_busy(struct lfsm_context *context)
{
/* Sanity checks */
PIOS_DEBUG_Assert(context->user_rx);
context->user_rx = NULL;
context->user_tx = NULL;
context->link_state = OPAHRS_MSG_LINK_STATE_BUSY;
lfsm_update_link_tx(context);
context->rx = context->link_rx;
context->tx = context->link_tx;
lfsm_init_rx(context);
PIOS_SPI_TransferBlock(PIOS_SPI_OP, context->tx, context->rx,
context->user_payload_len,
lfsm_irq_callback);
}
static void go_user_busy_rx_pending(struct lfsm_context *context)
{
/* Sanity checks */
PIOS_DEBUG_Assert(context->user_rx);
context->link_state = OPAHRS_MSG_LINK_STATE_BUSY;
lfsm_update_link_tx(context);
context->rx = context->link_rx;
context->tx = context->link_tx;
lfsm_init_rx(context);
PIOS_SPI_TransferBlock(PIOS_SPI_OP, context->tx, context->rx,
context->user_payload_len,
lfsm_irq_callback);
}
static void go_user_busy_tx_pending(struct lfsm_context *context)
{
/* Sanity checks */
PIOS_DEBUG_Assert(context->user_tx);
context->link_state = OPAHRS_MSG_LINK_STATE_BUSY;
lfsm_update_link_tx(context);
context->rx = context->link_rx;
context->tx = context->link_tx;
lfsm_init_rx(context);
PIOS_SPI_TransferBlock(PIOS_SPI_OP, context->tx, context->rx,
context->user_payload_len,
lfsm_irq_callback);
}
static void go_user_busy_rxtx_pending(struct lfsm_context *context)
{
/* Sanity checks */
PIOS_DEBUG_Assert(context->user_rx);
PIOS_DEBUG_Assert(context->user_tx);
context->link_state = OPAHRS_MSG_LINK_STATE_BUSY;
lfsm_update_link_tx(context);
context->rx = context->link_rx;
context->tx = context->link_tx;
lfsm_init_rx(context);
PIOS_SPI_TransferBlock(PIOS_SPI_OP, context->tx, context->rx,
context->user_payload_len,
lfsm_irq_callback);
}
static void go_user_rx_pending(struct lfsm_context *context)
{
/* Sanity checks */
PIOS_DEBUG_Assert(context->user_rx);
context->link_state = OPAHRS_MSG_LINK_STATE_BUSY;
lfsm_update_link_tx(context);
context->rx = context->link_rx;
context->tx = context->link_tx;
lfsm_init_rx(context);
PIOS_SPI_TransferBlock(PIOS_SPI_OP, context->tx, context->rx,
context->user_payload_len,
lfsm_irq_callback);
}
static void go_user_tx_pending(struct lfsm_context *context)
{
/* Sanity checks */
PIOS_DEBUG_Assert(context->user_tx);
context->link_state = OPAHRS_MSG_LINK_STATE_BUSY;
lfsm_update_link_tx(context);
context->rx = context->link_rx;
context->tx = context->link_tx;
lfsm_init_rx(context);
PIOS_SPI_TransferBlock(PIOS_SPI_OP, context->tx, context->rx,
context->user_payload_len,
lfsm_irq_callback);
}
static void go_user_rxtx_pending(struct lfsm_context *context)
{
/* Sanity checks */
PIOS_DEBUG_Assert(context->user_rx);
PIOS_DEBUG_Assert(context->user_tx);
context->link_state = OPAHRS_MSG_LINK_STATE_BUSY;
lfsm_update_link_tx(context);
context->rx = context->link_rx;
context->tx = context->link_tx;
lfsm_init_rx(context);
PIOS_SPI_TransferBlock(PIOS_SPI_OP, context->tx, context->rx,
context->user_payload_len,
lfsm_irq_callback);
}
static void go_user_rx_active(struct lfsm_context *context)
{
/* Sanity checks */
PIOS_DEBUG_Assert(context->user_rx);
context->rx = context->user_rx;
context->tx = context->link_tx;
context->link_state = OPAHRS_MSG_LINK_STATE_READY;
lfsm_update_link_tx(context);
lfsm_init_rx(context);
PIOS_SPI_TransferBlock(PIOS_SPI_OP, context->tx, context->rx,
context->user_payload_len,
lfsm_irq_callback);
}
static void go_user_tx_active(struct lfsm_context *context)
{
/* Sanity checks */
PIOS_DEBUG_Assert(context->user_tx);
context->link_state = OPAHRS_MSG_LINK_STATE_BUSY;
context->rx = context->link_rx;
context->tx = context->user_tx;
lfsm_init_rx(context);
PIOS_SPI_TransferBlock(PIOS_SPI_OP, context->tx, context->rx,
context->user_payload_len,
lfsm_irq_callback);
}
static void go_user_rxtx_active(struct lfsm_context *context)
{
/* Sanity checks */
PIOS_DEBUG_Assert(context->user_rx);
PIOS_DEBUG_Assert(context->user_tx);
context->link_state = OPAHRS_MSG_LINK_STATE_READY;
context->rx = context->user_rx;
context->tx = context->user_tx;
lfsm_init_rx(context);
PIOS_SPI_TransferBlock(PIOS_SPI_OP, context->tx, context->rx,
context->user_payload_len,
lfsm_irq_callback);
}
/*
*
* Misc Helper Functions
*
*/
static void lfsm_update_link_tx_v0(struct opahrs_msg_v0 *msg,
enum opahrs_msg_link_state state,
uint16_t errors)
{
opahrs_msg_v0_init_link_tx(msg, OPAHRS_MSG_LINK_TAG_NOP);
msg->payload.link.state = state;
msg->payload.link.errors = errors;
}
static void lfsm_update_link_tx_v1(struct opahrs_msg_v1 *msg,
enum opahrs_msg_link_state state,
uint16_t errors)
{
opahrs_msg_v1_init_link_tx(msg, OPAHRS_MSG_LINK_TAG_NOP);
msg->payload.link.state = state;
msg->payload.link.errors = errors;
}
static void lfsm_update_link_tx(struct lfsm_context *context)
{
PIOS_DEBUG_Assert(context->link_tx);
switch (context->user_payload_type) {
case OPAHRS_MSG_TYPE_USER_V0:
lfsm_update_link_tx_v0((struct opahrs_msg_v0 *)context->
link_tx, context->link_state,
context->errors);
break;
case OPAHRS_MSG_TYPE_USER_V1:
lfsm_update_link_tx_v1((struct opahrs_msg_v1 *)context->
link_tx, context->link_state,
context->errors);
break;
case OPAHRS_MSG_TYPE_LINK:
PIOS_DEBUG_Assert(0);
}
}
static void lfsm_init_rx(struct lfsm_context *context)
{
PIOS_DEBUG_Assert(context->rx);
switch (context->user_payload_type) {
case OPAHRS_MSG_TYPE_USER_V0:
opahrs_msg_v0_init_rx((struct opahrs_msg_v0 *)context->rx);
break;
case OPAHRS_MSG_TYPE_USER_V1:
opahrs_msg_v1_init_rx((struct opahrs_msg_v1 *)context->rx);
break;
case OPAHRS_MSG_TYPE_LINK:
PIOS_DEBUG_Assert(0);
}
}
/*
*
* External API
*
*/
void lfsm_inject_event(enum lfsm_event event)
{
PIOS_IRQ_Disable();
/*
* Move to the next state
*
* This is done prior to calling the new state's entry function to
* guarantee that the entry function never depends on the previous
* state. This way, it cannot ever know what the previous state was.
*/
context.curr_state =
lfsm_transitions[context.curr_state].next_state[event];
/* Call the entry function (if any) for the next state. */
if (lfsm_transitions[context.curr_state].entry_fn) {
lfsm_transitions[context.curr_state].entry_fn(&context);
}
PIOS_IRQ_Enable();
}
void lfsm_init(void)
{
context.curr_state = LFSM_STATE_STOPPED;
go_stopped(&context);
}
void lfsm_set_link_proto_v0(struct opahrs_msg_v0 *link_tx,
struct opahrs_msg_v0 *link_rx)
{
PIOS_DEBUG_Assert(link_tx);
context.link_tx = (uint8_t *) link_tx;
context.link_rx = (uint8_t *) link_rx;
context.user_payload_type = OPAHRS_MSG_TYPE_USER_V0;
context.user_payload_len = sizeof(*link_tx);
lfsm_update_link_tx_v0(link_tx, context.link_state,
context.errors);
lfsm_inject_event(LFSM_EVENT_INIT_LINK);
}
void lfsm_set_link_proto_v1(struct opahrs_msg_v1 *link_tx,
struct opahrs_msg_v1 *link_rx)
{
PIOS_DEBUG_Assert(link_tx);
context.link_tx = (uint8_t *) link_tx;
context.link_rx = (uint8_t *) link_rx;
context.user_payload_type = OPAHRS_MSG_TYPE_USER_V1;
context.user_payload_len = sizeof(*link_tx);
lfsm_update_link_tx_v1(link_tx, context.link_state,
context.errors);
lfsm_inject_event(LFSM_EVENT_INIT_LINK);
}
void lfsm_user_set_tx_v0(struct opahrs_msg_v0 *user_tx)
{
PIOS_DEBUG_Assert(user_tx);
PIOS_DEBUG_Assert(context.user_payload_type ==
OPAHRS_MSG_TYPE_USER_V0);
context.user_tx = (uint8_t *) user_tx;
lfsm_inject_event(LFSM_EVENT_USER_SET_TX);
}
void lfsm_user_set_rx_v0(struct opahrs_msg_v0 *user_rx)
{
PIOS_DEBUG_Assert(user_rx);
PIOS_DEBUG_Assert(context.user_payload_type ==
OPAHRS_MSG_TYPE_USER_V0);
context.user_rx = (uint8_t *) user_rx;
lfsm_inject_event(LFSM_EVENT_USER_SET_RX);
}
void lfsm_user_set_tx_v1(struct opahrs_msg_v1 *user_tx)
{
PIOS_DEBUG_Assert(user_tx);
PIOS_DEBUG_Assert(context.user_payload_type ==
OPAHRS_MSG_TYPE_USER_V1);
context.user_tx = (uint8_t *) user_tx;
lfsm_inject_event(LFSM_EVENT_USER_SET_TX);
}
void lfsm_user_set_rx_v1(struct opahrs_msg_v1 *user_rx)
{
PIOS_DEBUG_Assert(user_rx);
PIOS_DEBUG_Assert(context.user_payload_type ==
OPAHRS_MSG_TYPE_USER_V1);
context.user_rx = (uint8_t *) user_rx;
lfsm_inject_event(LFSM_EVENT_USER_SET_RX);
}
void lfsm_user_done(void)
{
lfsm_inject_event(LFSM_EVENT_USER_DONE);
}
void lfsm_stop(void)
{
lfsm_inject_event(LFSM_EVENT_STOP);
}
void lfsm_get_link_stats(struct lfsm_link_stats *stats)
{
PIOS_DEBUG_Assert(stats);
*stats = context.stats;
}
enum lfsm_state lfsm_get_state(void)
{
return context.curr_state;
}
/*
*
* ISR Callback
*
*/
void lfsm_irq_callback(uint8_t crc_ok, uint8_t crc_val)
{
if (!crc_ok) {
context.stats.rx_badcrc++;
lfsm_inject_event(LFSM_EVENT_RX_UNKNOWN);
return;
}
if (!context.rx) {
/* No way to know what we just received, assume invalid */
lfsm_inject_event(LFSM_EVENT_RX_UNKNOWN);
return;
}
/* Recover the head and tail pointers from the message */
struct opahrs_msg_link_head *head = NULL;
struct opahrs_msg_link_tail *tail = NULL;
switch (context.user_payload_type) {
case OPAHRS_MSG_TYPE_USER_V0:
head = &((struct opahrs_msg_v0 *)context.rx)->head;
tail = &((struct opahrs_msg_v0 *)context.rx)->tail;
break;
case OPAHRS_MSG_TYPE_USER_V1:
head = &((struct opahrs_msg_v1 *)context.rx)->head;
tail = &((struct opahrs_msg_v1 *)context.rx)->tail;
break;
case OPAHRS_MSG_TYPE_LINK:
/* Should never be rx'ing before the link protocol version is known */
PIOS_DEBUG_Assert(0);
break;
}
/* Check for bad magic */
if ((head->magic != OPAHRS_MSG_MAGIC_HEAD) ||
(tail->magic != OPAHRS_MSG_MAGIC_TAIL)) {
if (head->magic != OPAHRS_MSG_MAGIC_HEAD) {
context.stats.rx_badmagic_head++;
}
if (tail->magic != OPAHRS_MSG_MAGIC_TAIL) {
context.stats.rx_badmagic_tail++;
}
lfsm_inject_event(LFSM_EVENT_RX_UNKNOWN);
return;
}
/* Good magic, find out what type of payload we've got */
switch (head->type) {
case OPAHRS_MSG_TYPE_LINK:
context.stats.rx_link++;
lfsm_inject_event(LFSM_EVENT_RX_LINK);
break;
case OPAHRS_MSG_TYPE_USER_V0:
case OPAHRS_MSG_TYPE_USER_V1:
if (head->type == context.user_payload_type) {
context.stats.rx_user++;
lfsm_inject_event(LFSM_EVENT_RX_USER);
} else {
/* Mismatched user payload type */
context.stats.rx_badver++;
lfsm_inject_event(LFSM_EVENT_RX_UNKNOWN);
}
break;
default:
/* Unidentifiable payload type */
context.stats.rx_badtype++;
lfsm_inject_event(LFSM_EVENT_RX_UNKNOWN);
}
}
/**
* @}
* @}
*/

View File

@ -1,853 +0,0 @@
/**
******************************************************************************
* @addtogroup AHRS AHRS
* @brief The AHRS Modules perform
*
* @{
* @addtogroup AHRS_Main
* @brief Main function which does the hardware dependent stuff
* @{
*
*
* @file ahrs.c
* @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2010.
* @brief INSGPS Test Program
* @see The GNU Public License (GPL) Version 3
*
*****************************************************************************/
/*
* This program 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 3 of the License, or
* (at your option) any later version.
*
* This program 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 this program; if not, write to the Free Software Foundation, Inc.,
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
/* OpenPilot Includes */
#include "ahrs.h"
#include "ahrs_adc.h"
#include "ahrs_timer.h"
#include "pios_opahrs_proto.h"
//#include "ahrs_fsm.h" /* lfsm_state */
#include "insgps.h"
#include "CoordinateConversions.h"
#include "ahrs_spi_comm.h"
// For debugging the raw sensors
//#define DUMP_RAW
//#define DUMP_FRIENDLY
//#define DUMP_EKF
#ifdef DUMP_EKF
#define NUMX 13 // number of states, X is the state vector
#define NUMW 9 // number of plant noise inputs, w is disturbance noise vector
#define NUMV 10 // number of measurements, v is the measurement noise vector
#define NUMU 6 // number of deterministic inputs, U is the input vector
extern float F[NUMX][NUMX], G[NUMX][NUMW], H[NUMV][NUMX]; // linearized system matrices
extern float P[NUMX][NUMX], X[NUMX]; // covariance matrix and state vector
extern float Q[NUMW], R[NUMV]; // input noise and measurement noise variances
extern float K[NUMX][NUMV]; // feedback gain matrix
#endif
volatile enum algorithms ahrs_algorithm;
/**
* @addtogroup AHRS_Structures Local Structres
* @{
*/
//! Contains the data from the mag sensor chip
struct mag_sensor {
uint8_t id[4];
uint8_t updated;
struct {
int16_t axis[3];
} raw;
struct {
float axis[3];
} scaled;
struct {
float bias[3];
float scale[3];
float variance[3];
} calibration;
} mag_data;
//! Contains the data from the accelerometer
struct accel_sensor {
struct {
uint16_t x;
uint16_t y;
uint16_t z;
} raw;
struct {
float x;
float y;
float z;
} filtered;
struct {
float bias[3];
float scale[3];
float variance[3];
} calibration;
} accel_data;
//! Contains the data from the gyro
struct gyro_sensor {
struct {
uint16_t x;
uint16_t y;
uint16_t z;
} raw;
struct {
float x;
float y;
float z;
} filtered;
struct {
float bias[3];
float scale[3];
float variance[3];
} calibration;
struct {
uint16_t xy;
uint16_t z;
} temp;
} gyro_data;
//! Conains the current estimate of the attitude
struct attitude_solution {
struct {
float q1;
float q2;
float q3;
float q4;
} quaternion;
} attitude_data;
//! Contains data from the altitude sensor
struct altitude_sensor {
float altitude;
bool updated;
} altitude_data;
//! Contains data from the GPS (via the SPI link)
struct gps_sensor {
float NED[3];
float heading;
float groundspeed;
float quality;
bool updated;
} gps_data;
/**
* @}
*/
/* Function Prototypes */
void process_spi_request(void);
void downsample_data(void);
void calibrate_sensors(void);
void reset_values();
void send_calibration(void);
void altitude_callback(AhrsObjHandle obj);
void calibration_callback(AhrsObjHandle obj);
void gps_callback(AhrsObjHandle obj);
void settings_callback(AhrsObjHandle obj);
volatile uint32_t last_counter_idle_start = 0;
volatile uint32_t last_counter_idle_end = 0;
volatile uint32_t idle_counts;
volatile uint32_t running_counts;
uint32_t counter_val;
/**
* @addtogroup AHRS_Global_Data AHRS Global Data
* @{
* Public data. Used by both EKF and the sender
*/
//! Filter coefficients used in decimation. Limited order so filter can't run between samples
int16_t fir_coeffs[50];
//! The oversampling rate, ekf is 2k / this
static uint8_t adc_oversampling = 17;
/**
* @}
*/
/**
* @brief AHRS Main function
*/
int main()
{
float gyro[3], accel[3], mag[3];
float vel[3] = { 0, 0, 0 };
gps_data.quality = -1;
ahrs_algorithm = INSGPS_Algo;
/* Brings up System using CMSIS functions, enables the LEDs. */
PIOS_SYS_Init();
/* Delay system */
PIOS_DELAY_Init();
/* Communication system */
PIOS_COM_Init();
/* ADC system */
AHRS_ADC_Config(adc_oversampling);
/* Setup the Accelerometer FS (Full-Scale) GPIO */
PIOS_GPIO_Enable(0);
SET_ACCEL_2G;
#if defined(PIOS_INCLUDE_HMC5843) && defined(PIOS_INCLUDE_I2C)
/* Magnetic sensor system */
PIOS_I2C_Init();
PIOS_HMC5843_Init();
// Get 3 ID bytes
strcpy((char *)mag_data.id, "ZZZ");
PIOS_HMC5843_ReadID(mag_data.id);
#endif
/* SPI link to master */
// PIOS_SPI_Init();
// lfsm_init();
reset_values();
ahrs_state = AHRS_IDLE;
AhrsInitComms();
ahrs_state = AHRS_IDLE;
while(!AhrsLinkReady()) {
AhrsPoll();
while(ahrs_state != AHRS_DATA_READY) ;
ahrs_state = AHRS_PROCESSING;
downsample_data();
ahrs_state = AHRS_IDLE;
if((total_conversion_blocks % 10) == 0)
PIOS_LED_Toggle(LED1);
}
/* we didn't connect the callbacks before because we have to wait
for all data to be up to date before doing anything*/
AHRSCalibrationConnectCallback(calibration_callback);
GPSPositionConnectCallback(gps_callback);
BaroAltitudeConnectCallback(altitude_callback);
AHRSSettingsConnectCallback(settings_callback);
calibration_callback(AHRSCalibrationHandle()); //force an update
/* Use simple averaging filter for now */
for (int i = 0; i < adc_oversampling; i++)
fir_coeffs[i] = 1;
fir_coeffs[adc_oversampling] = adc_oversampling;
INSGPSInit();
#ifdef DUMP_RAW
int previous_conversion;
while (1) {
AhrsPoll();
int result;
uint8_t framing[16] =
{ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
15 };
while (ahrs_state != AHRS_DATA_READY) ;
ahrs_state = AHRS_PROCESSING;
if (total_conversion_blocks != previous_conversion + 1)
PIOS_LED_On(LED1); // not keeping up
else
PIOS_LED_Off(LED1);
previous_conversion = total_conversion_blocks;
downsample_data();
ahrs_state = AHRS_IDLE;;
// Dump raw buffer
result = PIOS_COM_SendBuffer(PIOS_COM_AUX, &framing[0], 16); // framing header
result += PIOS_COM_SendBuffer(PIOS_COM_AUX, (uint8_t *) & total_conversion_blocks, sizeof(total_conversion_blocks)); // dump block number
result +=
PIOS_COM_SendBuffer(PIOS_COM_AUX,
(uint8_t *) & valid_data_buffer[0],
adc_oversampling *
ADC_CONTINUOUS_CHANNELS *
sizeof(valid_data_buffer[0]));
if (result == 0)
PIOS_LED_Off(LED1);
else {
PIOS_LED_On(LED1);
}
}
#endif
timer_start();
/******************* Main EKF loop ****************************/
while(1) {
AhrsPoll();
AhrsStatus2Data status;
AhrsStatus2Get(&status);
status.CPULoad = ((float)running_counts /
(float)(idle_counts + running_counts)) * 100;
status.IdleTimePerCyle = idle_counts / (TIMER_RATE / 10000);
status.RunningTimePerCyle = running_counts / (TIMER_RATE / 10000);
status.DroppedUpdates = ekf_too_slow;
AhrsStatus2Set(&status);
// Alive signal
if ((total_conversion_blocks % 100) == 0)
PIOS_LED_Toggle(LED1);
#if defined(PIOS_INCLUDE_HMC5843) && defined(PIOS_INCLUDE_I2C)
// Get magnetic readings
if (PIOS_HMC5843_NewDataAvailable()) {
PIOS_HMC5843_ReadMag(mag_data.raw.axis);
mag_data.scaled.axis[0] = (mag_data.raw.axis[0] * mag_data.calibration.scale[0]) + mag_data.calibration.bias[0];
mag_data.scaled.axis[1] = (mag_data.raw.axis[1] * mag_data.calibration.scale[1]) + mag_data.calibration.bias[1];
mag_data.scaled.axis[2] = (mag_data.raw.axis[2] * mag_data.calibration.scale[2]) + mag_data.calibration.bias[2];
mag_data.updated = 1;
}
#endif
// Delay for valid data
counter_val = timer_count();
running_counts = counter_val - last_counter_idle_end;
last_counter_idle_start = counter_val;
while (ahrs_state != AHRS_DATA_READY) ;
counter_val = timer_count();
idle_counts = counter_val - last_counter_idle_start;
last_counter_idle_end = counter_val;
ahrs_state = AHRS_PROCESSING;
downsample_data();
/******************** INS ALGORITHM **************************/
if (ahrs_algorithm == INSGPS_Algo) {
// format data for INS algo
gyro[0] = gyro_data.filtered.x;
gyro[1] = gyro_data.filtered.y;
gyro[2] = gyro_data.filtered.z;
accel[0] = accel_data.filtered.x,
accel[1] = accel_data.filtered.y,
accel[2] = accel_data.filtered.z,
// Note: The magnetometer driver returns registers X,Y,Z from the chip which are
// (left, backward, up). Remapping to (forward, right, down).
mag[0] = -mag_data.scaled.axis[1];
mag[1] = -mag_data.scaled.axis[0];
mag[2] = -mag_data.scaled.axis[2];
INSStatePrediction(gyro, accel, 1 / (float)EKF_RATE);
process_spi_request(); // get message out quickly
INSCovariancePrediction(1 / (float)EKF_RATE);
if (gps_data.updated && gps_data.quality == 1) {
// Compute velocity from Heading and groundspeed
vel[0] =
gps_data.groundspeed *
cos(gps_data.heading * M_PI / 180);
vel[1] =
gps_data.groundspeed *
sin(gps_data.heading * M_PI / 180);
INSSetPosVelVar(0.004);
if (gps_data.updated) {
//TOOD: add check for altitude updates
FullCorrection(mag, gps_data.NED,
vel,
altitude_data.
altitude);
gps_data.updated = 0;
} else {
GpsBaroCorrection(gps_data.NED,
vel,
altitude_data.
altitude);
}
gps_data.updated = false;
mag_data.updated = 0;
} else if (gps_data.quality != -1
&& mag_data.updated == 1) {
float mag_var[3] = {mag_data.calibration.variance[1], mag_data.calibration.variance[0], mag_data.calibration.variance[2]};
INSSetMagVar(mag_var);
MagCorrection(mag); // only trust mags if outdoors
mag_data.updated = 0;
} else {
// Indoors, update with zero position and velocity and high covariance
INSSetPosVelVar(0.1);
vel[0] = 0;
vel[1] = 0;
vel[2] = 0;
if(mag_data.updated == 1) {
float mag_var[3] = {10,10,10};
INSSetMagVar(mag_var);
MagVelBaroCorrection(mag,vel,altitude_data.altitude); // only trust mags if outdoors
mag_data.updated = 0;
} else {
VelBaroCorrection(vel, altitude_data.altitude);
}
}
attitude_data.quaternion.q1 = Nav.q[0];
attitude_data.quaternion.q2 = Nav.q[1];
attitude_data.quaternion.q3 = Nav.q[2];
attitude_data.quaternion.q4 = Nav.q[3];
} else if (ahrs_algorithm == SIMPLE_Algo) {
float q[4];
float rpy[3];
/***************** SIMPLE ATTITUDE FROM NORTH AND ACCEL ************/
/* Very simple computation of the heading and attitude from accel. */
rpy[2] =
atan2((mag_data.raw.axis[0]),
(-1 * mag_data.raw.axis[1])) * 180 /
M_PI;
rpy[1] =
atan2(accel_data.filtered.x,
accel_data.filtered.z) * 180 / M_PI;
rpy[0] =
atan2(accel_data.filtered.y,
accel_data.filtered.z) * 180 / M_PI;
RPY2Quaternion(rpy, q);
attitude_data.quaternion.q1 = q[0];
attitude_data.quaternion.q2 = q[1];
attitude_data.quaternion.q3 = q[2];
attitude_data.quaternion.q4 = q[3];
process_spi_request();
}
ahrs_state = AHRS_IDLE;
#ifdef DUMP_FRIENDLY
PIOS_COM_SendFormattedStringNonBlocking(PIOS_COM_AUX, "b: %d\r\n",
total_conversion_blocks);
PIOS_COM_SendFormattedStringNonBlocking(PIOS_COM_AUX,"a: %d %d %d\r\n",
(int16_t) (accel_data.filtered.x * 1000),
(int16_t) (accel_data.filtered.y * 1000),
(int16_t) (accel_data.filtered.z * 1000));
PIOS_COM_SendFormattedStringNonBlocking(PIOS_COM_AUX, "g: %d %d %d\r\n",
(int16_t) (gyro_data.filtered.x * 1000),
(int16_t) (gyro_data.filtered.y * 1000),
(int16_t) (gyro_data.filtered.z * 1000));
PIOS_COM_SendFormattedStringNonBlocking(PIOS_COM_AUX,"m: %d %d %d\r\n",
mag_data.raw.axis[0],
mag_data.raw.axis[1],
mag_data.raw.axis[2]);
PIOS_COM_SendFormattedStringNonBlocking(PIOS_COM_AUX,
"q: %d %d %d %d\r\n",
(int16_t) (Nav.q[0] * 1000),
(int16_t) (Nav.q[1] * 1000),
(int16_t) (Nav.q[2] * 1000),
(int16_t) (Nav.q[3] * 1000));
#endif
#ifdef DUMP_EKF
uint8_t framing[16] =
{ 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1,
0 };
extern float F[NUMX][NUMX], G[NUMX][NUMW], H[NUMV][NUMX]; // linearized system matrices
extern float P[NUMX][NUMX], X[NUMX]; // covariance matrix and state vector
extern float Q[NUMW], R[NUMV]; // input noise and measurement noise variances
extern float K[NUMX][NUMV]; // feedback gain matrix
// Dump raw buffer
int8_t result;
result = PIOS_COM_SendBuffer(PIOS_COM_AUX, &framing[0], 16); // framing header
result += PIOS_COM_SendBuffer(PIOS_COM_AUX, (uint8_t *) & total_conversion_blocks, sizeof(total_conversion_blocks)); // dump block number
result +=
PIOS_COM_SendBuffer(PIOS_COM_AUX,
(uint8_t *) & mag_data,
sizeof(mag_data));
result +=
PIOS_COM_SendBuffer(PIOS_COM_AUX,
(uint8_t *) & gps_data,
sizeof(gps_data));
result +=
PIOS_COM_SendBuffer(PIOS_COM_AUX,
(uint8_t *) & accel_data,
sizeof(accel_data));
result +=
PIOS_COM_SendBuffer(PIOS_COM_AUX,
(uint8_t *) & gyro_data,
sizeof(gyro_data));
result +=
PIOS_COM_SendBuffer(PIOS_COM_AUX, (uint8_t *) & Q,
sizeof(float) * NUMX * NUMX);
result +=
PIOS_COM_SendBuffer(PIOS_COM_AUX, (uint8_t *) & K,
sizeof(float) * NUMX * NUMV);
result +=
PIOS_COM_SendBuffer(PIOS_COM_AUX, (uint8_t *) & X,
sizeof(float) * NUMX * NUMX);
if (result == 0)
PIOS_LED_Off(LED1);
else {
PIOS_LED_On(LED1);
}
#endif
}
return 0;
}
/**
* @brief Downsample the analog data
* @return none
*
* Tried to make as much of the filtering fixed point when possible. Need to account
* for offset for each sample before the multiplication if filter not a boxcar. Could
* precompute fixed offset as sum[fir_coeffs[i]] * ACCEL_OFFSET. Puts data into global
* data structures @ref accel_data and @ref gyro_data.
*
* The accel_data values are converted into a coordinate system where X is forwards along
* the fuselage, Y is along right the wing, and Z is down.
*/
void downsample_data()
{
uint16_t i;
// Get the Y data. Third byte in. Convert to m/s
accel_data.filtered.y = 0;
for (i = 0; i < adc_oversampling; i++)
accel_data.filtered.y += valid_data_buffer[0 + i * PIOS_ADC_NUM_PINS] * fir_coeffs[i];
accel_data.filtered.y /= (float) fir_coeffs[adc_oversampling];
accel_data.filtered.y = (accel_data.filtered.y * accel_data.calibration.scale[1]) + accel_data.calibration.bias[1];
// Get the X data which projects forward/backwards. Fifth byte in. Convert to m/s
accel_data.filtered.x = 0;
for (i = 0; i < adc_oversampling; i++)
accel_data.filtered.x += valid_data_buffer[2 + i * PIOS_ADC_NUM_PINS] * fir_coeffs[i];
accel_data.filtered.x /= (float) fir_coeffs[adc_oversampling];
accel_data.filtered.x = (accel_data.filtered.x * accel_data.calibration.scale[0]) + accel_data.calibration.bias[0];
// Get the Z data. Third byte in. Convert to m/s
accel_data.filtered.z = 0;
for (i = 0; i < adc_oversampling; i++)
accel_data.filtered.z += valid_data_buffer[4 + i * PIOS_ADC_NUM_PINS] * fir_coeffs[i];
accel_data.filtered.z /= (float) fir_coeffs[adc_oversampling];
accel_data.filtered.z = (accel_data.filtered.z * accel_data.calibration.scale[2]) + accel_data.calibration.bias[2];
// Get the X gyro data. Seventh byte in. Convert to deg/s.
gyro_data.filtered.x = 0;
for (i = 0; i < adc_oversampling; i++)
gyro_data.filtered.x += valid_data_buffer[1 + i * PIOS_ADC_NUM_PINS] * fir_coeffs[i];
gyro_data.filtered.x /= fir_coeffs[adc_oversampling];
gyro_data.filtered.x = (gyro_data.filtered.x * gyro_data.calibration.scale[0]) + gyro_data.calibration.bias[0];
// Get the Y gyro data. Second byte in. Convert to deg/s.
gyro_data.filtered.y = 0;
for (i = 0; i < adc_oversampling; i++)
gyro_data.filtered.y += valid_data_buffer[3 + i * PIOS_ADC_NUM_PINS] * fir_coeffs[i];
gyro_data.filtered.y /= fir_coeffs[adc_oversampling];
gyro_data.filtered.y = (gyro_data.filtered.y * gyro_data.calibration.scale[1]) + gyro_data.calibration.bias[1];
// Get the Z gyro data. Fifth byte in. Convert to deg/s.
gyro_data.filtered.z = 0;
for (i = 0; i < adc_oversampling; i++)
gyro_data.filtered.z += valid_data_buffer[5 + i * PIOS_ADC_NUM_PINS] * fir_coeffs[i];
gyro_data.filtered.z /= fir_coeffs[adc_oversampling];
gyro_data.filtered.z = (gyro_data.filtered.z * gyro_data.calibration.scale[2]) + gyro_data.calibration.bias[2];
AttitudeRawData raw;
raw.gyros[0] = valid_data_buffer[1];
raw.gyros[1] = valid_data_buffer[3];
raw.gyros[2] = valid_data_buffer[5];
raw.gyros_filtered[0] = gyro_data.filtered.x;
raw.gyros_filtered[1] = gyro_data.filtered.y;
raw.gyros_filtered[2] = gyro_data.filtered.z;
raw.accels[0] = valid_data_buffer[2];
raw.accels[1] = valid_data_buffer[0];
raw.accels[2] = valid_data_buffer[4];
raw.accels_filtered[0] = accel_data.filtered.x;
raw.accels_filtered[1] = accel_data.filtered.y;
raw.accels_filtered[2] = accel_data.filtered.z;
raw.magnetometers[0] = mag_data.scaled.axis[0];
raw.magnetometers[1] = mag_data.scaled.axis[1];
raw.magnetometers[2] = mag_data.scaled.axis[2];
AttitudeRawSet(&raw);
}
/**
* @brief Assumes board is not moving computes biases and variances of sensors
* @returns None
*
* All data is stored in global structures. This function should be called from OP when
* aircraft is in stable state and then the data stored to SD card.
*
* After this function the bias for each sensor will be the mean value. This doesn't make
* sense for the z accel so make sure 6 point calibration is also run and those values set
* after these read.
*/
#define NBIAS 100
#define NVAR 500
void calibrate_sensors()
{
int i,j;
float accel_bias[3] = {0, 0, 0};
float gyro_bias[3] = {0, 0, 0};
float mag_bias[3] = {0, 0, 0};
for (i = 0, j = 0; i < NBIAS; i++) {
while (ahrs_state != AHRS_DATA_READY) ;
ahrs_state = AHRS_PROCESSING;
downsample_data();
gyro_bias[0] += gyro_data.filtered.x / NBIAS;
gyro_bias[1] += gyro_data.filtered.y / NBIAS;
gyro_bias[2] += gyro_data.filtered.z / NBIAS;
accel_bias[0] += accel_data.filtered.x / NBIAS;
accel_bias[1] += accel_data.filtered.y / NBIAS;
accel_bias[2] += accel_data.filtered.z / NBIAS;
ahrs_state = AHRS_IDLE;
#if defined(PIOS_INCLUDE_HMC5843) && defined(PIOS_INCLUDE_I2C)
if(PIOS_HMC5843_NewDataAvailable()) {
j ++;
PIOS_HMC5843_ReadMag(mag_data.raw.axis);
mag_data.scaled.axis[0] = (mag_data.raw.axis[0] * mag_data.calibration.scale[0]) + mag_data.calibration.bias[0];
mag_data.scaled.axis[1] = (mag_data.raw.axis[1] * mag_data.calibration.scale[1]) + mag_data.calibration.bias[1];
mag_data.scaled.axis[2] = (mag_data.raw.axis[2] * mag_data.calibration.scale[2]) + mag_data.calibration.bias[2];
mag_bias[0] += mag_data.scaled.axis[0];
mag_bias[1] += mag_data.scaled.axis[1];
mag_bias[2] += mag_data.scaled.axis[2];
}
#endif
}
mag_bias[0] /= j;
mag_bias[1] /= j;
mag_bias[2] /= j;
gyro_data.calibration.variance[0] = 0;
gyro_data.calibration.variance[1] = 0;
gyro_data.calibration.variance[2] = 0;
mag_data.calibration.variance[0] = 0;
mag_data.calibration.variance[1] = 0;
mag_data.calibration.variance[2] = 0;
accel_data.calibration.variance[0] = 0;
accel_data.calibration.variance[1] = 0;
accel_data.calibration.variance[2] = 0;
for (i = 0, j = 0; j < NVAR; j++) {
while (ahrs_state != AHRS_DATA_READY) ;
ahrs_state = AHRS_PROCESSING;
downsample_data();
gyro_data.calibration.variance[0] += pow(gyro_data.filtered.x-gyro_bias[0],2) / NVAR;
gyro_data.calibration.variance[1] += pow(gyro_data.filtered.y-gyro_bias[1],2) / NVAR;
gyro_data.calibration.variance[2] += pow(gyro_data.filtered.z-gyro_bias[2],2) / NVAR;
accel_data.calibration.variance[0] += pow(accel_data.filtered.x-accel_bias[0],2) / NVAR;
accel_data.calibration.variance[1] += pow(accel_data.filtered.y-accel_bias[1],2) / NVAR;
accel_data.calibration.variance[2] += pow(accel_data.filtered.z-accel_bias[2],2) / NVAR;
ahrs_state = AHRS_IDLE;
#if defined(PIOS_INCLUDE_HMC5843) && defined(PIOS_INCLUDE_I2C)
if(PIOS_HMC5843_NewDataAvailable()) {
j ++;
PIOS_HMC5843_ReadMag(mag_data.raw.axis);
mag_data.scaled.axis[0] = (mag_data.raw.axis[0] * mag_data.calibration.scale[0]) + mag_data.calibration.bias[0];
mag_data.scaled.axis[1] = (mag_data.raw.axis[1] * mag_data.calibration.scale[1]) + mag_data.calibration.bias[1];
mag_data.scaled.axis[2] = (mag_data.raw.axis[2] * mag_data.calibration.scale[2]) + mag_data.calibration.bias[2];
mag_data.calibration.variance[0] += pow(mag_data.scaled.axis[0]-mag_bias[0],2);
mag_data.calibration.variance[1] += pow(mag_data.scaled.axis[1]-mag_bias[1],2);
mag_data.calibration.variance[2] += pow(mag_data.scaled.axis[2]-mag_bias[2],2);
}
#endif
}
mag_data.calibration.variance[0] /= j;
mag_data.calibration.variance[1] /= j;
mag_data.calibration.variance[2] /= j;
gyro_data.calibration.bias[0] -= gyro_bias[0];
gyro_data.calibration.bias[1] -= gyro_bias[1];
gyro_data.calibration.bias[2] -= gyro_bias[2];
}
/**
* @brief Populate fields with initial values
*/
void reset_values() {
accel_data.calibration.scale[0] = 0.012;
accel_data.calibration.scale[1] = 0.012;
accel_data.calibration.scale[2] = -0.012;
accel_data.calibration.bias[0] = 24;
accel_data.calibration.bias[1] = 24;
accel_data.calibration.bias[2] = -24;
accel_data.calibration.variance[0] = 1e-4;
accel_data.calibration.variance[1] = 1e-4;
accel_data.calibration.variance[2] = 1e-4;
gyro_data.calibration.scale[0] = -0.014;
gyro_data.calibration.scale[1] = 0.014;
gyro_data.calibration.scale[2] = -0.014;
gyro_data.calibration.bias[0] = -24;
gyro_data.calibration.bias[1] = -24;
gyro_data.calibration.bias[2] = -24;
gyro_data.calibration.variance[0] = 1;
gyro_data.calibration.variance[1] = 1;
gyro_data.calibration.variance[2] = 1;
mag_data.calibration.scale[0] = 1;
mag_data.calibration.scale[1] = 1;
mag_data.calibration.scale[2] = 1;
mag_data.calibration.bias[0] = 0;
mag_data.calibration.bias[1] = 0;
mag_data.calibration.bias[2] = 0;
mag_data.calibration.variance[0] = 1;
mag_data.calibration.variance[1] = 1;
mag_data.calibration.variance[2] = 1;
}
void process_spi_request(void)
{
AttitudeActualData attitude;
attitude.q1 = attitude_data.quaternion.q1;
attitude.q2 = attitude_data.quaternion.q2;
attitude.q3 = attitude_data.quaternion.q3;
attitude.q4 = attitude_data.quaternion.q4;
float rpy[3];
Quaternion2RPY(&attitude_data.quaternion.q1, rpy);
attitude.Roll = rpy[0];
attitude.Pitch = rpy[1];
attitude.Yaw = rpy[2];
AttitudeActualSet(&attitude);
}
void send_calibration(void)
{
AHRSCalibrationData cal;
AHRSCalibrationGet(&cal);
for(int ct=0; ct<3; ct++)
{
cal.accel_var[ct] = accel_data.calibration.variance[ct];
cal.gyro_bias[ct] = gyro_data.calibration.bias[ct];
cal.gyro_var[ct] = gyro_data.calibration.variance[ct];
cal.mag_var[ct] = mag_data.calibration.variance[ct];
}
cal.measure_var = AHRSCALIBRATION_MEASURE_VAR_SET;
AHRSCalibrationSet(&cal);
}
/**
* @brief AHRS calibration callback
*
* Called when the OP board sets the calibration
*/
void calibration_callback(AhrsObjHandle obj)
{
AHRSCalibrationData cal;
AHRSCalibrationGet(&cal);
if(cal.measure_var == AHRSCALIBRATION_MEASURE_VAR_SET){
for(int ct=0; ct<3; ct++)
{
accel_data.calibration.scale[ct] = cal.accel_scale[ct];
accel_data.calibration.bias[ct] = cal.accel_bias[ct];
accel_data.calibration.variance[ct] = cal.accel_var[ct];
gyro_data.calibration.scale[ct] = cal.gyro_scale[ct];
gyro_data.calibration.bias[ct] = cal.gyro_bias[ct];
gyro_data.calibration.variance[ct] = cal.gyro_var[ct];
mag_data.calibration.bias[ct] = cal.mag_bias[ct];
mag_data.calibration.scale[ct] = cal.mag_scale[ct];
mag_data.calibration.variance[ct] = cal.mag_var[ct];
}
}else if(cal.measure_var == AHRSCALIBRATION_MEASURE_VAR_MEASURE){
calibrate_sensors();
AHRSCalibrationData cal;
AHRSCalibrationGet(&cal);
cal.measure_var = AHRSCALIBRATION_MEASURE_VAR_SET;
AHRSCalibrationSet(&cal);
}else if(cal.measure_var == AHRSCALIBRATION_MEASURE_VAR_ECHO){
send_calibration();
}
}
void gps_callback(AhrsObjHandle obj)
{
GPSPositionData pos;
GPSPositionGet(&pos);
HomeLocationData home;
HomeLocationGet(&home);
if(home.Set == HOMELOCATION_SET_FALSE || home.Indoor == HOMELOCATION_INDOOR_TRUE) {
gps_data.NED[0] = 0;
gps_data.NED[1] = 0;
gps_data.NED[2] = 0;
gps_data.groundspeed = 0;
gps_data.heading = 0;
gps_data.quality = -1; // indicates indoor mode, high variance zeros update
gps_data.updated = true;
return;
}
if(pos.Status != GPSPOSITION_STATUS_FIX3D) //FIXME: Will this work? the old ahrs_comms does it differently.
{
gps_data.quality = 0;
gps_data.updated = true;
return;
}
double LLA[3] = {(double) pos.Latitude / 1e7, (double) pos.Longitude / 1e7, (double) (pos.GeoidSeparation + pos.Altitude)};
// convert from cm back to meters
double ECEF[3] = {(double) (home.ECEF[0] / 100), (double) (home.ECEF[1] / 100), (double) (home.ECEF[2] / 100)};
LLA2Base(LLA, ECEF, (float (*)[3]) home.RNE, gps_data.NED);
gps_data.heading = pos.Heading;
gps_data.groundspeed = pos.Groundspeed;
gps_data.quality = 1;
gps_data.updated = true;
}
void altitude_callback(AhrsObjHandle obj)
{
BaroAltitudeData alt;
BaroAltitudeGet(&alt);
altitude_data.altitude = alt.Altitude;
altitude_data.updated = true;
}
void settings_callback(AhrsObjHandle obj)
{
AHRSSettingsData settings;
AHRSSettingsGet(&settings);
if(settings.Algorithm == AHRSSETTINGS_ALGORITHM_INSGPS)
{
ahrs_algorithm = INSGPS_Algo;
}else
{
ahrs_algorithm = SIMPLE_Algo;
}
}
/**
* @}
*/

View File

@ -5,7 +5,7 @@ static AttitudeRawData AttitudeRaw;
static AttitudeActualData AttitudeActual; static AttitudeActualData AttitudeActual;
static AHRSCalibrationData AHRSCalibration; static AHRSCalibrationData AHRSCalibration;
static AttitudeSettingsData AttitudeSettings; static AttitudeSettingsData AttitudeSettings;
static AhrsStatus2Data AhrsStatus2; static AhrsStatusData AhrsStatus;
static BaroAltitudeData BaroAltitude; static BaroAltitudeData BaroAltitude;
static GPSPositionData GPSPosition; static GPSPositionData GPSPosition;
static PositionActualData PositionActual; static PositionActualData PositionActual;
@ -28,7 +28,7 @@ CREATEHANDLE( 0, AttitudeRaw );
CREATEHANDLE( 1, AttitudeActual ); CREATEHANDLE( 1, AttitudeActual );
CREATEHANDLE( 2, AHRSCalibration ); CREATEHANDLE( 2, AHRSCalibration );
CREATEHANDLE( 3, AttitudeSettings ); CREATEHANDLE( 3, AttitudeSettings );
CREATEHANDLE( 4, AhrsStatus2 ); CREATEHANDLE( 4, AhrsStatus );
CREATEHANDLE( 5, BaroAltitude ); CREATEHANDLE( 5, BaroAltitude );
CREATEHANDLE( 6, GPSPosition ); CREATEHANDLE( 6, GPSPosition );
CREATEHANDLE( 7, PositionActual ); CREATEHANDLE( 7, PositionActual );
@ -70,7 +70,7 @@ void AhrsInitHandles( void )
ADDHANDLE( idx++, AttitudeActual ); ADDHANDLE( idx++, AttitudeActual );
ADDHANDLE( idx++, AHRSCalibration ); ADDHANDLE( idx++, AHRSCalibration );
ADDHANDLE( idx++, AttitudeSettings ); ADDHANDLE( idx++, AttitudeSettings );
ADDHANDLE( idx++, AhrsStatus2 ); ADDHANDLE( idx++, AhrsStatus );
ADDHANDLE( idx++, BaroAltitude ); ADDHANDLE( idx++, BaroAltitude );
ADDHANDLE( idx++, GPSPosition ); ADDHANDLE( idx++, GPSPosition );
ADDHANDLE( idx++, PositionActual ); ADDHANDLE( idx++, PositionActual );

View File

@ -4,7 +4,7 @@
#include "attitudeactual.h" #include "attitudeactual.h"
#include "attituderaw.h" #include "attituderaw.h"
#include "attitudesettings.h" #include "attitudesettings.h"
#include "ahrsstatus2.h" #include "ahrsstatus.h"
#include "baroaltitude.h" #include "baroaltitude.h"
#include "gpsposition.h" #include "gpsposition.h"
#include "positionactual.h" #include "positionactual.h"
@ -20,7 +20,7 @@ typedef union {
AttitudeActualData AttitudeActual; AttitudeActualData AttitudeActual;
AHRSCalibrationData AHRSCalibration; AHRSCalibrationData AHRSCalibration;
AttitudeSettingsData AttitudeSettings; AttitudeSettingsData AttitudeSettings;
AhrsStatus2Data AhrsStatus2; AhrsStatusData AhrsStatus;
BaroAltitudeData BaroAltitude; BaroAltitudeData BaroAltitude;
GPSPositionData GPSPosition; GPSPositionData GPSPosition;
PositionActualData PositionActual; PositionActualData PositionActual;

View File

@ -217,10 +217,11 @@ SRC += $(PIOSSTM32F10X)/pios_usb_hid_pwr.c
SRC += $(PIOSCOMMON)/pios_sdcard.c SRC += $(PIOSCOMMON)/pios_sdcard.c
SRC += $(PIOSCOMMON)/pios_com.c SRC += $(PIOSCOMMON)/pios_com.c
SRC += $(PIOSCOMMON)/pios_bmp085.c SRC += $(PIOSCOMMON)/pios_bmp085.c
SRC += $(PIOSCOMMON)/pios_opahrs.c #SRC += $(PIOSCOMMON)/pios_opahrs.c
SRC += $(PIOSCOMMON)/pios_opahrs_proto.c #SRC += $(PIOSCOMMON)/pios_opahrs_proto.c
SRC += $(PIOSCOMMON)/printf-stdarg.c SRC += $(PIOSCOMMON)/printf-stdarg.c
SRC += $(FLIGHTLIB)/ahrs_spi_comm.c
SRC += $(FLIGHTLIB)/ahrs_comm_objects.c
## Libraries for flight calculations ## Libraries for flight calculations
SRC += $(FLIGHTLIB)/buffer.c SRC += $(FLIGHTLIB)/buffer.c
SRC += $(FLIGHTLIB)/WorldMagModel.c SRC += $(FLIGHTLIB)/WorldMagModel.c

View File

@ -31,11 +31,11 @@
*/ */
/** /**
* Input object: AttitudeSettings * Input objects: As defined in PiOS/inc/pios_ahrs_comms.h
* Output object: AttitudeActual * Output objects: As defined in PiOS/inc/pios_ahrs_comms.h
* *
* This module will periodically update the value of latest attitude solution * This module will periodically update the values of latest attitude solution
* that is available from the AHRS. * and other objects that are transferred to and from the AHRS
* The module settings can configure how often AHRS is polled for a new solution. * The module settings can configure how often AHRS is polled for a new solution.
* *
* The module executes in its own thread. * The module executes in its own thread.
@ -51,26 +51,11 @@
*/ */
#include "ahrs_comms.h" #include "ahrs_comms.h"
#include "attitudeactual.h"
#include "ahrssettings.h"
#include "attituderaw.h"
#include "attitudesettings.h"
#include "ahrsstatus.h"
#include "alarms.h"
#include "baroaltitude.h"
#include "stdbool.h"
#include "gpsposition.h"
#include "positionactual.h"
#include "velocityactual.h"
#include "homelocation.h"
#include "ahrscalibration.h"
#include "CoordinateConversions.h"
#include "pios_opahrs.h" // library for OpenPilot AHRS access functions #include "ahrs_spi_comm.h"
#include "pios_opahrs_proto.h"
// Private constants // Private constants
#define STACK_SIZE 450 #define STACK_SIZE 1400
#define TASK_PRIORITY (tskIDLE_PRIORITY+4) #define TASK_PRIORITY (tskIDLE_PRIORITY+4)
// Private types // Private types
@ -78,52 +63,10 @@
// Private variables // Private variables
static xTaskHandle taskHandle; static xTaskHandle taskHandle;
// Private functions // Private functions
static void ahrscommsTask(void *parameters); static void ahrscommsTask(void* parameters);
static void load_baro_altitude(struct opahrs_msg_v1_req_update *update);
static void load_gps_position(struct opahrs_msg_v1_req_update *update);
static void load_magnetic_north(struct opahrs_msg_v1_req_north *north);
static void load_calibration(struct opahrs_msg_v1_req_calibration *calibration);
static void update_attitude_raw(struct opahrs_msg_v1_rsp_attituderaw *attituderaw);
static void update_ahrs_status(struct opahrs_msg_v1_rsp_serial *serial);
static void update_calibration(struct opahrs_msg_v1_rsp_calibration *calibration);
static void process_update(struct opahrs_msg_v1_rsp_update *update); // main information parser
static bool AHRSSettingsIsUpdatedFlag = false;
static void AHRSSettingsUpdatedCb(UAVObjEvent * ev)
{
AHRSSettingsIsUpdatedFlag = true;
}
static bool BaroAltitudeIsUpdatedFlag = false;
static void BaroAltitudeUpdatedCb(UAVObjEvent * ev)
{
BaroAltitudeIsUpdatedFlag = true;
}
static bool GPSPositionIsUpdatedFlag = false;
static void GPSPositionUpdatedCb(UAVObjEvent * ev)
{
GPSPositionIsUpdatedFlag = true;
}
static bool HomeLocationIsUpdatedFlag = false;
static void HomeLocationUpdatedCb(UAVObjEvent * ev)
{
HomeLocationIsUpdatedFlag = true;
}
static bool AHRSCalibrationIsUpdatedFlag = false;
static bool AHRSCalibrationIsLocallyUpdateFlag = false;
static void AHRSCalibrationUpdatedCb(UAVObjEvent * ev)
{
if (AHRSCalibrationIsLocallyUpdateFlag == true)
AHRSCalibrationIsLocallyUpdateFlag = false;
else
AHRSCalibrationIsUpdatedFlag = true;
}
static uint32_t GPSGoodUpdates;
/** /**
* Initialise the module, called on startup * Initialise the module, called on startup
@ -131,438 +74,67 @@ static uint32_t GPSGoodUpdates;
*/ */
int32_t AHRSCommsInitialize(void) int32_t AHRSCommsInitialize(void)
{ {
AHRSSettingsConnectCallback(AHRSSettingsUpdatedCb); AhrsInitComms();
BaroAltitudeConnectCallback(BaroAltitudeUpdatedCb);
GPSPositionConnectCallback(GPSPositionUpdatedCb);
HomeLocationConnectCallback(HomeLocationUpdatedCb);
AHRSCalibrationConnectCallback(AHRSCalibrationUpdatedCb);
PIOS_OPAHRS_Init();
// Start main task // Start main task
xTaskCreate(ahrscommsTask, (signed char *)"AHRSComms", STACK_SIZE, NULL, TASK_PRIORITY, &taskHandle); xTaskCreate(ahrscommsTask, (signed char*)"AHRSComms", STACK_SIZE, NULL, TASK_PRIORITY, &taskHandle);
return 0; return 0;
} }
static uint16_t update_errors = 0;
static uint16_t attituderaw_errors = 0;
static uint16_t home_errors = 0;
static uint16_t calibration_errors = 0;
static uint16_t algorithm_errors = 0;
/** /**
* Module thread, should not return. * Module thread, should not return.
*/ */
static void ahrscommsTask(void *parameters) static void ahrscommsTask(void* parameters)
{ {
enum opahrs_result result;
portTickType lastSysTime; portTickType lastSysTime;
GPSGoodUpdates = 0;
AhrsStatusData data;
AhrsStatusGet(&data);
data.CalibrationSet = AHRSSTATUS_CALIBRATIONSET_FALSE;
AhrsStatusSet(&data);
// Main task loop
while (1) {
struct opahrs_msg_v1 rsp;
struct opahrs_msg_v1 req;
AhrsStatusData data; AhrsStatusData data;
AlarmsSet(SYSTEMALARMS_ALARM_AHRSCOMMS, SYSTEMALARMS_ALARM_CRITICAL); AlarmsSet(SYSTEMALARMS_ALARM_AHRSCOMMS, SYSTEMALARMS_ALARM_CRITICAL);
/* Spin here until we're in sync */ /*Until AHRS connects, assume it doesn't know home */
while (PIOS_OPAHRS_resync() != OPAHRS_RESULT_OK) {
vTaskDelay(100 / portTICK_RATE_MS);
}
/* Give the other side a chance to keep up */
//vTaskDelay(100 / portTICK_RATE_MS);
if (PIOS_OPAHRS_GetSerial(&rsp) == OPAHRS_RESULT_OK) {
update_ahrs_status(&(rsp.payload.user.v.rsp.serial));
} else {
/* Comms error */
continue;
}
/* Whenever resyncing, assume AHRS doesn't reset and doesn't know home */
AhrsStatusGet(&data); AhrsStatusGet(&data);
req.payload.user.v.req.initialized.initialized = AHRS_INIT_QUERY;
result = PIOS_OPAHRS_SetGetInitialized(&req, &rsp);
if ((result != OPAHRS_RESULT_OK) || (rsp.payload.user.v.rsp.initialized.initialized == AHRS_UNINITIALIZED)) {
data.Initialized = AHRSSTATUS_INITIALIZED_FALSE;
data.HomeSet = AHRSSTATUS_HOMESET_FALSE; data.HomeSet = AHRSSTATUS_HOMESET_FALSE;
data.CalibrationSet = AHRSSTATUS_CALIBRATIONSET_FALSE; //data.CalibrationSet = AHRSSTATUS_CALIBRATIONSET_FALSE;
data.AlgorithmSet = AHRSSTATUS_ALGORITHMSET_FALSE; data.AlgorithmSet = AHRSSTATUS_CALIBRATIONSET_FALSE;
} else {
data.Initialized = AHRSSTATUS_INITIALIZED_TRUE;
AlarmsClear(SYSTEMALARMS_ALARM_AHRSCOMMS);
}
AhrsStatusSet(&data); AhrsStatusSet(&data);
/* We're in sync with the AHRS, spin here until an error occurs */ // Main task loop
lastSysTime = xTaskGetTickCount(); while (1)
while (1) { {
AHRSSettingsData settings; AHRSSettingsData settings;
/* Update settings with latest value */
AHRSSettingsGet(&settings); AHRSSettingsGet(&settings);
AhrsStatusGet(&data); AhrsSendObjects();
if ((data.HomeSet == AHRSSTATUS_HOMESET_TRUE) && (data.CalibrationSet == AHRSSTATUS_CALIBRATIONSET_TRUE) AhrsCommStatus stat = AhrsGetStatus();
&& (data.AlgorithmSet == AHRSSTATUS_ALGORITHMSET_TRUE)) { if(stat.linkOk)
{
req.payload.user.v.req.initialized.initialized = AHRS_INITIALIZED;
if ((result = PIOS_OPAHRS_SetGetInitialized(&req, &rsp)) == OPAHRS_RESULT_OK) {
data.Initialized = AHRSSTATUS_INITIALIZED_TRUE;
AhrsStatusSet(&data);
PIOS_OPAHRS_SetGetInitialized(&req, &rsp);
AlarmsClear(SYSTEMALARMS_ALARM_AHRSCOMMS); AlarmsClear(SYSTEMALARMS_ALARM_AHRSCOMMS);
} else { }else
break; {
AlarmsSet(SYSTEMALARMS_ALARM_AHRSCOMMS, SYSTEMALARMS_ALARM_WARNING);
} }
} AhrsStatusData sData;
// Update home coordinate if it hasn't been updated AhrsStatusGet(&sData);
AhrsStatusGet(&data);
if (HomeLocationIsUpdatedFlag || (data.HomeSet == AHRSSTATUS_HOMESET_FALSE)) {
struct opahrs_msg_v1 req;
load_magnetic_north(&(req.payload.user.v.req.north)); sData.LinkRunning = stat.linkOk;
if ((result = PIOS_OPAHRS_SetMagNorth(&req)) == OPAHRS_RESULT_OK) { sData.AhrsKickstarts = stat.remote.kickStarts;
HomeLocationIsUpdatedFlag = false; sData.AhrsCrcErrors = stat.remote.crcErrors;
data.HomeSet = AHRSSTATUS_HOMESET_TRUE; sData.AhrsRetries = stat.remote.retries;
AhrsStatusSet(&data); sData.AhrsInvalidPackets = stat.remote.invalidPacket;
} else { sData.OpCrcErrors = stat.local.crcErrors;
/* Comms error */ sData.OpRetries = stat.local.retries;
home_errors++; sData.OpInvalidPackets = stat.local.invalidPacket;
data.HomeSet = AHRSSTATUS_HOMESET_FALSE;
AhrsStatusSet(&data);
break;
}
}
// Update calibration if necessary
AhrsStatusGet(&data);
if (AHRSCalibrationIsUpdatedFlag || (data.CalibrationSet == AHRSSTATUS_CALIBRATIONSET_FALSE)) {
struct opahrs_msg_v1 req;
struct opahrs_msg_v1 rsp;
load_calibration(&(req.payload.user.v.req.calibration));
if ((result = PIOS_OPAHRS_SetGetCalibration(&req, &rsp)) == OPAHRS_RESULT_OK) {
update_calibration(&(rsp.payload.user.v.rsp.calibration));
AHRSCalibrationIsUpdatedFlag = false;
if (rsp.payload.user.v.req.calibration.measure_var != AHRS_ECHO)
data.CalibrationSet = AHRSSTATUS_CALIBRATIONSET_TRUE;
AhrsStatusSet(&data);
} else {
/* Comms error */
data.CalibrationSet = AHRSSTATUS_CALIBRATIONSET_FALSE;
AhrsStatusSet(&data);
calibration_errors++;
break;
}
}
// Update algorithm
if (AHRSSettingsIsUpdatedFlag || (data.AlgorithmSet == AHRSSTATUS_ALGORITHMSET_FALSE)) {
struct opahrs_msg_v1 req;
if (settings.Algorithm == AHRSSETTINGS_ALGORITHM_INSGPS)
req.payload.user.v.req.algorithm.algorithm = INSGPS_Algo;
if (settings.Algorithm == AHRSSETTINGS_ALGORITHM_SIMPLE)
req.payload.user.v.req.algorithm.algorithm = SIMPLE_Algo;
if ((result = PIOS_OPAHRS_SetAlgorithm(&req)) == OPAHRS_RESULT_OK) {
data.AlgorithmSet = AHRSSTATUS_ALGORITHMSET_TRUE;
AhrsStatusSet(&data);
} else {
/* Comms error */
data.AlgorithmSet = AHRSSTATUS_ALGORITHMSET_FALSE;
AhrsStatusSet(&data);
algorithm_errors++;
break;
}
}
// If settings indicate, grab the raw and filtered data instead of estimate
if (settings.UpdateRaw) {
if ((result = PIOS_OPAHRS_GetAttitudeRaw(&rsp)) == OPAHRS_RESULT_OK) {
update_attitude_raw(&(rsp.payload.user.v.rsp.attituderaw));
} else {
/* Comms error */
attituderaw_errors++;
break;
}
}
if (settings.UpdateFiltered) {
// Otherwise do standard technique
struct opahrs_msg_v1 req;
struct opahrs_msg_v1 rsp;
// Load barometer if updated
if (BaroAltitudeIsUpdatedFlag)
load_baro_altitude(&(req.payload.user.v.req.update));
else
req.payload.user.v.req.update.barometer.updated = 0;
// Load GPS if updated
if (GPSPositionIsUpdatedFlag)
load_gps_position(&(req.payload.user.v.req.update));
else
req.payload.user.v.req.update.gps.updated = 0;
// Transfer packet and process returned attitude
if ((result = PIOS_OPAHRS_SetGetUpdate(&req, &rsp)) == OPAHRS_RESULT_OK) {
if (req.payload.user.v.req.update.barometer.updated)
BaroAltitudeIsUpdatedFlag = false;
if (req.payload.user.v.req.update.gps.updated)
GPSPositionIsUpdatedFlag = false;
process_update(&(rsp.payload.user.v.rsp.update));
} else {
/* Comms error */
update_errors++;
break;
}
}
AhrsStatusSet(&sData);
/* Wait for the next update interval */ /* Wait for the next update interval */
vTaskDelayUntil(&lastSysTime, settings.UpdatePeriod / portTICK_RATE_MS); vTaskDelayUntil(&lastSysTime, settings.UpdatePeriod / portTICK_RATE_MS );
}
} }
} }
static void load_calibration(struct opahrs_msg_v1_req_calibration *calibration)
{
AHRSCalibrationData data;
AHRSCalibrationGet(&data);
if (data.measure_var == AHRSCALIBRATION_MEASURE_VAR_SET)
calibration->measure_var = AHRS_SET;
else if (data.measure_var == AHRSCALIBRATION_MEASURE_VAR_MEASURE)
calibration->measure_var = AHRS_MEASURE;
else
calibration->measure_var = AHRS_ECHO;
calibration->accel_bias[0] = data.accel_bias[0];
calibration->accel_bias[1] = data.accel_bias[1];
calibration->accel_bias[2] = data.accel_bias[2];
calibration->accel_scale[0] = data.accel_scale[0];
calibration->accel_scale[1] = data.accel_scale[1];
calibration->accel_scale[2] = data.accel_scale[2];
calibration->accel_var[0] = data.accel_var[0];
calibration->accel_var[1] = data.accel_var[1];
calibration->accel_var[2] = data.accel_var[2];
calibration->gyro_bias[0] = data.gyro_bias[0];
calibration->gyro_bias[1] = data.gyro_bias[1];
calibration->gyro_bias[2] = data.gyro_bias[2];
calibration->gyro_scale[0] = data.gyro_scale[0];
calibration->gyro_scale[1] = data.gyro_scale[1];
calibration->gyro_scale[2] = data.gyro_scale[2];
calibration->gyro_var[0] = data.gyro_var[0];
calibration->gyro_var[1] = data.gyro_var[1];
calibration->gyro_var[2] = data.gyro_var[2];
calibration->mag_bias[0] = data.mag_bias[0];
calibration->mag_bias[1] = data.mag_bias[1];
calibration->mag_bias[2] = data.mag_bias[2];
calibration->mag_scale[0] = data.mag_scale[0];
calibration->mag_scale[1] = data.mag_scale[1];
calibration->mag_scale[2] = data.mag_scale[2];
calibration->mag_var[0] = data.mag_var[0];
calibration->mag_var[1] = data.mag_var[1];
calibration->mag_var[2] = data.mag_var[2];
}
static void update_calibration(struct opahrs_msg_v1_rsp_calibration *calibration)
{
AHRSCalibrationData data;
AHRSCalibrationGet(&data);
AHRSCalibrationIsLocallyUpdateFlag = true;
data.accel_var[0] = calibration->accel_var[0];
data.accel_var[1] = calibration->accel_var[1];
data.accel_var[2] = calibration->accel_var[2];
data.gyro_var[0] = calibration->gyro_var[0];
data.gyro_var[1] = calibration->gyro_var[1];
data.gyro_var[2] = calibration->gyro_var[2];
data.mag_var[0] = calibration->mag_var[0];
data.mag_var[1] = calibration->mag_var[1];
data.mag_var[2] = calibration->mag_var[2];
AHRSCalibrationSet(&data);
}
static void load_magnetic_north(struct opahrs_msg_v1_req_north *mag_north)
{
HomeLocationData data;
HomeLocationGet(&data);
mag_north->Be[0] = data.Be[0];
mag_north->Be[1] = data.Be[1];
mag_north->Be[2] = data.Be[2];
if (data.Be[0] == 0 && data.Be[1] == 0 && data.Be[2] == 0) {
// in case nothing has been set go to default to prevent NaN in attitude solution
mag_north->Be[0] = 1;
mag_north->Be[1] = 0;
mag_north->Be[2] = 0;
} else {
// normalize for unit length here
float len = sqrt(data.Be[0] * data.Be[0] + data.Be[1] * data.Be[1] + data.Be[2] * data.Be[2]);
mag_north->Be[0] = data.Be[0] / len;
mag_north->Be[1] = data.Be[1] / len;
mag_north->Be[2] = data.Be[2] / len;
}
}
static void load_baro_altitude(struct opahrs_msg_v1_req_update *update)
{
BaroAltitudeData data;
BaroAltitudeGet(&data);
update->barometer.altitude = data.Altitude;
update->barometer.updated = TRUE;
}
static void load_gps_position(struct opahrs_msg_v1_req_update *update)
{
GPSPositionData data;
GPSPositionGet(&data);
HomeLocationData home;
HomeLocationGet(&home);
update->gps.updated = TRUE;
if (home.Set == HOMELOCATION_SET_FALSE || home.Indoor == HOMELOCATION_INDOOR_TRUE) {
PositionActualData pos;
PositionActualGet(&pos);
update->gps.NED[0] = 0;
update->gps.NED[1] = 0;
update->gps.NED[2] = 0;
update->gps.groundspeed = 0;
update->gps.heading = 0;
update->gps.quality = -1; // indicates indoor mode, high variance zeros update
} else {
// TODO: Parameterize these heuristics into the settings
if (data.Satellites >= 7 && data.PDOP < 3.5) {
if (GPSGoodUpdates < 30) {
GPSGoodUpdates++;
update->gps.quality = 0;
} else {
update->gps.groundspeed = data.Groundspeed;
update->gps.heading = data.Heading;
double LLA[3] =
{ (double)data.Latitude / 1e7, (double)data.Longitude / 1e7, (double)(data.GeoidSeparation + data.Altitude) };
// convert from cm back to meters
double ECEF[3] = { (double)(home.ECEF[0] / 100), (double)(home.ECEF[1] / 100), (double)(home.ECEF[2] / 100) };
LLA2Base(LLA, ECEF, (float (*)[3])home.RNE, update->gps.NED);
update->gps.quality = 1;
}
} else {
GPSGoodUpdates = 0;
update->gps.quality = 0;
}
}
}
static void process_update(struct opahrs_msg_v1_rsp_update *update)
{
AttitudeActualData data;
AttitudeSettingsData attitudeSettings;
AttitudeSettingsGet(&attitudeSettings);
data.q1 = update->quaternion.q1;
data.q2 = update->quaternion.q2;
data.q3 = update->quaternion.q3;
data.q4 = update->quaternion.q4;
float q[4] = { data.q1, data.q2, data.q3, data.q4 };
float rpy[3];
Quaternion2RPY(q, rpy);
data.Roll = rpy[0] - attitudeSettings.RollBias;
data.Pitch = rpy[1] - attitudeSettings.PitchBias;
data.Yaw = rpy[2];
if (data.Yaw < 0)
data.Yaw += 360;
AttitudeActualSet(&data);
PositionActualData pos;
PositionActualGet(&pos);
pos.North = update->NED[0];
pos.East = update->NED[1];
pos.Down = update->NED[2];
PositionActualSet(&pos);
VelocityActualData vel;
VelocityActualGet(&vel);
vel.North = update->Vel[0];
vel.East = update->Vel[1];
vel.Down = update->Vel[2];
VelocityActualSet(&vel);
AhrsStatusData status;
AhrsStatusGet(&status);
status.CPULoad = update->load;
status.IdleTimePerCyle = update->idle_time;
status.RunningTimePerCyle = update->run_time;
status.DroppedUpdates = update->dropped_updates;
AhrsStatusSet(&status);
}
static void update_attitude_raw(struct opahrs_msg_v1_rsp_attituderaw *attituderaw)
{
AttitudeRawData data;
data.magnetometers[ATTITUDERAW_MAGNETOMETERS_X] = attituderaw->mags.x;
data.magnetometers[ATTITUDERAW_MAGNETOMETERS_Y] = attituderaw->mags.y;
data.magnetometers[ATTITUDERAW_MAGNETOMETERS_Z] = attituderaw->mags.z;
data.gyros[ATTITUDERAW_GYROS_X] = attituderaw->gyros.x;
data.gyros[ATTITUDERAW_GYROS_Y] = attituderaw->gyros.y;
data.gyros[ATTITUDERAW_GYROS_Z] = attituderaw->gyros.z;
data.gyros_filtered[ATTITUDERAW_GYROS_FILTERED_X] = attituderaw->gyros_filtered.x;
data.gyros_filtered[ATTITUDERAW_GYROS_FILTERED_Y] = attituderaw->gyros_filtered.y;
data.gyros_filtered[ATTITUDERAW_GYROS_FILTERED_Z] = attituderaw->gyros_filtered.z;
data.gyrotemp[ATTITUDERAW_GYROTEMP_XY] = attituderaw->gyros.xy_temp;
data.gyrotemp[ATTITUDERAW_GYROTEMP_Z] = attituderaw->gyros.z_temp;
data.accels[ATTITUDERAW_ACCELS_X] = attituderaw->accels.x;
data.accels[ATTITUDERAW_ACCELS_Y] = attituderaw->accels.y;
data.accels[ATTITUDERAW_ACCELS_Z] = attituderaw->accels.z;
data.accels_filtered[ATTITUDERAW_ACCELS_FILTERED_X] = attituderaw->accels_filtered.x;
data.accels_filtered[ATTITUDERAW_ACCELS_FILTERED_Y] = attituderaw->accels_filtered.y;
data.accels_filtered[ATTITUDERAW_ACCELS_FILTERED_Z] = attituderaw->accels_filtered.z;
AttitudeRawSet(&data);
}
static void update_ahrs_status(struct opahrs_msg_v1_rsp_serial *serial)
{
AhrsStatusData data;
// Get the current object data
AhrsStatusGet(&data);
for (uint8_t i = 0; i < sizeof(serial->serial_bcd); i++) {
data.SerialNumber[i] = serial->serial_bcd[i];
}
data.CommErrors[AHRSSTATUS_COMMERRORS_UPDATE] = update_errors;
data.CommErrors[AHRSSTATUS_COMMERRORS_ATTITUDERAW] = attituderaw_errors;
data.CommErrors[AHRSSTATUS_COMMERRORS_HOMELOCATION] = home_errors;
data.CommErrors[AHRSSTATUS_COMMERRORS_CALIBRATION] = calibration_errors;
data.CommErrors[AHRSSTATUS_COMMERRORS_ALGORITHM] = algorithm_errors;
AhrsStatusSet(&data);
}
/** /**
* @} * @}

View File

@ -35,3 +35,4 @@
int32_t AHRSCommsInitialize(void); int32_t AHRSCommsInitialize(void);
#endif // AHRS_COMMS_H #endif // AHRS_COMMS_H

View File

@ -1,111 +0,0 @@
/**
******************************************************************************
* @addtogroup UAVObjects OpenPilot UAVObjects
* @{
* @addtogroup AhrsStatus2 AhrsStatus2
* @brief Status for the @ref AHRSCommsModule, including communication errors
*
* Autogenerated files and functions for AhrsStatus2 Object
* @{
*
* @file ahrsstatus2.c
* @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2010.
* @brief Implementation of the AhrsStatus2 object. This file has been
* automatically generated by the UAVObjectGenerator.
*
* @note Object definition file: ahrsstatus2.xml.
* This is an automatically generated file.
* DO NOT modify manually.
*
* @see The GNU Public License (GPL) Version 3
*
*****************************************************************************/
/*
* This program 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 3 of the License, or
* (at your option) any later version.
*
* This program 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 this program; if not, write to the Free Software Foundation, Inc.,
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include "openpilot.h"
#include "ahrsstatus2.h"
// Private variables
static UAVObjHandle handle;
// Private functions
static void setDefaults(UAVObjHandle obj, uint16_t instId);
/**
* Initialize object.
* \return 0 Success
* \return -1 Failure
*/
int32_t AhrsStatus2Initialize()
{
// Register object with the object manager
handle = UAVObjRegister(AHRSSTATUS2_OBJID, AHRSSTATUS2_NAME, AHRSSTATUS2_METANAME, 0,
AHRSSTATUS2_ISSINGLEINST, AHRSSTATUS2_ISSETTINGS, AHRSSTATUS2_NUMBYTES, &setDefaults);
// Done
if (handle != 0)
{
return 0;
}
else
{
return -1;
}
}
/**
* Initialize object fields and metadata with the default values.
* If a default value is not specified the object fields
* will be initialized to zero.
*/
static void setDefaults(UAVObjHandle obj, uint16_t instId)
{
AhrsStatus2Data data;
UAVObjMetadata metadata;
// Initialize object fields to their default values
UAVObjGetInstanceData(obj, instId, &data);
memset(&data, 0, sizeof(AhrsStatus2Data));
UAVObjSetInstanceData(obj, instId, &data);
// Initialize object metadata to their default values
metadata.access = ACCESS_READWRITE;
metadata.gcsAccess = ACCESS_READWRITE;
metadata.telemetryAcked = 0;
metadata.telemetryUpdateMode = UPDATEMODE_PERIODIC;
metadata.telemetryUpdatePeriod = 1000;
metadata.gcsTelemetryAcked = 0;
metadata.gcsTelemetryUpdateMode = UPDATEMODE_MANUAL;
metadata.gcsTelemetryUpdatePeriod = 0;
metadata.loggingUpdateMode = UPDATEMODE_PERIODIC;
metadata.loggingUpdatePeriod = 1000;
UAVObjSetMetadata(obj, &metadata);
}
/**
* Get object handle
*/
UAVObjHandle AhrsStatus2Handle()
{
return handle;
}
/**
* @}
*/

View File

@ -41,7 +41,7 @@
#define AHRSSTATUS_H #define AHRSSTATUS_H
// Object constants // Object constants
#define AHRSSTATUS_OBJID 4061809000U #define AHRSSTATUS_OBJID 188215176U
#define AHRSSTATUS_NAME "AhrsStatus" #define AHRSSTATUS_NAME "AhrsStatus"
#define AHRSSTATUS_METANAME "AhrsStatusMeta" #define AHRSSTATUS_METANAME "AhrsStatusMeta"
#define AHRSSTATUS_ISSINGLEINST 1 #define AHRSSTATUS_ISSINGLEINST 1
@ -71,35 +71,33 @@
// Object data // Object data
typedef struct { typedef struct {
uint8_t SerialNumber[25]; uint8_t SerialNumber[8];
uint8_t CPULoad; uint8_t CPULoad;
uint8_t IdleTimePerCyle; uint8_t IdleTimePerCyle;
uint8_t RunningTimePerCyle; uint8_t RunningTimePerCyle;
uint8_t DroppedUpdates; uint8_t DroppedUpdates;
uint8_t CommErrors[5];
uint8_t Initialized;
uint8_t AlgorithmSet; uint8_t AlgorithmSet;
uint8_t CalibrationSet; uint8_t CalibrationSet;
uint8_t HomeSet; uint8_t HomeSet;
uint8_t LinkRunning;
uint8_t AhrsKickstarts;
uint8_t AhrsCrcErrors;
uint8_t AhrsRetries;
uint8_t AhrsInvalidPackets;
uint8_t OpCrcErrors;
uint8_t OpRetries;
uint8_t OpInvalidPackets;
} __attribute__((packed)) AhrsStatusData; } __attribute__((packed)) AhrsStatusData;
// Field information // Field information
// Field SerialNumber information // Field SerialNumber information
/* Number of elements for field SerialNumber */ /* Number of elements for field SerialNumber */
#define AHRSSTATUS_SERIALNUMBER_NUMELEM 25 #define AHRSSTATUS_SERIALNUMBER_NUMELEM 8
// Field CPULoad information // Field CPULoad information
// Field IdleTimePerCyle information // Field IdleTimePerCyle information
// Field RunningTimePerCyle information // Field RunningTimePerCyle information
// Field DroppedUpdates information // Field DroppedUpdates information
// Field CommErrors information
/* Array element names for field CommErrors */
typedef enum { AHRSSTATUS_COMMERRORS_ALGORITHM=0, AHRSSTATUS_COMMERRORS_UPDATE=1, AHRSSTATUS_COMMERRORS_ATTITUDERAW=2, AHRSSTATUS_COMMERRORS_HOMELOCATION=3, AHRSSTATUS_COMMERRORS_CALIBRATION=4 } AhrsStatusCommErrorsElem;
/* Number of elements for field CommErrors */
#define AHRSSTATUS_COMMERRORS_NUMELEM 5
// Field Initialized information
/* Enumeration options for field Initialized */
typedef enum { AHRSSTATUS_INITIALIZED_FALSE=0, AHRSSTATUS_INITIALIZED_TRUE=1 } AhrsStatusInitializedOptions;
// Field AlgorithmSet information // Field AlgorithmSet information
/* Enumeration options for field AlgorithmSet */ /* Enumeration options for field AlgorithmSet */
typedef enum { AHRSSTATUS_ALGORITHMSET_FALSE=0, AHRSSTATUS_ALGORITHMSET_TRUE=1 } AhrsStatusAlgorithmSetOptions; typedef enum { AHRSSTATUS_ALGORITHMSET_FALSE=0, AHRSSTATUS_ALGORITHMSET_TRUE=1 } AhrsStatusAlgorithmSetOptions;
@ -109,6 +107,16 @@ typedef enum { AHRSSTATUS_CALIBRATIONSET_FALSE=0, AHRSSTATUS_CALIBRATIONSET_TRUE
// Field HomeSet information // Field HomeSet information
/* Enumeration options for field HomeSet */ /* Enumeration options for field HomeSet */
typedef enum { AHRSSTATUS_HOMESET_FALSE=0, AHRSSTATUS_HOMESET_TRUE=1 } AhrsStatusHomeSetOptions; typedef enum { AHRSSTATUS_HOMESET_FALSE=0, AHRSSTATUS_HOMESET_TRUE=1 } AhrsStatusHomeSetOptions;
// Field LinkRunning information
/* Enumeration options for field LinkRunning */
typedef enum { AHRSSTATUS_LINKRUNNING_FALSE=0, AHRSSTATUS_LINKRUNNING_TRUE=1 } AhrsStatusLinkRunningOptions;
// Field AhrsKickstarts information
// Field AhrsCrcErrors information
// Field AhrsRetries information
// Field AhrsInvalidPackets information
// Field OpCrcErrors information
// Field OpRetries information
// Field OpInvalidPackets information
// Generic interface functions // Generic interface functions

View File

@ -1,131 +0,0 @@
/**
******************************************************************************
* @addtogroup UAVObjects OpenPilot UAVObjects
* @{
* @addtogroup AhrsStatus2 AhrsStatus2
* @brief Status for the @ref AHRSCommsModule, including communication errors
*
* Autogenerated files and functions for AhrsStatus2 Object
* @{
*
* @file ahrsstatus2.h
* @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2010.
* @brief Implementation of the AhrsStatus2 object. This file has been
* automatically generated by the UAVObjectGenerator.
*
* @note Object definition file: ahrsstatus2.xml.
* This is an automatically generated file.
* DO NOT modify manually.
*
* @see The GNU Public License (GPL) Version 3
*
*****************************************************************************/
/*
* This program 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 3 of the License, or
* (at your option) any later version.
*
* This program 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 this program; if not, write to the Free Software Foundation, Inc.,
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#ifndef AHRSSTATUS2_H
#define AHRSSTATUS2_H
// Object constants
#define AHRSSTATUS2_OBJID 805003662U
#define AHRSSTATUS2_NAME "AhrsStatus2"
#define AHRSSTATUS2_METANAME "AhrsStatus2Meta"
#define AHRSSTATUS2_ISSINGLEINST 1
#define AHRSSTATUS2_ISSETTINGS 0
#define AHRSSTATUS2_NUMBYTES sizeof(AhrsStatus2Data)
// Object access macros
/**
* @function AhrsStatus2Get(dataOut)
* @brief Populate a AhrsStatus2Data object
* @param[out] dataOut
*/
#define AhrsStatus2Get(dataOut) UAVObjGetData(AhrsStatus2Handle(), dataOut)
#define AhrsStatus2Set(dataIn) UAVObjSetData(AhrsStatus2Handle(), dataIn)
#define AhrsStatus2InstGet(instId, dataOut) UAVObjGetInstanceData(AhrsStatus2Handle(), instId, dataOut)
#define AhrsStatus2InstSet(instId, dataIn) UAVObjSetInstanceData(AhrsStatus2Handle(), instId, dataIn)
#define AhrsStatus2ConnectQueue(queue) UAVObjConnectQueue(AhrsStatus2Handle(), queue, EV_MASK_ALL_UPDATES)
#define AhrsStatus2ConnectCallback(cb) UAVObjConnectCallback(AhrsStatus2Handle(), cb, EV_MASK_ALL_UPDATES)
#define AhrsStatus2CreateInstance() UAVObjCreateInstance(AhrsStatus2Handle())
#define AhrsStatus2RequestUpdate() UAVObjRequestUpdate(AhrsStatus2Handle())
#define AhrsStatus2RequestInstUpdate(instId) UAVObjRequestInstanceUpdate(AhrsStatus2Handle(), instId)
#define AhrsStatus2Updated() UAVObjUpdated(AhrsStatus2Handle())
#define AhrsStatus2InstUpdated(instId) UAVObjUpdated(AhrsStatus2Handle(), instId)
#define AhrsStatus2GetMetadata(dataOut) UAVObjGetMetadata(AhrsStatus2Handle(), dataOut)
#define AhrsStatus2SetMetadata(dataIn) UAVObjSetMetadata(AhrsStatus2Handle(), dataIn)
#define AhrsStatus2ReadOnly(dataIn) UAVObjReadOnly(AhrsStatus2Handle())
// Object data
typedef struct {
uint8_t SerialNumber[8];
uint8_t CPULoad;
uint8_t IdleTimePerCyle;
uint8_t RunningTimePerCyle;
uint8_t DroppedUpdates;
uint8_t AlgorithmSet;
uint8_t CalibrationSet;
uint8_t HomeSet;
uint8_t LinkRunning;
uint8_t AhrsKickstarts;
uint8_t AhrsCrcErrors;
uint8_t AhrsRetries;
uint8_t AhrsInvalidPackets;
uint8_t OpCrcErrors;
uint8_t OpRetries;
uint8_t OpInvalidPackets;
} __attribute__((packed)) AhrsStatus2Data;
// Field information
// Field SerialNumber information
/* Number of elements for field SerialNumber */
#define AHRSSTATUS2_SERIALNUMBER_NUMELEM 8
// Field CPULoad information
// Field IdleTimePerCyle information
// Field RunningTimePerCyle information
// Field DroppedUpdates information
// Field AlgorithmSet information
/* Enumeration options for field AlgorithmSet */
typedef enum { AHRSSTATUS2_ALGORITHMSET_FALSE=0, AHRSSTATUS2_ALGORITHMSET_TRUE=1 } AhrsStatus2AlgorithmSetOptions;
// Field CalibrationSet information
/* Enumeration options for field CalibrationSet */
typedef enum { AHRSSTATUS2_CALIBRATIONSET_FALSE=0, AHRSSTATUS2_CALIBRATIONSET_TRUE=1 } AhrsStatus2CalibrationSetOptions;
// Field HomeSet information
/* Enumeration options for field HomeSet */
typedef enum { AHRSSTATUS2_HOMESET_FALSE=0, AHRSSTATUS2_HOMESET_TRUE=1 } AhrsStatus2HomeSetOptions;
// Field LinkRunning information
/* Enumeration options for field LinkRunning */
typedef enum { AHRSSTATUS2_LINKRUNNING_FALSE=0, AHRSSTATUS2_LINKRUNNING_TRUE=1 } AhrsStatus2LinkRunningOptions;
// Field AhrsKickstarts information
// Field AhrsCrcErrors information
// Field AhrsRetries information
// Field AhrsInvalidPackets information
// Field OpCrcErrors information
// Field OpRetries information
// Field OpInvalidPackets information
// Generic interface functions
int32_t AhrsStatus2Initialize();
UAVObjHandle AhrsStatus2Handle();
#endif // AHRSSTATUS2_H
/**
* @}
* @}
*/

View File

@ -34,7 +34,6 @@
#include "ahrscalibration.h" #include "ahrscalibration.h"
#include "ahrssettings.h" #include "ahrssettings.h"
#include "ahrsstatus.h" #include "ahrsstatus.h"
#include "ahrsstatus2.h"
#include "attitudeactual.h" #include "attitudeactual.h"
#include "attitudedesired.h" #include "attitudedesired.h"
#include "attituderaw.h" #include "attituderaw.h"
@ -81,7 +80,6 @@ void UAVObjectsInitializeAll()
AHRSCalibrationInitialize(); AHRSCalibrationInitialize();
AHRSSettingsInitialize(); AHRSSettingsInitialize();
AhrsStatusInitialize(); AhrsStatusInitialize();
AhrsStatus2Initialize();
AttitudeActualInitialize(); AttitudeActualInitialize();
AttitudeDesiredInitialize(); AttitudeDesiredInitialize();
AttitudeRawInitialize(); AttitudeRawInitialize();

View File

@ -27,7 +27,6 @@
#ifndef STM32103CB_AHRS_H_ #ifndef STM32103CB_AHRS_H_
#define STM32103CB_AHRS_H_ #define STM32103CB_AHRS_H_
//------------------------ //------------------------
// Timers and Channels Used // Timers and Channels Used
//------------------------ //------------------------

View File

@ -51,23 +51,6 @@ AhrsStatus::AhrsStatus(): UAVDataObject(OBJID, ISSINGLEINST, ISSETTINGS, NAME)
SerialNumberElemNames.append("5"); SerialNumberElemNames.append("5");
SerialNumberElemNames.append("6"); SerialNumberElemNames.append("6");
SerialNumberElemNames.append("7"); SerialNumberElemNames.append("7");
SerialNumberElemNames.append("8");
SerialNumberElemNames.append("9");
SerialNumberElemNames.append("10");
SerialNumberElemNames.append("11");
SerialNumberElemNames.append("12");
SerialNumberElemNames.append("13");
SerialNumberElemNames.append("14");
SerialNumberElemNames.append("15");
SerialNumberElemNames.append("16");
SerialNumberElemNames.append("17");
SerialNumberElemNames.append("18");
SerialNumberElemNames.append("19");
SerialNumberElemNames.append("20");
SerialNumberElemNames.append("21");
SerialNumberElemNames.append("22");
SerialNumberElemNames.append("23");
SerialNumberElemNames.append("24");
fields.append( new UAVObjectField(QString("SerialNumber"), QString("n/a"), UAVObjectField::UINT8, SerialNumberElemNames, QStringList()) ); fields.append( new UAVObjectField(QString("SerialNumber"), QString("n/a"), UAVObjectField::UINT8, SerialNumberElemNames, QStringList()) );
QStringList CPULoadElemNames; QStringList CPULoadElemNames;
CPULoadElemNames.append("0"); CPULoadElemNames.append("0");
@ -81,19 +64,6 @@ AhrsStatus::AhrsStatus(): UAVDataObject(OBJID, ISSINGLEINST, ISSETTINGS, NAME)
QStringList DroppedUpdatesElemNames; QStringList DroppedUpdatesElemNames;
DroppedUpdatesElemNames.append("0"); DroppedUpdatesElemNames.append("0");
fields.append( new UAVObjectField(QString("DroppedUpdates"), QString("count"), UAVObjectField::UINT8, DroppedUpdatesElemNames, QStringList()) ); fields.append( new UAVObjectField(QString("DroppedUpdates"), QString("count"), UAVObjectField::UINT8, DroppedUpdatesElemNames, QStringList()) );
QStringList CommErrorsElemNames;
CommErrorsElemNames.append("Algorithm");
CommErrorsElemNames.append("Update");
CommErrorsElemNames.append("AttitudeRaw");
CommErrorsElemNames.append("HomeLocation");
CommErrorsElemNames.append("Calibration");
fields.append( new UAVObjectField(QString("CommErrors"), QString("count"), UAVObjectField::UINT8, CommErrorsElemNames, QStringList()) );
QStringList InitializedElemNames;
InitializedElemNames.append("0");
QStringList InitializedEnumOptions;
InitializedEnumOptions.append("FALSE");
InitializedEnumOptions.append("TRUE");
fields.append( new UAVObjectField(QString("Initialized"), QString(""), UAVObjectField::ENUM, InitializedElemNames, InitializedEnumOptions) );
QStringList AlgorithmSetElemNames; QStringList AlgorithmSetElemNames;
AlgorithmSetElemNames.append("0"); AlgorithmSetElemNames.append("0");
QStringList AlgorithmSetEnumOptions; QStringList AlgorithmSetEnumOptions;
@ -112,6 +82,33 @@ AhrsStatus::AhrsStatus(): UAVDataObject(OBJID, ISSINGLEINST, ISSETTINGS, NAME)
HomeSetEnumOptions.append("FALSE"); HomeSetEnumOptions.append("FALSE");
HomeSetEnumOptions.append("TRUE"); HomeSetEnumOptions.append("TRUE");
fields.append( new UAVObjectField(QString("HomeSet"), QString(""), UAVObjectField::ENUM, HomeSetElemNames, HomeSetEnumOptions) ); fields.append( new UAVObjectField(QString("HomeSet"), QString(""), UAVObjectField::ENUM, HomeSetElemNames, HomeSetEnumOptions) );
QStringList LinkRunningElemNames;
LinkRunningElemNames.append("0");
QStringList LinkRunningEnumOptions;
LinkRunningEnumOptions.append("FALSE");
LinkRunningEnumOptions.append("TRUE");
fields.append( new UAVObjectField(QString("LinkRunning"), QString(""), UAVObjectField::ENUM, LinkRunningElemNames, LinkRunningEnumOptions) );
QStringList AhrsKickstartsElemNames;
AhrsKickstartsElemNames.append("0");
fields.append( new UAVObjectField(QString("AhrsKickstarts"), QString("count"), UAVObjectField::UINT8, AhrsKickstartsElemNames, QStringList()) );
QStringList AhrsCrcErrorsElemNames;
AhrsCrcErrorsElemNames.append("0");
fields.append( new UAVObjectField(QString("AhrsCrcErrors"), QString("count"), UAVObjectField::UINT8, AhrsCrcErrorsElemNames, QStringList()) );
QStringList AhrsRetriesElemNames;
AhrsRetriesElemNames.append("0");
fields.append( new UAVObjectField(QString("AhrsRetries"), QString("count"), UAVObjectField::UINT8, AhrsRetriesElemNames, QStringList()) );
QStringList AhrsInvalidPacketsElemNames;
AhrsInvalidPacketsElemNames.append("0");
fields.append( new UAVObjectField(QString("AhrsInvalidPackets"), QString("count"), UAVObjectField::UINT8, AhrsInvalidPacketsElemNames, QStringList()) );
QStringList OpCrcErrorsElemNames;
OpCrcErrorsElemNames.append("0");
fields.append( new UAVObjectField(QString("OpCrcErrors"), QString("count"), UAVObjectField::UINT8, OpCrcErrorsElemNames, QStringList()) );
QStringList OpRetriesElemNames;
OpRetriesElemNames.append("0");
fields.append( new UAVObjectField(QString("OpRetries"), QString("count"), UAVObjectField::UINT8, OpRetriesElemNames, QStringList()) );
QStringList OpInvalidPacketsElemNames;
OpInvalidPacketsElemNames.append("0");
fields.append( new UAVObjectField(QString("OpInvalidPackets"), QString("count"), UAVObjectField::UINT8, OpInvalidPacketsElemNames, QStringList()) );
// Initialize object // Initialize object
initializeFields(fields, (quint8*)&data, NUMBYTES); initializeFields(fields, (quint8*)&data, NUMBYTES);

View File

@ -43,35 +43,33 @@ class UAVOBJECTS_EXPORT AhrsStatus: public UAVDataObject
public: public:
// Field structure // Field structure
typedef struct { typedef struct {
quint8 SerialNumber[25]; quint8 SerialNumber[8];
quint8 CPULoad; quint8 CPULoad;
quint8 IdleTimePerCyle; quint8 IdleTimePerCyle;
quint8 RunningTimePerCyle; quint8 RunningTimePerCyle;
quint8 DroppedUpdates; quint8 DroppedUpdates;
quint8 CommErrors[5];
quint8 Initialized;
quint8 AlgorithmSet; quint8 AlgorithmSet;
quint8 CalibrationSet; quint8 CalibrationSet;
quint8 HomeSet; quint8 HomeSet;
quint8 LinkRunning;
quint8 AhrsKickstarts;
quint8 AhrsCrcErrors;
quint8 AhrsRetries;
quint8 AhrsInvalidPackets;
quint8 OpCrcErrors;
quint8 OpRetries;
quint8 OpInvalidPackets;
} __attribute__((packed)) DataFields; } __attribute__((packed)) DataFields;
// Field information // Field information
// Field SerialNumber information // Field SerialNumber information
/* Number of elements for field SerialNumber */ /* Number of elements for field SerialNumber */
static const quint32 SERIALNUMBER_NUMELEM = 25; static const quint32 SERIALNUMBER_NUMELEM = 8;
// Field CPULoad information // Field CPULoad information
// Field IdleTimePerCyle information // Field IdleTimePerCyle information
// Field RunningTimePerCyle information // Field RunningTimePerCyle information
// Field DroppedUpdates information // Field DroppedUpdates information
// Field CommErrors information
/* Array element names for field CommErrors */
typedef enum { COMMERRORS_ALGORITHM=0, COMMERRORS_UPDATE=1, COMMERRORS_ATTITUDERAW=2, COMMERRORS_HOMELOCATION=3, COMMERRORS_CALIBRATION=4 } CommErrorsElem;
/* Number of elements for field CommErrors */
static const quint32 COMMERRORS_NUMELEM = 5;
// Field Initialized information
/* Enumeration options for field Initialized */
typedef enum { INITIALIZED_FALSE=0, INITIALIZED_TRUE=1 } InitializedOptions;
// Field AlgorithmSet information // Field AlgorithmSet information
/* Enumeration options for field AlgorithmSet */ /* Enumeration options for field AlgorithmSet */
typedef enum { ALGORITHMSET_FALSE=0, ALGORITHMSET_TRUE=1 } AlgorithmSetOptions; typedef enum { ALGORITHMSET_FALSE=0, ALGORITHMSET_TRUE=1 } AlgorithmSetOptions;
@ -81,10 +79,20 @@ public:
// Field HomeSet information // Field HomeSet information
/* Enumeration options for field HomeSet */ /* Enumeration options for field HomeSet */
typedef enum { HOMESET_FALSE=0, HOMESET_TRUE=1 } HomeSetOptions; typedef enum { HOMESET_FALSE=0, HOMESET_TRUE=1 } HomeSetOptions;
// Field LinkRunning information
/* Enumeration options for field LinkRunning */
typedef enum { LINKRUNNING_FALSE=0, LINKRUNNING_TRUE=1 } LinkRunningOptions;
// Field AhrsKickstarts information
// Field AhrsCrcErrors information
// Field AhrsRetries information
// Field AhrsInvalidPackets information
// Field OpCrcErrors information
// Field OpRetries information
// Field OpInvalidPackets information
// Constants // Constants
static const quint32 OBJID = 4061809000U; static const quint32 OBJID = 188215176U;
static const QString NAME; static const QString NAME;
static const bool ISSINGLEINST = 1; static const bool ISSINGLEINST = 1;
static const bool ISSETTINGS = 0; static const bool ISSETTINGS = 0;

View File

@ -40,7 +40,7 @@ _fields = [ \
uavobject.UAVObjectField( uavobject.UAVObjectField(
'SerialNumber', 'SerialNumber',
'B', 'B',
25, 8,
[ [
'0', '0',
'1', '1',
@ -50,23 +50,6 @@ _fields = [ \
'5', '5',
'6', '6',
'7', '7',
'8',
'9',
'10',
'11',
'12',
'13',
'14',
'15',
'16',
'17',
'18',
'19',
'20',
'21',
'22',
'23',
'24',
], ],
{ {
} }
@ -111,32 +94,6 @@ _fields = [ \
{ {
} }
), ),
uavobject.UAVObjectField(
'CommErrors',
'B',
5,
[
'Algorithm',
'Update',
'AttitudeRaw',
'HomeLocation',
'Calibration',
],
{
}
),
uavobject.UAVObjectField(
'Initialized',
'b',
1,
[
'0',
],
{
'0' : 'FALSE',
'1' : 'TRUE',
}
),
uavobject.UAVObjectField( uavobject.UAVObjectField(
'AlgorithmSet', 'AlgorithmSet',
'b', 'b',
@ -173,12 +130,94 @@ _fields = [ \
'1' : 'TRUE', '1' : 'TRUE',
} }
), ),
uavobject.UAVObjectField(
'LinkRunning',
'b',
1,
[
'0',
],
{
'0' : 'FALSE',
'1' : 'TRUE',
}
),
uavobject.UAVObjectField(
'AhrsKickstarts',
'B',
1,
[
'0',
],
{
}
),
uavobject.UAVObjectField(
'AhrsCrcErrors',
'B',
1,
[
'0',
],
{
}
),
uavobject.UAVObjectField(
'AhrsRetries',
'B',
1,
[
'0',
],
{
}
),
uavobject.UAVObjectField(
'AhrsInvalidPackets',
'B',
1,
[
'0',
],
{
}
),
uavobject.UAVObjectField(
'OpCrcErrors',
'B',
1,
[
'0',
],
{
}
),
uavobject.UAVObjectField(
'OpRetries',
'B',
1,
[
'0',
],
{
}
),
uavobject.UAVObjectField(
'OpInvalidPackets',
'B',
1,
[
'0',
],
{
}
),
] ]
class AhrsStatus(uavobject.UAVObject): class AhrsStatus(uavobject.UAVObject):
## Object constants ## Object constants
OBJID = 4061809000 OBJID = 188215176
NAME = "AhrsStatus" NAME = "AhrsStatus"
METANAME = "AhrsStatusMeta" METANAME = "AhrsStatusMeta"
ISSINGLEINST = 1 ISSINGLEINST = 1

View File

@ -1,192 +0,0 @@
/**
******************************************************************************
*
* @file ahrsstatus2.cpp
* @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2010.
* @see The GNU Public License (GPL) Version 3
* @addtogroup GCSPlugins GCS Plugins
* @{
* @addtogroup UAVObjectsPlugin UAVObjects Plugin
* @{
*
* @note Object definition file: ahrsstatus2.xml.
* This is an automatically generated file.
* DO NOT modify manually.
*
* @brief The UAVUObjects GCS plugin
*****************************************************************************/
/*
* This program 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 3 of the License, or
* (at your option) any later version.
*
* This program 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 this program; if not, write to the Free Software Foundation, Inc.,
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include "ahrsstatus2.h"
#include "uavobjectfield.h"
const QString AhrsStatus2::NAME = QString("AhrsStatus2");
/**
* Constructor
*/
AhrsStatus2::AhrsStatus2(): UAVDataObject(OBJID, ISSINGLEINST, ISSETTINGS, NAME)
{
// Create fields
QList<UAVObjectField*> fields;
QStringList SerialNumberElemNames;
SerialNumberElemNames.append("0");
SerialNumberElemNames.append("1");
SerialNumberElemNames.append("2");
SerialNumberElemNames.append("3");
SerialNumberElemNames.append("4");
SerialNumberElemNames.append("5");
SerialNumberElemNames.append("6");
SerialNumberElemNames.append("7");
fields.append( new UAVObjectField(QString("SerialNumber"), QString("n/a"), UAVObjectField::UINT8, SerialNumberElemNames, QStringList()) );
QStringList CPULoadElemNames;
CPULoadElemNames.append("0");
fields.append( new UAVObjectField(QString("CPULoad"), QString("count"), UAVObjectField::UINT8, CPULoadElemNames, QStringList()) );
QStringList IdleTimePerCyleElemNames;
IdleTimePerCyleElemNames.append("0");
fields.append( new UAVObjectField(QString("IdleTimePerCyle"), QString("10x ms"), UAVObjectField::UINT8, IdleTimePerCyleElemNames, QStringList()) );
QStringList RunningTimePerCyleElemNames;
RunningTimePerCyleElemNames.append("0");
fields.append( new UAVObjectField(QString("RunningTimePerCyle"), QString("10x ms"), UAVObjectField::UINT8, RunningTimePerCyleElemNames, QStringList()) );
QStringList DroppedUpdatesElemNames;
DroppedUpdatesElemNames.append("0");
fields.append( new UAVObjectField(QString("DroppedUpdates"), QString("count"), UAVObjectField::UINT8, DroppedUpdatesElemNames, QStringList()) );
QStringList AlgorithmSetElemNames;
AlgorithmSetElemNames.append("0");
QStringList AlgorithmSetEnumOptions;
AlgorithmSetEnumOptions.append("FALSE");
AlgorithmSetEnumOptions.append("TRUE");
fields.append( new UAVObjectField(QString("AlgorithmSet"), QString(""), UAVObjectField::ENUM, AlgorithmSetElemNames, AlgorithmSetEnumOptions) );
QStringList CalibrationSetElemNames;
CalibrationSetElemNames.append("0");
QStringList CalibrationSetEnumOptions;
CalibrationSetEnumOptions.append("FALSE");
CalibrationSetEnumOptions.append("TRUE");
fields.append( new UAVObjectField(QString("CalibrationSet"), QString(""), UAVObjectField::ENUM, CalibrationSetElemNames, CalibrationSetEnumOptions) );
QStringList HomeSetElemNames;
HomeSetElemNames.append("0");
QStringList HomeSetEnumOptions;
HomeSetEnumOptions.append("FALSE");
HomeSetEnumOptions.append("TRUE");
fields.append( new UAVObjectField(QString("HomeSet"), QString(""), UAVObjectField::ENUM, HomeSetElemNames, HomeSetEnumOptions) );
QStringList LinkRunningElemNames;
LinkRunningElemNames.append("0");
QStringList LinkRunningEnumOptions;
LinkRunningEnumOptions.append("FALSE");
LinkRunningEnumOptions.append("TRUE");
fields.append( new UAVObjectField(QString("LinkRunning"), QString(""), UAVObjectField::ENUM, LinkRunningElemNames, LinkRunningEnumOptions) );
QStringList AhrsKickstartsElemNames;
AhrsKickstartsElemNames.append("0");
fields.append( new UAVObjectField(QString("AhrsKickstarts"), QString("count"), UAVObjectField::UINT8, AhrsKickstartsElemNames, QStringList()) );
QStringList AhrsCrcErrorsElemNames;
AhrsCrcErrorsElemNames.append("0");
fields.append( new UAVObjectField(QString("AhrsCrcErrors"), QString("count"), UAVObjectField::UINT8, AhrsCrcErrorsElemNames, QStringList()) );
QStringList AhrsRetriesElemNames;
AhrsRetriesElemNames.append("0");
fields.append( new UAVObjectField(QString("AhrsRetries"), QString("count"), UAVObjectField::UINT8, AhrsRetriesElemNames, QStringList()) );
QStringList AhrsInvalidPacketsElemNames;
AhrsInvalidPacketsElemNames.append("0");
fields.append( new UAVObjectField(QString("AhrsInvalidPackets"), QString("count"), UAVObjectField::UINT8, AhrsInvalidPacketsElemNames, QStringList()) );
QStringList OpCrcErrorsElemNames;
OpCrcErrorsElemNames.append("0");
fields.append( new UAVObjectField(QString("OpCrcErrors"), QString("count"), UAVObjectField::UINT8, OpCrcErrorsElemNames, QStringList()) );
QStringList OpRetriesElemNames;
OpRetriesElemNames.append("0");
fields.append( new UAVObjectField(QString("OpRetries"), QString("count"), UAVObjectField::UINT8, OpRetriesElemNames, QStringList()) );
QStringList OpInvalidPacketsElemNames;
OpInvalidPacketsElemNames.append("0");
fields.append( new UAVObjectField(QString("OpInvalidPackets"), QString("count"), UAVObjectField::UINT8, OpInvalidPacketsElemNames, QStringList()) );
// Initialize object
initializeFields(fields, (quint8*)&data, NUMBYTES);
// Set the default field values
setDefaultFieldValues();
}
/**
* Get the default metadata for this object
*/
UAVObject::Metadata AhrsStatus2::getDefaultMetadata()
{
UAVObject::Metadata metadata;
metadata.flightAccess = ACCESS_READWRITE;
metadata.gcsAccess = ACCESS_READWRITE;
metadata.gcsTelemetryAcked = 0;
metadata.gcsTelemetryUpdateMode = UAVObject::UPDATEMODE_MANUAL;
metadata.gcsTelemetryUpdatePeriod = 0;
metadata.flightTelemetryAcked = 0;
metadata.flightTelemetryUpdateMode = UAVObject::UPDATEMODE_PERIODIC;
metadata.flightTelemetryUpdatePeriod = 1000;
metadata.loggingUpdateMode = UAVObject::UPDATEMODE_PERIODIC;
metadata.loggingUpdatePeriod = 1000;
return metadata;
}
/**
* Initialize object fields with the default values.
* If a default value is not specified the object fields
* will be initialized to zero.
*/
void AhrsStatus2::setDefaultFieldValues()
{
}
/**
* Get the object data fields
*/
AhrsStatus2::DataFields AhrsStatus2::getData()
{
QMutexLocker locker(mutex);
return data;
}
/**
* Set the object data fields
*/
void AhrsStatus2::setData(const DataFields& data)
{
QMutexLocker locker(mutex);
// Get metadata
Metadata mdata = getMetadata();
// Update object if the access mode permits
if ( mdata.gcsAccess == ACCESS_READWRITE )
{
this->data = data;
emit objectUpdatedAuto(this); // trigger object updated event
emit objectUpdated(this);
}
}
/**
* Create a clone of this object, a new instance ID must be specified.
* Do not use this function directly to create new instances, the
* UAVObjectManager should be used instead.
*/
UAVDataObject* AhrsStatus2::clone(quint32 instID)
{
AhrsStatus2* obj = new AhrsStatus2();
obj->initialize(instID, this->getMetaObject());
return obj;
}
/**
* Static function to retrieve an instance of the object.
*/
AhrsStatus2* AhrsStatus2::GetInstance(UAVObjectManager* objMngr, quint32 instID)
{
return dynamic_cast<AhrsStatus2*>(objMngr->getObject(AhrsStatus2::OBJID, instID));
}

View File

@ -1,118 +0,0 @@
/**
******************************************************************************
*
* @file ahrsstatus2.h
* @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2010.
* @see The GNU Public License (GPL) Version 3
* @addtogroup GCSPlugins GCS Plugins
* @{
* @addtogroup UAVObjectsPlugin UAVObjects Plugin
* @{
*
* @note Object definition file: ahrsstatus2.xml.
* This is an automatically generated file.
* DO NOT modify manually.
*
* @brief The UAVUObjects GCS plugin
*****************************************************************************/
/*
* This program 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 3 of the License, or
* (at your option) any later version.
*
* This program 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 this program; if not, write to the Free Software Foundation, Inc.,
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#ifndef AHRSSTATUS2_H
#define AHRSSTATUS2_H
#include "uavdataobject.h"
#include "uavobjectmanager.h"
class UAVOBJECTS_EXPORT AhrsStatus2: public UAVDataObject
{
Q_OBJECT
public:
// Field structure
typedef struct {
quint8 SerialNumber[8];
quint8 CPULoad;
quint8 IdleTimePerCyle;
quint8 RunningTimePerCyle;
quint8 DroppedUpdates;
quint8 AlgorithmSet;
quint8 CalibrationSet;
quint8 HomeSet;
quint8 LinkRunning;
quint8 AhrsKickstarts;
quint8 AhrsCrcErrors;
quint8 AhrsRetries;
quint8 AhrsInvalidPackets;
quint8 OpCrcErrors;
quint8 OpRetries;
quint8 OpInvalidPackets;
} __attribute__((packed)) DataFields;
// Field information
// Field SerialNumber information
/* Number of elements for field SerialNumber */
static const quint32 SERIALNUMBER_NUMELEM = 8;
// Field CPULoad information
// Field IdleTimePerCyle information
// Field RunningTimePerCyle information
// Field DroppedUpdates information
// Field AlgorithmSet information
/* Enumeration options for field AlgorithmSet */
typedef enum { ALGORITHMSET_FALSE=0, ALGORITHMSET_TRUE=1 } AlgorithmSetOptions;
// Field CalibrationSet information
/* Enumeration options for field CalibrationSet */
typedef enum { CALIBRATIONSET_FALSE=0, CALIBRATIONSET_TRUE=1 } CalibrationSetOptions;
// Field HomeSet information
/* Enumeration options for field HomeSet */
typedef enum { HOMESET_FALSE=0, HOMESET_TRUE=1 } HomeSetOptions;
// Field LinkRunning information
/* Enumeration options for field LinkRunning */
typedef enum { LINKRUNNING_FALSE=0, LINKRUNNING_TRUE=1 } LinkRunningOptions;
// Field AhrsKickstarts information
// Field AhrsCrcErrors information
// Field AhrsRetries information
// Field AhrsInvalidPackets information
// Field OpCrcErrors information
// Field OpRetries information
// Field OpInvalidPackets information
// Constants
static const quint32 OBJID = 805003662U;
static const QString NAME;
static const bool ISSINGLEINST = 1;
static const bool ISSETTINGS = 0;
static const quint32 NUMBYTES = sizeof(DataFields);
// Functions
AhrsStatus2();
DataFields getData();
void setData(const DataFields& data);
Metadata getDefaultMetadata();
UAVDataObject* clone(quint32 instID);
static AhrsStatus2* GetInstance(UAVObjectManager* objMngr, quint32 instID = 0);
private:
DataFields data;
void setDefaultFieldValues();
};
#endif // AHRSSTATUS2_H

View File

@ -1,251 +0,0 @@
##
##############################################################################
#
# @file ahrsstatus2.py
# @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2010.
# @brief Implementation of the AhrsStatus2 object. This file has been
# automatically generated by the UAVObjectGenerator.
#
# @note Object definition file: ahrsstatus2.xml.
# This is an automatically generated file.
# DO NOT modify manually.
#
# @see The GNU Public License (GPL) Version 3
#
#############################################################################/
#
# This program 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 3 of the License, or
# (at your option) any later version.
#
# This program 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 this program; if not, write to the Free Software Foundation, Inc.,
# 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#
import uavobject
import struct
from collections import namedtuple
# This is a list of instances of the data fields contained in this object
_fields = [ \
uavobject.UAVObjectField(
'SerialNumber',
'B',
8,
[
'0',
'1',
'2',
'3',
'4',
'5',
'6',
'7',
],
{
}
),
uavobject.UAVObjectField(
'CPULoad',
'B',
1,
[
'0',
],
{
}
),
uavobject.UAVObjectField(
'IdleTimePerCyle',
'B',
1,
[
'0',
],
{
}
),
uavobject.UAVObjectField(
'RunningTimePerCyle',
'B',
1,
[
'0',
],
{
}
),
uavobject.UAVObjectField(
'DroppedUpdates',
'B',
1,
[
'0',
],
{
}
),
uavobject.UAVObjectField(
'AlgorithmSet',
'b',
1,
[
'0',
],
{
'0' : 'FALSE',
'1' : 'TRUE',
}
),
uavobject.UAVObjectField(
'CalibrationSet',
'b',
1,
[
'0',
],
{
'0' : 'FALSE',
'1' : 'TRUE',
}
),
uavobject.UAVObjectField(
'HomeSet',
'b',
1,
[
'0',
],
{
'0' : 'FALSE',
'1' : 'TRUE',
}
),
uavobject.UAVObjectField(
'LinkRunning',
'b',
1,
[
'0',
],
{
'0' : 'FALSE',
'1' : 'TRUE',
}
),
uavobject.UAVObjectField(
'AhrsKickstarts',
'B',
1,
[
'0',
],
{
}
),
uavobject.UAVObjectField(
'AhrsCrcErrors',
'B',
1,
[
'0',
],
{
}
),
uavobject.UAVObjectField(
'AhrsRetries',
'B',
1,
[
'0',
],
{
}
),
uavobject.UAVObjectField(
'AhrsInvalidPackets',
'B',
1,
[
'0',
],
{
}
),
uavobject.UAVObjectField(
'OpCrcErrors',
'B',
1,
[
'0',
],
{
}
),
uavobject.UAVObjectField(
'OpRetries',
'B',
1,
[
'0',
],
{
}
),
uavobject.UAVObjectField(
'OpInvalidPackets',
'B',
1,
[
'0',
],
{
}
),
]
class AhrsStatus2(uavobject.UAVObject):
## Object constants
OBJID = 805003662
NAME = "AhrsStatus2"
METANAME = "AhrsStatus2Meta"
ISSINGLEINST = 1
ISSETTINGS = 0
def __init__(self):
uavobject.UAVObject.__init__(self,
self.OBJID,
self.NAME,
self.METANAME,
0,
self.ISSINGLEINST)
for f in _fields:
self.add_field(f)
def __str__(self):
s = ("0x%08X (%10u) %-30s %3u bytes format '%s'\n"
% (self.OBJID, self.OBJID, self.NAME, self.get_struct().size, self.get_struct().format))
for f in self.get_tuple()._fields:
s += ("\t%s\n" % f)
return (s)
def main():
# Instantiate the object and dump out some interesting info
x = AhrsStatus2()
print (x)
if __name__ == "__main__":
#import pdb ; pdb.run('main()')
main()

View File

@ -48,8 +48,7 @@ HEADERS += uavobjects_global.h \
velocityactual.h \ velocityactual.h \
guidancesettings.h \ guidancesettings.h \
positiondesired.h \ positiondesired.h \
attitudesettings.h \ attitudesettings.h
ahrsstatus2.h
SOURCES += uavobject.cpp \ SOURCES += uavobject.cpp \
uavmetaobject.cpp \ uavmetaobject.cpp \
@ -95,6 +94,5 @@ SOURCES += uavobject.cpp \
velocityactual.cpp \ velocityactual.cpp \
guidancesettings.cpp \ guidancesettings.cpp \
positiondesired.cpp \ positiondesired.cpp \
attitudesettings.cpp \ attitudesettings.cpp
ahrsstatus2.cpp
OTHER_FILES += UAVObjects.pluginspec OTHER_FILES += UAVObjects.pluginspec

View File

@ -36,7 +36,6 @@
#include "ahrscalibration.h" #include "ahrscalibration.h"
#include "ahrssettings.h" #include "ahrssettings.h"
#include "ahrsstatus.h" #include "ahrsstatus.h"
#include "ahrsstatus2.h"
#include "attitudeactual.h" #include "attitudeactual.h"
#include "attitudedesired.h" #include "attitudedesired.h"
#include "attituderaw.h" #include "attituderaw.h"
@ -83,7 +82,6 @@ void UAVObjectsInitialize(UAVObjectManager* objMngr)
objMngr->registerObject( new AHRSCalibration() ); objMngr->registerObject( new AHRSCalibration() );
objMngr->registerObject( new AHRSSettings() ); objMngr->registerObject( new AHRSSettings() );
objMngr->registerObject( new AhrsStatus() ); objMngr->registerObject( new AhrsStatus() );
objMngr->registerObject( new AhrsStatus2() );
objMngr->registerObject( new AttitudeActual() ); objMngr->registerObject( new AttitudeActual() );
objMngr->registerObject( new AttitudeDesired() ); objMngr->registerObject( new AttitudeDesired() );
objMngr->registerObject( new AttitudeRaw() ); objMngr->registerObject( new AttitudeRaw() );

View File

@ -1,16 +1,24 @@
<xml> <xml>
<object name="AhrsStatus" singleinstance="true" settings="false"> <object name="AhrsStatus" singleinstance="true" settings="false">
<description>Status for the @ref AHRSCommsModule, including communication errors</description> <description>Status for the @ref AHRSCommsModule, including communication errors</description>
<field name="SerialNumber" units="n/a" type="uint8" elements="25"/> <field name="SerialNumber" units="n/a" type="uint8" elements="8"/>
<field name="CPULoad" units="count" type="uint8" elements="1"/> <field name="CPULoad" units="count" type="uint8" elements="1"/>
<field name="IdleTimePerCyle" units="10x ms" type="uint8" elements="1"/> <field name="IdleTimePerCyle" units="10x ms" type="uint8" elements="1"/>
<field name="RunningTimePerCyle" units="10x ms" type="uint8" elements="1"/> <field name="RunningTimePerCyle" units="10x ms" type="uint8" elements="1"/>
<field name="DroppedUpdates" units="count" type="uint8" elements="1"/> <field name="DroppedUpdates" units="count" type="uint8" elements="1"/>
<field name="CommErrors" units="count" type="uint8" elementnames="Algorithm,Update,AttitudeRaw,HomeLocation,Calibration"/>
<field name="Initialized" units="" type="enum" elements="1" options="FALSE,TRUE"/>
<field name="AlgorithmSet" units="" type="enum" elements="1" options="FALSE,TRUE"/> <field name="AlgorithmSet" units="" type="enum" elements="1" options="FALSE,TRUE"/>
<field name="CalibrationSet" units="" type="enum" elements="1" options="FALSE,TRUE"/> <field name="CalibrationSet" units="" type="enum" elements="1" options="FALSE,TRUE"/>
<field name="HomeSet" units="" type="enum" elements="1" options="FALSE,TRUE"/> <field name="HomeSet" units="" type="enum" elements="1" options="FALSE,TRUE"/>
<field name="LinkRunning" units="" type="enum" elements="1" options="FALSE,TRUE"/>
<field name="AhrsKickstarts" units="count" type="uint8" elements="1"/>
<field name="AhrsCrcErrors" units="count" type="uint8" elements="1"/>
<field name="AhrsRetries" units="count" type="uint8" elements="1"/>
<field name="AhrsInvalidPackets" units="count" type="uint8" elements="1"/>
<field name="OpCrcErrors" units="count" type="uint8" elements="1"/>
<field name="OpRetries" units="count" type="uint8" elements="1"/>
<field name="OpInvalidPackets" units="count" type="uint8" elements="1"/>
<access gcs="readwrite" flight="readwrite"/> <access gcs="readwrite" flight="readwrite"/>
<telemetrygcs acked="false" updatemode="manual" period="0"/> <telemetrygcs acked="false" updatemode="manual" period="0"/>
<telemetryflight acked="false" updatemode="periodic" period="1000"/> <telemetryflight acked="false" updatemode="periodic" period="1000"/>

View File

@ -1,27 +0,0 @@
<xml>
<object name="AhrsStatus2" singleinstance="true" settings="false">
<description>Status for the @ref AHRSCommsModule, including communication errors</description>
<field name="SerialNumber" units="n/a" type="uint8" elements="8"/>
<field name="CPULoad" units="count" type="uint8" elements="1"/>
<field name="IdleTimePerCyle" units="10x ms" type="uint8" elements="1"/>
<field name="RunningTimePerCyle" units="10x ms" type="uint8" elements="1"/>
<field name="DroppedUpdates" units="count" type="uint8" elements="1"/>
<field name="AlgorithmSet" units="" type="enum" elements="1" options="FALSE,TRUE"/>
<field name="CalibrationSet" units="" type="enum" elements="1" options="FALSE,TRUE"/>
<field name="HomeSet" units="" type="enum" elements="1" options="FALSE,TRUE"/>
<field name="LinkRunning" units="" type="enum" elements="1" options="FALSE,TRUE"/>
<field name="AhrsKickstarts" units="count" type="uint8" elements="1"/>
<field name="AhrsCrcErrors" units="count" type="uint8" elements="1"/>
<field name="AhrsRetries" units="count" type="uint8" elements="1"/>
<field name="AhrsInvalidPackets" units="count" type="uint8" elements="1"/>
<field name="OpCrcErrors" units="count" type="uint8" elements="1"/>
<field name="OpRetries" units="count" type="uint8" elements="1"/>
<field name="OpInvalidPackets" units="count" type="uint8" elements="1"/>
<access gcs="readwrite" flight="readwrite"/>
<telemetrygcs acked="false" updatemode="manual" period="0"/>
<telemetryflight acked="false" updatemode="periodic" period="1000"/>
<logging updatemode="periodic" period="1000"/>
</object>
</xml>