diff --git a/conf/airframes/AGGIEAIR/aggieair_ark_quad_lisa_mx.xml b/conf/airframes/AGGIEAIR/aggieair_ark_quad_lisa_mx.xml
index 3086b7767d..abf35096de 100644
--- a/conf/airframes/AGGIEAIR/aggieair_ark_quad_lisa_mx.xml
+++ b/conf/airframes/AGGIEAIR/aggieair_ark_quad_lisa_mx.xml
@@ -16,29 +16,52 @@
+
+
+
+
+
+
+
+
+
+
-
+
+
+
+
+
+
+
+
+
+
+
-
-
-
+
+
+
+
+
+
-
+
@@ -90,7 +113,24 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
+
-
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/conf/airframes/AGGIEAIR/aggieair_conf.xml b/conf/airframes/AGGIEAIR/aggieair_conf.xml
index 2ca9d177ef..baf1e91ab5 100644
--- a/conf/airframes/AGGIEAIR/aggieair_conf.xml
+++ b/conf/airframes/AGGIEAIR/aggieair_conf.xml
@@ -3,22 +3,22 @@
name="Ark_Quad"
ac_id="2"
airframe="airframes/AGGIEAIR/aggieair_ark_quad_lisa_mx.xml"
- radio="radios/AGGIEAIR/aggieair_taranis.xml"
- telemetry="telemetry/default_rotorcraft.xml"
+ radio="radios/AGGIEAIR/aggieair_sbus_fakerator.xml"
+ telemetry="telemetry/AGGIEAIR/aggieair_rotorcraft.xml"
flight_plan="flight_plans/rotorcraft_basic_geofence.xml"
- settings="settings/rotorcraft_basic.xml settings/control/rotorcraft_guidance.xml settings/nps.xml settings/control/stabilization_att_float_euler.xml"
- settings_modules=""
+ settings="settings/rotorcraft_basic.xml settings/control/rotorcraft_guidance.xml settings/nps.xml"
+ settings_modules="modules/gps.xml"
gui_color="#ffff954c0000"
/>
diff --git a/conf/airframes/AGGIEAIR/aggieair_control_panel.xml b/conf/airframes/AGGIEAIR/aggieair_control_panel.xml
new file mode 100644
index 0000000000..f953b70f64
--- /dev/null
+++ b/conf/airframes/AGGIEAIR/aggieair_control_panel.xml
@@ -0,0 +1,216 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/conf/airframes/AGGIEAIR/aggieair_rp3_lia.xml b/conf/airframes/AGGIEAIR/aggieair_rp3_lia.xml
index e86ace1859..a934a51135 100644
--- a/conf/airframes/AGGIEAIR/aggieair_rp3_lia.xml
+++ b/conf/airframes/AGGIEAIR/aggieair_rp3_lia.xml
@@ -7,17 +7,26 @@ RP3 Lisa MX
-
-
+
+
+
+
+
-
+
+
+
+
+
+
@@ -37,7 +46,7 @@ RP3 Lisa MX
-
+
@@ -45,17 +54,23 @@ RP3 Lisa MX
+
+
+
+
+
+
-
-
+
+
-
+
@@ -107,7 +122,6 @@ RP3 Lisa MX
-
@@ -130,10 +144,20 @@ RP3 Lisa MX
@@ -144,7 +168,8 @@ RP3 Lisa MX
-
+
+
@@ -247,6 +272,10 @@ RP3 Lisa MX
+
+
+
+
diff --git a/conf/airframes/AGGIEAIR/ark_hexa_1-8.xml b/conf/airframes/AGGIEAIR/ark_hexa_1-8.xml
new file mode 100644
index 0000000000..5c821a98f9
--- /dev/null
+++ b/conf/airframes/AGGIEAIR/ark_hexa_1-8.xml
@@ -0,0 +1,283 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/conf/conf_tests.xml b/conf/conf_tests.xml
index 2203723c98..8560a0da8c 100644
--- a/conf/conf_tests.xml
+++ b/conf/conf_tests.xml
@@ -2,10 +2,10 @@
#
+USE_HITL ?= 0
+
nps.ARCHDIR = sim
# include Makefile.nps instead of Makefile.sim
nps.MAKEFILE = nps
nps.CFLAGS += -DSITL -DUSE_NPS
-nps.CFLAGS += $(shell pkg-config glib-2.0 --cflags)
-nps.LDFLAGS += $(shell pkg-config glib-2.0 --libs) -lm -lglibivy $(shell pcre-config --libs) -lgsl -lgslcblas
+nps.LDFLAGS += -lm -livy $(shell pcre-config --libs) -lgsl -lgslcblas -lrt
nps.CFLAGS += -I$(SRC_FIRMWARE) -I$(SRC_BOARD) -I$(PAPARAZZI_SRC)/sw/simulator -I$(PAPARAZZI_SRC)/sw/simulator/nps -I$(PAPARAZZI_HOME)/conf/simulator/nps
+
+# sdl needed for joystick input
nps.LDFLAGS += $(shell sdl-config --libs)
@@ -25,7 +30,7 @@ nps.LDFLAGS += $(shell sdl-config --libs)
VPATH += $(PAPARAZZI_SRC)/sw/simulator
NPSDIR = nps
-nps.srcs += $(NPSDIR)/nps_main.c \
+nps.srcs += \
$(NPSDIR)/nps_random.c \
$(NPSDIR)/nps_sensors.c \
$(NPSDIR)/nps_sensors_utils.c \
@@ -39,11 +44,20 @@ nps.srcs += $(NPSDIR)/nps_main.c \
$(NPSDIR)/nps_sensor_temperature.c \
$(NPSDIR)/nps_electrical.c \
$(NPSDIR)/nps_atmosphere.c \
+ $(NPSDIR)/nps_ivy.c \
+ $(NPSDIR)/nps_flightgear.c \
$(NPSDIR)/nps_radio_control.c \
$(NPSDIR)/nps_radio_control_joystick.c \
$(NPSDIR)/nps_radio_control_spektrum.c \
- $(NPSDIR)/nps_ivy.c \
- $(NPSDIR)/nps_flightgear.c
+ $(NPSDIR)/nps_main_common.c
+
+ifeq ($(USE_HITL),1)
+$(info USE_HITL defined)
+include $(CFG_SHARED)/nps_hitl.makefile
+else
+$(info USE_HITL undefined)
+include $(CFG_SHARED)/nps_sitl.makefile
+endif
# for geo mag calculation
nps.srcs += math/pprz_geodetic_wmm2015.c
diff --git a/conf/firmwares/subsystems/shared/nps_hitl.makefile b/conf/firmwares/subsystems/shared/nps_hitl.makefile
new file mode 100644
index 0000000000..4f8166186e
--- /dev/null
+++ b/conf/firmwares/subsystems/shared/nps_hitl.makefile
@@ -0,0 +1,28 @@
+# Hey Emacs, this is a -*- makefile -*-
+
+#
+# NPS HITL Simulator
+#
+# HITL specific makefile
+#
+
+nps.srcs += $(NPSDIR)/nps_main_hitl.c
+
+# TODO: have this in ins_vectornav.xml
+# will hopefully work better once nps and HITL are separate targets
+nps.srcs += $(NPSDIR)/nps_ins_vectornav.c
+
+# glib is still needed for some components (such as radio input)
+nps.CFLAGS += $(shell pkg-config glib-2.0 --cflags)
+nps.LDFLAGS += $(shell pkg-config glib-2.0 --libs)
+
+INS_DEV ?= \"/dev/ttyUSB1\"
+INS_BAUD ?= B921600
+
+AP_DEV ?= \"/dev/ttyUSB2\"
+AP_BAUD ?= B921600
+
+nps.CFLAGS += -DAP_DEV=\"$(AP_DEV)\"
+nps.CFLAGS += -DAP_BAUD=$(AP_BAUD)
+nps.CFLAGS += -DINS_DEV=\"$(INS_DEV)\"
+nps.CFLAGS += -DINS_BAUD=$(INS_BAUD)
diff --git a/conf/firmwares/subsystems/shared/nps_sitl.makefile b/conf/firmwares/subsystems/shared/nps_sitl.makefile
new file mode 100644
index 0000000000..d851b72176
--- /dev/null
+++ b/conf/firmwares/subsystems/shared/nps_sitl.makefile
@@ -0,0 +1,13 @@
+# Hey Emacs, this is a -*- makefile -*-
+
+#
+# NPS SITL Simulator
+#
+# SITL specific makefile
+#
+
+# glib is still needed for some components (such as radio input)
+nps.CFLAGS += $(shell pkg-config glib-2.0 --cflags)
+nps.LDFLAGS += $(shell pkg-config glib-2.0 --libs)
+
+nps.srcs += $(NPSDIR)/nps_main_sitl.c
diff --git a/conf/flight_plans/AGGIEAIR/BasicTuning_Launcher.xml b/conf/flight_plans/AGGIEAIR/BasicTuning_Launcher.xml
index 1ceffb9254..88089a0056 100644
--- a/conf/flight_plans/AGGIEAIR/BasicTuning_Launcher.xml
+++ b/conf/flight_plans/AGGIEAIR/BasicTuning_Launcher.xml
@@ -56,6 +56,11 @@
+
+
+
+
+
diff --git a/conf/flight_plans/basic_sim.xml b/conf/flight_plans/basic_sim.xml
new file mode 100644
index 0000000000..337e8732ef
--- /dev/null
+++ b/conf/flight_plans/basic_sim.xml
@@ -0,0 +1,92 @@
+
+
+
+
+#include "subsystems/datalink/datalink.h"
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/conf/modules/extra_dl.xml b/conf/modules/extra_dl.xml
index 0c0c1da894..966860b8b7 100644
--- a/conf/modules/extra_dl.xml
+++ b/conf/modules/extra_dl.xml
@@ -3,25 +3,43 @@
Extra datalink (PPRZ transport)
-
+
+
+ # Check for UDP port
ifneq (,$(findstring udp,$(EXTRA_DL_PORT_LOWER)))
include $(CFG_SHARED)/udp.makefile
else
+ ifneq (,$(findstring usb_serial,$(EXTRA_DL_PORT_LOWER)))
+ # usb_serial telemetry chosen, add files based on architecture
+ ifeq ($(ARCH), lpc21)
+ $(TARGET).srcs += $(SRC_ARCH)/usb_ser_hw.c $(SRC_ARCH)/lpcusb/usbhw_lpc.c $(SRC_ARCH)/lpcusb/usbcontrol.c
+ $(TARGET).srcs += $(SRC_ARCH)/lpcusb/usbstdreq.c $(SRC_ARCH)/lpcusb/usbinit.c
+ else
+ ifeq ($(ARCH), stm32)
+ $(TARGET).srcs += $(SRC_ARCH)/usb_ser_hw.c
+ else
+ ifneq ($(ARCH), sim)
+ $(error telemetry_transparent_usb currently only implemented for the lpc21 and stm32)
+ endif
+ endif
+ endif
+ else
EXTRA_DL_BAUD ?= B57600
$(TARGET).CFLAGS += -D$(EXTRA_DL_PORT_UPPER)_BAUD=$(EXTRA_DL_BAUD)
- endif
+ endif # USB serial
+ endif # UDP
diff --git a/conf/modules/ins_vectornav.xml b/conf/modules/ins_vectornav.xml
index 01562e646a..87ca37e68f 100644
--- a/conf/modules/ins_vectornav.xml
+++ b/conf/modules/ins_vectornav.xml
@@ -48,4 +48,11 @@
endif
+
+
diff --git a/conf/radios/AGGIEAIR/aggieair_sbus_fakerator.xml b/conf/radios/AGGIEAIR/aggieair_sbus_fakerator.xml
new file mode 100644
index 0000000000..b8c71b5497
--- /dev/null
+++ b/conf/radios/AGGIEAIR/aggieair_sbus_fakerator.xml
@@ -0,0 +1,43 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/conf/simulator/jsbsim/aircraft/AGGIEAIR/aggieair_ark_hexa.xml b/conf/simulator/jsbsim/aircraft/AGGIEAIR/aggieair_ark_hexa.xml
new file mode 100644
index 0000000000..4085974cdb
--- /dev/null
+++ b/conf/simulator/jsbsim/aircraft/AGGIEAIR/aggieair_ark_hexa.xml
@@ -0,0 +1,502 @@
+
+
+
+
+
+ AggieAir
+ 27-01-2015
+ Version 0.1 - beta
+ AggieAir ARK hexarotor
+
+
+
+ 78.53
+ 10
+ 6.79
+ 0
+ 0
+ 0
+ 0
+
+ 0
+ 0
+ 0
+
+
+ 0
+ 0
+ 0
+
+
+ 0
+ 0
+ 0
+
+
+
+
+ 0.005
+ 0.005
+ 0.010
+ 0.
+ 0.
+ 0.
+ 0.84
+
+ 0
+ 0
+ 0
+
+
+
+
+
+
+ -0.15
+ 0
+ -0.1
+
+ 0.8
+ 0.5
+ 500
+ 100
+ 1000
+ 0.0
+ NONE
+ 0
+
+
+
+
+ 0.15
+ 0
+ -0.1
+
+ 0.8
+ 0.5
+ 500
+ 100
+ 1000
+ 0.0
+ NONE
+ 0
+
+
+
+
+ 0.
+ 0.15
+ -0.1
+
+ 0.8
+ 0.5
+ 500
+ 100
+ 1000
+ 0.0
+ NONE
+ 0
+
+
+
+
+ 0.
+ -0.15
+ -0.1
+
+ 0.8
+ 0.5
+ 500
+ 100
+ 1000
+ 0.0
+ NONE
+ 0
+
+
+
+
+
+
+
+
+ fcs/f_motor
+ fcs/fr_motor
+ fcs/br_motor
+ fcs/b_motor
+ fcs/bl_motor
+ fcs/fl_motor
+
+
+
+
+
+
+ fcs/f_motor
+ 0.84
+
+
+
+ -21
+ 0
+ 0
+
+
+ 0
+ 0
+ -1
+
+
+
+
+
+
+ fcs/fr_motor
+ 0.84
+
+
+
+ -10.5
+ 18.1865
+ 0
+
+
+ 0
+ 0
+ -1
+
+
+
+
+
+
+ fcs/br_motor
+ 0.84
+
+
+
+ 10.5
+ 18.1865
+ 0
+
+
+ 0
+ 0
+ -1
+
+
+
+
+
+
+ fcs/b_motor
+ 0.84
+
+
+
+ 21
+ 0
+ 0
+
+
+ 0
+ 0
+ -1
+
+
+
+
+
+
+ fcs/bl_motor
+ 0.84
+
+
+
+ 10.5
+ -18.1865
+ 0
+
+
+ 0
+ 0
+ -1
+
+
+
+
+
+
+ fcs/fl_motor
+ 0.84
+
+
+
+ -10.5
+ -18.1865
+ 0
+
+
+ 0
+ 0
+ -1
+
+
+
+
+
+
+
+
+ fcs/f_motor
+ 0.84
+
+
+
+ -27.375
+ 0
+ 0
+
+
+ 0
+ -1
+ 0
+
+
+
+
+
+
+ fcs/f_motor
+ 0.84
+
+
+
+ -14.625
+ 0
+ 0
+
+
+ 0
+ 1
+ 0
+
+
+
+
+
+
+ fcs/fr_motor
+ 0.84
+
+
+
+
+ -10.5
+ 11.8115
+ 0
+
+
+ -1
+ 0
+ 0
+
+
+
+
+
+
+ fcs/fr_motor
+ 0.84
+
+
+
+ -10.5
+ 24.5615
+ 0
+
+
+ 1
+ 0
+ 0
+
+
+
+
+
+
+ fcs/br_motor
+ 0.84
+
+
+
+
+ 10.5
+ 11.8115
+ 0
+
+
+ 1
+ 0
+ 0
+
+
+
+
+
+
+ fcs/br_motor
+ 0.84
+
+
+
+ 10.5
+ 24.5615
+ 0
+
+
+ -1
+ 0
+ 0
+
+
+
+
+
+
+
+ fcs/b_motor
+ 0.84
+
+
+
+ 27.375
+ 0
+ 0
+
+
+ 0
+ -1
+ 0
+
+
+
+
+
+
+ fcs/b_motor
+ 0.84
+
+
+
+ 14.625
+ 0
+ 0
+
+
+ 0
+ 1
+ 0
+
+
+
+
+
+
+ fcs/bl_motor
+ 0.84
+
+
+
+ 10.5
+ -11.8115
+ 0
+
+
+ -1
+ 0
+ 0
+
+
+
+
+
+
+ fcs/bl_motor
+ 0.84
+
+
+
+ 10.5
+ -24.5615
+ 0
+
+
+ 1
+ 0
+ 0
+
+
+
+
+
+
+ fcs/fl_motor
+ 0.84
+
+
+
+
+ -10.5
+ -11.8115
+ 0
+
+
+ 1
+ 0
+ 0
+
+
+
+
+
+
+ fcs/fl_motor
+ 0.84
+
+
+
+ -10.5
+ -24.5615
+ 0
+
+
+ -1
+ 0
+ 0
+
+
+
+
+
+
+
+
+
+
+
+ Drag
+
+ aero/qbar-psf
+ 47.9
+ 0.0151
+ 0.224808943
+
+
+
+
+
+
diff --git a/conf/telemetry/AGGIEAIR/aggieair_fixedwing.xml b/conf/telemetry/AGGIEAIR/aggieair_fixedwing.xml
new file mode 100644
index 0000000000..372204c6be
--- /dev/null
+++ b/conf/telemetry/AGGIEAIR/aggieair_fixedwing.xml
@@ -0,0 +1,125 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/conf/telemetry/AGGIEAIR/aggieair_rotorcraft.xml b/conf/telemetry/AGGIEAIR/aggieair_rotorcraft.xml
new file mode 100644
index 0000000000..a4fa0bcdf3
--- /dev/null
+++ b/conf/telemetry/AGGIEAIR/aggieair_rotorcraft.xml
@@ -0,0 +1,173 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/sw/airborne/modules/datalink/extra_pprz_dl.c b/sw/airborne/modules/datalink/extra_pprz_dl.c
index 20693a2d9d..65a16a73d9 100644
--- a/sw/airborne/modules/datalink/extra_pprz_dl.c
+++ b/sw/airborne/modules/datalink/extra_pprz_dl.c
@@ -1,6 +1,7 @@
/*
* Copyright (C) 2006 Pascal Brisset, Antoine Drouin
* Copyright (C) 2010 ENAC
+ * Copyright (C) 2016 2016 Michal Podhradsky
*
* This file is part of paparazzi.
*
@@ -20,8 +21,31 @@
* Boston, MA 02111-1307, USA.
*
*/
+/**
+ * @file "modules/datalink/extra_pprz_dl.c"
+ * Extra datalink and telemetry using PPRZ protocol
+ *
+ * NOTES (for future reference):
+ * This note is not needed unless we want to define our own messages - in such case you would define the two
+ * structs below and then define individual messages and registered them in the same way as
+ * periodic telemetry.
+ * struct telemetry_cb_slots telemetry_cbs_logger[TELEMETRY_PPRZ_NB_MSG] = TELEMETRY_PPRZ_CBS;
+ * struct periodic_telemetry logger_telemetry = { TELEMETRY_PPRZ_NB_MSG, telemetry_cbs_logger };
+ *
+ * The registration should be done in the init function:
+ * register_periodic_telemetry(&extra_telemetry, PPRZ_MSG_ID_xxx, send_xxx_message);
+ *
+ * Two extra notes for the periodic function:
+ * 1) this sends registered messages from ExtraTelemetry process (as mentioned above) over dedicated port do:
+ * periodic_telemetry_send_ExtraTelemetryr(&extra_telemetry, &pprz_tp_extra.trans_tx, &(EXTRA_TELEMETRY_PORT).device);
+ * 2) to send ExtraTelemetry messages over default channel just change to:
+ * periodic_telemetry_send_ExtraTelemetry(DefaultPeriodic, &(DefaultChannel).trans_tx, &(DefaultDevice).device);
+ */
+#define PERIODIC_C_EXTRA
#include "modules/datalink/extra_pprz_dl.h"
+#include "subsystems/datalink/telemetry.h"
+
struct pprz_transport extra_pprz_tp;
@@ -30,3 +54,11 @@ void extra_pprz_dl_init(void)
pprz_transport_init(&extra_pprz_tp);
}
+void extra_pprz_dl_periodic(void)
+{
+#if PERIODIC_TELEMETRY
+ // send periodic messages as defined in the Extra process, we are using DefaultPeriodic so we can send standard messages
+ periodic_telemetry_send_Extra(DefaultPeriodic, &extra_pprz_tp.trans_tx, &(EXTRA_DOWNLINK_DEVICE).device);
+#endif
+}
+
diff --git a/sw/airborne/modules/datalink/extra_pprz_dl.h b/sw/airborne/modules/datalink/extra_pprz_dl.h
index 3752d81f8f..faa940f136 100644
--- a/sw/airborne/modules/datalink/extra_pprz_dl.h
+++ b/sw/airborne/modules/datalink/extra_pprz_dl.h
@@ -1,5 +1,6 @@
/*
* Copyright (C) 2010 ENAC
+ * Copyright (C) 2016 2016 Michal Podhradsky
*
* This file is part of paparazzi.
*
@@ -19,12 +20,10 @@
* Boston, MA 02111-1307, USA.
*
*/
-
-/** \file extra_pprz_dl.h
- * \brief Extra datalink using PPRZ protocol
- *
+/**
+ * @file "modules/datalink/extra_pprz_dl.h"
+ * Extra datalink and telemetry using PPRZ protocol
*/
-
#ifndef EXTRA_PPRZ_DL_H
#define EXTRA_PPRZ_DL_H
@@ -35,12 +34,15 @@
#include "mcu_periph/udp.h"
#endif
+#if USE_USB_SERIAL
+#include "mcu_periph/usb_serial.h"
+#endif
+
/* PPRZ transport structure */
extern struct pprz_transport extra_pprz_tp;
/* Datalink Event */
-
-#define ExtraDatalinkEvent() { \
+#define ExtraDatalinkEvent() { \
pprz_check_and_parse(&EXTRA_DOWNLINK_DEVICE.device, &extra_pprz_tp, dl_buffer, &dl_msg_available); \
DlCheckAndParse(&EXTRA_DOWNLINK_DEVICE.device, &extra_pprz_tp.trans_tx, dl_buffer); \
}
@@ -48,5 +50,11 @@ extern struct pprz_transport extra_pprz_tp;
/** Init function */
extern void extra_pprz_dl_init(void);
+/** Periodic function
+ *
+ * should be called at TELEMETRY_FREQUENCY
+ */
+extern void extra_pprz_dl_periodic(void);
+
#endif /* EXTRA_PPRZ_DL_H */
diff --git a/sw/airborne/subsystems/datalink/bluegiga.c b/sw/airborne/subsystems/datalink/bluegiga.c
index c15373f230..9f5bd2e759 100644
--- a/sw/airborne/subsystems/datalink/bluegiga.c
+++ b/sw/airborne/subsystems/datalink/bluegiga.c
@@ -63,7 +63,7 @@ struct spi_transaction bluegiga_spi;
uint8_t broadcast_msg[20];
-void bluegiga_load_tx(struct bluegiga_periph *p, struct spi_transaction *trans);
+void bluegiga_load_tx(struct bluegiga_periph *p);
void bluegiga_transmit(struct bluegiga_periph *p, uint8_t data);
void bluegiga_receive(struct spi_transaction *trans);
@@ -214,7 +214,7 @@ void bluegiga_transmit(struct bluegiga_periph *p, uint8_t data)
}
/* Load waiting data into tx peripheral buffer */
-void bluegiga_load_tx(struct bluegiga_periph *p, struct spi_transaction *trans)
+void bluegiga_load_tx(struct bluegiga_periph *p)
{
uint8_t packet_len;
// check data available in buffer to send
@@ -330,7 +330,7 @@ void bluegiga_receive(struct spi_transaction *trans)
}
// load next message to be sent into work buffer, needs to be loaded before calling spi_slave_register
- bluegiga_load_tx(&bluegiga_p, trans);
+ bluegiga_load_tx(&bluegiga_p);
// register spi slave read for next transaction
spi_slave_register(&(BLUEGIGA_SPI_DEV), trans);
diff --git a/sw/airborne/test/test_can.c b/sw/airborne/test/test_can.c
index 9515cf79a1..277131ff6b 100644
--- a/sw/airborne/test/test_can.c
+++ b/sw/airborne/test/test_can.c
@@ -70,7 +70,7 @@ static inline void main_init(void)
mcu_init();
sys_time_register_timer((0.5 / PERIODIC_FREQUENCY), NULL);
downlink_init();
- ppz_can_init(main_on_can_msg);
+ ppz_can_init((can_rx_callback_t)main_on_can_msg);
}
static inline void main_periodic_task(void)
diff --git a/sw/simulator/nps/nps_atmosphere.c b/sw/simulator/nps/nps_atmosphere.c
index 6b8355eee1..2a1a9ccd5f 100644
--- a/sw/simulator/nps/nps_atmosphere.c
+++ b/sw/simulator/nps/nps_atmosphere.c
@@ -101,7 +101,7 @@ void nps_atmosphere_update(double dt)
req_time += dt;
if (req_time - nps_atmosphere.last_world_env_req >= NPS_WORLD_ENV_UPDATE) {
nps_atmosphere.last_world_env_req = req_time;
- nps_ivy_send_WORLD_ENV_REQ();
+ nps_ivy_send_world_env = true;
}
nps_fdm_set_wind_ned(nps_atmosphere.wind.x, nps_atmosphere.wind.y, nps_atmosphere.wind.z);
diff --git a/sw/simulator/nps/nps_autopilot.h b/sw/simulator/nps/nps_autopilot.h
index 9957524e42..b1cba54254 100644
--- a/sw/simulator/nps/nps_autopilot.h
+++ b/sw/simulator/nps/nps_autopilot.h
@@ -15,14 +15,9 @@
#if defined MOTOR_MIXING_NB_MOTOR
#define NPS_COMMANDS_NB MOTOR_MIXING_NB_MOTOR
#else
-#ifdef NPS_ACTUATOR_NAMES
#define NPS_COMMANDS_NB COMMANDS_NB
-#else
-/* not using explicitly set NPS_ACTUATOR_NAMES -> throttle,roll,pitch,yaw commands */
-#define NPS_COMMANDS_NB 4
-#endif
-#endif
-#endif
+#endif /* #if defined MOTOR_MIXING_NB_MOTOR */
+#endif /* #ifndef NPS_COMMANDS_NB */
struct NpsAutopilot {
double commands[NPS_COMMANDS_NB];
diff --git a/sw/simulator/nps/nps_autopilot_fixedwing.c b/sw/simulator/nps/nps_autopilot_fixedwing.c
index c1c0269713..3745882467 100644
--- a/sw/simulator/nps/nps_autopilot_fixedwing.c
+++ b/sw/simulator/nps/nps_autopilot_fixedwing.c
@@ -77,7 +77,9 @@ void nps_autopilot_init(enum NpsRadioControlType type_rc, int num_rc_script, cha
autopilot.launch = FALSE;
- nps_radio_control_init(type_rc, num_rc_script, rc_dev);
+ if (rc_dev != NULL) {
+ nps_radio_control_init(type_rc, num_rc_script, rc_dev);
+ }
nps_electrical_init();
nps_bypass_ahrs = NPS_BYPASS_AHRS;
@@ -180,10 +182,8 @@ void nps_autopilot_run_step(double time)
#ifdef COMMAND_YAW
PRINT_CONFIG_VAR(COMMAND_YAW)
autopilot.commands[COMMAND_YAW] = (double)commands[COMMAND_YAW] / MAX_PPRZ;
-#else
- autopilot.commands[3] = 0.;
-#endif
-#endif
+#endif /* COMMAND_YAW */
+#endif /* NPS_ACTUATOR_NAMES */
// do the launch when clicking launch in GCS
autopilot.launch = launch && !kill_throttle;
diff --git a/sw/simulator/nps/nps_fdm_jsbsim.cpp b/sw/simulator/nps/nps_fdm_jsbsim.cpp
index 4d89830d60..5de4c08905 100644
--- a/sw/simulator/nps/nps_fdm_jsbsim.cpp
+++ b/sw/simulator/nps/nps_fdm_jsbsim.cpp
@@ -52,7 +52,7 @@
// end ignore unused param warnings in JSBSim
#pragma GCC diagnostic pop
-
+#include "nps_autopilot.h"
#include "nps_fdm.h"
#include "math/pprz_geodetic.h"
#include "math/pprz_geodetic_double.h"
@@ -124,12 +124,13 @@
* Around 1/10000 seems to be good for ground impacts
*/
#define MIN_DT (1.0/10240.0)
+// TODO: maybe lower for slower CPUs & HITL?
+//#define MIN_DT (1.0/1000.0)
using namespace JSBSim;
using namespace std;
static void feed_jsbsim(double *commands, int commands_nb);
-static void feed_jsbsim(double throttle, double aileron, double elevator, double rudder);
static void fetch_state(void);
static int check_for_nan(void);
@@ -289,7 +290,7 @@ void nps_fdm_set_temperature(double temp, double h)
* @param commands Pointer to array of doubles holding actuator commands
* @param commands_nb Number of commands (length of array)
*/
-static void feed_jsbsim(double *commands, int commands_nb)
+static void feed_jsbsim(double *commands, int commands_nb __attribute__((unused)))
{
#ifdef NPS_ACTUATOR_NAMES
char buf[64];
@@ -302,42 +303,48 @@ static void feed_jsbsim(double *commands, int commands_nb)
property = string(buf);
FDMExec->GetPropertyManager()->GetNode(property)->SetDouble("", commands[i]);
}
-#else
- if (commands_nb != 4) {
- cerr << "commands_nb must be 4!" << endl;
- exit(-1);
- }
- /* call version that directly feeds throttle, aileron, elevator, rudder */
- feed_jsbsim(commands[COMMAND_THROTTLE], commands[COMMAND_ROLL], commands[COMMAND_PITCH], commands[3]);
-#endif
-}
+#else /* use COMMAND names */
-static void feed_jsbsim(double throttle, double aileron, double elevator, double rudder)
-{
+ // get FGFCS instance
FGFCS *FCS = FDMExec->GetFCS();
- FGPropulsion *FProp = FDMExec->GetPropulsion();
// Set trims
FCS->SetPitchTrimCmd(NPS_JSBSIM_PITCH_TRIM);
FCS->SetRollTrimCmd(NPS_JSBSIM_ROLL_TRIM);
FCS->SetYawTrimCmd(NPS_JSBSIM_YAW_TRIM);
- // Set commands
- FCS->SetDaCmd(aileron);
- FCS->SetDeCmd(elevator);
- FCS->SetDrCmd(rudder);
-
+#ifdef COMMAND_THROTTLE
+ FGPropulsion *FProp = FDMExec->GetPropulsion();
for (unsigned int i = 0; i < FDMExec->GetPropulsion()->GetNumEngines(); i++) {
- FCS->SetThrottleCmd(i, throttle);
+ FCS->SetThrottleCmd(i, commands[COMMAND_THROTTLE]);
- if (throttle > 0.01) {
+ // Hack to show spinning propellers in flight gear models
+ if (commands[COMMAND_THROTTLE] > 0.01) {
FProp->SetStarter(1);
} else {
FProp->SetStarter(0);
}
}
-}
+#endif /* COMMAND_THROTTLE */
+#ifdef COMMAND_ROLL
+ FCS->SetDaCmd(commands[COMMAND_ROLL]);
+#endif /* COMMAND_ROLL */
+
+#ifdef COMMAND_PITCH
+ FCS->SetDeCmd(commands[COMMAND_PITCH]);
+#endif /* COMMAND_PITCH */
+
+#ifdef COMMAND_YAW
+ FCS->SetDrCmd(commands[COMMAND_YAW]);
+#endif /* COMMAND_YAW */
+
+#ifdef COMMAND_FLAP
+ FCS->SetDfCmd(commands[COMMAND_FLAP]);
+#endif /* COMMAND_FLAP */
+
+#endif /* NPS_ACTUATOR_NAMES */
+}
/**
* Populates the NPS fdm struct after a simulation step.
@@ -597,7 +604,8 @@ static void init_jsbsim(double dt)
}
// initial commands to zero
- feed_jsbsim(0.0, 0.0, 0.0, 0.0);
+ double init_commands[NPS_COMMANDS_NB] = {0.0};
+ feed_jsbsim(init_commands, NPS_COMMANDS_NB);
//loop JSBSim once w/o integrating
if (!FDMExec->RunIC()) {
diff --git a/sw/simulator/nps/nps_flightgear.c b/sw/simulator/nps/nps_flightgear.c
index ae105d2a98..ac994e46e0 100644
--- a/sw/simulator/nps/nps_flightgear.c
+++ b/sw/simulator/nps/nps_flightgear.c
@@ -10,10 +10,11 @@
#include
#include
#include
-
+#include
#include "std.h"
#include "../flight_gear.h"
+#include "nps_main.h"
#include "nps_fdm.h"
#include "nps_atmosphere.h"
@@ -25,6 +26,9 @@ static struct {
unsigned int time_offset;
} flightgear;
+pthread_t th_fg_rx; // fligh gear receive thread
+
+void* nps_flightgear_receive(void* data __attribute__((unused)));
double htond(double x)
{
@@ -98,6 +102,9 @@ void nps_flightgear_init(const char *host, unsigned int port, unsigned int port
time_t t = time(NULL);
flightgear.initial_time = t;
flightgear.time_offset = time_offset;
+
+ // launch rx thread
+ pthread_create(&th_fg_rx, NULL, nps_flightgear_receive, NULL);
}
/**
@@ -221,7 +228,8 @@ void nps_flightgear_send()
/**
* Receive Flight Gear environment messages
*/
-void nps_flightgear_receive() {
+void* nps_flightgear_receive(void* data __attribute__((unused)))
+{
if (flightgear.socket_in != -1) {
// socket is correctly opened
@@ -230,32 +238,37 @@ void nps_flightgear_receive() {
size_t s_env = sizeof(env);
int bytes_read;
- //read first message
- memset(&env, 0, s_env);
- bytes_read = recvfrom(flightgear.socket_in, (char*)(&env), s_env, MSG_DONTWAIT, NULL, NULL);
- while (bytes_read != -1) { // while we read a message (empty buffer)
- if (bytes_read == (int)s_env){
- // Update wind info
- nps_atmosphere_set_wind_ned(
- (double)env.wind_from_north,
- (double)env.wind_from_east,
- (double)env.wind_from_down);
- }
- else {
- //error
- printf("WARNING : ignoring packet with size %d (%d expected)", bytes_read, (int)s_env);
- }
-
- //read next message
+ while(TRUE)
+ {
+ //read first message
memset(&env, 0, s_env);
- bytes_read = recvfrom(flightgear.socket_in, (char*)(&env), s_env, MSG_DONTWAIT, NULL, NULL);
- }
+ bytes_read = recvfrom(flightgear.socket_in, (char*)(&env), s_env, MSG_WAITALL, NULL, NULL);
+ while (bytes_read != -1) { // while we read a message (empty buffer)
+ if (bytes_read == (int)s_env){
+ // Update wind info
+ pthread_mutex_lock(&fdm_mutex);
+ nps_atmosphere_set_wind_ned(
+ (double)env.wind_from_north,
+ (double)env.wind_from_east,
+ (double)env.wind_from_down);
+ pthread_mutex_unlock(&fdm_mutex);
+ }
+ else {
+ //error
+ printf("WARNING : ignoring packet with size %d (%d expected)", bytes_read, (int)s_env);
+ }
- if ((errno & (EAGAIN | EWOULDBLOCK)) == 0) {
- perror("nps_flightgear_receive recvfrom()");
+ //read next message
+ memset(&env, 0, s_env);
+ bytes_read = recvfrom(flightgear.socket_in, (char*)(&env), s_env, MSG_WAITALL, NULL, NULL);
+ }
+
+ if ((errno & (EAGAIN | EWOULDBLOCK)) == 0) {
+ perror("nps_flightgear_receive recvfrom()");
+ }
}
}
-
+ return NULL;
}
diff --git a/sw/simulator/nps/nps_flightgear.h b/sw/simulator/nps/nps_flightgear.h
index d463d49cc4..183a07b73c 100644
--- a/sw/simulator/nps/nps_flightgear.h
+++ b/sw/simulator/nps/nps_flightgear.h
@@ -5,7 +5,6 @@
extern void nps_flightgear_init(const char* host, unsigned int port, unsigned int port_in, unsigned int time_offset);
extern void nps_flightgear_send();
extern void nps_flightgear_send_fdm();
-extern void nps_flightgear_receive();
#endif /* NPS_FLIGHTGEAR_H */
diff --git a/sw/simulator/nps/nps_ins.h b/sw/simulator/nps/nps_ins.h
new file mode 100644
index 0000000000..af18bfaea4
--- /dev/null
+++ b/sw/simulator/nps/nps_ins.h
@@ -0,0 +1,44 @@
+/*
+ * Copyright (C) 2009 Antoine Drouin
+ * Copyright (C) 2012 The Paparazzi Team
+ * Copyright (C) 2016 Michal Podhradsky
+ *
+ * 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.
+ */
+#ifndef NPS_INS_H
+#define NPS_INS_H
+
+#include "std.h"
+#include "nps_fdm.h"
+
+// if undefined, match with control frequency because that is how it should be used
+#ifndef INS_FREQUENCY
+#ifdef CONTROL_FREQUENCY
+#define INS_FREQUENCY CONTROL_FREQUENCY
+#else
+#define INS_FREQUENCY PERIODIC_FREQUENCY
+#endif
+#endif
+
+extern uint8_t *ins_buffer;
+
+extern void nps_ins_init(void);
+void nps_ins_fetch_data(struct NpsFdm *fdm_ins);
+uint16_t nps_ins_fill_buffer(void);
+
+#endif /* NPS_INS_H */
diff --git a/sw/simulator/nps/nps_ins_vectornav.c b/sw/simulator/nps/nps_ins_vectornav.c
new file mode 100644
index 0000000000..eff50175db
--- /dev/null
+++ b/sw/simulator/nps/nps_ins_vectornav.c
@@ -0,0 +1,273 @@
+/*
+ * Copyright (C) 2009 Antoine Drouin
+ * Copyright (C) 2012 The Paparazzi Team
+ * Copyright (C) 2016 Michal Podhradsky
+ *
+ * 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.
+ */
+
+#include "nps_ins.h"
+#include
+#include "nps_fdm.h"
+#include
+#include
+
+/*
+ * Vectornav info
+ */
+#define VN_DATA_START 10
+#define VN_BUFFER_SIZE 512
+#define GPS_SEC_IN_DAY 86400
+
+static uint8_t VN_SYNC = 0xFA;
+static uint8_t VN_OUTPUT_GROUP = 0x39;
+static uint16_t VN_GROUP_FIELD_1 = 0x01E9;
+static uint16_t VN_GROUP_FIELD_2 = 0x061A;
+static uint16_t VN_GROUP_FIELD_3 = 0x0140;
+static uint16_t VN_GROUP_FIELD_4 = 0x0009;
+
+uint8_t vn_buffer[VN_BUFFER_SIZE];
+
+uint8_t *ins_buffer;
+
+struct VectornavData {
+ uint64_t TimeStartup;
+ float YawPitchRoll[3];
+ float AngularRate[3];
+ double Position[3];
+ float Velocity[3];
+ float Accel[3];
+ uint64_t Tow;
+ uint8_t NumSats;
+ uint8_t Fix;
+ float PosU[3];
+ float VelU;
+ float LinearAccelBody[3];
+ float YprU[3];
+ uint16_t InsStatus;
+ float VelBody[3];
+};
+
+struct VectornavData vn_data;
+
+void ins_vectornav_init(void) {}
+void ins_vectornav_event(void) {}
+
+/**
+ * Calculates the 16-bit CRC for the given ASCII or binary message.
+ * The CRC is calculated over the packet starting just after the sync byte (not including the sync byte)
+ * and ending at the end of payload.
+ */
+unsigned short vn_calculate_crc(unsigned char data[], unsigned int length)
+{
+ unsigned int i;
+ unsigned short crc = 0;
+ for (i = 0; i < length; i++) {
+ crc = (unsigned char)(crc >> 8) | (crc << 8);
+ crc ^= data[i];
+ crc ^= (unsigned char)(crc & 0xff) >> 4;
+ crc ^= crc << 12;
+ crc ^= (crc & 0x00ff) << 5;
+ }
+ return crc;
+}
+
+void nps_ins_init(void)
+{
+ ins_buffer = &vn_buffer[0];
+}
+
+
+/**
+ * @return GPS TOW
+ */
+static uint64_t vn_get_time_of_week(void)
+{
+ struct timeval curTime;
+ gettimeofday(&curTime, NULL);
+ int milli = curTime.tv_usec / 1000;
+ struct tm t_res;
+ localtime_r(&curTime.tv_sec, &t_res);
+ struct tm *tt = &t_res;
+
+ uint64_t tow = GPS_SEC_IN_DAY * tt->tm_wday + 3600 * tt->tm_hour + 60 * tt->tm_min + tt->tm_sec; // sec
+ tow = tow * 1000; // tow to ms
+ tow = tow + milli; // tow with added ms
+ tow = tow * 1e6; // tow in nanoseconds
+
+ return tow;
+}
+
+void nps_ins_fetch_data(struct NpsFdm *fdm_ins)
+{
+ struct NpsFdm fdm_data;
+ memcpy(&fdm_data, fdm_ins, sizeof(struct NpsFdm));
+
+ // Timestamp
+ vn_data.TimeStartup = (uint64_t)(fdm_data.time * 1000000000.0);
+
+ //Attitude, float, [degrees], yaw, pitch, roll, NED frame
+ vn_data.YawPitchRoll[0] = DegOfRad((float)fdm_data.ltp_to_body_eulers.psi); // yaw
+ vn_data.YawPitchRoll[1] = DegOfRad((float)fdm_data.ltp_to_body_eulers.theta); // pitch
+ vn_data.YawPitchRoll[2] = DegOfRad((float)fdm_data.ltp_to_body_eulers.phi); // roll
+
+ // Rates (imu frame), float, [rad/s]
+ vn_data.AngularRate[0] = (float)fdm_data.body_ecef_rotvel.p;
+ vn_data.AngularRate[1] = (float)fdm_data.body_ecef_rotvel.q;
+ vn_data.AngularRate[2] = (float)fdm_data.body_ecef_rotvel.r;
+
+ //Pos LLA, double,[beg, deg, m]
+ //The estimated position given as latitude, longitude, and altitude given in [deg, deg, m] respectfully.
+ vn_data.Position[0] = DegOfRad(fdm_data.lla_pos.lat);
+ vn_data.Position[1] = DegOfRad(fdm_data.lla_pos.lon);
+ vn_data.Position[2] = fdm_data.lla_pos.alt; // TODO: make sure it shows the correct starting point
+
+ //VelNed, float [m/s]
+ //The estimated velocity in the North East Down (NED) frame, given in m/s.
+ vn_data.Velocity[0] = (float)fdm_data.ltp_ecef_vel.x;
+ vn_data.Velocity[1] = (float)fdm_data.ltp_ecef_vel.y;
+ vn_data.Velocity[2] = (float)fdm_data.ltp_ecef_vel.z;
+
+ // Accel (imu-frame), float, [m/s^-2]
+ vn_data.Accel[0] = (float)fdm_data.body_ecef_accel.x;
+ vn_data.Accel[1] = (float)fdm_data.body_ecef_accel.y;
+ vn_data.Accel[2] = (float)fdm_data.body_ecef_accel.z;
+
+ // tow (in nanoseconds), uint64
+ vn_data.Tow = vn_get_time_of_week();
+
+ //num sats, uint8
+ vn_data.NumSats = 8; // random number
+
+ //gps fix, uint8
+ vn_data.Fix = 3; // 3D fix
+
+ //posU, float[3]
+ // TODO
+
+ //velU, float
+ // TODO
+
+ //linear acceleration imu-body frame, float [m/s^2]
+ vn_data.LinearAccelBody[0] = (float)fdm_data.ltp_ecef_vel.x;
+ vn_data.LinearAccelBody[1] = (float)fdm_data.ltp_ecef_vel.y;
+ vn_data.LinearAccelBody[2] = (float)fdm_data.ltp_ecef_vel.z;
+
+ //YprU, float[3]
+ // TODO
+
+ //instatus, uint16
+ vn_data.InsStatus = 0x02;
+
+ //Vel body, float [m/s]
+ // The estimated velocity in the body (i.e. imu) frame, given in m/s.
+ vn_data.VelBody[0] = (float)fdm_data.body_accel.x;
+ vn_data.VelBody[1] = (float)fdm_data.body_accel.y;
+ vn_data.VelBody[2] = (float)fdm_data.body_accel.z;
+}
+
+
+uint16_t nps_ins_fill_buffer(void)
+{
+ static uint16_t idx;
+
+ vn_buffer[0] = VN_SYNC;
+ vn_buffer[1] = VN_OUTPUT_GROUP;
+ vn_buffer[2] = (uint8_t)(VN_GROUP_FIELD_1 >> 8);
+ vn_buffer[3] = (uint8_t)(VN_GROUP_FIELD_1);
+ vn_buffer[4] = (uint8_t)(VN_GROUP_FIELD_2 >> 8);
+ vn_buffer[5] = (uint8_t)(VN_GROUP_FIELD_2);
+ vn_buffer[6] = (uint8_t)(VN_GROUP_FIELD_3 >> 8);
+ vn_buffer[7] = (uint8_t)(VN_GROUP_FIELD_3);
+ vn_buffer[8] = (uint8_t)(VN_GROUP_FIELD_4 >> 8);
+ vn_buffer[9] = (uint8_t)(VN_GROUP_FIELD_4);
+
+ idx = VN_DATA_START;
+
+ // Timestamp
+ memcpy(&vn_buffer[idx], &vn_data.TimeStartup, sizeof(uint64_t));
+ idx += sizeof(uint64_t);
+
+ //Attitude, float, [degrees], yaw, pitch, roll, NED frame
+ memcpy(&vn_buffer[idx], &vn_data.YawPitchRoll, 3 * sizeof(float));
+ idx += 3 * sizeof(float);
+
+ // Rates (imu frame), float, [rad/s]
+ memcpy(&vn_buffer[idx], &vn_data.AngularRate, 3 * sizeof(float));
+ idx += 3 * sizeof(float);
+
+ //Pos LLA, double,[beg, deg, m]
+ //The estimated position given as latitude, longitude, and altitude given in [deg, deg, m] respectfully.
+ memcpy(&vn_buffer[idx], &vn_data.Position, 3 * sizeof(double));
+ idx += 3 * sizeof(double);
+
+ //VelNed, float [m/s]
+ //The estimated velocity in the North East Down (NED) frame, given in m/s.
+ memcpy(&vn_buffer[idx], &vn_data.Velocity, 3 * sizeof(float));
+ idx += 3 * sizeof(float);
+
+ // Accel (imu-frame), float, [m/s^-2]
+ memcpy(&vn_buffer[idx], &vn_data.Accel, 3 * sizeof(float));
+ idx += 3 * sizeof(float);
+
+ // tow (in nanoseconds), uint64
+ memcpy(&vn_buffer[idx], &vn_data.Tow, sizeof(uint64_t));
+ idx += sizeof(uint64_t);
+
+ //num sats, uint8
+ vn_buffer[idx] = vn_data.NumSats;
+ idx++;
+
+ //gps fix, uint8
+ vn_buffer[idx] = vn_data.Fix;
+ idx++;
+
+ //posU, float[3]
+ memcpy(&vn_buffer[idx], &vn_data.PosU, 3 * sizeof(float));
+ idx += 3 * sizeof(float);
+
+ //velU, float
+ memcpy(&vn_buffer[idx], &vn_data.VelU, sizeof(float));
+ idx += sizeof(float);
+
+ //linear acceleration imu-body frame, float [m/s^2]
+ memcpy(&vn_buffer[idx], &vn_data.LinearAccelBody, 3 * sizeof(float));
+ idx += 3 * sizeof(float);
+
+ //YprU, float[3]
+ memcpy(&vn_buffer[idx], &vn_data.YprU, 3 * sizeof(float));
+ idx += 3 * sizeof(float);
+
+ //instatus, uint16
+ memcpy(&vn_buffer[idx], &vn_data.InsStatus, sizeof(uint16_t));
+ idx += sizeof(uint16_t);
+
+ //Vel body, float [m/s]
+ // The estimated velocity in the body (i.e. imu) frame, given in m/s.
+ memcpy(&vn_buffer[idx], &vn_data.VelBody, 3 * sizeof(float));
+ idx += 3 * sizeof(float);
+
+ // calculate checksum & send
+ uint16_t chk = vn_calculate_crc(&vn_buffer[1], idx - 1);
+ vn_buffer[idx] = (uint8_t)(chk >> 8);
+ idx++;
+ vn_buffer[idx] = (uint8_t)(chk & 0xFF);
+ idx++;
+
+ return idx;
+}
diff --git a/sw/simulator/nps/nps_ivy.c b/sw/simulator/nps/nps_ivy.c
index 4a62d901d5..92b915f34e 100644
--- a/sw/simulator/nps/nps_ivy.c
+++ b/sw/simulator/nps/nps_ivy.c
@@ -5,7 +5,9 @@
#include
#include
#include
-#include
+
+#include
+#include
#include "generated/airframe.h"
#include "math/pprz_algebra_float.h"
@@ -16,7 +18,9 @@
#include "nps_sensors.h"
#include "nps_atmosphere.h"
-//#include "subsystems/navigation/common_flight_plan.h"
+#include "generated/settings.h"
+#include "pprzlink/dl_protocol.h"
+#include "subsystems/datalink/downlink.h"
#if USE_GPS
#include "subsystems/gps.h"
@@ -24,6 +28,12 @@
#include NPS_SENSORS_PARAMS
+pthread_t th_ivy_main; // runs main Ivy loop
+static MsgRcvPtr ivyPtr = NULL;
+static int seq = 1;
+static int ap_launch_index;
+
+
/* Gaia Ivy functions */
static void on_WORLD_ENV(IvyClientPtr app __attribute__((unused)),
void *user_data __attribute__((unused)),
@@ -34,6 +44,18 @@ static void on_DL_SETTING(IvyClientPtr app __attribute__((unused)),
void *user_data __attribute__((unused)),
int argc __attribute__((unused)), char *argv[]);
+void* ivy_main_loop(void* data __attribute__((unused)));
+
+int find_launch_index(void);
+
+
+void* ivy_main_loop(void* data __attribute__((unused)))
+{
+ IvyMainLoop();
+
+ return NULL;
+}
+
void nps_ivy_init(char *ivy_bus)
{
const char *agent_name = AIRFRAME_NAME"_NPS";
@@ -56,6 +78,14 @@ void nps_ivy_init(char *ivy_bus)
} else {
IvyStart(ivy_bus);
}
+
+ nps_ivy_send_world_env = false;
+
+ ap_launch_index = find_launch_index();
+
+ // Launch separate thread with IvyMainLoop()
+ pthread_create(&th_ivy_main, NULL, ivy_main_loop, NULL);
+
}
/*
@@ -90,8 +120,7 @@ static void on_WORLD_ENV(IvyClientPtr app __attribute__((unused)),
/*
* Send a WORLD_ENV_REQ message
*/
-static MsgRcvPtr ivyPtr = NULL;
-static int seq = 1;
+
void nps_ivy_send_WORLD_ENV_REQ(void)
{
@@ -102,24 +131,41 @@ void nps_ivy_send_WORLD_ENV_REQ(void)
}
int pid = (int)getpid();
+
// Bind to the reply
ivyPtr = IvyBindMsg(on_WORLD_ENV, NULL, "^%d_%d (\\S*) WORLD_ENV (\\S*) (\\S*) (\\S*) (\\S*) (\\S*) (\\S*)", pid, seq);
+
// Send actual request
+ struct NpsFdm fdm_ivy;
+ memcpy(&fdm_ivy, &fdm, sizeof(struct NpsFdm));
+
IvySendMsg("nps %d_%d WORLD_ENV_REQ %f %f %f %f %f %f",
pid, seq,
- DegOfRad(fdm.lla_pos_pprz.lat),
- DegOfRad(fdm.lla_pos_pprz.lon),
- (fdm.hmsl),
- (fdm.ltpprz_pos.x),
- (fdm.ltpprz_pos.y),
- (fdm.ltpprz_pos.z));
+ DegOfRad(fdm_ivy.lla_pos_pprz.lat),
+ DegOfRad(fdm_ivy.lla_pos_pprz.lon),
+ (fdm_ivy.hmsl),
+ (fdm_ivy.ltpprz_pos.x),
+ (fdm_ivy.ltpprz_pos.y),
+ (fdm_ivy.ltpprz_pos.z));
seq++;
+
+ nps_ivy_send_world_env = false;
}
+int find_launch_index(void)
+{
+ static const char ap_launch[] = "lau"; // short name has only 3 first letters
+ char *ap_settings[NB_SETTING] = SETTINGS_NAMES_SHORT;
+
+ // list through the settinsg
+ for (uint8_t idx=0;idx= 0) || (ap_launch_index < NB_SETTING)) {
+ if (index==ap_launch_index){
+ nps_update_launch_from_dl(value);
+ }
+ }
}
-void nps_ivy_display(void)
+
+void nps_ivy_display(struct NpsFdm* fdm_data, struct NpsSensors* sensors_data)
{
+ struct NpsFdm fdm_ivy;
+ memcpy (&fdm_ivy, fdm_data, sizeof(struct NpsFdm));
+
+ struct NpsSensors sensors_ivy;
+ memcpy (&sensors_ivy, sensors_data, sizeof(struct NpsSensors));
+
IvySendMsg("%d NPS_RATE_ATTITUDE %f %f %f %f %f %f",
AC_ID,
- DegOfRad(fdm.body_ecef_rotvel.p),
- DegOfRad(fdm.body_ecef_rotvel.q),
- DegOfRad(fdm.body_ecef_rotvel.r),
- DegOfRad(fdm.ltp_to_body_eulers.phi),
- DegOfRad(fdm.ltp_to_body_eulers.theta),
- DegOfRad(fdm.ltp_to_body_eulers.psi));
+ DegOfRad(fdm_ivy.body_ecef_rotvel.p),
+ DegOfRad(fdm_ivy.body_ecef_rotvel.q),
+ DegOfRad(fdm_ivy.body_ecef_rotvel.r),
+ DegOfRad(fdm_ivy.ltp_to_body_eulers.phi),
+ DegOfRad(fdm_ivy.ltp_to_body_eulers.theta),
+ DegOfRad(fdm_ivy.ltp_to_body_eulers.psi));
IvySendMsg("%d NPS_POS_LLH %f %f %f %f %f %f %f %f %f",
AC_ID,
- (fdm.lla_pos_pprz.lat),
- (fdm.lla_pos_geod.lat),
- (fdm.lla_pos_geoc.lat),
- (fdm.lla_pos_pprz.lon),
- (fdm.lla_pos_geod.lon),
- (fdm.lla_pos_pprz.alt),
- (fdm.lla_pos_geod.alt),
- (fdm.agl),
- (fdm.hmsl));
+ (fdm_ivy.lla_pos_pprz.lat),
+ (fdm_ivy.lla_pos_geod.lat),
+ (fdm_ivy.lla_pos_geoc.lat),
+ (fdm_ivy.lla_pos_pprz.lon),
+ (fdm_ivy.lla_pos_geod.lon),
+ (fdm_ivy.lla_pos_pprz.alt),
+ (fdm_ivy.lla_pos_geod.alt),
+ (fdm_ivy.agl),
+ (fdm_ivy.hmsl));
IvySendMsg("%d NPS_SPEED_POS %f %f %f %f %f %f %f %f %f",
AC_ID,
- (fdm.ltpprz_ecef_accel.x),
- (fdm.ltpprz_ecef_accel.y),
- (fdm.ltpprz_ecef_accel.z),
- (fdm.ltpprz_ecef_vel.x),
- (fdm.ltpprz_ecef_vel.y),
- (fdm.ltpprz_ecef_vel.z),
- (fdm.ltpprz_pos.x),
- (fdm.ltpprz_pos.y),
- (fdm.ltpprz_pos.z));
+ (fdm_ivy.ltpprz_ecef_accel.x),
+ (fdm_ivy.ltpprz_ecef_accel.y),
+ (fdm_ivy.ltpprz_ecef_accel.z),
+ (fdm_ivy.ltpprz_ecef_vel.x),
+ (fdm_ivy.ltpprz_ecef_vel.y),
+ (fdm_ivy.ltpprz_ecef_vel.z),
+ (fdm_ivy.ltpprz_pos.x),
+ (fdm_ivy.ltpprz_pos.y),
+ (fdm_ivy.ltpprz_pos.z));
IvySendMsg("%d NPS_GYRO_BIAS %f %f %f",
AC_ID,
- DegOfRad(RATE_FLOAT_OF_BFP(sensors.gyro.bias_random_walk_value.x) + sensors.gyro.bias_initial.x),
- DegOfRad(RATE_FLOAT_OF_BFP(sensors.gyro.bias_random_walk_value.y) + sensors.gyro.bias_initial.y),
- DegOfRad(RATE_FLOAT_OF_BFP(sensors.gyro.bias_random_walk_value.z) + sensors.gyro.bias_initial.z));
+ DegOfRad(RATE_FLOAT_OF_BFP(sensors_ivy.gyro.bias_random_walk_value.x) + sensors_ivy.gyro.bias_initial.x),
+ DegOfRad(RATE_FLOAT_OF_BFP(sensors_ivy.gyro.bias_random_walk_value.y) + sensors_ivy.gyro.bias_initial.y),
+ DegOfRad(RATE_FLOAT_OF_BFP(sensors_ivy.gyro.bias_random_walk_value.z) + sensors_ivy.gyro.bias_initial.z));
/* transform magnetic field to body frame */
struct DoubleVect3 h_body;
- double_quat_vmult(&h_body, &fdm.ltp_to_body_quat, &fdm.ltp_h);
+ double_quat_vmult(&h_body, &fdm_ivy.ltp_to_body_quat, &fdm_ivy.ltp_h);
IvySendMsg("%d NPS_SENSORS_SCALED %f %f %f %f %f %f",
AC_ID,
- ((sensors.accel.value.x - sensors.accel.neutral.x) / NPS_ACCEL_SENSITIVITY_XX),
- ((sensors.accel.value.y - sensors.accel.neutral.y) / NPS_ACCEL_SENSITIVITY_YY),
- ((sensors.accel.value.z - sensors.accel.neutral.z) / NPS_ACCEL_SENSITIVITY_ZZ),
+ ((sensors_ivy.accel.value.x - sensors_ivy.accel.neutral.x) / NPS_ACCEL_SENSITIVITY_XX),
+ ((sensors_ivy.accel.value.y - sensors_ivy.accel.neutral.y) / NPS_ACCEL_SENSITIVITY_YY),
+ ((sensors_ivy.accel.value.z - sensors_ivy.accel.neutral.z) / NPS_ACCEL_SENSITIVITY_ZZ),
h_body.x,
h_body.y,
h_body.z);
IvySendMsg("%d NPS_WIND %f %f %f",
AC_ID,
- fdm.wind.x,
- fdm.wind.y,
- fdm.wind.z);
+ fdm_ivy.wind.x,
+ fdm_ivy.wind.y,
+ fdm_ivy.wind.z);
+
+ if(nps_ivy_send_world_env){
+ nps_ivy_send_WORLD_ENV_REQ();
+ }
}
diff --git a/sw/simulator/nps/nps_ivy.h b/sw/simulator/nps/nps_ivy.h
index 22b922dd30..6ada725a70 100644
--- a/sw/simulator/nps/nps_ivy.h
+++ b/sw/simulator/nps/nps_ivy.h
@@ -1,8 +1,13 @@
#ifndef NPS_IVY
#define NPS_IVY
+#include "nps_fdm.h"
+#include "nps_sensors.h"
+
+bool nps_ivy_send_world_env;
+
extern void nps_ivy_init(char *ivy_bus);
-extern void nps_ivy_display(void);
+extern void nps_ivy_display(struct NpsFdm* fdm_ivy, struct NpsSensors* sensors_ivy);
extern void nps_ivy_send_WORLD_ENV_REQ(void);
#endif /* NPS_IVY */
diff --git a/sw/simulator/nps/nps_main.h b/sw/simulator/nps/nps_main.h
index 61dcc5abc7..c6c9c2f4d4 100644
--- a/sw/simulator/nps/nps_main.h
+++ b/sw/simulator/nps/nps_main.h
@@ -1,6 +1,62 @@
#ifndef NPS_MAIN_H
#define NPS_MAIN_H
-extern void nps_set_time_factor(float time_factor);
+#include
+#include
+#include "nps_fdm.h"
+#include "mcu_periph/sys_time.h"
+#include "nps_atmosphere.h"
+#include "nps_sensors.h"
+#include "nps_autopilot.h"
+
+#define SIM_DT (1./SYS_TIME_FREQUENCY)
+#define DISPLAY_DT (1./30.)
+#define HOST_TIMEOUT_MS 40
+
+pthread_t th_flight_gear; // sends/receives flight gear packets
+pthread_t th_display_ivy; // sends Ivy messages
+pthread_t th_main_loop; // handles simulation
+
+pthread_mutex_t fdm_mutex; // mutex for fdm data
+
+int pauseSignal; // for catching SIGTSTP
+
+bool nps_main_parse_options(int argc, char **argv);
+
+int nps_main_init(int argc, char **argv);
+void nps_radio_and_autopilot_init(void);
+void nps_main_run_sim_step(void);
+void nps_set_time_factor(float time_factor);
+
+void* nps_main_loop(void* data __attribute__((unused)));
+void* nps_flight_gear_loop(void* data __attribute__((unused)));
+void* nps_main_display(void* data __attribute__((unused)));
+
+void tstp_hdl(int n __attribute__((unused)));
+void cont_hdl(int n __attribute__((unused)));
+
+double time_to_double(struct timeval *t);
+double ntime_to_double(struct timespec *t);
+
+void nps_update_launch_from_dl(uint8_t value);
+
+struct NpsMain {
+ double real_initial_time;
+ double scaled_initial_time;
+ double host_time_factor;
+ double sim_time;
+ double display_time;
+ char *fg_host;
+ unsigned int fg_port;
+ unsigned int fg_port_in;
+ unsigned int fg_time_offset;
+ int fg_fdm;
+ char *js_dev;
+ char *spektrum_dev;
+ int rc_script;
+ char *ivy_bus;
+};
+
+struct NpsMain nps_main;
#endif /* NPS_MAIN_H */
diff --git a/sw/simulator/nps/nps_main.c b/sw/simulator/nps/nps_main_common.c
similarity index 57%
rename from sw/simulator/nps/nps_main.c
rename to sw/simulator/nps/nps_main_common.c
index e716bc14df..bf470eac52 100644
--- a/sw/simulator/nps/nps_main.c
+++ b/sw/simulator/nps/nps_main_common.c
@@ -1,6 +1,7 @@
/*
* Copyright (C) 2009 Antoine Drouin
* Copyright (C) 2012 The Paparazzi Team
+ * Copyright (C) 2016 Michal Podhradsky
*
* This file is part of paparazzi.
*
@@ -20,51 +21,14 @@
* Boston, MA 02111-1307, USA.
*/
-#include
-#include
-#include
+#include "nps_main.h"
#include
-#include
-#include
+#include
#include
-#include "nps_main.h"
-#include "nps_fdm.h"
-#include "nps_sensors.h"
-#include "nps_atmosphere.h"
-#include "nps_autopilot.h"
-#include "nps_ivy.h"
#include "nps_flightgear.h"
-#include "mcu_periph/sys_time.h"
-#define SIM_DT (1./SYS_TIME_FREQUENCY)
-#define DISPLAY_DT (1./30.)
-#define HOST_TIMEOUT_MS 40
-
-static struct {
- double real_initial_time;
- double scaled_initial_time;
- double host_time_factor;
- double sim_time;
- double display_time;
- char *fg_host;
- unsigned int fg_port;
- unsigned int fg_port_in;
- unsigned int fg_time_offset;
- int fg_fdm;
- char *js_dev;
- char *spektrum_dev;
- int rc_script;
- char *ivy_bus;
-} nps_main;
-
-static bool nps_main_parse_options(int argc, char **argv);
-static void nps_main_init(void);
-static void nps_main_display(void);
-static void nps_main_run_sim_step(void);
-static gboolean nps_main_periodic(gpointer data __attribute__((unused)));
-
-int pauseSignal = 0;
+#include "nps_ivy.h"
void tstp_hdl(int n __attribute__((unused)))
{
@@ -77,6 +41,7 @@ void tstp_hdl(int n __attribute__((unused)))
}
}
+
void cont_hdl(int n __attribute__((unused)))
{
signal(SIGCONT, cont_hdl);
@@ -84,13 +49,20 @@ void cont_hdl(int n __attribute__((unused)))
printf("Press to continue.\n");
}
+
double time_to_double(struct timeval *t)
{
return ((double)t->tv_sec + (double)(t->tv_usec * 1e-6));
}
-int main(int argc, char **argv)
+double ntime_to_double(struct timespec *t)
{
+ return ((double)t->tv_sec + (double)(t->tv_nsec * 1e-9));
+}
+
+int nps_main_init(int argc, char **argv)
+{
+ pauseSignal = 0;
if (!nps_main_parse_options(argc, argv)) { return 1; }
@@ -101,22 +73,6 @@ int main(int argc, char **argv)
*/
setbuf(stdout, NULL);
- nps_main_init();
-
- signal(SIGCONT, cont_hdl);
- signal(SIGTSTP, tstp_hdl);
- printf("Time factor is %f. (Press Ctrl-Z to change)\n", nps_main.host_time_factor);
-
- GMainLoop *ml = g_main_loop_new(NULL, FALSE);
- g_timeout_add(HOST_TIMEOUT_MS, nps_main_periodic, NULL);
- g_main_loop_run(ml);
-
- return 0;
-}
-
-
-static void nps_main_init(void)
-{
nps_main.sim_time = 0.;
nps_main.display_time = 0.;
@@ -125,67 +81,22 @@ static void nps_main_init(void)
nps_main.real_initial_time = time_to_double(&t);
nps_main.scaled_initial_time = time_to_double(&t);
- nps_ivy_init(nps_main.ivy_bus);
nps_fdm_init(SIM_DT);
nps_atmosphere_init();
nps_sensors_init(nps_main.sim_time);
printf("Simulating with dt of %f\n", SIM_DT);
- enum NpsRadioControlType rc_type;
- char *rc_dev = NULL;
- if (nps_main.js_dev) {
- rc_type = JOYSTICK;
- rc_dev = nps_main.js_dev;
- } else if (nps_main.spektrum_dev) {
- rc_type = SPEKTRUM;
- rc_dev = nps_main.spektrum_dev;
- } else {
- rc_type = SCRIPT;
- }
- nps_autopilot_init(rc_type, nps_main.rc_script, rc_dev);
-
- if (nps_main.fg_host)
- nps_flightgear_init(nps_main.fg_host, nps_main.fg_port, nps_main.fg_port_in, nps_main.fg_time_offset);
-
+ nps_radio_and_autopilot_init();
#if DEBUG_NPS_TIME
printf("host_time_factor,host_time_elapsed,host_time_now,scaled_initial_time,sim_time_before,display_time_before,sim_time_after,display_time_after\n");
#endif
-}
+ signal(SIGCONT, cont_hdl);
+ signal(SIGTSTP, tstp_hdl);
+ printf("Time factor is %f. (Press Ctrl-Z to change)\n", nps_main.host_time_factor);
-
-
-static void nps_main_run_sim_step(void)
-{
- // printf("sim at %f\n", nps_main.sim_time);
-
- nps_atmosphere_update(SIM_DT);
-
- nps_autopilot_run_systime_step();
-
- nps_fdm_run_step(autopilot.launch, autopilot.commands, NPS_COMMANDS_NB);
-
- nps_sensors_run_step(nps_main.sim_time);
-
- nps_autopilot_run_step(nps_main.sim_time);
-
-}
-
-
-static void nps_main_display(void)
-{
- // printf("display at %f\n", nps_main.display_time);
- nps_ivy_display();
-
- if (nps_main.fg_host) {
- if (nps_main.fg_fdm) {
- nps_flightgear_send_fdm();
- } else {
- nps_flightgear_send();
- }
- }
- nps_flightgear_receive();
+ return 0;
}
@@ -217,84 +128,7 @@ void nps_set_time_factor(float time_factor)
}
-static gboolean nps_main_periodic(gpointer data __attribute__((unused)))
-{
- struct timeval tv_now;
- double host_time_now;
-
- if (pauseSignal) {
- char line[128];
- double tf = 1.0;
- double t1, t2, irt;
-
- gettimeofday(&tv_now, NULL);
- t1 = time_to_double(&tv_now);
- /* unscale to initial real time*/
- irt = t1 - (t1 - nps_main.scaled_initial_time) * nps_main.host_time_factor;
-
- printf("Press to continue (or CTRL-Z to suspend).\nEnter a new time factor if needed (current: %f): ",
- nps_main.host_time_factor);
- fflush(stdout);
- if (fgets(line, 127, stdin)) {
- if ((sscanf(line, " %le ", &tf) == 1)) {
- if (tf > 0 && tf < 1000) {
- nps_main.host_time_factor = tf;
- }
- }
- printf("Time factor is %f\n", nps_main.host_time_factor);
- }
- gettimeofday(&tv_now, NULL);
- t2 = time_to_double(&tv_now);
- /* add the pause to initial real time */
- irt += t2 - t1;
- nps_main.real_initial_time += t2 - t1;
- /* convert to scaled initial real time */
- nps_main.scaled_initial_time = t2 - (t2 - irt) / nps_main.host_time_factor;
- pauseSignal = 0;
- }
-
- gettimeofday(&tv_now, NULL);
- host_time_now = time_to_double(&tv_now);
- double host_time_elapsed = nps_main.host_time_factor * (host_time_now - nps_main.scaled_initial_time);
-
-#if DEBUG_NPS_TIME
- printf("%f,%f,%f,%f,%f,%f,", nps_main.host_time_factor, host_time_elapsed, host_time_now, nps_main.scaled_initial_time,
- nps_main.sim_time, nps_main.display_time);
-#endif
-
- int cnt = 0;
- static int prev_cnt = 0;
- static int grow_cnt = 0;
- while (nps_main.sim_time <= host_time_elapsed) {
- nps_main_run_sim_step();
- nps_main.sim_time += SIM_DT;
- if (nps_main.display_time < (host_time_now - nps_main.real_initial_time)) {
- nps_main_display();
- nps_main.display_time += DISPLAY_DT;
- }
- cnt++;
- }
-
- /* Check to make sure the simulation doesn't get too far behind real time looping */
- if (cnt > (prev_cnt)) {grow_cnt++;}
- else { grow_cnt--;}
- if (grow_cnt < 0) {grow_cnt = 0;}
- prev_cnt = cnt;
-
- if (grow_cnt > 10) {
- printf("Warning: The time factor is too large for efficient operation! Please reduce the time factor.\n");
- }
-
-#if DEBUG_NPS_TIME
- printf("%f,%f\n", nps_main.sim_time, nps_main.display_time);
-#endif
-
- return TRUE;
-
-}
-
-
-static bool nps_main_parse_options(int argc, char **argv)
+bool nps_main_parse_options(int argc, char **argv)
{
nps_main.fg_host = NULL;
@@ -391,3 +225,93 @@ static bool nps_main_parse_options(int argc, char **argv)
}
return TRUE;
}
+
+
+void *nps_flight_gear_loop(void *data __attribute__((unused)))
+{
+ struct timespec requestStart;
+ struct timespec requestEnd;
+ struct timespec waitFor;
+ long int period_ns = DISPLAY_DT * 1000000000L; // thread period in nanoseconds
+ long int task_ns = 0; // time it took to finish the task in nanoseconds
+
+
+ nps_flightgear_init(nps_main.fg_host, nps_main.fg_port, nps_main.fg_port_in, nps_main.fg_time_offset);
+
+ while (TRUE) {
+ clock_gettime(CLOCK_REALTIME, &requestStart);
+
+ pthread_mutex_lock(&fdm_mutex);
+ if (nps_main.fg_host) {
+ if (nps_main.fg_fdm) {
+ nps_flightgear_send_fdm();
+ } else {
+ nps_flightgear_send();
+ }
+ }
+ pthread_mutex_unlock(&fdm_mutex);
+
+ clock_gettime(CLOCK_REALTIME, &requestEnd);
+
+ // Calculate time it took
+ task_ns = (requestEnd.tv_sec - requestStart.tv_sec) * 1000000000L + (requestEnd.tv_nsec - requestStart.tv_nsec);
+
+ // task took less than one period, sleep for the rest of time
+ if (task_ns < period_ns) {
+ waitFor.tv_sec = 0;
+ waitFor.tv_nsec = period_ns - task_ns;
+ nanosleep(&waitFor, NULL);
+ } else {
+ // task took longer than the period
+ printf("FG THREAD: task took longer than one period, exactly %f [ms], but the period is %f [ms]\n",
+ (double)task_ns / 1E6, (double)period_ns / 1E6);
+ }
+ }
+
+ return(NULL);
+}
+
+
+
+void *nps_main_display(void *data __attribute__((unused)))
+{
+ struct timespec requestStart;
+ struct timespec requestEnd;
+ struct timespec waitFor;
+ long int period_ns = 3 * DISPLAY_DT * 1000000000L; // thread period in nanoseconds
+ long int task_ns = 0; // time it took to finish the task in nanoseconds
+
+ struct NpsFdm fdm_ivy;
+ struct NpsSensors sensors_ivy;
+
+ nps_ivy_init(nps_main.ivy_bus);
+
+ while (TRUE) {
+ clock_gettime(CLOCK_REALTIME, &requestStart);
+
+ pthread_mutex_lock(&fdm_mutex);
+ memcpy(&fdm_ivy, &fdm, sizeof(fdm));
+ memcpy(&sensors_ivy, &sensors, sizeof(sensors));
+ pthread_mutex_unlock(&fdm_mutex);
+
+ nps_ivy_display(&fdm_ivy, &sensors_ivy);
+
+ clock_gettime(CLOCK_REALTIME, &requestEnd);
+
+ // Calculate time it took
+ task_ns = (requestEnd.tv_sec - requestStart.tv_sec) * 1000000000L + (requestEnd.tv_nsec - requestStart.tv_nsec);
+
+ // task took less than one period, sleep for the rest of time
+ if (task_ns < period_ns) {
+ waitFor.tv_sec = 0;
+ waitFor.tv_nsec = period_ns - task_ns;
+ nanosleep(&waitFor, NULL);
+ } else {
+ // task took longer than the period
+ printf("IVY DISPLAY THREAD: task took longer than one period, exactly %f [ms], but the period is %f [ms]\n",
+ (double)task_ns / 1E6, (double)period_ns / 1E6);
+ }
+
+ }
+ return(NULL);
+}
diff --git a/sw/simulator/nps/nps_main_hitl.c b/sw/simulator/nps/nps_main_hitl.c
new file mode 100644
index 0000000000..6177629f68
--- /dev/null
+++ b/sw/simulator/nps/nps_main_hitl.c
@@ -0,0 +1,334 @@
+/*
+ * Copyright (C) 2009 Antoine Drouin
+ * Copyright (C) 2012 The Paparazzi Team
+ * Copyright (C) 2016 Michal Podhradsky
+ *
+ * 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.
+ */
+
+#include
+#include
+#include
+#include
+
+#include "termios.h"
+#include
+#include
+
+
+#include "paparazzi.h"
+#include "pprzlink/messages.h"
+#include "pprzlink/dl_protocol.h"
+#include "pprzlink/pprz_transport.h"
+#include "generated/airframe.h"
+
+/* Message id helpers */
+#define SenderIdOfPprzMsg(x) (x[0])
+#define IdOfPprzMsg(x) (x[1])
+
+#include "nps_main.h"
+#include "nps_sensors.h"
+#include "nps_atmosphere.h"
+#include "nps_autopilot.h"
+#include "nps_ivy.h"
+#include "nps_flightgear.h"
+#include "mcu_periph/sys_time.h"
+
+#include "nps_ins.h"
+
+void *nps_ins_data_loop(void *data __attribute__((unused)));
+void *nps_ap_data_loop(void *data __attribute__((unused)));
+
+pthread_t th_ins_data; // sends INS packets to the autopilot
+pthread_t th_ap_data; // receives commands from the autopilot
+
+#define NPS_MAX_MSG_SIZE 512
+
+int main(int argc, char **argv)
+{
+ nps_main_init(argc, argv);
+
+ if (nps_main.fg_host) {
+ pthread_create(&th_flight_gear, NULL, nps_flight_gear_loop, NULL);
+ }
+ pthread_create(&th_display_ivy, NULL, nps_main_display, NULL);
+ pthread_create(&th_main_loop, NULL, nps_main_loop, NULL);
+ pthread_create(&th_ins_data, NULL, nps_ins_data_loop, NULL);
+ pthread_create(&th_ap_data, NULL, nps_ap_data_loop, NULL);
+ pthread_join(th_main_loop, NULL);
+
+ return 0;
+}
+
+void nps_radio_and_autopilot_init(void)
+{
+ enum NpsRadioControlType rc_type;
+ char *rc_dev = NULL;
+ if (nps_main.js_dev) {
+ rc_type = JOYSTICK;
+ rc_dev = nps_main.js_dev;
+ } else if (nps_main.spektrum_dev) {
+ rc_type = SPEKTRUM;
+ rc_dev = nps_main.spektrum_dev;
+ } else {
+ rc_type = SCRIPT;
+ }
+ nps_autopilot_init(rc_type, nps_main.rc_script, rc_dev);
+}
+
+void nps_update_launch_from_dl(uint8_t value)
+{
+ autopilot.launch = value;
+}
+
+void nps_main_run_sim_step(void)
+{
+ nps_atmosphere_update(SIM_DT);
+ nps_fdm_run_step(autopilot.launch, autopilot.commands, NPS_COMMANDS_NB);
+}
+
+void *nps_ins_data_loop(void *data __attribute__((unused)))
+{
+ struct timespec requestStart;
+ struct timespec requestEnd;
+ struct timespec waitFor;
+ long int period_ns = (1. / INS_FREQUENCY) * 1000000000L; // thread period in nanoseconds
+ long int task_ns = 0; // time it took to finish the task in nanoseconds
+
+ nps_ins_init(); // initialize ins variables and pointers
+
+ // configure port
+ int fd = open(INS_DEV, O_WRONLY | O_NOCTTY | O_SYNC);//open(INS_DEV, O_RDWR | O_NOCTTY);
+ if (fd < 0) {
+ printf("INS THREAD: data loop error opening port %i\n", fd);
+ return(NULL);
+ }
+
+ struct termios new_settings;
+ tcgetattr(fd, &new_settings);
+ memset(&new_settings, 0, sizeof(new_settings));
+ new_settings.c_iflag = 0;
+ new_settings.c_cflag = 0;
+ new_settings.c_lflag = 0;
+ new_settings.c_cc[VMIN] = 0;
+ new_settings.c_cc[VTIME] = 0;
+ cfsetispeed(&new_settings, (speed_t)INS_BAUD);
+ cfsetospeed(&new_settings, (speed_t)INS_BAUD);
+ tcsetattr(fd, TCSANOW, &new_settings);
+
+ struct NpsFdm fdm_ins;
+
+ while (TRUE) {
+ // lock mutex
+ pthread_mutex_lock(&fdm_mutex);
+
+ // start timing
+ clock_gettime(CLOCK_REALTIME, &requestStart);
+
+ // make a copy of fdm struct to speed things up
+ memcpy(&fdm_ins, &fdm, sizeof(fdm));
+
+ // unlock mutex
+ pthread_mutex_unlock(&fdm_mutex);
+
+ // fetch data
+ nps_ins_fetch_data(&fdm_ins);
+
+ // send ins data here
+ static uint16_t idx;
+ idx = nps_ins_fill_buffer();
+
+ static int wlen;
+ wlen = write(fd, ins_buffer, idx);
+ if (wlen != idx) {
+ printf("INS THREAD: Warning - sent only %u bytes to the autopilot, instead of expected %u\n", wlen, idx);
+ }
+
+ clock_gettime(CLOCK_REALTIME, &requestEnd);
+
+ // Calculate time it took
+ task_ns = (requestEnd.tv_sec - requestStart.tv_sec) * 1000000000L + (requestEnd.tv_nsec - requestStart.tv_nsec);
+
+ // task took less than one period, sleep for the rest of time
+ if (task_ns < period_ns) {
+ waitFor.tv_sec = 0;
+ waitFor.tv_nsec = period_ns - task_ns;
+ nanosleep(&waitFor, NULL);
+ } else {
+ // task took longer than the period
+ printf("INS THREAD: task took longer than one period, exactly %f [ms], but the period is %f [ms]\n",
+ (double)task_ns / 1E6, (double)period_ns / 1E6);
+ }
+ }
+ return(NULL);
+}
+
+
+
+void *nps_ap_data_loop(void *data __attribute__((unused)))
+{
+ // configure port
+ int fd = open(AP_DEV, O_RDONLY | O_NOCTTY);
+ if (fd < 0) {
+ printf("AP data loop error opening port %i\n", fd);
+ return(NULL);
+ }
+
+ struct termios new_settings;
+ tcgetattr(fd, &new_settings);
+ memset(&new_settings, 0, sizeof(new_settings));
+ new_settings.c_iflag = 0;
+ new_settings.c_cflag = 0;
+ new_settings.c_lflag = 0;
+ new_settings.c_cc[VMIN] = 1;
+ new_settings.c_cc[VTIME] = 5;
+ cfsetispeed(&new_settings, (speed_t)AP_BAUD);
+ cfsetospeed(&new_settings, (speed_t)AP_BAUD);
+ tcsetattr(fd, TCSANOW, &new_settings);
+
+ int rdlen;
+ uint8_t buf[NPS_MAX_MSG_SIZE];
+ uint8_t cmd_len;
+ pprz_t cmd_buf[NPS_COMMANDS_NB];
+
+ struct pprz_transport pprz_tp_logger;
+
+ while (TRUE) {
+ // receive messages from the autopilot
+ rdlen = read(fd, buf, sizeof(buf) - 1);
+
+ for (int i = 0; i < rdlen; i++) {
+ // parse data
+ parse_pprz(&pprz_tp_logger, buf[i]);
+
+ // if msg_available then read
+ if (pprz_tp_logger.trans_rx.msg_received) {
+ for (int k = 0; k < pprz_tp_logger.trans_rx.payload_len; k++) {
+ buf[k] = pprz_tp_logger.trans_rx.payload[k];
+ }
+ //Parse message
+ uint8_t sender_id = SenderIdOfPprzMsg(buf);
+ uint8_t msg_id = IdOfPprzMsg(buf);
+
+ // parse telemetry messages coming from other AC
+ if (sender_id != AC_ID) {
+ switch (msg_id) {
+ default: {
+ break;
+ }
+ }
+ } else {
+ /* parse telemetry messages coming from the correct AC_ID */
+ switch (msg_id) {
+ case DL_COMMANDS:
+ // parse commands message
+ cmd_len = DL_COMMANDS_values_length(buf);
+ memcpy(&cmd_buf, DL_COMMANDS_values(buf), cmd_len * sizeof(int16_t));
+ pthread_mutex_lock(&fdm_mutex);
+ // update commands
+ for (uint8_t i = 0; i < NPS_COMMANDS_NB; i++) {
+ autopilot.commands[i] = (double)cmd_buf[i] / MAX_PPRZ;
+ }
+ // hack: invert pitch to fit most JSBSim models
+ autopilot.commands[COMMAND_PITCH] = -(double)cmd_buf[COMMAND_PITCH] / MAX_PPRZ;
+ pthread_mutex_unlock(&fdm_mutex);
+ break;
+ case DL_MOTOR_MIXING:
+ // parse actuarors message
+ cmd_len = DL_MOTOR_MIXING_values_length(buf);
+ memcpy(&cmd_buf, DL_MOTOR_MIXING_values(buf), cmd_len * sizeof(int16_t));
+ pthread_mutex_lock(&fdm_mutex);
+ // update commands
+ for (uint8_t i = 0; i < NPS_COMMANDS_NB; i++) {
+ autopilot.commands[i] = (double)cmd_buf[i] / MAX_PPRZ;
+ }
+ pthread_mutex_unlock(&fdm_mutex);
+ break;
+ default:
+ break;
+ }
+ }
+ pprz_tp_logger.trans_rx.msg_received = false;
+ }
+ }
+ }
+ return(NULL);
+}
+
+
+
+
+void *nps_main_loop(void *data __attribute__((unused)))
+{
+ struct timespec requestStart;
+ struct timespec requestEnd;
+ struct timespec waitFor;
+ long int period_ns = SIM_DT * 1000000000L; // thread period in nanoseconds
+ long int task_ns = 0; // time it took to finish the task in nanoseconds
+
+ // check the sim time difference from the realtime
+ // fdm.time - simulation time
+ struct timespec startTime;
+ struct timespec realTime;
+ clock_gettime(CLOCK_REALTIME, &startTime);
+ double start_secs = ntime_to_double(&startTime);
+ double real_secs = 0;
+ double real_time = 0;
+ static int guard;
+
+ while (TRUE) {
+ clock_gettime(CLOCK_REALTIME, &requestStart);
+
+ pthread_mutex_lock(&fdm_mutex);
+
+ // check the current simulation time
+ clock_gettime(CLOCK_REALTIME, &realTime);
+ real_secs = ntime_to_double(&realTime);
+ real_time = real_secs - start_secs; // real time elapsed
+
+ guard = 0;
+ while ((real_time - fdm.time) > SIM_DT) {
+ nps_main_run_sim_step();
+ guard++;
+ if (guard > 2) {
+ //If we are too much behind, catch up incrementaly
+ break;
+ }
+ }
+ pthread_mutex_unlock(&fdm_mutex);
+
+ clock_gettime(CLOCK_REALTIME, &requestEnd);
+
+ // Calculate time it took
+ task_ns = (requestEnd.tv_sec - requestStart.tv_sec) * 1000000000L + (requestEnd.tv_nsec - requestStart.tv_nsec);
+
+ // task took less than one period, sleep for the rest of time
+ if (task_ns < period_ns) {
+ waitFor.tv_sec = 0;
+ waitFor.tv_nsec = period_ns - task_ns;
+ nanosleep(&waitFor, NULL);
+ } else {
+ // task took longer than the period
+ printf("MAIN THREAD: task took longer than one period, exactly %f [ms], but the period is %f [ms]\n",
+ (double)task_ns / 1E6, (double)period_ns / 1E6);
+ }
+ }
+ return(NULL);
+}
+
+
diff --git a/sw/simulator/nps/nps_main_sitl.c b/sw/simulator/nps/nps_main_sitl.c
new file mode 100644
index 0000000000..bf2b03fb84
--- /dev/null
+++ b/sw/simulator/nps/nps_main_sitl.c
@@ -0,0 +1,182 @@
+/*
+ * Copyright (C) 2009 Antoine Drouin
+ * Copyright (C) 2012 The Paparazzi Team
+ * Copyright (C) 2016 Michal Podhradsky
+ *
+ * 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.
+ */
+
+#include
+#include
+#include
+#include
+
+#include "nps_main.h"
+#include "nps_fdm.h"
+
+
+
+
+int main(int argc, char **argv)
+{
+ if (nps_main_init(argc, argv)) {
+ return 1;
+ }
+
+ if (nps_main.fg_host) {
+ pthread_create(&th_flight_gear, NULL, nps_flight_gear_loop, NULL);
+ }
+ pthread_create(&th_display_ivy, NULL, nps_main_display, NULL);
+ pthread_create(&th_main_loop, NULL, nps_main_loop, NULL);
+ pthread_join(th_main_loop, NULL);
+
+ return 0;
+}
+
+
+void nps_update_launch_from_dl(uint8_t value __attribute__((unused))) {}
+
+
+void nps_radio_and_autopilot_init(void)
+{
+ enum NpsRadioControlType rc_type;
+ char *rc_dev = NULL;
+ if (nps_main.js_dev) {
+ rc_type = JOYSTICK;
+ rc_dev = nps_main.js_dev;
+ } else if (nps_main.spektrum_dev) {
+ rc_type = SPEKTRUM;
+ rc_dev = nps_main.spektrum_dev;
+ } else {
+ rc_type = SCRIPT;
+ }
+ nps_autopilot_init(rc_type, nps_main.rc_script, rc_dev);
+}
+
+
+void nps_main_run_sim_step(void)
+{
+ nps_atmosphere_update(SIM_DT);
+
+ nps_autopilot_run_systime_step();
+
+ nps_fdm_run_step(autopilot.launch, autopilot.commands, NPS_COMMANDS_NB);
+
+ nps_sensors_run_step(nps_main.sim_time);
+
+ nps_autopilot_run_step(nps_main.sim_time);
+
+}
+
+
+void *nps_main_loop(void *data __attribute__((unused)))
+{
+ struct timespec requestStart;
+ struct timespec requestEnd;
+ struct timespec waitFor;
+ long int period_ns = HOST_TIMEOUT_MS * 1000000LL; // thread period in nanoseconds
+ long int task_ns = 0; // time it took to finish the task in nanoseconds
+
+ struct timeval tv_now;
+ double host_time_now;
+
+ while (TRUE) {
+ if (pauseSignal) {
+ char line[128];
+ double tf = 1.0;
+ double t1, t2, irt;
+
+ gettimeofday(&tv_now, NULL);
+ t1 = time_to_double(&tv_now);
+ // unscale to initial real time
+ irt = t1 - (t1 - nps_main.scaled_initial_time) * nps_main.host_time_factor;
+
+ printf("Press to continue (or CTRL-Z to suspend).\nEnter a new time factor if needed (current: %f): ",
+ nps_main.host_time_factor);
+ fflush(stdout);
+ if (fgets(line, 127, stdin)) {
+ if ((sscanf(line, " %le ", &tf) == 1)) {
+ if (tf > 0 && tf < 1000) {
+ nps_main.host_time_factor = tf;
+ }
+ }
+ printf("Time factor is %f\n", nps_main.host_time_factor);
+ }
+ gettimeofday(&tv_now, NULL);
+ t2 = time_to_double(&tv_now);
+ // add the pause to initial real time
+ irt += t2 - t1;
+ nps_main.real_initial_time += t2 - t1;
+ // convert to scaled initial real time
+ nps_main.scaled_initial_time = t2 - (t2 - irt) / nps_main.host_time_factor;
+ pauseSignal = 0;
+ }
+
+ clock_gettime(CLOCK_REALTIME, &requestStart); // init measurement (after the pause signal)
+
+ gettimeofday(&tv_now, NULL);
+ host_time_now = time_to_double(&tv_now);
+ double host_time_elapsed = nps_main.host_time_factor * (host_time_now - nps_main.scaled_initial_time);
+
+#if DEBUG_NPS_TIME
+ printf("%f,%f,%f,%f,%f,%f,", nps_main.host_time_factor, host_time_elapsed, host_time_now, nps_main.scaled_initial_time,
+ nps_main.sim_time, nps_main.display_time);
+#endif
+
+ int cnt = 0;
+ static int prev_cnt = 0;
+ static int grow_cnt = 0;
+ while (nps_main.sim_time <= host_time_elapsed) {
+ pthread_mutex_lock(&fdm_mutex);
+ nps_main_run_sim_step();
+ nps_main.sim_time += SIM_DT;
+ pthread_mutex_unlock(&fdm_mutex);
+ cnt++;
+ }
+
+ // Check to make sure the simulation doesn't get too far behind real time looping
+ if (cnt > (prev_cnt)) {grow_cnt++;}
+ else { grow_cnt--;}
+ if (grow_cnt < 0) {grow_cnt = 0;}
+ prev_cnt = cnt;
+
+ if (grow_cnt > 10) {
+ printf("Warning: The time factor is too large for efficient operation! Please reduce the time factor.\n");
+ }
+
+#if DEBUG_NPS_TIME
+ printf("%f,%f\n", nps_main.sim_time, nps_main.display_time);
+#endif
+
+ clock_gettime(CLOCK_REALTIME, &requestEnd); // end measurement
+
+ // Calculate time it took
+ task_ns = (requestEnd.tv_sec - requestStart.tv_sec) * 1000000000L + (requestEnd.tv_nsec - requestStart.tv_nsec);
+
+ if (task_ns > 0) {
+ waitFor.tv_sec = 0;
+ waitFor.tv_nsec = period_ns - task_ns;
+ nanosleep(&waitFor, NULL);
+ } else {
+ // task took longer than the period
+ printf("MAIN THREAD: task took longer than one period, exactly %f [ms], but the period is %f [ms]\n",
+ (double)task_ns / 1E6, (double)period_ns / 1E6);
+ }
+ }
+ return(NULL);
+}
diff --git a/sw/simulator/nps/nps_radio_control.c b/sw/simulator/nps/nps_radio_control.c
index cfe1398739..2cfc4224a4 100644
--- a/sw/simulator/nps/nps_radio_control.c
+++ b/sw/simulator/nps/nps_radio_control.c
@@ -48,6 +48,8 @@ void nps_radio_control_init(enum NpsRadioControlType type, int num_script, char
break;
case SCRIPT:
break;
+ default:
+ break;
}
}
diff --git a/sw/simulator/nps/nps_radio_control_spektrum.c b/sw/simulator/nps/nps_radio_control_spektrum.c
index a84db7319b..c9faf6849f 100644
--- a/sw/simulator/nps/nps_radio_control_spektrum.c
+++ b/sw/simulator/nps/nps_radio_control_spektrum.c
@@ -16,6 +16,8 @@
#define IUCLC 0
#endif
+#define CHANNEL_OF_FRAME(i) ((((frame_buf[2*i]<<8) + frame_buf[2*i+1])&0x03FF)-512)
+
static int sp_fd;
static gboolean on_serial_data_received(GIOChannel *source,
@@ -132,19 +134,12 @@ static void parse_data(char *buf, int len)
}
}
-
-#define CHANNEL_OF_FRAME(i) ((((frame_buf[2*i]<<8) + frame_buf[2*i+1])&0x03FF)-512)
static void handle_frame(void)
{
-
-
nps_radio_control.roll = (float)CHANNEL_OF_FRAME(0) / -340.;
nps_radio_control.throttle = (float)(CHANNEL_OF_FRAME(1) + 340) / 680.;
nps_radio_control.pitch = (float)CHANNEL_OF_FRAME(2) / -340.;
nps_radio_control.yaw = (float)CHANNEL_OF_FRAME(3) / -340.;
nps_radio_control.mode = (float)CHANNEL_OF_FRAME(5) / 340.;
-
-
// printf("%f %f %f %f %f \n", nps_radio_control.roll, nps_radio_control.throttle, nps_radio_control.pitch, nps_radio_control.yaw, nps_radio_control.mode);
-
}