diff --git a/conf/airframes/CDW/cdw_classix.xml b/conf/airframes/CDW/cdw_classix.xml
index a3fb9fd86a..e107c0fdad 100644
--- a/conf/airframes/CDW/cdw_classix.xml
+++ b/conf/airframes/CDW/cdw_classix.xml
@@ -216,9 +216,9 @@
-
-
-
+
+
+
diff --git a/conf/airframes/CDW/cdw_twoseastwenty.xml b/conf/airframes/CDW/cdw_twoseastwenty.xml
index e6bc58c9d3..333d4e24f1 100644
--- a/conf/airframes/CDW/cdw_twoseastwenty.xml
+++ b/conf/airframes/CDW/cdw_twoseastwenty.xml
@@ -36,10 +36,10 @@
-
-
-
-
+
+
+
+
@@ -70,10 +70,10 @@
-
-
-
-
+
+
+
+
diff --git a/conf/airframes/CDW/cdw_yapa_xsens.xml b/conf/airframes/CDW/cdw_yapa_xsens.xml
index e34c994ff9..9253102bb7 100644
--- a/conf/airframes/CDW/cdw_yapa_xsens.xml
+++ b/conf/airframes/CDW/cdw_yapa_xsens.xml
@@ -25,10 +25,10 @@
-
-
-
-
+
+
+
+
diff --git a/conf/airframes/examples/microjet_imu_xsens.xml b/conf/airframes/examples/microjet_imu_xsens.xml
index 1ab3a1316b..92d91d3b86 100644
--- a/conf/airframes/examples/microjet_imu_xsens.xml
+++ b/conf/airframes/examples/microjet_imu_xsens.xml
@@ -21,10 +21,10 @@
-
-
-
-
+
+
+
+
diff --git a/conf/airframes/examples/microjet_lisa_m_xsens.xml b/conf/airframes/examples/microjet_lisa_m_xsens.xml
index ee9ddd2269..7278c17917 100644
--- a/conf/airframes/examples/microjet_lisa_m_xsens.xml
+++ b/conf/airframes/examples/microjet_lisa_m_xsens.xml
@@ -21,10 +21,10 @@
-
-
-
-
+
+
+
+
diff --git a/conf/firmwares/subsystems/fixedwing/imu_xsens.makefile b/conf/firmwares/subsystems/fixedwing/imu_xsens.makefile
index b18ab3bd5f..67d4ac948e 100644
--- a/conf/firmwares/subsystems/fixedwing/imu_xsens.makefile
+++ b/conf/firmwares/subsystems/fixedwing/imu_xsens.makefile
@@ -1,68 +1 @@
-# Hey Emacs, this is a -*- makefile -*-
-
-# XSens Mti just providing IMU measurements
-
-#
-#
-#
-#
-#
-#
-#
-#
-#
-#
-#
-#
-#
-#
-#
-#
-#
-#
-#
-#
-#
-#
-#
-#
-#
-#
-#
-#
-#
-#
-#
-#
-#
-#
-#
-#
-#
-#
-#
-#
-#
-#
-#
-#
-#
-#
-
-
-#########################################
-## IMU
-
-ap.CFLAGS += -DUSE_IMU
-ap.CFLAGS += -DIMU_TYPE_H=\"modules/ins/ins_xsens.h\"
-ap.srcs += $(SRC_MODULES)/ins/ins_xsens.c
-ap.srcs += $(SRC_SUBSYSTEMS)/imu.c
-
-ifndef XSENS_UART_BAUD
- XSENS_UART_BAUD = B115200
-endif
-
-ap.CFLAGS += -DUSE_UART$(XSENS_UART_NR)
-ap.CFLAGS += -DINS_LINK=uart$(XSENS_UART_NR)
-ap.CFLAGS += -DUART$(XSENS_UART_NR)_BAUD=$(XSENS_UART_BAUD)
-ap.CFLAGS += -DXSENS_OUTPUT_MODE=0x1836
+$(error Error: The imu xsens subsystem has been converted to a module, replace by )
diff --git a/conf/firmwares/subsystems/fixedwing/ins_xsens.makefile b/conf/firmwares/subsystems/fixedwing/ins_xsens.makefile
index c243ad9f96..038ff5b548 100644
--- a/conf/firmwares/subsystems/fixedwing/ins_xsens.makefile
+++ b/conf/firmwares/subsystems/fixedwing/ins_xsens.makefile
@@ -1,70 +1 @@
-# Hey Emacs, this is a -*- makefile -*-
-
-# XSens Mti-G
-
-#
-#
-#
-#
-
-
-
-#########################################
-## ATTITUDE
-
-ap.CFLAGS += -DUSE_INS_MODULE
-
-# AHRS Results
-ap.CFLAGS += -DINS_TYPE_H=\"modules/ins/ins_xsens.h\"
-
-ifndef XSENS_UART_BAUD
- XSENS_UART_BAUD = B115200
-endif
-
-#B230400
-#B115200
-
-ap.CFLAGS += -DUSE_UART$(XSENS_UART_NR)
-ap.CFLAGS += -DINS_LINK=uart$(XSENS_UART_NR)
-ap.CFLAGS += -DUART$(XSENS_UART_NR)_BAUD=$(XSENS_UART_BAUD)
-ap.CFLAGS += -DXSENS_OUTPUT_MODE=0x1836
-ap.srcs += $(SRC_SUBSYSTEMS)/ins.c
-ap.srcs += $(SRC_MODULES)/ins/ins_xsens.c
-ap.CFLAGS += -DAHRS_TRIGGERED_ATTITUDE_LOOP
-
-
-
-#########################################
-## GPS
-
-ap.CFLAGS += -DUSE_GPS_XSENS
-ap.CFLAGS += -DUSE_GPS_XSENS_RAW_DATA
-ap.CFLAGS += -DGPS_NB_CHANNELS=16
-ap.CFLAGS += -DUSE_GPS
-ap.CFLAGS += -DGPS_TYPE_H=\"modules/ins/ins_xsens.h\"
-ap.srcs += $(SRC_SUBSYSTEMS)/gps.c
-
-
-#########################################
-## Simulator
-SIM_TARGETS = sim nps
-
-ifneq (,$(findstring $(TARGET),$(SIM_TARGETS)))
-
-$(TARGET).CFLAGS += -DAHRS_TYPE_H=\"subsystems/ahrs/ahrs_sim.h\"
-$(TARGET).CFLAGS += -DUSE_AHRS
-
-$(TARGET).srcs += $(SRC_SUBSYSTEMS)/ahrs.c
-$(TARGET).srcs += $(SRC_SUBSYSTEMS)/ahrs/ahrs_sim.c
-
-$(TARGET).srcs += $(SRC_SUBSYSTEMS)/ins.c
-$(TARGET).CFLAGS += -DINS_TYPE_H=\"subsystems/ins/ins_gps_passthrough_utm.h\"
-$(TARGET).srcs += $(SRC_SUBSYSTEMS)/ins/ins_gps_passthrough_utm.c
-
-$(TARGET).CFLAGS += -DUSE_GPS
-$(TARGET).CFLAGS += -DGPS_TYPE_H=\"subsystems/gps/gps_sim.h\"
-$(TARGET).srcs += $(SRC_SUBSYSTEMS)/gps/gps_sim.c
-$(TARGET).srcs += $(SRC_SUBSYSTEMS)/gps.c
-
-endif
-
+$(error Error: The ins xsens subsystem has been converted to a module, replace by )
diff --git a/conf/firmwares/subsystems/shared/ins_xsens700.makefile b/conf/firmwares/subsystems/shared/ins_xsens700.makefile
index 58be4d9d3f..bf4eb71b37 100644
--- a/conf/firmwares/subsystems/shared/ins_xsens700.makefile
+++ b/conf/firmwares/subsystems/shared/ins_xsens700.makefile
@@ -1,64 +1 @@
-# Hey Emacs, this is a -*- makefile -*-
-
-# XSens Mti-G
-
-#
-#
-#
-#
-
-
-#########################################
-## ATTITUDE
-
-ap.CFLAGS += -DUSE_INS_MODULE
-
-# AHRS Results
-ap.CFLAGS += -DINS_TYPE_H=\"modules/ins/ins_xsens.h\"
-
-ifndef XSENS_UART_BAUD
- XSENS_UART_BAUD = B115200
-endif
-
-ap.CFLAGS += -DUSE_UART$(XSENS_UART_NR)
-ap.CFLAGS += -DINS_LINK=uart$(XSENS_UART_NR)
-ap.CFLAGS += -DUART$(XSENS_UART_NR)_BAUD=$(XSENS_UART_BAUD)
-ap.CFLAGS += -DXSENS_OUTPUT_MODE=0x1836
-ap.srcs += $(SRC_SUBSYSTEMS)/ins.c
-ap.srcs += $(SRC_MODULES)/ins/ins_xsens700.c
-ap.CFLAGS += -DAHRS_TRIGGERED_ATTITUDE_LOOP
-
-
-#########################################
-## GPS
-
-ap.CFLAGS += -DUSE_GPS_XSENS
-ap.CFLAGS += -DGPS_NB_CHANNELS=50
-ap.CFLAGS += -DUSE_GPS
-ap.CFLAGS += -DGPS_TYPE_H=\"modules/ins/ins_xsens.h\"
-ap.srcs += $(SRC_SUBSYSTEMS)/gps.c
-
-
-#########################################
-## Simulator
-SIM_TARGETS = sim nps
-
-ifneq (,$(findstring $(TARGET),$(SIM_TARGETS)))
-
-$(TARGET).CFLAGS += -DAHRS_TYPE_H=\"subsystems/ahrs/ahrs_sim.h\"
-$(TARGET).CFLAGS += -DUSE_AHRS
-
-$(TARGET).srcs += $(SRC_SUBSYSTEMS)/ahrs.c
-$(TARGET).srcs += $(SRC_SUBSYSTEMS)/ahrs/ahrs_sim.c
-
-$(TARGET).srcs += $(SRC_SUBSYSTEMS)/ins.c
-$(TARGET).CFLAGS += -DINS_TYPE_H=\"subsystems/ins/ins_gps_passthrough_utm.h\"
-$(TARGET).srcs += $(SRC_SUBSYSTEMS)/ins/ins_gps_passthrough_utm.c
-
-$(TARGET).CFLAGS += -DUSE_GPS
-$(TARGET).CFLAGS += -DGPS_TYPE_H=\"subsystems/gps/gps_sim.h\"
-$(TARGET).srcs += $(SRC_SUBSYSTEMS)/gps/gps_sim.c
-$(TARGET).srcs += $(SRC_SUBSYSTEMS)/gps.c
-
-endif
-
+$(error Error: The ins xsens700 subsystem has been converted to a module, replace by )
diff --git a/conf/modules/imu_xsens.xml b/conf/modules/imu_xsens.xml
new file mode 100644
index 0000000000..8e464f0d13
--- /dev/null
+++ b/conf/modules/imu_xsens.xml
@@ -0,0 +1,49 @@
+
+
+
+
+
+ XSens IMU
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ ap.CFLAGS += -DIMU_TYPE_H=\"modules/ins/imu_xsens.h\"
+
+
+
+
+
+
+
+
+ sim.CFLAGS += -DAHRS_TYPE_H=\"subsystems/ahrs/ahrs_sim.h\"
+
+
+
+
+
+
+
+ nps.CFLAGS += -DIMU_TYPE_H=\"subsystems/imu/imu_nps.h\"
+
+
+
+
diff --git a/conf/modules/ins_xsens.xml b/conf/modules/ins_xsens.xml
index 6ec0d450ef..4c93bdcfa8 100644
--- a/conf/modules/ins_xsens.xml
+++ b/conf/modules/ins_xsens.xml
@@ -1,16 +1,77 @@
-
+
- XSens
+
+ XSens Mti-G INS
+
+
+
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ ap.CFLAGS += -DGPS_TYPE_H=\"modules/ins/ins_xsens.h\"
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ sim.CFLAGS += -DAHRS_TYPE_H=\"subsystems/ahrs/ahrs_sim.h\"
+ sim.CFLAGS += -DINS_TYPE_H=\"subsystems/ins/ins_gps_passthrough_utm.h\"
+ sim.CFLAGS += -DGPS_TYPE_H=\"subsystems/gps/gps_sim.h\"
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ nps.CFLAGS += -DINS_TYPE_H=\"subsystems/ins/ins_gps_passthrough_utm.h\"
+ nps.CFLAGS += -DGPS_TYPE_H=\"subsystems/gps/gps_sim_nps.h\"
+
diff --git a/conf/modules/ins_xsens700.xml b/conf/modules/ins_xsens700.xml
new file mode 100644
index 0000000000..4247003015
--- /dev/null
+++ b/conf/modules/ins_xsens700.xml
@@ -0,0 +1,76 @@
+
+
+
+
+
+ XSens Mti-G 700 INS
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ ap.CFLAGS += -DGPS_TYPE_H=\"modules/ins/ins_xsens700.h\"
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ sim.CFLAGS += -DAHRS_TYPE_H=\"subsystems/ahrs/ahrs_sim.h\"
+ sim.CFLAGS += -DINS_TYPE_H=\"subsystems/ins/ins_gps_passthrough_utm.h\"
+ sim.CFLAGS += -DGPS_TYPE_H=\"subsystems/gps/gps_sim.h\"
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ nps.CFLAGS += -DINS_TYPE_H=\"subsystems/ins/ins_gps_passthrough_utm.h\"
+ nps.CFLAGS += -DGPS_TYPE_H=\"subsystems/gps/gps_sim_nps.h\"
+
+
+
+
diff --git a/conf/modules/ins_xsens_MTiG_Uart0.xml b/conf/modules/ins_xsens_MTiG_Uart0.xml
deleted file mode 100644
index 0438e3776a..0000000000
--- a/conf/modules/ins_xsens_MTiG_Uart0.xml
+++ /dev/null
@@ -1,26 +0,0 @@
-
-
-
-
- XSens MTiG
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/conf/modules/ins_xsens_MTi_Uart0.xml b/conf/modules/ins_xsens_MTi_Uart0.xml
deleted file mode 100644
index 8bcb60694c..0000000000
--- a/conf/modules/ins_xsens_MTi_Uart0.xml
+++ /dev/null
@@ -1,24 +0,0 @@
-
-
-
-
- XSens MTi
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/sw/airborne/modules/ins/imu_xsens.c b/sw/airborne/modules/ins/imu_xsens.c
new file mode 100644
index 0000000000..37c186dd8f
--- /dev/null
+++ b/sw/airborne/modules/ins/imu_xsens.c
@@ -0,0 +1,96 @@
+/*
+ * Copyright (C) 2003 Pascal Brisset, Antoine Drouin
+ *
+ * This file is part of paparazzi.
+ *
+ * paparazzi is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * paparazzi is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with paparazzi; see the file COPYING. If not, write to
+ * the Free Software Foundation, 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ */
+
+/** @file imu_xsens.c
+ * XSENS to just provide IMU measurements.
+ * For use with an external AHRS algorithm.
+ */
+
+#include "imu_xsens.h"
+#include "xsens.h"
+#include "xsens_common.h"
+
+#include "generated/airframe.h"
+
+#include "mcu_periph/sys_time.h"
+#include "subsystems/abi.h"
+
+static void handle_ins_msg(void);
+
+void imu_xsens_init(void)
+{
+ xsens_init();
+}
+
+void imu_xsens_event(void)
+{
+ xsens_event();
+ if (xsens.msg_received) {
+ parse_xsens_msg();
+ handle_ins_msg();
+ xsens.msg_received = FALSE;
+ }
+}
+
+static void handle_ins_msg(void)
+{
+ uint32_t now_ts = get_sys_time_usec();
+#ifdef XSENS_BACKWARDS
+ if (xsens.gyro_available) {
+ RATES_ASSIGN(imu.gyro_unscaled, -RATE_BFP_OF_REAL(xsens.gyro.p), -RATE_BFP_OF_REAL(xsens.gyro.q), RATE_BFP_OF_REAL(xsens.gyro.r));
+ xsens.gyro_available = FALSE;
+ imu_scale_gyro(&imu);
+ AbiSendMsgIMU_GYRO_INT32(IMU_XSENS_ID, now_ts, &imu.gyro);
+ }
+ if (xsens.accel_available) {
+ VECT3_ASSIGN(imu.accel_unscaled, -ACCEL_BFP_OF_REAL(xsens.accel.ax), -ACCEL_BFP_OF_REAL(xsens.accel.ay), ACCEL_BFP_OF_REAL(xsens.accel.az));
+ xsens.accel_available = FALSE;
+ imu_scale_accel(&imu);
+ AbiSendMsgIMU_ACCEL_INT32(IMU_XSENS_ID, now_ts, &imu.accel);
+ }
+ if (xsens.mag_available) {
+ VECT3_ASSIGN(imu.mag_unscaled, -MAG_BFP_OF_REAL(xsens.mag.mx), -MAG_BFP_OF_REAL(xsens.mag.my), MAG_BFP_OF_REAL(xsens.mag.mz));
+ xsens.mag_available = FALSE;
+ imu_scale_mag(&imu);
+ AbiSendMsgIMU_MAG_INT32(IMU_XSENS_ID, now_ts, &imu.mag);
+ }
+#else
+ if (xsens.gyro_available) {
+ RATES_BFP_OF_REAL(imu.gyro_unscaled, xsens.gyro);
+ xsens.gyro_available = FALSE;
+ imu_scale_gyro(&imu);
+ AbiSendMsgIMU_GYRO_INT32(IMU_XSENS_ID, now_ts, &imu.gyro);
+ }
+ if (xsens.accel_available) {
+ ACCELS_BFP_OF_REAL(imu.accel_unscaled, xsens.accel);
+ xsens.accel_available = FALSE;
+ imu_scale_accel(&imu);
+ AbiSendMsgIMU_ACCEL_INT32(IMU_XSENS_ID, now_ts, &imu.accel);
+ }
+ if (xsens.mag_available) {
+ MAGS_BFP_OF_REAL(imu.mag_unscaled, xsens.mag);
+ xsens.mag_available = FALSE;
+ imu_scale_mag(&imu);
+ AbiSendMsgIMU_MAG_INT32(IMU_XSENS_ID, now_ts, &imu.mag);
+ }
+#endif /* XSENS_BACKWARDS */
+}
diff --git a/sw/airborne/modules/ins/imu_xsens.h b/sw/airborne/modules/ins/imu_xsens.h
new file mode 100644
index 0000000000..d347515a52
--- /dev/null
+++ b/sw/airborne/modules/ins/imu_xsens.h
@@ -0,0 +1,45 @@
+/*
+ * Copyright (C) 2010 ENAC
+ *
+ * This file is part of paparazzi.
+ *
+ * paparazzi is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * paparazzi is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with paparazzi; see the file COPYING. If not, write to
+ * the Free Software Foundation, 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ */
+
+/**
+ * @file modules/ins/imu_xsens.h
+ *
+ * XSENS to just provide IMU measurements.
+ * For use with an external AHRS algorithm.
+ */
+
+#ifndef IMU_XSENS_H
+#define IMU_XSENS_H
+
+#include "std.h"
+
+#include "subsystems/imu.h"
+#include "xsens.h"
+
+extern void imu_xsens_init(void);
+extern void imu_xsens_event(void);
+
+#define ImuEvent imu_xsens_event
+#define imu_impl_init imu_xsens_init
+#define imu_periodic xsens_periodic
+
+#endif
diff --git a/sw/airborne/modules/ins/ins_xsens.c b/sw/airborne/modules/ins/ins_xsens.c
index f24b6d5f0c..33feafd5ad 100644
--- a/sw/airborne/modules/ins/ins_xsens.c
+++ b/sw/airborne/modules/ins/ins_xsens.c
@@ -21,244 +21,28 @@
*/
/** @file ins_xsens.c
- * Parser for the Xsens protocol.
+ * Xsens as a full INS solution
*/
-#include "ins_module.h"
#include "ins_xsens.h"
+#include "xsens_common.h"
#include "subsystems/ins.h"
-#include
-
#include "generated/airframe.h"
#include "mcu_periph/sys_time.h"
-#include "pprzlink/messages.h"
+#include "subsystems/abi.h"
+#include "state.h"
#if USE_GPS_XSENS
#if !USE_GPS
#error "USE_GPS needs to be 1 to use the Xsens GPS!"
#endif
#include "subsystems/gps.h"
-#include "subsystems/abi.h"
-#include "math/pprz_geodetic_wgs84.h"
#include "math/pprz_geodetic_float.h"
#include "subsystems/navigation/common_nav.h" /* needed for nav_utm_zone0 */
-bool_t gps_xsens_msg_available;
#endif
-// positions
-INS_FORMAT ins_x;
-INS_FORMAT ins_y;
-INS_FORMAT ins_z;
-
-// velocities
-INS_FORMAT ins_vx;
-INS_FORMAT ins_vy;
-INS_FORMAT ins_vz;
-
-// body angles
-INS_FORMAT ins_phi;
-INS_FORMAT ins_theta;
-INS_FORMAT ins_psi;
-
-// angle rates
-INS_FORMAT ins_p;
-INS_FORMAT ins_q;
-INS_FORMAT ins_r;
-
-// accelerations
-INS_FORMAT ins_ax;
-INS_FORMAT ins_ay;
-INS_FORMAT ins_az;
-
-// magnetic
-INS_FORMAT ins_mx;
-INS_FORMAT ins_my;
-INS_FORMAT ins_mz;
-
-#if USE_INS_MODULE
-float ins_pitch_neutral;
-float ins_roll_neutral;
-#endif
-
-
-//////////////////////////////////////////////////////////////////////////////////////////
-//
-// XSens Specific
-//
-
-volatile uint8_t ins_msg_received;
-
-#define XsensInitCheksum() { send_ck = 0; }
-#define XsensUpdateChecksum(c) { send_ck += c; }
-
-#define XsensSend1(c) { uint8_t i8=c; InsUartSend1(i8); XsensUpdateChecksum(i8); }
-#define XsensSend1ByAddr(x) { XsensSend1(*x); }
-#define XsensSend2ByAddr(x) { XsensSend1(*(x+1)); XsensSend1(*x); }
-#define XsensSend4ByAddr(x) { XsensSend1(*(x+3)); XsensSend1(*(x+2)); XsensSend1(*(x+1)); XsensSend1(*x); }
-
-#define XsensHeader(msg_id, len) { \
- InsUartSend1(XSENS_START); \
- XsensInitCheksum(); \
- XsensSend1(XSENS_BID); \
- XsensSend1(msg_id); \
- XsensSend1(len); \
- }
-#define XsensTrailer() { uint8_t i8=0x100-send_ck; InsUartSend1(i8); }
-
-/** Includes macros generated from xsens_MTi-G.xml */
-#include "xsens_protocol.h"
-
-
-#define XSENS_MAX_PAYLOAD 254
-uint8_t xsens_msg_buf[XSENS_MAX_PAYLOAD];
-
-/* output mode : calibrated, orientation, position, velocity, status
- * -----------
- *
- * bit 0 temp
- * bit 1 calibrated
- * bit 2 orentation
- * bit 3 aux
- *
- * bit 4 position
- * bit 5 velocity
- * bit 6-7 Reserved
- *
- * bit 8-10 Reserved
- * bit 11 status
- *
- * bit 12 GPS PVT+baro
- * bit 13 Reserved
- * bit 14 Raw
- * bit 15 Reserved
- */
-
-#ifndef XSENS_OUTPUT_MODE
-#define XSENS_OUTPUT_MODE 0x1836
-#endif
-/* output settings : timestamp, euler, acc, rate, mag, float, no aux, lla, m/s, NED
- * -----------
- *
- * bit 01 0=none, 1=sample counter, 2=utc, 3=sample+utc
- * bit 23 0=quaternion, 1=euler, 2=DCM
- *
- * bit 4 1=disable acc output
- * bit 5 1=disable gyro output
- * bit 6 1=disable magneto output
- * bit 7 Reserved
- *
- * bit 89 0=float, 1=fixedpoint12.20, 2=fixedpoint16.32
- * bit 10 1=disable aux analog 1
- * bit 11 1=disable aux analog 2
- *
- * bit 12-15 0-only: 14-16 WGS84
- *
- * bit 16-19 0-only: 16-18 m/s XYZ
- *
- * bit 20-23 Reserved
- *
- * bit 24-27 Reseverd
- *
- * bit 28-30 Reseverd
- * bit 31 0=X-North-Z-Up, 1=North-East-Down
- */
-#ifndef XSENS_OUTPUT_SETTINGS
-#define XSENS_OUTPUT_SETTINGS 0x80000C05
-#endif
-
-#define UNINIT 0
-#define GOT_START 1
-#define GOT_BID 2
-#define GOT_MID 3
-#define GOT_LEN 4
-#define GOT_DATA 5
-#define GOT_CHECKSUM 6
-
-// FIXME Debugging Only
-#include "mcu_periph/uart.h"
-#include "pprzlink/messages.h"
-#include "subsystems/datalink/downlink.h"
-
-
-uint8_t xsens_errorcode;
-uint8_t xsens_msg_status;
-uint16_t xsens_time_stamp;
-uint16_t xsens_output_mode;
-uint32_t xsens_output_settings;
-
-
-float xsens_declination = 0;
-float xsens_gps_arm_x = 0;
-float xsens_gps_arm_y = 0;
-float xsens_gps_arm_z = 0;
-
-#if USE_GPS_XSENS
-struct LlaCoor_f lla_f;
-struct UtmCoor_f utm_f;
-#endif
-
-struct XsensTime xsens_time;
-
-static uint8_t xsens_id;
-static uint8_t xsens_status;
-static uint8_t xsens_len;
-static uint8_t xsens_msg_idx;
-static uint8_t ck;
-uint8_t send_ck;
-
-volatile int xsens_configured = 0;
-
-void xsens_init(void);
-
-void xsens_init(void)
-{
-
- xsens_status = UNINIT;
- xsens_configured = 20;
-
-#if USE_INS_MODULE
- ins_pitch_neutral = INS_PITCH_NEUTRAL_DEFAULT;
- ins_roll_neutral = INS_ROLL_NEUTRAL_DEFAULT;
-#endif
-
- xsens_msg_status = 0;
- xsens_time_stamp = 0;
- xsens_output_mode = XSENS_OUTPUT_MODE;
- xsens_output_settings = XSENS_OUTPUT_SETTINGS;
-}
-
-#if USE_IMU
-struct ImuXsens imu_xsens;
-
-void imu_impl_init(void)
-{
- xsens_init();
- imu_xsens.gyro_available = FALSE;
- imu_xsens.accel_available = FALSE;
- imu_xsens.mag_available = FALSE;
-}
-
-void imu_periodic(void)
-{
- xsens_periodic();
-}
-#endif /* USE_IMU */
-
-#if USE_INS_MODULE
-void ins_xsens_update_gps(struct GpsState *gps_s);
-
-void ins_xsens_init(void)
-{
- struct UtmCoor_f utm0 = { nav_utm_north0, nav_utm_east0, 0., nav_utm_zone0 };
- stateSetLocalUtmOrigin_f(&utm0);
- stateSetPositionUtm_f(&utm0);
-
- xsens_init();
-}
-
-#include "subsystems/abi.h"
/** ABI binding for gps data.
* Used for GPS ABI messages.
*/
@@ -267,12 +51,15 @@ void ins_xsens_init(void)
#endif
PRINT_CONFIG_VAR(INS_XSENS_GPS_ID)
static abi_event gps_ev;
+
+float ins_pitch_neutral;
+float ins_roll_neutral;
+
+static void handle_ins_msg(void);
+static void update_state_interface(void);
static void gps_cb(uint8_t sender_id __attribute__((unused)),
uint32_t stamp __attribute__((unused)),
- struct GpsState *gps_s)
-{
- ins_xsens_update_gps(gps_s);
-}
+ struct GpsState *gps_s);
void ins_xsens_register(void)
{
@@ -280,7 +67,31 @@ void ins_xsens_register(void)
AbiBindMsgGPS(INS_XSENS_GPS_ID, &gps_ev, gps_cb);
}
-void ins_xsens_update_gps(struct GpsState *gps_s)
+void ins_xsens_init(void)
+{
+ xsens_init();
+
+ ins_pitch_neutral = INS_PITCH_NEUTRAL_DEFAULT;
+ ins_roll_neutral = INS_ROLL_NEUTRAL_DEFAULT;
+
+ struct UtmCoor_f utm0 = { nav_utm_north0, nav_utm_east0, 0., nav_utm_zone0 };
+ stateSetLocalUtmOrigin_f(&utm0);
+ stateSetPositionUtm_f(&utm0);
+}
+
+void ins_xsens_event(void)
+{
+ xsens_event();
+ if (xsens.msg_received) {
+ parse_xsens_msg();
+ handle_ins_msg();
+ xsens.msg_received = FALSE;
+ }
+}
+
+static void gps_cb(uint8_t sender_id __attribute__((unused)),
+ uint32_t stamp __attribute__((unused)),
+ struct GpsState *gps_s)
{
struct UtmCoor_f utm = utm_float_from_gps(gps_s, nav_utm_zone0);
utm.alt = gps_s->hmsl / 1000.;
@@ -296,485 +107,85 @@ void ins_xsens_update_gps(struct GpsState *gps_s)
// set velocity
stateSetSpeedNed_f(&ned_vel);
}
-#endif
#if USE_GPS_XSENS
void gps_xsens_init(void)
{
- gps.nb_channels = 0;
+ xsens.gps.nb_channels = 0;
}
static void gps_xsens_publish(void)
{
// publish gps data
uint32_t now_ts = get_sys_time_usec();
- gps.last_msg_ticks = sys_time.nb_sec_rem;
- gps.last_msg_time = sys_time.nb_sec;
- if (gps.fix == GPS_FIX_3D) {
- gps.last_3dfix_ticks = sys_time.nb_sec_rem;
- gps.last_3dfix_time = sys_time.nb_sec;
+ xsens.gps.last_msg_ticks = sys_time.nb_sec_rem;
+ xsens.gps.last_msg_time = sys_time.nb_sec;
+ if (xsens.gps.fix == GPS_FIX_3D) {
+ xsens.gps.last_3dfix_ticks = sys_time.nb_sec_rem;
+ xsens.gps.last_3dfix_time = sys_time.nb_sec;
}
- AbiSendMsgGPS(GPS_XSENS_ID, now_ts, &gps);
+ AbiSendMsgGPS(GPS_XSENS_ID, now_ts, &xsens.gps);
}
#endif
-void xsens_periodic(void)
-{
- if (xsens_configured > 0) {
- switch (xsens_configured) {
- case 20:
- /* send mode and settings to MT */
- XSENS_GoToConfig();
- XSENS_SetOutputMode(xsens_output_mode);
- XSENS_SetOutputSettings(xsens_output_settings);
- break;
- case 18:
- // Give pulses on SyncOut
- XSENS_SetSyncOutSettings(0, 0x0002);
- break;
- case 17:
- // 1 pulse every 100 samples
- XSENS_SetSyncOutSettings(1, 100);
- break;
- case 2:
- XSENS_ReqLeverArmGps();
- break;
- case 6:
- XSENS_ReqMagneticDeclination();
- break;
-
- case 13:
-#ifdef AHRS_H_X
-#pragma message "Sending XSens Magnetic Declination."
- xsens_declination = atan2(AHRS_H_Y, AHRS_H_X);
- XSENS_SetMagneticDeclination(xsens_declination);
-#endif
- break;
- case 12:
-#ifdef GPS_IMU_LEVER_ARM_X
-#pragma message "Sending XSens GPS Arm."
- XSENS_SetLeverArmGps(GPS_IMU_LEVER_ARM_X, GPS_IMU_LEVER_ARM_Y, GPS_IMU_LEVER_ARM_Z);
-#endif
- break;
- case 10: {
- uint8_t baud = 1;
- XSENS_SetBaudrate(baud);
- }
- break;
-
- case 1:
- XSENS_GoToMeasurment();
- break;
-
- default:
- break;
- }
- xsens_configured--;
- return;
- }
-
- RunOnceEvery(100, XSENS_ReqGPSStatus());
-}
-
-#if USE_INS_MODULE
-#include "state.h"
-
-static inline void update_state_interface(void)
+static void update_state_interface(void)
{
// Send to Estimator (Control)
#ifdef XSENS_BACKWARDS
struct FloatEulers att = {
- -ins_phi + ins_roll_neutral,
- -ins_theta + ins_pitch_neutral,
- ins_psi + RadOfDeg(180)
+ -xsens.euler.phi + ins_roll_neutral,
+ -xsens.euler.theta + ins_pitch_neutral,
+ xsens.euler.psi + RadOfDeg(180)
};
- struct FloatRates rates = {
- -ins_p,
- -ins_q,
- ins_r
+ struct FloatEulerstRates rates = {
+ -xsens.gyro.p,
+ -xsens.gyro.q,
+ xsens.gyro.r
};
#else
struct FloatEulers att = {
- ins_phi + ins_roll_neutral,
- ins_theta + ins_pitch_neutral,
- ins_psi
- };
- struct FloatRates rates = {
- ins_p,
- ins_q,
- ins_r
+ xsens.euler.phi + ins_roll_neutral,
+ xsens.euler.theta + ins_pitch_neutral,
+ xsens.euler.psi
};
+ struct FloatRates rates = xsens.gyro;
#endif
stateSetNedToBodyEulers_f(&att);
stateSetBodyRates_f(&rates);
}
-#endif /* USE_INS_MODULE */
-void handle_ins_msg(void)
+
+static void handle_ins_msg(void)
{
-#if USE_INS_MODULE
update_state_interface();
-#endif
-#if USE_IMU
- uint32_t now_ts = get_sys_time_usec();
-#ifdef XSENS_BACKWARDS
- if (imu_xsens.gyro_available) {
- RATES_ASSIGN(imu.gyro_unscaled, -RATE_BFP_OF_REAL(ins_p), -RATE_BFP_OF_REAL(ins_q), RATE_BFP_OF_REAL(ins_r));
- imu_xsens.gyro_available = FALSE;
- imu_scale_gyro(&imu);
- AbiSendMsgIMU_GYRO_INT32(IMU_XSENS_ID, now_ts, &imu.gyro);
+ if (xsens.new_attitude) {
+ new_ins_attitude = TRUE;
+ xsens.new_attitude = FALSE;
}
- if (imu_xsens.accel_available) {
- VECT3_ASSIGN(imu.accel_unscaled, -ACCEL_BFP_OF_REAL(ins_ax), -ACCEL_BFP_OF_REAL(ins_ay), ACCEL_BFP_OF_REAL(ins_az));
- imu_xsens.accel_available = FALSE;
- imu_scale_accel(&imu);
- AbiSendMsgIMU_ACCEL_INT32(IMU_XSENS_ID, now_ts, &imu.accel);
- }
- if (imu_xsens.mag_available) {
- VECT3_ASSIGN(imu.mag_unscaled, -MAG_BFP_OF_REAL(ins_mx), -MAG_BFP_OF_REAL(ins_my), MAG_BFP_OF_REAL(ins_mz));
- imu_xsens.mag_available = FALSE;
- imu_scale_mag(&imu);
- AbiSendMsgIMU_MAG_INT32(IMU_XSENS_ID, now_ts, &imu.mag);
- }
-#else
- if (imu_xsens.gyro_available) {
- RATES_ASSIGN(imu.gyro_unscaled, RATE_BFP_OF_REAL(ins_p), RATE_BFP_OF_REAL(ins_q), RATE_BFP_OF_REAL(ins_r));
- imu_xsens.gyro_available = FALSE;
- imu_scale_gyro(&imu);
- AbiSendMsgIMU_GYRO_INT32(IMU_XSENS_ID, now_ts, &imu.gyro);
- }
- if (imu_xsens.accel_available) {
- VECT3_ASSIGN(imu.accel_unscaled, ACCEL_BFP_OF_REAL(ins_ax), ACCEL_BFP_OF_REAL(ins_ay), ACCEL_BFP_OF_REAL(ins_az));
- imu_xsens.accel_available = FALSE;
- imu_scale_accel(&imu);
- AbiSendMsgIMU_ACCEL_INT32(IMU_XSENS_ID, now_ts, &imu.accel);
- }
- if (imu_xsens.mag_available) {
- VECT3_ASSIGN(imu.mag_unscaled, MAG_BFP_OF_REAL(ins_mx), MAG_BFP_OF_REAL(ins_my), MAG_BFP_OF_REAL(ins_mz));
- imu_xsens.mag_available = FALSE;
- imu_scale_mag(&imu);
- AbiSendMsgIMU_MAG_INT32(IMU_XSENS_ID, now_ts, &imu.mag);
- }
-#endif /* XSENS_BACKWARDS */
-#endif /* USE_IMU */
#if USE_GPS_XSENS
+ if (xsens.gps_available) {
+ // Horizontal speed
+ float fspeed = FLOAT_VECT2_NORM(xsens.vel);
+ if (xsens.gps.fix != GPS_FIX_3D) {
+ fspeed = 0;
+ }
+ xsens.gps.gspeed = fspeed * 100.;
+ xsens.gps.speed_3d = float_vect3_norm(&xsens.vel) * 100;
- // Horizontal speed
- float fspeed = sqrt(ins_vx * ins_vx + ins_vy * ins_vy);
- if (gps.fix != GPS_FIX_3D) {
- fspeed = 0;
+ float fcourse = atan2f(xsens.vel.y, xsens.vel.x);
+ xsens.gps.course = fcourse * 1e7;
+ SetBit(xsens.gps.valid_fields, GPS_VALID_COURSE_BIT);
+
+ gps_xsens_publish();
+ xsens.gps_available = FALSE;
}
- gps.gspeed = fspeed * 100.;
- gps.speed_3d = (uint16_t)(sqrt(ins_vx * ins_vx + ins_vy * ins_vy + ins_vz * ins_vz) * 100);
-
- float fcourse = atan2f((float)ins_vy, (float)ins_vx);
- gps.course = fcourse * 1e7;
- SetBit(gps.valid_fields, GPS_VALID_COURSE_BIT);
#endif // USE_GPS_XSENS
}
-void parse_ins_msg(void)
-{
- uint8_t offset = 0;
- if (xsens_id == XSENS_ReqOutputModeAck_ID) {
- xsens_output_mode = XSENS_ReqOutputModeAck_mode(xsens_msg_buf);
- } else if (xsens_id == XSENS_ReqOutputSettings_ID) {
- xsens_output_settings = XSENS_ReqOutputSettingsAck_settings(xsens_msg_buf);
- } else if (xsens_id == XSENS_ReqMagneticDeclinationAck_ID) {
- xsens_declination = DegOfRad(XSENS_ReqMagneticDeclinationAck_declination(xsens_msg_buf));
-
- DOWNLINK_SEND_IMU_MAG_SETTINGS(DefaultChannel, DefaultDevice, &xsens_declination, &xsens_declination, &xsens_gps_arm_x,
- &xsens_gps_arm_y, &xsens_gps_arm_z);
- } else if (xsens_id == XSENS_ReqLeverArmGpsAck_ID) {
- xsens_gps_arm_x = XSENS_ReqLeverArmGpsAck_x(xsens_msg_buf);
- xsens_gps_arm_y = XSENS_ReqLeverArmGpsAck_y(xsens_msg_buf);
- xsens_gps_arm_z = XSENS_ReqLeverArmGpsAck_z(xsens_msg_buf);
-
- DOWNLINK_SEND_IMU_MAG_SETTINGS(DefaultChannel, DefaultDevice, &xsens_declination, &xsens_declination, &xsens_gps_arm_x,
- &xsens_gps_arm_y, &xsens_gps_arm_z);
- } else if (xsens_id == XSENS_Error_ID) {
- xsens_errorcode = XSENS_Error_errorcode(xsens_msg_buf);
- }
-#if USE_GPS_XSENS
- else if (xsens_id == XSENS_GPSStatus_ID) {
- gps.nb_channels = XSENS_GPSStatus_nch(xsens_msg_buf);
- gps.num_sv = 0;
-
- uint8_t i;
- // Do not write outside buffer
- for (i = 0; i < Min(gps.nb_channels, GPS_NB_CHANNELS); i++) {
- uint8_t ch = XSENS_GPSStatus_chn(xsens_msg_buf, i);
- if (ch > gps.nb_channels) { continue; }
- gps.svinfos[ch].svid = XSENS_GPSStatus_svid(xsens_msg_buf, i);
- gps.svinfos[ch].flags = XSENS_GPSStatus_bitmask(xsens_msg_buf, i);
- gps.svinfos[ch].qi = XSENS_GPSStatus_qi(xsens_msg_buf, i);
- gps.svinfos[ch].cno = XSENS_GPSStatus_cnr(xsens_msg_buf, i);
- if (gps.svinfos[ch].flags > 0) {
- gps.num_sv++;
- }
- }
- }
-#endif
- else if (xsens_id == XSENS_MTData_ID) {
- /* test RAW modes else calibrated modes */
- //if ((XSENS_MASK_RAWInertial(xsens_output_mode)) || (XSENS_MASK_RAWGPS(xsens_output_mode))) {
- if (XSENS_MASK_RAWInertial(xsens_output_mode)) {
- ins_p = XSENS_DATA_RAWInertial_gyrX(xsens_msg_buf, offset);
- ins_q = XSENS_DATA_RAWInertial_gyrY(xsens_msg_buf, offset);
- ins_r = XSENS_DATA_RAWInertial_gyrZ(xsens_msg_buf, offset);
-#if USE_IMU
- imu_xsens.gyro_available = TRUE;
-#endif
- offset += XSENS_DATA_RAWInertial_LENGTH;
- }
- if (XSENS_MASK_RAWGPS(xsens_output_mode)) {
-#if USE_GPS_XSENS_RAW_DATA && USE_GPS_XSENS
-
- gps.week = 0; // FIXME
- gps.tow = XSENS_DATA_RAWGPS_itow(xsens_msg_buf, offset) * 10;
- gps.lla_pos.lat = XSENS_DATA_RAWGPS_lat(xsens_msg_buf, offset);
- gps.lla_pos.lon = XSENS_DATA_RAWGPS_lon(xsens_msg_buf, offset);
- gps.lla_pos.alt = XSENS_DATA_RAWGPS_alt(xsens_msg_buf, offset);
- SetBit(gps.valid_fields, GPS_VALID_POS_LLA_BIT);
-
- /* Set the real UTM zone */
- gps.utm_pos.zone = (gps.lla_pos.lon / 1e7 + 180) / 6 + 1;
- LLA_FLOAT_OF_BFP(lla_f, gps.lla_pos);
- utm_f.zone = nav_utm_zone0;
- /* convert to utm */
- utm_of_lla_f(&utm_f, &lla_f);
- /* copy results of utm conversion */
- gps.utm_pos.east = utm_f.east * 100;
- gps.utm_pos.north = utm_f.north * 100;
- gps.utm_pos.alt = gps.lla_pos.alt;
- SetBit(gps.valid_fields, GPS_VALID_POS_UTM_BIT);
-
- ins_x = utm_f.east;
- ins_y = utm_f.north;
- // Altitude: Xsens LLH gives ellipsoid height
- ins_z = -(INS_FORMAT)XSENS_DATA_RAWGPS_alt(xsens_msg_buf, offset) / 1000.;
-
- // Compute geoid (MSL) height
- float hmsl = wgs84_ellipsoid_to_geoid(lla_f.lat, lla_f.lon);
- gps.hmsl = XSENS_DATA_RAWGPS_alt(xsens_msg_buf, offset) - (hmsl * 1000.0f);
- SetBit(gps.valid_fields, GPS_VALID_HMSL_BIT);
-
- ins_vx = ((INS_FORMAT)XSENS_DATA_RAWGPS_vel_n(xsens_msg_buf, offset)) / 100.;
- ins_vy = ((INS_FORMAT)XSENS_DATA_RAWGPS_vel_e(xsens_msg_buf, offset)) / 100.;
- ins_vz = ((INS_FORMAT)XSENS_DATA_RAWGPS_vel_d(xsens_msg_buf, offset)) / 100.;
- gps.ned_vel.x = XSENS_DATA_RAWGPS_vel_n(xsens_msg_buf, offset);
- gps.ned_vel.y = XSENS_DATA_RAWGPS_vel_e(xsens_msg_buf, offset);
- gps.ned_vel.z = XSENS_DATA_RAWGPS_vel_d(xsens_msg_buf, offset);
- SetBit(gps.valid_fields, GPS_VALID_VEL_NED_BIT);
- gps.pacc = XSENS_DATA_RAWGPS_hacc(xsens_msg_buf, offset) / 100;
- gps.sacc = XSENS_DATA_RAWGPS_sacc(xsens_msg_buf, offset) / 100;
- gps.pdop = 5; // FIXME Not output by XSens
-
- gps_xsens_publish();
-#endif
- offset += XSENS_DATA_RAWGPS_LENGTH;
- }
- //} else {
- if (XSENS_MASK_Temp(xsens_output_mode)) {
- offset += XSENS_DATA_Temp_LENGTH;
- }
- if (XSENS_MASK_Calibrated(xsens_output_mode)) {
- uint8_t l = 0;
- if (!XSENS_MASK_AccOut(xsens_output_settings)) {
- ins_ax = XSENS_DATA_Calibrated_accX(xsens_msg_buf, offset);
- ins_ay = XSENS_DATA_Calibrated_accY(xsens_msg_buf, offset);
- ins_az = XSENS_DATA_Calibrated_accZ(xsens_msg_buf, offset);
-#if USE_IMU
- imu_xsens.accel_available = TRUE;
-#endif
- l++;
- }
- if (!XSENS_MASK_GyrOut(xsens_output_settings)) {
- ins_p = XSENS_DATA_Calibrated_gyrX(xsens_msg_buf, offset);
- ins_q = XSENS_DATA_Calibrated_gyrY(xsens_msg_buf, offset);
- ins_r = XSENS_DATA_Calibrated_gyrZ(xsens_msg_buf, offset);
-#if USE_IMU
- imu_xsens.gyro_available = TRUE;
-#endif
- l++;
- }
- if (!XSENS_MASK_MagOut(xsens_output_settings)) {
- ins_mx = XSENS_DATA_Calibrated_magX(xsens_msg_buf, offset);
- ins_my = XSENS_DATA_Calibrated_magY(xsens_msg_buf, offset);
- ins_mz = XSENS_DATA_Calibrated_magZ(xsens_msg_buf, offset);
-#if USE_IMU
- imu_xsens.mag_available = TRUE;
-#endif
- l++;
- }
- offset += l * XSENS_DATA_Calibrated_LENGTH / 3;
- }
- if (XSENS_MASK_Orientation(xsens_output_mode)) {
- if (XSENS_MASK_OrientationMode(xsens_output_settings) == 0x00) {
- float q0 = XSENS_DATA_Quaternion_q0(xsens_msg_buf, offset);
- float q1 = XSENS_DATA_Quaternion_q1(xsens_msg_buf, offset);
- float q2 = XSENS_DATA_Quaternion_q2(xsens_msg_buf, offset);
- float q3 = XSENS_DATA_Quaternion_q3(xsens_msg_buf, offset);
- float dcm00 = 1.0 - 2 * (q2 * q2 + q3 * q3);
- float dcm01 = 2 * (q1 * q2 + q0 * q3);
- float dcm02 = 2 * (q1 * q3 - q0 * q2);
- float dcm12 = 2 * (q2 * q3 + q0 * q1);
- float dcm22 = 1.0 - 2 * (q1 * q1 + q2 * q2);
- ins_phi = atan2(dcm12, dcm22);
- ins_theta = -asin(dcm02);
- ins_psi = atan2(dcm01, dcm00);
- offset += XSENS_DATA_Quaternion_LENGTH;
- }
- if (XSENS_MASK_OrientationMode(xsens_output_settings) == 0x01) {
- ins_phi = XSENS_DATA_Euler_roll(xsens_msg_buf, offset) * M_PI / 180;
- ins_theta = XSENS_DATA_Euler_pitch(xsens_msg_buf, offset) * M_PI / 180;
- ins_psi = XSENS_DATA_Euler_yaw(xsens_msg_buf, offset) * M_PI / 180;
- offset += XSENS_DATA_Euler_LENGTH;
- }
- if (XSENS_MASK_OrientationMode(xsens_output_settings) == 0x10) {
- offset += XSENS_DATA_Matrix_LENGTH;
- }
- new_ins_attitude = 1;
- }
- if (XSENS_MASK_Auxiliary(xsens_output_mode)) {
- uint8_t l = 0;
- if (!XSENS_MASK_Aux1Out(xsens_output_settings)) {
- l++;
- }
- if (!XSENS_MASK_Aux2Out(xsens_output_settings)) {
- l++;
- }
- offset += l * XSENS_DATA_Auxiliary_LENGTH / 2;
- }
- if (XSENS_MASK_Position(xsens_output_mode)) {
-#if (! USE_GPS_XSENS_RAW_DATA) && USE_GPS_XSENS
- lla_f.lat = RadOfDeg(XSENS_DATA_Position_lat(xsens_msg_buf, offset));
- lla_f.lon = RadOfDeg(XSENS_DATA_Position_lon(xsens_msg_buf, offset));
- gps.lla_pos.lat = (int32_t)(DegOfRad(lla_f.lat) * 1e7);
- gps.lla_pos.lon = (int32_t)(DegOfRad(lla_f.lon) * 1e7);
- SetBit(gps.valid_fields, GPS_VALID_POS_LLA_BIT);
- gps.utm_pos.zone = (DegOfRad(lla_f.lon) + 180) / 6 + 1;
- /* convert to utm */
- utm_of_lla_f(&utm_f, &lla_f);
- /* copy results of utm conversion */
- gps.utm_pos.east = utm_f.east * 100;
- gps.utm_pos.north = utm_f.north * 100;
- SetBit(gps.valid_fields, GPS_VALID_POS_UTM_BIT);
- ins_x = utm_f.east;
- ins_y = utm_f.north;
- ins_z = XSENS_DATA_Position_alt(xsens_msg_buf, offset); //TODO is this hms or above ellipsoid?
- gps.hmsl = ins_z * 1000;
- SetBit(gps.valid_fields, GPS_VALID_HMSL_BIT);
- // what about gps.lla_pos.alt and gps.utm_pos.alt ?
-
- gps_xsens_publish();
-#endif
- offset += XSENS_DATA_Position_LENGTH;
- }
- if (XSENS_MASK_Velocity(xsens_output_mode)) {
-#if (! USE_GPS_XSENS_RAW_DATA) && USE_GPS_XSENS
- ins_vx = XSENS_DATA_Velocity_vx(xsens_msg_buf, offset);
- ins_vy = XSENS_DATA_Velocity_vy(xsens_msg_buf, offset);
- ins_vz = XSENS_DATA_Velocity_vz(xsens_msg_buf, offset);
-#endif
- offset += XSENS_DATA_Velocity_LENGTH;
- }
- if (XSENS_MASK_Status(xsens_output_mode)) {
- xsens_msg_status = XSENS_DATA_Status_status(xsens_msg_buf, offset);
-#if USE_GPS_XSENS
- if (bit_is_set(xsens_msg_status, 2)) { gps.fix = GPS_FIX_3D; } // gps fix
- else if (bit_is_set(xsens_msg_status, 1)) { gps.fix = 0x01; } // efk valid
- else { gps.fix = GPS_FIX_NONE; }
-#ifdef GPS_LED
- if (gps.fix == GPS_FIX_3D) {
- LED_ON(GPS_LED);
- } else {
- LED_TOGGLE(GPS_LED);
- }
-#endif // GPS_LED
-#endif // USE_GPS_XSENS
- offset += XSENS_DATA_Status_LENGTH;
- }
- if (XSENS_MASK_TimeStamp(xsens_output_settings)) {
- xsens_time_stamp = XSENS_DATA_TimeStamp_ts(xsens_msg_buf, offset);
-#if USE_GPS_XSENS
- gps.tow = xsens_time_stamp;
-#endif
- offset += XSENS_DATA_TimeStamp_LENGTH;
- }
- if (XSENS_MASK_UTC(xsens_output_settings)) {
- xsens_time.hour = XSENS_DATA_UTC_hour(xsens_msg_buf, offset);
- xsens_time.min = XSENS_DATA_UTC_min(xsens_msg_buf, offset);
- xsens_time.sec = XSENS_DATA_UTC_sec(xsens_msg_buf, offset);
- xsens_time.nanosec = XSENS_DATA_UTC_nanosec(xsens_msg_buf, offset);
- xsens_time.year = XSENS_DATA_UTC_year(xsens_msg_buf, offset);
- xsens_time.month = XSENS_DATA_UTC_month(xsens_msg_buf, offset);
- xsens_time.day = XSENS_DATA_UTC_day(xsens_msg_buf, offset);
-
- offset += XSENS_DATA_UTC_LENGTH;
- }
- //}
- }
-
-}
-
-void parse_ins_buffer(uint8_t c)
-{
- ck += c;
- switch (xsens_status) {
- case UNINIT:
- if (c != XSENS_START) {
- goto error;
- }
- xsens_status++;
- ck = 0;
- break;
- case GOT_START:
- if (c != XSENS_BID) {
- goto error;
- }
- xsens_status++;
- break;
- case GOT_BID:
- xsens_id = c;
- xsens_status++;
- break;
- case GOT_MID:
- xsens_len = c;
- if (xsens_len > XSENS_MAX_PAYLOAD) {
- goto error;
- }
- xsens_msg_idx = 0;
- xsens_status++;
- break;
- case GOT_LEN:
- xsens_msg_buf[xsens_msg_idx] = c;
- xsens_msg_idx++;
- if (xsens_msg_idx >= xsens_len) {
- xsens_status++;
- }
- break;
- case GOT_DATA:
- if (ck != 0) {
- goto error;
- }
- ins_msg_received = TRUE;
- goto restart;
- break;
- default:
- break;
- }
- return;
-error:
-restart:
- xsens_status = UNINIT;
- return;
-}
-
#ifdef USE_GPS_XSENS
/*
* register callbacks & structs
diff --git a/sw/airborne/modules/ins/ins_xsens.h b/sw/airborne/modules/ins/ins_xsens.h
index 2b7bf22a9d..9e55c00136 100644
--- a/sw/airborne/modules/ins/ins_xsens.h
+++ b/sw/airborne/modules/ins/ins_xsens.h
@@ -21,7 +21,8 @@
*/
/**
- * \brief Library for the XSENS AHRS
+ * @file modules/ins/ins_xsens.h
+ * Xsens as a full INS solution
*/
#ifndef INS_XSENS_H
@@ -29,54 +30,22 @@
#include "std.h"
-#include "ins_module.h"
+// hack to not use this in sim/nps
+#ifndef SITL
+#include "xsens.h"
-struct XsensTime {
- int8_t hour;
- int8_t min;
- int8_t sec;
- int32_t nanosec;
- int16_t year;
- int8_t month;
- int8_t day;
-};
-
-extern struct XsensTime xsens_time;
-
-extern uint8_t xsens_msg_status;
-extern uint16_t xsens_time_stamp;
-
-extern void xsens_periodic(void);
-
-/* To use Xsens to just provide IMU measurements
- * for use with an external AHRS algorithm
- */
-#if USE_IMU
-#include "subsystems/imu.h"
-#include "subsystems/abi.h"
-
-struct ImuXsens {
- bool_t gyro_available;
- bool_t accel_available;
- bool_t mag_available;
-};
-extern struct ImuXsens imu_xsens;
-
-#define ImuEvent() {}
-#endif /* USE_IMU */
-
-
-/* use Xsens as a full INS solution */
-#if USE_INS_MODULE
-#define InsEvent() { \
- ins_event_check_and_handle(handle_ins_msg); \
- }
-#define DefaultInsImpl ins_xsens
-#define InsPeriodic xsens_periodic
-extern void ins_xsens_init(void);
-extern void ins_xsens_register(void);
+#ifdef AHRS_TRIGGERED_ATTITUDE_LOOP
+extern volatile uint8_t new_ins_attitude;
#endif
+extern float ins_pitch_neutral;
+extern float ins_roll_neutral;
+
+#define DefaultInsImpl ins_xsens
+
+extern void ins_xsens_init(void);
+extern void ins_xsens_register(void);
+extern void ins_xsens_event(void);
#if USE_GPS_XSENS
#ifndef PRIMARY_GPS
@@ -86,4 +55,11 @@ extern void gps_xsens_init(void);
extern void gps_xsens_register(void);
#endif
+#else // SITL
+
+static inline void xsens_periodic(void) {}
+static inline void ins_xsens_event(void) {}
+
+#endif
+
#endif
diff --git a/sw/airborne/modules/ins/ins_xsens700.c b/sw/airborne/modules/ins/ins_xsens700.c
index a9a180616b..0f10a185e2 100644
--- a/sw/airborne/modules/ins/ins_xsens700.c
+++ b/sw/airborne/modules/ins/ins_xsens700.c
@@ -22,15 +22,13 @@
/**
* @file modules/ins/ins_xsens700.c
- * Parser for the Xsens protocol.
+ * Xsens700 as a full INS solution
*/
-#include "ins_module.h"
-#include "ins_xsens.h"
+#include "ins_xsens700.h"
+#include "xsens_common.h"
#include "subsystems/ins.h"
-#include
-
#include "generated/airframe.h"
#include "mcu_periph/sys_time.h"
@@ -48,148 +46,6 @@
#include "subsystems/navigation/common_nav.h" /* needed for nav_utm_zone0 */
#endif
-// positions
-INS_FORMAT ins_x;
-INS_FORMAT ins_y;
-INS_FORMAT ins_z;
-
-// velocities
-INS_FORMAT ins_vx;
-INS_FORMAT ins_vy;
-INS_FORMAT ins_vz;
-
-// body angles
-INS_FORMAT ins_phi;
-INS_FORMAT ins_theta;
-INS_FORMAT ins_psi;
-
-// angle rates
-INS_FORMAT ins_p;
-INS_FORMAT ins_q;
-INS_FORMAT ins_r;
-
-// accelerations
-INS_FORMAT ins_ax;
-INS_FORMAT ins_ay;
-INS_FORMAT ins_az;
-
-// magnetic
-INS_FORMAT ins_mx;
-INS_FORMAT ins_my;
-INS_FORMAT ins_mz;
-
-#if USE_INS_MODULE
-float ins_pitch_neutral;
-float ins_roll_neutral;
-#endif
-
-
-//////////////////////////////////////////////////////////////////////////////////////////
-//
-// XSens Specific
-//
-
-volatile uint8_t ins_msg_received;
-
-#define XsensInitCheksum() { send_ck = 0; }
-#define XsensUpdateChecksum(c) { send_ck += c; }
-
-#define XsensSend1(c) { uint8_t i8=c; InsUartSend1(i8); XsensUpdateChecksum(i8); }
-#define XsensSend1ByAddr(x) { XsensSend1(*x); }
-#define XsensSend2ByAddr(x) { XsensSend1(*(x+1)); XsensSend1(*x); }
-#define XsensSend4ByAddr(x) { XsensSend1(*(x+3)); XsensSend1(*(x+2)); XsensSend1(*(x+1)); XsensSend1(*x); }
-
-#define XsensHeader(msg_id, len) { \
- InsUartSend1(XSENS_START); \
- XsensInitCheksum(); \
- XsensSend1(XSENS_BID); \
- XsensSend1(msg_id); \
- XsensSend1(len); \
- }
-#define XsensTrailer() { uint8_t i8=0x100-send_ck; InsUartSend1(i8); }
-
-/** Includes macros generated from xsens_MTi-G.xml */
-#include "xsens_protocol.h"
-
-
-#define XSENS_MAX_PAYLOAD 254
-uint8_t xsens_msg_buf[XSENS_MAX_PAYLOAD];
-
-
-#define UNINIT 0
-#define GOT_START 1
-#define GOT_BID 2
-#define GOT_MID 3
-#define GOT_LEN 4
-#define GOT_DATA 5
-#define GOT_CHECKSUM 6
-
-// FIXME Debugging Only
-#include "mcu_periph/uart.h"
-#include "pprzlink/messages.h"
-#include "subsystems/datalink/downlink.h"
-
-
-uint8_t xsens_errorcode;
-uint32_t xsens_msg_statusword;
-uint16_t xsens_time_stamp;
-uint16_t xsens_output_mode;
-uint32_t xsens_output_settings;
-float xsens_declination = 0;
-float xsens_gps_arm_x = 0;
-float xsens_gps_arm_y = 0;
-float xsens_gps_arm_z = 0;
-
-
-int8_t xsens_hour;
-int8_t xsens_min;
-int8_t xsens_sec;
-int32_t xsens_nanosec;
-int16_t xsens_year;
-int8_t xsens_month;
-int8_t xsens_day;
-
-static uint8_t xsens_id;
-static uint8_t xsens_status;
-static uint8_t xsens_len;
-static uint8_t xsens_msg_idx;
-static uint8_t ck;
-uint8_t send_ck;
-
-struct LlaCoor_f lla_f;
-struct UtmCoor_f utm_f;
-
-volatile int xsens_configured = 0;
-
-void xsens_init(void);
-
-void xsens_init(void)
-{
-
- xsens_status = UNINIT;
- xsens_configured = 30;
-
- xsens_msg_statusword = 0;
- xsens_time_stamp = 0;
-
-}
-
-#if USE_INS_MODULE
-void ins_xsens_update_gps(struct GpsState *gps_s);
-
-void ins_xsens_init(void)
-{
- struct UtmCoor_f utm0 = { nav_utm_north0, nav_utm_east0, 0., nav_utm_zone0 };
- stateSetLocalUtmOrigin_f(&utm0);
- stateSetPositionUtm_f(&utm0);
-
- ins_pitch_neutral = INS_PITCH_NEUTRAL_DEFAULT;
- ins_roll_neutral = INS_ROLL_NEUTRAL_DEFAULT;
-
- xsens_init();
-}
-
-#include "subsystems/abi.h"
/** ABI binding for gps data.
* Used for GPS ABI messages.
*/
@@ -198,20 +54,47 @@ void ins_xsens_init(void)
#endif
PRINT_CONFIG_VAR(INS_XSENS700_GPS_ID)
static abi_event gps_ev;
+
+float ins_pitch_neutral;
+float ins_roll_neutral;
+
+static void handle_ins_msg(void);
+static void update_state_interface(void);
static void gps_cb(uint8_t sender_id __attribute__((unused)),
uint32_t stamp __attribute__((unused)),
- struct GpsState *gps_s)
-{
- ins_xsens_update_gps(gps_s);
-}
+ struct GpsState *gps_s);
-void ins_xsens_register(void)
+void ins_xsens700_register(void)
{
- ins_register_impl(ins_xsens_init);
+ ins_register_impl(ins_xsens700_init);
AbiBindMsgGPS(INS_XSENS700_GPS_ID, &gps_ev, gps_cb);
}
-void ins_xsens_update_gps(struct GpsState *gps_s)
+void ins_xsens700_init(void)
+{
+ xsens700_init();
+
+ ins_pitch_neutral = INS_PITCH_NEUTRAL_DEFAULT;
+ ins_roll_neutral = INS_ROLL_NEUTRAL_DEFAULT;
+
+ struct UtmCoor_f utm0 = { nav_utm_north0, nav_utm_east0, 0., nav_utm_zone0 };
+ stateSetLocalUtmOrigin_f(&utm0);
+ stateSetPositionUtm_f(&utm0);
+}
+
+void ins_xsens700_event(void)
+{
+ xsens_event();
+ if (xsens700.msg_received) {
+ parse_xsens700_msg();
+ handle_ins_msg();
+ xsens700.msg_received = FALSE;
+ }
+}
+
+static void gps_cb(uint8_t sender_id __attribute__((unused)),
+ uint32_t stamp __attribute__((unused)),
+ struct GpsState *gps_s)
{
struct UtmCoor_f utm = utm_float_from_gps(gps_s, nav_utm_zone0);
utm.alt = gps_s->hmsl / 1000.;
@@ -227,409 +110,97 @@ void ins_xsens_update_gps(struct GpsState *gps_s)
// set velocity
stateSetSpeedNed_f(&ned_vel);
}
-#endif
+
#if USE_GPS_XSENS
-void gps_xsens_init(void)
+void gps_xsens700_init(void)
{
- gps.nb_channels = 0;
+ xsens700.gps.nb_channels = 0;
}
-static void gps_xsens_publish(void)
+static void gps_xsens700_publish(void)
{
// publish gps data
uint32_t now_ts = get_sys_time_usec();
- gps.last_msg_ticks = sys_time.nb_sec_rem;
- gps.last_msg_time = sys_time.nb_sec;
- if (gps.fix == GPS_FIX_3D) {
- gps.last_3dfix_ticks = sys_time.nb_sec_rem;
- gps.last_3dfix_time = sys_time.nb_sec;
+ xsens700.gps.last_msg_ticks = sys_time.nb_sec_rem;
+ xsens700.gps.last_msg_time = sys_time.nb_sec;
+ if (xsens700.gps.fix == GPS_FIX_3D) {
+ xsens700.gps.last_3dfix_ticks = sys_time.nb_sec_rem;
+ xsens700.gps.last_3dfix_time = sys_time.nb_sec;
}
- AbiSendMsgGPS(GPS_XSENS_ID, now_ts, &gps);
+ AbiSendMsgGPS(GPS_XSENS_ID, now_ts, &xsens700.gps);
}
#endif
-static void xsens_ask_message_rate(uint8_t c1, uint8_t c2, uint8_t freq)
-{
- uint8_t foo = 0;
- XsensSend1ByAddr(&c1);
- XsensSend1ByAddr(&c2);
- XsensSend1ByAddr(&foo);
- XsensSend1ByAddr(&freq);
-}
-void xsens_periodic(void)
-{
- if (xsens_configured > 0) {
- switch (xsens_configured) {
- case 25:
- /* send mode and settings to MT */
- XSENS_GoToConfig();
- //XSENS_SetOutputMode(xsens_output_mode);
- //XSENS_SetOutputSettings(xsens_output_settings);
- break;
- case 18:
- // Give pulses on SyncOut
- //XSENS_SetSyncOutSettings(0,0x0002);
- break;
- case 17:
-
- XsensHeader(XSENS_SetOutputConfiguration_ID, 44);
- xsens_ask_message_rate(0x10, 0x10, 4); // UTC
- xsens_ask_message_rate(0x20, 0x30, 100); // Attitude Euler
- xsens_ask_message_rate(0x40, 0x10, 100); // Delta-V
- xsens_ask_message_rate(0x80, 0x20, 100); // Rate of turn
- xsens_ask_message_rate(0xE0, 0x20, 50); // Status
- xsens_ask_message_rate(0x30, 0x10, 50); // Baro Pressure
- xsens_ask_message_rate(0x88, 0x40, 1); // NavSol
- xsens_ask_message_rate(0x88, 0xA0, 1); // SV Info
- xsens_ask_message_rate(0x50, 0x20, 50); // GPS Altitude Ellipsiod
- xsens_ask_message_rate(0x50, 0x40, 50); // GPS Position
- xsens_ask_message_rate(0xD0, 0x10, 50); // GPS Speed
- XsensTrailer();
- break;
- case 2:
- //XSENS_ReqLeverArmGps();
- break;
-
- case 6:
- //XSENS_ReqMagneticDeclination();
- break;
-
- case 13:
- //#ifdef AHRS_H_X
- //#pragma message "Sending XSens Magnetic Declination."
- //xsens_declination = atan2(AHRS_H_Y, AHRS_H_X);
- //XSENS_SetMagneticDeclination(xsens_declination);
- //#endif
- break;
- case 12:
-#ifdef GPS_IMU_LEVER_ARM_X
-#pragma message "Sending XSens GPS Arm."
- XSENS_SetLeverArmGps(GPS_IMU_LEVER_ARM_X, GPS_IMU_LEVER_ARM_Y, GPS_IMU_LEVER_ARM_Z);
-#endif
- break;
- case 10: {
- uint8_t baud = 1;
- XSENS_SetBaudrate(baud);
- }
- break;
-
- case 1:
- XSENS_GoToMeasurment();
- break;
- default:
- break;
- }
- xsens_configured--;
- return;
- }
-
- //RunOnceEvery(100,XSENS_ReqGPSStatus());
-}
-
-#if USE_INS_MODULE
-#include "state.h"
-
-static inline void update_state_interface(void)
+static void update_state_interface(void)
{
// Send to Estimator (Control)
-#if XSENS_BACKWARDS
+#ifdef XSENS_BACKWARDS
struct FloatEulers att = {
- ins_phi + ins_roll_neutral,
- -ins_theta + ins_pitch_neutral,
- -ins_psi + RadOfDeg(180)
+ xsens700.euler.phi + ins_roll_neutral,
+ -xsens700.euler.theta + ins_pitch_neutral,
+ -xsens700.euler.psi + RadOfDeg(180)
};
- struct FloatRates rates = {
- ins_p,
- -ins_q,
- -ins_r
+ struct FloatEulerstRates rates = {
+ xsens700.gyro.p,
+ -xsens700.gyro.q,
+ -xsens700.gyro.r
};
#else
struct FloatEulers att = {
- -ins_phi + ins_roll_neutral,
- ins_theta + ins_pitch_neutral,
- -ins_psi
+ -xsens700.euler.phi + ins_roll_neutral,
+ xsens700.euler.theta + ins_pitch_neutral,
+ -xsens700.euler.psi
};
- struct FloatRates rates = {
- -ins_p,
- ins_q,
- -ins_r
+ struct FloatRates rates = {
+ -xsens700.gyro.p,
+ xsens700.gyro.q,
+ -xsens700.gyro.r
};
#endif
stateSetNedToBodyEulers_f(&att);
stateSetBodyRates_f(&rates);
}
-#endif /* USE_INS_MODULE */
+
void handle_ins_msg(void)
{
-#if USE_INS_MODULE
update_state_interface();
-#endif
+
+ if (xsens700.new_attitude) {
+ new_ins_attitude = TRUE;
+ xsens700.new_attitude = FALSE;
+ }
#if USE_GPS_XSENS
- // Horizontal speed
- float fspeed = sqrt(ins_vx * ins_vx + ins_vy * ins_vy);
- if (gps.fix != GPS_FIX_3D) {
- fspeed = 0;
- }
- gps.gspeed = fspeed * 100.;
- gps.speed_3d = (uint16_t)(sqrt(ins_vx * ins_vx + ins_vy * ins_vy + ins_vz * ins_vz) * 100);
+ if (xsens700.gps_available) {
+ // Horizontal speed
+ float fspeed = FLOAT_VECT2_NORM(xsens700.vel);
+ if (xsens700.gps.fix != GPS_FIX_3D) {
+ fspeed = 0;
+ }
+ xsens700.gps.gspeed = fspeed * 100.;
+ xsens700.gps.speed_3d = float_vect3_norm(&xsens700.vel) * 100;
- float fcourse = atan2f((float)ins_vy, (float)ins_vx);
- gps.course = fcourse * 1e7;
+ float fcourse = atan2f(xsens700.vel.y, xsens700.vel.x);
+ xsens700.gps.course = fcourse * 1e7;
+ SetBit(xsens700.gps.valid_fields, GPS_VALID_COURSE_BIT);
+
+ gps_xsens700_publish();
+ xsens700.gps_available = FALSE;
+ }
#endif // USE_GPS_XSENS
}
-void parse_ins_msg(void)
-{
- uint8_t offset = 0;
- if (xsens_id == XSENS_ReqLeverArmGpsAck_ID) {
- xsens_gps_arm_x = XSENS_ReqLeverArmGpsAck_x(xsens_msg_buf);
- xsens_gps_arm_y = XSENS_ReqLeverArmGpsAck_y(xsens_msg_buf);
- xsens_gps_arm_z = XSENS_ReqLeverArmGpsAck_z(xsens_msg_buf);
-
- DOWNLINK_SEND_IMU_MAG_SETTINGS(DefaultChannel, DefaultDevice, &xsens_declination, &xsens_declination, &xsens_gps_arm_x,
- &xsens_gps_arm_y, &xsens_gps_arm_z);
- } else if (xsens_id == XSENS_Error_ID) {
- xsens_errorcode = XSENS_Error_errorcode(xsens_msg_buf);
- } else if (xsens_id == XSENS_MTData2_ID) {
- for (offset = 0; offset < xsens_len;) {
- uint8_t code1 = xsens_msg_buf[offset];
- uint8_t code2 = xsens_msg_buf[offset + 1];
- int subpacklen = (int)xsens_msg_buf[offset + 2];
- offset += 3;
-
-
- if (code1 == 0x10) {
- if (code2 == 0x10) {
- // UTC
- } else if (code2 == 0x20) {
- // Packet Counter
- }
- if (code2 == 0x30) {
- // ITOW
- }
- } else if (code1 == 0x20) {
- if (code2 == 0x30) {
- // Attitude Euler
- ins_phi = XSENS_DATA_Euler_roll(xsens_msg_buf, offset) * M_PI / 180;
- ins_theta = XSENS_DATA_Euler_pitch(xsens_msg_buf, offset) * M_PI / 180;
- ins_psi = XSENS_DATA_Euler_yaw(xsens_msg_buf, offset) * M_PI / 180;
-
- new_ins_attitude = 1;
-
- }
- } else if (code1 == 0x40) {
- if (code2 == 0x10) {
- // Delta-V
- ins_ax = XSENS_DATA_Acceleration_x(xsens_msg_buf, offset) * 100.0f;
- ins_ay = XSENS_DATA_Acceleration_y(xsens_msg_buf, offset) * 100.0f;
- ins_az = XSENS_DATA_Acceleration_z(xsens_msg_buf, offset) * 100.0f;
- }
- } else if (code1 == 0x80) {
- if (code2 == 0x20) {
- // Rate Of Turn
- ins_p = XSENS_DATA_RateOfTurn_x(xsens_msg_buf, offset) * M_PI / 180;
- ins_q = XSENS_DATA_RateOfTurn_y(xsens_msg_buf, offset) * M_PI / 180;
- ins_r = XSENS_DATA_RateOfTurn_z(xsens_msg_buf, offset) * M_PI / 180;
- }
- } else if (code1 == 0x30) {
- if (code2 == 0x10) {
- // Baro Pressure
- }
- } else if (code1 == 0xE0) {
- if (code2 == 0x20) {
- // Status Word
- xsens_msg_statusword = XSENS_DATA_StatusWord_status(xsens_msg_buf, offset);
- //gps.tow = xsens_msg_statusword;
-#if USE_GPS_XSENS
- if (bit_is_set(xsens_msg_statusword, 2) && bit_is_set(xsens_msg_statusword, 1)) {
- if (bit_is_set(xsens_msg_statusword, 23) && bit_is_set(xsens_msg_statusword, 24)) {
- gps.fix = GPS_FIX_3D;
- } else {
- gps.fix = GPS_FIX_2D;
- }
- } else { gps.fix = GPS_FIX_NONE; }
-#endif
- }
- } else if (code1 == 0x88) {
- if (code2 == 0x40) {
- gps.week = XSENS_DATA_GpsSol_week(xsens_msg_buf, offset);
- gps.num_sv = XSENS_DATA_GpsSol_numSv(xsens_msg_buf, offset);
- gps.pacc = XSENS_DATA_GpsSol_pAcc(xsens_msg_buf, offset);
- gps.sacc = XSENS_DATA_GpsSol_sAcc(xsens_msg_buf, offset);
- gps.pdop = XSENS_DATA_GpsSol_pDop(xsens_msg_buf, offset);
- } else if (code2 == 0xA0) {
- // SVINFO
- gps.tow = XSENS_XDI_GpsSvInfo_iTOW(xsens_msg_buf + offset);
-
-#if USE_GPS_XSENS
- gps.nb_channels = XSENS_XDI_GpsSvInfo_nch(xsens_msg_buf + offset);
-
- gps.last_3dfix_ticks = sys_time.nb_sec_rem;
- gps.last_3dfix_time = sys_time.nb_sec;
-
- uint8_t i;
- // Do not write outside buffer
- for (i = 0; i < Min(gps.nb_channels, GPS_NB_CHANNELS); i++) {
- uint8_t ch = XSENS_XDI_GpsSvInfo_chn(xsens_msg_buf + offset, i);
- if (ch > gps.nb_channels) { continue; }
- gps.svinfos[ch].svid = XSENS_XDI_GpsSvInfo_svid(xsens_msg_buf + offset, i);
- gps.svinfos[ch].flags = XSENS_XDI_GpsSvInfo_bitmask(xsens_msg_buf + offset, i);
- gps.svinfos[ch].qi = XSENS_XDI_GpsSvInfo_qi(xsens_msg_buf + offset, i);
- gps.svinfos[ch].cno = XSENS_XDI_GpsSvInfo_cnr(xsens_msg_buf + offset, i);
- }
-#endif
- }
- } else if (code1 == 0x50) {
- if (code2 == 0x10) {
- //gps.hmsl = XSENS_DATA_Altitude_h(xsens_msg_buf,offset)* 1000.0f;
- } else if (code2 == 0x20) {
- // Altitude Elipsoid
- gps.utm_pos.alt = XSENS_DATA_Altitude_h(xsens_msg_buf, offset) * 1000.0f;
-
- // Compute geoid (MSL) height
- float geoid_h = wgs84_ellipsoid_to_geoid(lla_f.lat, lla_f.lon);
- gps.hmsl = gps.utm_pos.alt - (geoid_h * 1000.0f);
- SetBit(gps.valid_fields, GPS_VALID_HMSL_BIT);
-
- //gps.tow = geoid_h * 1000.0f; //gps.utm_pos.alt;
- } else if (code2 == 0x40) {
- // LatLong
-#ifdef GPS_LED
- LED_TOGGLE(GPS_LED);
-#endif
- gps.last_3dfix_ticks = sys_time.nb_sec_rem;
- gps.last_3dfix_time = sys_time.nb_sec;
- gps.week = 0; // FIXME
- lla_f.lat = RadOfDeg(XSENS_DATA_LatLon_lat(xsens_msg_buf, offset));
- lla_f.lon = RadOfDeg(XSENS_DATA_LatLon_lon(xsens_msg_buf, offset));
-
- // Set the real UTM zone
- gps.utm_pos.zone = (DegOfRad(lla_f.lon) + 180) / 6 + 1;
-
- utm_f.zone = nav_utm_zone0;
- // convert to utm
- utm_of_lla_f(&utm_f, &lla_f);
- // copy results of utm conversion
- gps.utm_pos.east = utm_f.east * 100;
- gps.utm_pos.north = utm_f.north * 100;
- SetBit(gps.valid_fields, GPS_VALID_POS_UTM_BIT);
-
- gps_xsens_publish();
- }
- } else if (code1 == 0xD0) {
- if (code2 == 0x10) {
- // Velocity
- ins_vx = ((INS_FORMAT)XSENS_DATA_VelocityXYZ_x(xsens_msg_buf, offset));
- ins_vy = ((INS_FORMAT)XSENS_DATA_VelocityXYZ_y(xsens_msg_buf, offset));
- ins_vz = ((INS_FORMAT)XSENS_DATA_VelocityXYZ_z(xsens_msg_buf, offset));
- gps.ned_vel.x = ins_vx;
- gps.ned_vel.y = ins_vy;
- gps.ned_vel.z = ins_vx;
- SetBit(gps.valid_fields, GPS_VALID_VEL_NED_BIT);
- }
- }
-
- if (subpacklen < 0) {
- subpacklen = 0;
- }
- offset += subpacklen;
- }
-
-
- /*
-
- gps.pacc = XSENS_DATA_RAWGPS_hacc(xsens_msg_buf,offset) / 100;
- gps.sacc = XSENS_DATA_RAWGPS_sacc(xsens_msg_buf,offset) / 100;
- gps.pdop = 5; // FIXME Not output by XSens
- */
-
- /*
- */
-
-
- /*
- ins_mx = XSENS_DATA_Calibrated_magX(xsens_msg_buf,offset);
- ins_my = XSENS_DATA_Calibrated_magY(xsens_msg_buf,offset);
- ins_mz = XSENS_DATA_Calibrated_magZ(xsens_msg_buf,offset);
- */
-
-
- /*
- xsens_time_stamp = XSENS_DATA_TimeStamp_ts(xsens_msg_buf,offset);
- #if USE_GPS_XSENS
- gps.tow = xsens_time_stamp;
- #endif
- */
-
- }
-
-}
-
-
-void parse_ins_buffer(uint8_t c)
-{
- ck += c;
- switch (xsens_status) {
- case UNINIT:
- if (c != XSENS_START) {
- goto error;
- }
- xsens_status++;
- ck = 0;
- break;
- case GOT_START:
- if (c != XSENS_BID) {
- goto error;
- }
- xsens_status++;
- break;
- case GOT_BID:
- xsens_id = c;
- xsens_status++;
- break;
- case GOT_MID:
- xsens_len = c;
- if (xsens_len > XSENS_MAX_PAYLOAD) {
- goto error;
- }
- xsens_msg_idx = 0;
- xsens_status++;
- break;
- case GOT_LEN:
- xsens_msg_buf[xsens_msg_idx] = c;
- xsens_msg_idx++;
- if (xsens_msg_idx >= xsens_len) {
- xsens_status++;
- }
- break;
- case GOT_DATA:
- if (ck != 0) {
- goto error;
- }
- ins_msg_received = TRUE;
- goto restart;
- break;
- default:
- break;
- }
- return;
-error:
-restart:
- xsens_status = UNINIT;
- return;
-}
#ifdef USE_GPS_XSENS
/*
* register callbacks & structs
*/
-void gps_xsens_register(void)
+void gps_xsens700_register(void)
{
- gps_register_impl(gps_xsens_init, NULL, GPS_XSENS_ID);
+ gps_register_impl(gps_xsens700_init, NULL, GPS_XSENS_ID);
}
#endif
diff --git a/sw/airborne/modules/ins/ins_xsens700.h b/sw/airborne/modules/ins/ins_xsens700.h
new file mode 100644
index 0000000000..75bd5fc380
--- /dev/null
+++ b/sw/airborne/modules/ins/ins_xsens700.h
@@ -0,0 +1,56 @@
+/*
+ * Copyright (C) 2010 ENAC
+ *
+ * This file is part of paparazzi.
+ *
+ * paparazzi is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * paparazzi is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with paparazzi; see the file COPYING. If not, write to
+ * the Free Software Foundation, 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ */
+
+/**
+ * @file modules/ins/ins_xsens700.h
+ * Xsens700 as a full INS solution
+ */
+
+#ifndef INS_XSENS700_H
+#define INS_XSENS700_H
+
+#include "std.h"
+
+#include "xsens700.h"
+
+#ifdef AHRS_TRIGGERED_ATTITUDE_LOOP
+extern volatile uint8_t new_ins_attitude;
+#endif
+
+extern float ins_pitch_neutral;
+extern float ins_roll_neutral;
+
+#define DefaultInsImpl ins_xsens700
+
+extern void ins_xsens700_init(void);
+extern void ins_xsens700_register(void);
+extern void ins_xsens700_event(void);
+
+#if USE_GPS_XSENS
+#ifndef PRIMARY_GPS
+#define PRIMARY_GPS gps_xsens700
+#endif
+extern void gps_xsens700_init(void);
+extern void gps_xsens700_register(void);
+#endif
+
+#endif
diff --git a/sw/airborne/modules/ins/xsens.c b/sw/airborne/modules/ins/xsens.c
new file mode 100644
index 0000000000..f0ae21cf52
--- /dev/null
+++ b/sw/airborne/modules/ins/xsens.c
@@ -0,0 +1,373 @@
+/*
+ * Copyright (C) 2003 Pascal Brisset, Antoine Drouin
+ *
+ * This file is part of paparazzi.
+ *
+ * paparazzi is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * paparazzi is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with paparazzi; see the file COPYING. If not, write to
+ * the Free Software Foundation, 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+/** @file modules/ins/xsens.c
+ * Parser for the Xsens protocol.
+ */
+
+#include "xsens.h"
+#include "xsens_common.h"
+
+#include "generated/airframe.h"
+
+#if USE_GPS_XSENS
+#include "math/pprz_geodetic_wgs84.h"
+#endif
+
+// FIXME Debugging Only
+#include "mcu_periph/uart.h"
+#include "pprzlink/messages.h"
+#include "subsystems/datalink/downlink.h"
+
+
+/* output mode : calibrated, orientation, position, velocity, status
+ * -----------
+ *
+ * bit 0 temp
+ * bit 1 calibrated
+ * bit 2 orentation
+ * bit 3 aux
+ *
+ * bit 4 position
+ * bit 5 velocity
+ * bit 6-7 Reserved
+ *
+ * bit 8-10 Reserved
+ * bit 11 status
+ *
+ * bit 12 GPS PVT+baro
+ * bit 13 Reserved
+ * bit 14 Raw
+ * bit 15 Reserved
+ */
+
+#ifndef XSENS_OUTPUT_MODE
+#define XSENS_OUTPUT_MODE 0x1836
+#endif
+/* output settings : timestamp, euler, acc, rate, mag, float, no aux, lla, m/s, NED
+ * -----------
+ *
+ * bit 01 0=none, 1=sample counter, 2=utc, 3=sample+utc
+ * bit 23 0=quaternion, 1=euler, 2=DCM
+ *
+ * bit 4 1=disable acc output
+ * bit 5 1=disable gyro output
+ * bit 6 1=disable magneto output
+ * bit 7 Reserved
+ *
+ * bit 89 0=float, 1=fixedpoint12.20, 2=fixedpoint16.32
+ * bit 10 1=disable aux analog 1
+ * bit 11 1=disable aux analog 2
+ *
+ * bit 12-15 0-only: 14-16 WGS84
+ *
+ * bit 16-19 0-only: 16-18 m/s XYZ
+ *
+ * bit 20-23 Reserved
+ *
+ * bit 24-27 Reseverd
+ *
+ * bit 28-30 Reseverd
+ * bit 31 0=X-North-Z-Up, 1=North-East-Down
+ */
+#ifndef XSENS_OUTPUT_SETTINGS
+#define XSENS_OUTPUT_SETTINGS 0x80000C05
+#endif
+
+uint8_t xsens_errorcode;
+uint8_t xsens_msg_status;
+uint16_t xsens_time_stamp;
+uint16_t xsens_output_mode;
+uint32_t xsens_output_settings;
+
+
+float xsens_declination = 0;
+float xsens_gps_arm_x = 0;
+float xsens_gps_arm_y = 0;
+float xsens_gps_arm_z = 0;
+
+volatile int xsens_configured = 0;
+
+struct Xsens xsens;
+
+void parse_xsens_buffer(uint8_t c);
+
+void xsens_init(void)
+{
+ xsens_status = UNINIT;
+ xsens_configured = 20;
+
+ xsens_msg_status = 0;
+ xsens_time_stamp = 0;
+ xsens_output_mode = XSENS_OUTPUT_MODE;
+ xsens_output_settings = XSENS_OUTPUT_SETTINGS;
+}
+
+void xsens_periodic(void)
+{
+ if (xsens_configured > 0) {
+ switch (xsens_configured) {
+ case 20:
+ /* send mode and settings to MT */
+ XSENS_GoToConfig();
+ XSENS_SetOutputMode(xsens_output_mode);
+ XSENS_SetOutputSettings(xsens_output_settings);
+ break;
+ case 18:
+ // Give pulses on SyncOut
+ XSENS_SetSyncOutSettings(0, 0x0002);
+ break;
+ case 17:
+ // 1 pulse every 100 samples
+ XSENS_SetSyncOutSettings(1, 100);
+ break;
+ case 2:
+ XSENS_ReqLeverArmGps();
+ break;
+
+ case 6:
+ XSENS_ReqMagneticDeclination();
+ break;
+
+ case 13:
+#ifdef AHRS_H_X
+#pragma message "Sending XSens Magnetic Declination."
+ xsens_declination = atan2(AHRS_H_Y, AHRS_H_X);
+ XSENS_SetMagneticDeclination(xsens_declination);
+#endif
+ break;
+ case 12:
+#ifdef GPS_IMU_LEVER_ARM_X
+#pragma message "Sending XSens GPS Arm."
+ XSENS_SetLeverArmGps(GPS_IMU_LEVER_ARM_X, GPS_IMU_LEVER_ARM_Y, GPS_IMU_LEVER_ARM_Z);
+#endif
+ break;
+ case 10: {
+ uint8_t baud = 1;
+ XSENS_SetBaudrate(baud);
+ }
+ break;
+
+ case 1:
+ XSENS_GoToMeasurment();
+ break;
+
+ default:
+ break;
+ }
+ xsens_configured--;
+ return;
+ }
+
+ RunOnceEvery(100, XSENS_ReqGPSStatus());
+}
+
+
+void parse_xsens_msg(void)
+{
+ uint8_t offset = 0;
+ if (xsens_id == XSENS_ReqOutputModeAck_ID) {
+ xsens_output_mode = XSENS_ReqOutputModeAck_mode(xsens_msg_buf);
+ } else if (xsens_id == XSENS_ReqOutputSettings_ID) {
+ xsens_output_settings = XSENS_ReqOutputSettingsAck_settings(xsens_msg_buf);
+ } else if (xsens_id == XSENS_ReqMagneticDeclinationAck_ID) {
+ xsens_declination = DegOfRad(XSENS_ReqMagneticDeclinationAck_declination(xsens_msg_buf));
+
+ DOWNLINK_SEND_IMU_MAG_SETTINGS(DefaultChannel, DefaultDevice, &xsens_declination, &xsens_declination, &xsens_gps_arm_x,
+ &xsens_gps_arm_y, &xsens_gps_arm_z);
+ } else if (xsens_id == XSENS_ReqLeverArmGpsAck_ID) {
+ xsens_gps_arm_x = XSENS_ReqLeverArmGpsAck_x(xsens_msg_buf);
+ xsens_gps_arm_y = XSENS_ReqLeverArmGpsAck_y(xsens_msg_buf);
+ xsens_gps_arm_z = XSENS_ReqLeverArmGpsAck_z(xsens_msg_buf);
+
+ DOWNLINK_SEND_IMU_MAG_SETTINGS(DefaultChannel, DefaultDevice, &xsens_declination, &xsens_declination, &xsens_gps_arm_x,
+ &xsens_gps_arm_y, &xsens_gps_arm_z);
+ } else if (xsens_id == XSENS_Error_ID) {
+ xsens_errorcode = XSENS_Error_errorcode(xsens_msg_buf);
+ }
+#if USE_GPS_XSENS
+ else if (xsens_id == XSENS_GPSStatus_ID) {
+ xsens.gps.nb_channels = XSENS_GPSStatus_nch(xsens_msg_buf);
+ xsens.gps.num_sv = 0;
+
+ uint8_t i;
+ // Do not write outside buffer
+ for (i = 0; i < Min(xsens.gps.nb_channels, GPS_NB_CHANNELS); i++) {
+ uint8_t ch = XSENS_GPSStatus_chn(xsens_msg_buf, i);
+ if (ch > xsens.gps.nb_channels) { continue; }
+ xsens.gps.svinfos[ch].svid = XSENS_GPSStatus_svid(xsens_msg_buf, i);
+ xsens.gps.svinfos[ch].flags = XSENS_GPSStatus_bitmask(xsens_msg_buf, i);
+ xsens.gps.svinfos[ch].qi = XSENS_GPSStatus_qi(xsens_msg_buf, i);
+ xsens.gps.svinfos[ch].cno = XSENS_GPSStatus_cnr(xsens_msg_buf, i);
+ if (xsens.gps.svinfos[ch].flags > 0) {
+ xsens.gps.num_sv++;
+ }
+ }
+ }
+#endif
+ else if (xsens_id == XSENS_MTData_ID) {
+ /* test RAW modes else calibrated modes */
+ //if ((XSENS_MASK_RAWInertial(xsens_output_mode)) || (XSENS_MASK_RAWGPS(xsens_output_mode))) {
+ if (XSENS_MASK_RAWInertial(xsens_output_mode)) {
+ /* should we write raw data to separate struct? */
+ xsens.gyro.p = XSENS_DATA_RAWInertial_gyrX(xsens_msg_buf, offset);
+ xsens.gyro.q = XSENS_DATA_RAWInertial_gyrY(xsens_msg_buf, offset);
+ xsens.gyro.r = XSENS_DATA_RAWInertial_gyrZ(xsens_msg_buf, offset);
+ xsens.gyro_available = TRUE;
+ offset += XSENS_DATA_RAWInertial_LENGTH;
+ }
+ if (XSENS_MASK_RAWGPS(xsens_output_mode)) {
+#if USE_GPS_XSENS_RAW_DATA && USE_GPS_XSENS
+ xsens.gps.week = 0; // FIXME
+ xsens.gps.tow = XSENS_DATA_RAWGPS_itow(xsens_msg_buf, offset) * 10;
+ xsens.gps.lla_pos.lat = XSENS_DATA_RAWGPS_lat(xsens_msg_buf, offset);
+ xsens.gps.lla_pos.lon = XSENS_DATA_RAWGPS_lon(xsens_msg_buf, offset);
+ xsens.gps.lla_pos.alt = XSENS_DATA_RAWGPS_alt(xsens_msg_buf, offset);
+ SetBit(xsens.gps.valid_fields, GPS_VALID_POS_LLA_BIT);
+
+ // Compute geoid (MSL) height
+ float hmsl = wgs84_ellipsoid_to_geoid_i(xsens.gps.lla_pos.lat, xsens.gps.lla_pos.lon);
+ xsens.gps.hmsl = XSENS_DATA_RAWGPS_alt(xsens_msg_buf, offset) - (hmsl * 1000.0f);
+ SetBit(gps.valid_fields, GPS_VALID_HMSL_BIT);
+
+ xsens.gps.ned_vel.x = XSENS_DATA_RAWGPS_vel_n(xsens_msg_buf, offset);
+ xsens.gps.ned_vel.y = XSENS_DATA_RAWGPS_vel_e(xsens_msg_buf, offset);
+ xsens.gps.ned_vel.z = XSENS_DATA_RAWGPS_vel_d(xsens_msg_buf, offset);
+ SetBit(gps.valid_fields, GPS_VALID_VEL_NED_BIT);
+ xsens.gps.pacc = XSENS_DATA_RAWGPS_hacc(xsens_msg_buf, offset) / 100;
+ xsens.gps.sacc = XSENS_DATA_RAWGPS_sacc(xsens_msg_buf, offset) / 100;
+ xsens.gps.pdop = 5; // FIXME Not output by XSens
+
+ xsens.gps_available = TRUE;
+#endif
+ offset += XSENS_DATA_RAWGPS_LENGTH;
+ }
+ //} else {
+ if (XSENS_MASK_Temp(xsens_output_mode)) {
+ offset += XSENS_DATA_Temp_LENGTH;
+ }
+ if (XSENS_MASK_Calibrated(xsens_output_mode)) {
+ uint8_t l = 0;
+ if (!XSENS_MASK_AccOut(xsens_output_settings)) {
+ xsens.accel.x = XSENS_DATA_Calibrated_accX(xsens_msg_buf, offset);
+ xsens.accel.y = XSENS_DATA_Calibrated_accY(xsens_msg_buf, offset);
+ xsens.accel.z = XSENS_DATA_Calibrated_accZ(xsens_msg_buf, offset);
+ xsens.accel_available = TRUE;
+ l++;
+ }
+ if (!XSENS_MASK_GyrOut(xsens_output_settings)) {
+ xsens.gyro.p = XSENS_DATA_Calibrated_gyrX(xsens_msg_buf, offset);
+ xsens.gyro.q = XSENS_DATA_Calibrated_gyrY(xsens_msg_buf, offset);
+ xsens.gyro.r = XSENS_DATA_Calibrated_gyrZ(xsens_msg_buf, offset);
+ xsens.gyro_available = TRUE;
+ l++;
+ }
+ if (!XSENS_MASK_MagOut(xsens_output_settings)) {
+ xsens.mag.x = XSENS_DATA_Calibrated_magX(xsens_msg_buf, offset);
+ xsens.mag.y = XSENS_DATA_Calibrated_magY(xsens_msg_buf, offset);
+ xsens.mag.z = XSENS_DATA_Calibrated_magZ(xsens_msg_buf, offset);
+ xsens.mag_available = TRUE;
+ l++;
+ }
+ offset += l * XSENS_DATA_Calibrated_LENGTH / 3;
+ }
+ if (XSENS_MASK_Orientation(xsens_output_mode)) {
+ if (XSENS_MASK_OrientationMode(xsens_output_settings) == 0x00) {
+ xsens.quat.qi = XSENS_DATA_Quaternion_q0(xsens_msg_buf, offset);
+ xsens.quat.qx = XSENS_DATA_Quaternion_q1(xsens_msg_buf, offset);
+ xsens.quat.qy = XSENS_DATA_Quaternion_q2(xsens_msg_buf, offset);
+ xsens.quat.qz = XSENS_DATA_Quaternion_q3(xsens_msg_buf, offset);
+ //float_eulers_of_quat(&xsens.euler, &xsens.quat);
+ offset += XSENS_DATA_Quaternion_LENGTH;
+ }
+ if (XSENS_MASK_OrientationMode(xsens_output_settings) == 0x01) {
+ xsens.euler.phi = XSENS_DATA_Euler_roll(xsens_msg_buf, offset) * M_PI / 180;
+ xsens.euler.theta = XSENS_DATA_Euler_pitch(xsens_msg_buf, offset) * M_PI / 180;
+ xsens.euler.psi = XSENS_DATA_Euler_yaw(xsens_msg_buf, offset) * M_PI / 180;
+ offset += XSENS_DATA_Euler_LENGTH;
+ }
+ if (XSENS_MASK_OrientationMode(xsens_output_settings) == 0x10) {
+ offset += XSENS_DATA_Matrix_LENGTH;
+ }
+ xsens.new_attitude = TRUE;
+ }
+ if (XSENS_MASK_Auxiliary(xsens_output_mode)) {
+ uint8_t l = 0;
+ if (!XSENS_MASK_Aux1Out(xsens_output_settings)) {
+ l++;
+ }
+ if (!XSENS_MASK_Aux2Out(xsens_output_settings)) {
+ l++;
+ }
+ offset += l * XSENS_DATA_Auxiliary_LENGTH / 2;
+ }
+ if (XSENS_MASK_Position(xsens_output_mode)) {
+ xsens.lla_f.lat = RadOfDeg(XSENS_DATA_Position_lat(xsens_msg_buf, offset));
+ xsens.lla_f.lon = RadOfDeg(XSENS_DATA_Position_lon(xsens_msg_buf, offset));
+ xsens.lla_f.alt = XSENS_DATA_Position_alt(xsens_msg_buf, offset);
+ offset += XSENS_DATA_Position_LENGTH;
+
+#if (! USE_GPS_XSENS_RAW_DATA) && USE_GPS_XSENS
+ LLA_BFP_OF_REAL(xsens.gps.lla_pos, xsens.lla_f);
+ SetBit(gps.valid_fields, GPS_VALID_POS_LLA_BIT);
+ xsens.gps_available = TRUE;
+#endif
+ }
+ if (XSENS_MASK_Velocity(xsens_output_mode)) {
+ xsens.vel.x = XSENS_DATA_Velocity_vx(xsens_msg_buf, offset);
+ xsens.vel.y = XSENS_DATA_Velocity_vy(xsens_msg_buf, offset);
+ xsens.vel.z = XSENS_DATA_Velocity_vz(xsens_msg_buf, offset);
+ offset += XSENS_DATA_Velocity_LENGTH;
+ }
+ if (XSENS_MASK_Status(xsens_output_mode)) {
+ xsens_msg_status = XSENS_DATA_Status_status(xsens_msg_buf, offset);
+#if USE_GPS_XSENS
+ if (bit_is_set(xsens_msg_status, 2)) { xsens.gps.fix = GPS_FIX_3D; } // gps fix
+ else if (bit_is_set(xsens_msg_status, 1)) { xsens.gps.fix = 0x01; } // efk valid
+ else { xsens.gps.fix = GPS_FIX_NONE; }
+#ifdef GPS_LED
+ if (xsens.gps.fix == GPS_FIX_3D) {
+ LED_ON(GPS_LED);
+ } else {
+ LED_TOGGLE(GPS_LED);
+ }
+#endif // GPS_LED
+#endif // USE_GPS_XSENS
+ offset += XSENS_DATA_Status_LENGTH;
+ }
+ if (XSENS_MASK_TimeStamp(xsens_output_settings)) {
+ xsens.time_stamp = XSENS_DATA_TimeStamp_ts(xsens_msg_buf, offset);
+ offset += XSENS_DATA_TimeStamp_LENGTH;
+ }
+ if (XSENS_MASK_UTC(xsens_output_settings)) {
+ xsens.time.hour = XSENS_DATA_UTC_hour(xsens_msg_buf, offset);
+ xsens.time.min = XSENS_DATA_UTC_min(xsens_msg_buf, offset);
+ xsens.time.sec = XSENS_DATA_UTC_sec(xsens_msg_buf, offset);
+ xsens.time.nanosec = XSENS_DATA_UTC_nanosec(xsens_msg_buf, offset);
+ xsens.time.year = XSENS_DATA_UTC_year(xsens_msg_buf, offset);
+ xsens.time.month = XSENS_DATA_UTC_month(xsens_msg_buf, offset);
+ xsens.time.day = XSENS_DATA_UTC_day(xsens_msg_buf, offset);
+
+ offset += XSENS_DATA_UTC_LENGTH;
+ }
+ }
+
+}
diff --git a/sw/airborne/modules/ins/xsens.h b/sw/airborne/modules/ins/xsens.h
new file mode 100644
index 0000000000..b8a3f07930
--- /dev/null
+++ b/sw/airborne/modules/ins/xsens.h
@@ -0,0 +1,82 @@
+/*
+ * Copyright (C) 2010 ENAC
+ *
+ * This file is part of paparazzi.
+ *
+ * paparazzi is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * paparazzi is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with paparazzi; see the file COPYING. If not, write to
+ * the Free Software Foundation, 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ */
+
+/** @file modules/ins/xsens.h
+ * Parser for the Xsens protocol.
+ */
+
+#ifndef XSENS_H
+#define XSENS_H
+
+#include "std.h"
+#include "math/pprz_algebra_float.h"
+#include "math/pprz_geodetic_float.h"
+#include "math/pprz_geodetic_int.h"
+
+#if USE_GPS_XSENS
+#include "subsystems/gps.h"
+#endif
+
+struct XsensTime {
+ int8_t hour;
+ int8_t min;
+ int8_t sec;
+ int32_t nanosec;
+ int16_t year;
+ int8_t month;
+ int8_t day;
+};
+
+struct Xsens {
+ struct XsensTime time;
+ uint16_t time_stamp;
+
+ struct FloatRates gyro;
+ struct FloatVect3 accel;
+ struct FloatVect3 mag;
+
+ struct LlaCoor_f lla_f;
+ struct FloatVect3 vel; ///< NED velocity in m/s
+
+ struct FloatQuat quat;
+ struct FloatEulers euler;
+
+ volatile bool_t msg_received;
+ volatile bool_t new_attitude;
+
+ bool_t gyro_available;
+ bool_t accel_available;
+ bool_t mag_available;
+
+#if USE_GPS_XSENS
+ struct GpsState gps;
+ bool_t gps_available;
+#endif
+};
+
+extern struct Xsens xsens;
+
+extern void xsens_init(void);
+extern void xsens_periodic(void);
+extern void parse_xsens_msg(void);
+
+#endif /* XSENS_H */
diff --git a/sw/airborne/modules/ins/xsens700.c b/sw/airborne/modules/ins/xsens700.c
new file mode 100644
index 0000000000..c9e76ac923
--- /dev/null
+++ b/sw/airborne/modules/ins/xsens700.c
@@ -0,0 +1,285 @@
+/*
+ * Copyright (C) 2013 Christophe De Wagter
+ *
+ * This file is part of paparazzi.
+ *
+ * paparazzi is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * paparazzi is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with paparazzi; see the file COPYING. If not, write to
+ * the Free Software Foundation, 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ */
+
+/**
+ * @file modules/ins/xsens700.c
+ * Parser for the Xsens700 protocol.
+ */
+
+#include "xsens700.h"
+#include "xsens_common.h"
+
+#include "generated/airframe.h"
+
+#if USE_GPS_XSENS
+#include "math/pprz_geodetic_wgs84.h"
+#endif
+
+// FIXME Debugging Only
+#include "mcu_periph/uart.h"
+#include "pprzlink/messages.h"
+#include "subsystems/datalink/downlink.h"
+
+
+uint8_t xsens_errorcode;
+uint32_t xsens_msg_statusword;
+uint16_t xsens_time_stamp;
+uint16_t xsens_output_mode;
+uint32_t xsens_output_settings;
+
+float xsens_gps_arm_x = 0;
+float xsens_gps_arm_y = 0;
+float xsens_gps_arm_z = 0;
+
+struct Xsens xsens700;
+
+volatile int xsens_configured = 0;
+
+void xsens700_init(void)
+{
+ xsens_status = UNINIT;
+ xsens_configured = 30;
+
+ xsens_msg_statusword = 0;
+ xsens_time_stamp = 0;
+}
+
+static void xsens_ask_message_rate(uint8_t c1, uint8_t c2, uint8_t freq)
+{
+ uint8_t foo = 0;
+ XsensSend1ByAddr(&c1);
+ XsensSend1ByAddr(&c2);
+ XsensSend1ByAddr(&foo);
+ XsensSend1ByAddr(&freq);
+}
+
+void xsens700_periodic(void)
+{
+ if (xsens_configured > 0) {
+ switch (xsens_configured) {
+ case 25:
+ /* send mode and settings to MT */
+ XSENS_GoToConfig();
+ //XSENS_SetOutputMode(xsens_output_mode);
+ //XSENS_SetOutputSettings(xsens_output_settings);
+ break;
+ case 18:
+ // Give pulses on SyncOut
+ //XSENS_SetSyncOutSettings(0,0x0002);
+ break;
+ case 17:
+
+ XsensHeader(XSENS_SetOutputConfiguration_ID, 44);
+ xsens_ask_message_rate(0x10, 0x10, 4); // UTC
+ xsens_ask_message_rate(0x20, 0x30, 100); // Attitude Euler
+ xsens_ask_message_rate(0x40, 0x10, 100); // Delta-V
+ xsens_ask_message_rate(0x80, 0x20, 100); // Rate of turn
+ xsens_ask_message_rate(0xE0, 0x20, 50); // Status
+ xsens_ask_message_rate(0x30, 0x10, 50); // Baro Pressure
+ xsens_ask_message_rate(0x88, 0x40, 1); // NavSol
+ xsens_ask_message_rate(0x88, 0xA0, 1); // SV Info
+ xsens_ask_message_rate(0x50, 0x20, 50); // GPS Altitude Ellipsiod
+ xsens_ask_message_rate(0x50, 0x40, 50); // GPS Position
+ xsens_ask_message_rate(0xD0, 0x10, 50); // GPS Speed
+ XsensTrailer();
+ break;
+ case 2:
+ //XSENS_ReqLeverArmGps();
+ break;
+
+ case 6:
+ //XSENS_ReqMagneticDeclination();
+ break;
+
+ case 13:
+ //#ifdef AHRS_H_X
+ //#pragma message "Sending XSens Magnetic Declination."
+ //xsens_declination = atan2(AHRS_H_Y, AHRS_H_X);
+ //XSENS_SetMagneticDeclination(xsens_declination);
+ //#endif
+ break;
+ case 12:
+#ifdef GPS_IMU_LEVER_ARM_X
+#pragma message "Sending XSens GPS Arm."
+ XSENS_SetLeverArmGps(GPS_IMU_LEVER_ARM_X, GPS_IMU_LEVER_ARM_Y, GPS_IMU_LEVER_ARM_Z);
+#endif
+ break;
+ case 10: {
+ uint8_t baud = 1;
+ XSENS_SetBaudrate(baud);
+ }
+ break;
+
+ case 1:
+ XSENS_GoToMeasurment();
+ break;
+ default:
+ break;
+ }
+ xsens_configured--;
+ return;
+ }
+
+}
+
+
+void parse_xsens700_msg(void)
+{
+ uint8_t offset = 0;
+ if (xsens_id == XSENS_ReqLeverArmGpsAck_ID) {
+ xsens_gps_arm_x = XSENS_ReqLeverArmGpsAck_x(xsens_msg_buf);
+ xsens_gps_arm_y = XSENS_ReqLeverArmGpsAck_y(xsens_msg_buf);
+ xsens_gps_arm_z = XSENS_ReqLeverArmGpsAck_z(xsens_msg_buf);
+ } else if (xsens_id == XSENS_Error_ID) {
+ xsens_errorcode = XSENS_Error_errorcode(xsens_msg_buf);
+ } else if (xsens_id == XSENS_MTData2_ID) {
+ for (offset = 0; offset < xsens_len;) {
+ uint8_t code1 = xsens_msg_buf[offset];
+ uint8_t code2 = xsens_msg_buf[offset + 1];
+ int subpacklen = (int)xsens_msg_buf[offset + 2];
+ offset += 3;
+
+ if (code1 == 0x10) {
+ if (code2 == 0x10) {
+ // UTC
+ } else if (code2 == 0x20) {
+ // Packet Counter
+ }
+ if (code2 == 0x30) {
+ // ITOW
+ }
+ } else if (code1 == 0x20) {
+ if (code2 == 0x30) {
+ // Attitude Euler
+ xsens700.euler.phi = XSENS_DATA_Euler_roll(xsens_msg_buf, offset) * M_PI / 180;
+ xsens700.euler.theta = XSENS_DATA_Euler_pitch(xsens_msg_buf, offset) * M_PI / 180;
+ xsens700.euler.psi = XSENS_DATA_Euler_yaw(xsens_msg_buf, offset) * M_PI / 180;
+
+ xsens700.new_attitude = TRUE;
+ }
+ } else if (code1 == 0x40) {
+ if (code2 == 0x10) {
+ // Delta-V
+ xsens700.accel.x = XSENS_DATA_Acceleration_x(xsens_msg_buf, offset) * 100.0f;
+ xsens700.accel.y = XSENS_DATA_Acceleration_y(xsens_msg_buf, offset) * 100.0f;
+ xsens700.accel.z = XSENS_DATA_Acceleration_z(xsens_msg_buf, offset) * 100.0f;
+ }
+ } else if (code1 == 0x80) {
+ if (code2 == 0x20) {
+ // Rate Of Turn
+ xsens700.gyro.p = XSENS_DATA_RateOfTurn_x(xsens_msg_buf, offset) * M_PI / 180;
+ xsens700.gyro.q = XSENS_DATA_RateOfTurn_y(xsens_msg_buf, offset) * M_PI / 180;
+ xsens700.gyro.r = XSENS_DATA_RateOfTurn_z(xsens_msg_buf, offset) * M_PI / 180;
+ }
+ } else if (code1 == 0x30) {
+ if (code2 == 0x10) {
+ // Baro Pressure
+ }
+ } else if (code1 == 0xE0) {
+ if (code2 == 0x20) {
+ // Status Word
+ xsens_msg_statusword = XSENS_DATA_StatusWord_status(xsens_msg_buf, offset);
+ //xsens700.gps.tow = xsens_msg_statusword;
+#if USE_GPS_XSENS
+ if (bit_is_set(xsens_msg_statusword, 2) && bit_is_set(xsens_msg_statusword, 1)) {
+ if (bit_is_set(xsens_msg_statusword, 23) && bit_is_set(xsens_msg_statusword, 24)) {
+ xsens700.gps.fix = GPS_FIX_3D;
+ } else {
+ xsens700.gps.fix = GPS_FIX_2D;
+ }
+ } else { xsens700.gps.fix = GPS_FIX_NONE; }
+#endif
+ }
+ } else if (code1 == 0x88) {
+ if (code2 == 0x40) {
+ xsens700.gps.week = XSENS_DATA_GpsSol_week(xsens_msg_buf, offset);
+ xsens700.gps.num_sv = XSENS_DATA_GpsSol_numSv(xsens_msg_buf, offset);
+ xsens700.gps.pacc = XSENS_DATA_GpsSol_pAcc(xsens_msg_buf, offset);
+ xsens700.gps.sacc = XSENS_DATA_GpsSol_sAcc(xsens_msg_buf, offset);
+ xsens700.gps.pdop = XSENS_DATA_GpsSol_pDop(xsens_msg_buf, offset);
+ } else if (code2 == 0xA0) {
+ // SVINFO
+ xsens700.gps.tow = XSENS_XDI_GpsSvInfo_iTOW(xsens_msg_buf + offset);
+
+#if USE_GPS_XSENS
+ xsens700.gps.nb_channels = XSENS_XDI_GpsSvInfo_nch(xsens_msg_buf + offset);
+
+ xsens700.gps.last_3dfix_ticks = sys_time.nb_sec_rem;
+ xsens700.gps.last_3dfix_time = sys_time.nb_sec;
+
+ uint8_t i;
+ // Do not write outside buffer
+ for (i = 0; i < Min(xsens700.gps.nb_channels, GPS_NB_CHANNELS); i++) {
+ uint8_t ch = XSENS_XDI_GpsSvInfo_chn(xsens_msg_buf + offset, i);
+ if (ch > xsens700.gps.nb_channels) { continue; }
+ xsens700.gps.svinfos[ch].svid = XSENS_XDI_GpsSvInfo_svid(xsens_msg_buf + offset, i);
+ xsens700.gps.svinfos[ch].flags = XSENS_XDI_GpsSvInfo_bitmask(xsens_msg_buf + offset, i);
+ xsens700.gps.svinfos[ch].qi = XSENS_XDI_GpsSvInfo_qi(xsens_msg_buf + offset, i);
+ xsens700.gps.svinfos[ch].cno = XSENS_XDI_GpsSvInfo_cnr(xsens_msg_buf + offset, i);
+ }
+#endif
+ }
+ } else if (code1 == 0x50) {
+ if (code2 == 0x10) {
+ //xsens700.gps.hmsl = XSENS_DATA_Altitude_h(xsens_msg_buf,offset)* 1000.0f;
+ } else if (code2 == 0x20) {
+ // Altitude Elipsoid
+ xsens700.gps.lla_pos.alt = XSENS_DATA_Altitude_h(xsens_msg_buf, offset) * 1000.0f;
+
+ // Compute geoid (MSL) height
+ float geoid_h = wgs84_ellipsoid_to_geoid(xsens700.lla_f.lat, xsens700.lla_f.lon);
+ xsens700.gps.hmsl = xsens700.gps.lla_pos.alt - (geoid_h * 1000.0f);
+ SetBit(xsens700.gps.valid_fields, GPS_VALID_HMSL_BIT);
+
+ //xsens700.gps.tow = geoid_h * 1000.0f; //xsens700.gps.utm_pos.alt;
+ } else if (code2 == 0x40) {
+ // LatLong
+#ifdef GPS_LED
+ LED_TOGGLE(GPS_LED);
+#endif
+ xsens700.gps.last_3dfix_ticks = sys_time.nb_sec_rem;
+ xsens700.gps.last_3dfix_time = sys_time.nb_sec;
+ xsens700.gps.week = 0; // FIXME
+
+ xsens700.lla_f.lat = RadOfDeg(XSENS_DATA_LatLon_lat(xsens_msg_buf, offset));
+ xsens700.lla_f.lon = RadOfDeg(XSENS_DATA_LatLon_lon(xsens_msg_buf, offset));
+ }
+ } else if (code1 == 0xD0) {
+ if (code2 == 0x10) {
+ // Velocity
+ xsens700.vel.x = XSENS_DATA_VelocityXYZ_x(xsens_msg_buf, offset);
+ xsens700.vel.y = XSENS_DATA_VelocityXYZ_y(xsens_msg_buf, offset);
+ xsens700.vel.z = XSENS_DATA_VelocityXYZ_z(xsens_msg_buf, offset);
+ xsens700.gps.ned_vel.x = xsens700.vel.x;
+ xsens700.gps.ned_vel.y = xsens700.vel.y;
+ xsens700.gps.ned_vel.z = xsens700.vel.x;
+ SetBit(xsens700.gps.valid_fields, GPS_VALID_VEL_NED_BIT);
+ }
+ }
+
+ if (subpacklen < 0) {
+ subpacklen = 0;
+ }
+ offset += subpacklen;
+ }
+ }
+}
diff --git a/sw/airborne/modules/ins/xsens700.h b/sw/airborne/modules/ins/xsens700.h
new file mode 100644
index 0000000000..b5d0009fec
--- /dev/null
+++ b/sw/airborne/modules/ins/xsens700.h
@@ -0,0 +1,82 @@
+/*
+ * Copyright (C) 2010 ENAC
+ *
+ * This file is part of paparazzi.
+ *
+ * paparazzi is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * paparazzi is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with paparazzi; see the file COPYING. If not, write to
+ * the Free Software Foundation, 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ */
+
+/** @file modules/ins/xsens_700.h
+ * Parser for the Xsens protocol.
+ */
+
+#ifndef XSENS700_H
+#define XSENS700_H
+
+#include "std.h"
+#include "math/pprz_algebra_float.h"
+#include "math/pprz_geodetic_float.h"
+#include "math/pprz_geodetic_int.h"
+
+#if USE_GPS_XSENS
+#include "subsystems/gps.h"
+#endif
+
+struct XsensTime {
+ int8_t hour;
+ int8_t min;
+ int8_t sec;
+ int32_t nanosec;
+ int16_t year;
+ int8_t month;
+ int8_t day;
+};
+
+struct Xsens {
+ struct XsensTime time;
+ uint16_t time_stamp;
+
+ struct FloatRates gyro;
+ struct FloatVect3 accel;
+ struct FloatVect3 mag;
+
+ struct LlaCoor_f lla_f;
+ struct FloatVect3 vel; ///< NED velocity in m/s
+
+ struct FloatQuat quat;
+ struct FloatEulers euler;
+
+ volatile bool_t msg_received;
+ volatile bool_t new_attitude;
+
+ bool_t gyro_available;
+ bool_t accel_available;
+ bool_t mag_available;
+
+#if USE_GPS_XSENS
+ struct GpsState gps;
+ bool_t gps_available;
+#endif
+};
+
+extern struct Xsens xsens700;
+
+extern void xsens700_init(void);
+extern void xsens700_periodic(void);
+extern void parse_xsens700_msg(void);
+
+#endif /* XSENS700_H */
diff --git a/sw/airborne/modules/ins/xsens_common.c b/sw/airborne/modules/ins/xsens_common.c
new file mode 100644
index 0000000000..4c2c9ba95a
--- /dev/null
+++ b/sw/airborne/modules/ins/xsens_common.c
@@ -0,0 +1,105 @@
+/*
+ * Copyright (C) 2003 Pascal Brisset, Antoine Drouin
+ *
+ * This file is part of paparazzi.
+ *
+ * paparazzi is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * paparazzi is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with paparazzi; see the file COPYING. If not, write to
+ * the Free Software Foundation, 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+/** @file modules/ins/xsens_common.c
+ * Parser for the Xsens protocol.
+ */
+
+#include "xsens_common.h"
+
+#include "pprzlink/pprzlink_device.h"
+#include "mcu_periph/uart.h"
+
+volatile uint8_t xsens_msg_received;
+
+uint8_t xsens_id;
+uint8_t xsens_status;
+uint8_t xsens_len;
+uint8_t xsens_msg_idx;
+uint8_t ck;
+uint8_t send_ck;
+
+uint8_t xsens_msg_buf[XSENS_MAX_PAYLOAD];
+
+void parse_xsens_buffer(uint8_t c);
+
+void xsens_event(void)
+{
+ struct link_device *dev = &((XSENS_LINK).device);
+ if (dev->char_available(dev->periph)) {
+ while (dev->char_available(dev->periph) && !xsens_msg_received) {
+ parse_xsens_buffer(dev->get_byte(dev->periph));
+ }
+ }
+}
+
+void parse_xsens_buffer(uint8_t c)
+{
+ ck += c;
+ switch (xsens_status) {
+ case UNINIT:
+ if (c != XSENS_START) {
+ goto error;
+ }
+ xsens_status++;
+ ck = 0;
+ break;
+ case GOT_START:
+ if (c != XSENS_BID) {
+ goto error;
+ }
+ xsens_status++;
+ break;
+ case GOT_BID:
+ xsens_id = c;
+ xsens_status++;
+ break;
+ case GOT_MID:
+ xsens_len = c;
+ if (xsens_len > XSENS_MAX_PAYLOAD) {
+ goto error;
+ }
+ xsens_msg_idx = 0;
+ xsens_status++;
+ break;
+ case GOT_LEN:
+ xsens_msg_buf[xsens_msg_idx] = c;
+ xsens_msg_idx++;
+ if (xsens_msg_idx >= xsens_len) {
+ xsens_status++;
+ }
+ break;
+ case GOT_DATA:
+ if (ck != 0) {
+ goto error;
+ }
+ xsens_msg_received = TRUE;
+ goto restart;
+ break;
+ default:
+ break;
+ }
+ return;
+error:
+restart:
+ xsens_status = UNINIT;
+ return;
+}
diff --git a/sw/airborne/modules/ins/xsens_common.h b/sw/airborne/modules/ins/xsens_common.h
new file mode 100644
index 0000000000..8abd2dc9ed
--- /dev/null
+++ b/sw/airborne/modules/ins/xsens_common.h
@@ -0,0 +1,75 @@
+/*
+ * Copyright (C) 2003 Pascal Brisset, Antoine Drouin
+ *
+ * This file is part of paparazzi.
+ *
+ * paparazzi is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * paparazzi is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with paparazzi; see the file COPYING. If not, write to
+ * the Free Software Foundation, 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+/** @file modules/ins/xsens_common.h
+ * Parser for the Xsens protocol.
+ */
+
+#ifndef XSENS_COMMON_H
+#define XSENS_COMMON_H
+
+#include "std.h"
+
+/** Includes macros generated from xsens_MTi-G.xml */
+#include "xsens_protocol.h"
+
+extern uint8_t xsens_id;
+extern uint8_t xsens_status;
+extern uint8_t xsens_len;
+extern uint8_t xsens_msg_idx;
+extern uint8_t ck;
+extern uint8_t send_ck;
+
+#define XsensLinkDevice (&((XSENS_LINK).device))
+
+#define XsensInitCheksum() { send_ck = 0; }
+#define XsensUpdateChecksum(c) { send_ck += c; }
+
+#define XsensUartSend1(c) XsensLinkDevice->put_byte(XsensLinkDevice->periph, c)
+#define XsensSend1(c) { uint8_t i8=c; XsensUartSend1(i8); XsensUpdateChecksum(i8); }
+#define XsensSend1ByAddr(x) { XsensSend1(*x); }
+#define XsensSend2ByAddr(x) { XsensSend1(*(x+1)); XsensSend1(*x); }
+#define XsensSend4ByAddr(x) { XsensSend1(*(x+3)); XsensSend1(*(x+2)); XsensSend1(*(x+1)); XsensSend1(*x); }
+
+#define XsensHeader(msg_id, len) { \
+ XsensUartSend1(XSENS_START); \
+ XsensInitCheksum(); \
+ XsensSend1(XSENS_BID); \
+ XsensSend1(msg_id); \
+ XsensSend1(len); \
+ }
+#define XsensTrailer() { uint8_t i8=0x100-send_ck; XsensUartSend1(i8); }
+
+
+#define XSENS_MAX_PAYLOAD 254
+extern uint8_t xsens_msg_buf[XSENS_MAX_PAYLOAD];
+
+#define UNINIT 0
+#define GOT_START 1
+#define GOT_BID 2
+#define GOT_MID 3
+#define GOT_LEN 4
+#define GOT_DATA 5
+#define GOT_CHECKSUM 6
+
+extern void xsens_event(void);
+
+#endif /* XSENS_COMMON_H */