diff --git a/conf/airframes/TUDelft/airframes/heli450.xml b/conf/airframes/TUDelft/airframes/heli450.xml
new file mode 100644
index 0000000000..8e0b94c6b2
--- /dev/null
+++ b/conf/airframes/TUDelft/airframes/heli450.xml
@@ -0,0 +1,221 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/conf/airframes/TUDelft/conf.xml b/conf/airframes/TUDelft/conf.xml
index 3a6bdeda39..ad2eb5c13d 100644
--- a/conf/airframes/TUDelft/conf.xml
+++ b/conf/airframes/TUDelft/conf.xml
@@ -87,6 +87,17 @@
settings_modules="modules/geo_mag.xml modules/air_data.xml modules/video_thread.xml modules/video_rtp_stream.xml"
gui_color="red"
/>
+
-
+
@@ -8,6 +8,7 @@
+
@@ -15,6 +16,7 @@
+
@@ -57,6 +59,8 @@ driver CDATA #IMPLIED>
+
+
@@ -68,6 +72,10 @@ min CDATA #REQUIRED
neutral CDATA #REQUIRED
max CDATA #REQUIRED>
+
+
diff --git a/conf/modules/heli_swashplate_mixing.xml b/conf/modules/heli_swashplate_mixing.xml
new file mode 100644
index 0000000000..8740354b9d
--- /dev/null
+++ b/conf/modules/heli_swashplate_mixing.xml
@@ -0,0 +1,17 @@
+
+
+
+
+ Helicopter Swashplate Mixing
+
+ heli_throttle_curve.xml
+
+
+
+
+
+
+
+
diff --git a/conf/modules/heli_throttle_curve.xml b/conf/modules/heli_throttle_curve.xml
new file mode 100644
index 0000000000..8b036cb8ca
--- /dev/null
+++ b/conf/modules/heli_throttle_curve.xml
@@ -0,0 +1,15 @@
+
+
+
+
+ Throttle Curve Mixers
+
+
+
+
+
+
+
+
diff --git a/sw/airborne/firmwares/rotorcraft/autopilot.h b/sw/airborne/firmwares/rotorcraft/autopilot.h
index e3d5456aee..8602ea5d12 100644
--- a/sw/airborne/firmwares/rotorcraft/autopilot.h
+++ b/sw/airborne/firmwares/rotorcraft/autopilot.h
@@ -111,6 +111,15 @@ extern uint16_t autopilot_flight_time;
* Limit thrust and/or yaw depending of the in_flight
* and motors_on flag status
*/
+#ifdef ROTORCRAFT_IS_HELI
+#define SetRotorcraftCommands(_cmd, _in_flight, _motor_on) { \
+ commands[COMMAND_ROLL] = _cmd[COMMAND_ROLL]; \
+ commands[COMMAND_PITCH] = _cmd[COMMAND_PITCH]; \
+ commands[COMMAND_YAW] = _cmd[COMMAND_YAW]; \
+ commands[COMMAND_THRUST] = _cmd[COMMAND_THRUST]; \
+ }
+#else
+
#ifndef ROTORCRAFT_COMMANDS_YAW_ALWAYS_ENABLED
#define SetRotorcraftCommands(_cmd, _in_flight, _motor_on) { \
if (!(_in_flight)) { _cmd[COMMAND_YAW] = 0; } \
@@ -129,6 +138,7 @@ extern uint16_t autopilot_flight_time;
commands[COMMAND_THRUST] = _cmd[COMMAND_THRUST]; \
}
#endif
+#endif
/** Z-acceleration threshold to detect ground in m/s^2 */
#ifndef THRESHOLD_GROUND_DETECT
diff --git a/sw/airborne/modules/helicopter/swashplate_mixing.c b/sw/airborne/modules/helicopter/swashplate_mixing.c
new file mode 100644
index 0000000000..41e4864645
--- /dev/null
+++ b/sw/airborne/modules/helicopter/swashplate_mixing.c
@@ -0,0 +1,91 @@
+/*
+ * Copyright (C) 2015 C. De Wagter
+ * 2015 Freek van Tienen
+ *
+ * This file is part of paparazzi
+ *
+ * paparazzi is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * paparazzi is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with paparazzi; see the file COPYING. If not, see
+ * .
+ */
+/**
+ * @file "modules/helicopter/swashplate_mixing.c"
+ * @author C. De Wagter and Freek van Tienen
+ * Helicopter Swashplate Mixing
+ */
+
+#include "swashplate_mixing.h"
+#include "throttle_curve.h"
+
+PRINT_CONFIG_VAR(SW_MIXING_TYPE)
+struct swashplate_mixing_t swashplate_mixing;
+
+/* Coeficients per motor */
+static const float roll_coef[SW_NB] = SW_MIXING_ROLL_COEF;
+static const float pitch_coef[SW_NB] = SW_MIXING_PITCH_COEF;
+static const float coll_coef[SW_NB] = SW_MIXING_COLL_COEF;
+
+/* Default roll trim */
+#ifndef SW_MIXING_TRIM_ROLL
+#define SW_MIXING_TRIM_ROLL 0
+#endif
+PRINT_CONFIG_VAR(SW_MIXING_TRIM_ROLL)
+
+/* Default pitch trim */
+#ifndef SW_MIXING_TRIM_PITCH
+#define SW_MIXING_TRIM_PITCH 0
+#endif
+PRINT_CONFIG_VAR(SW_MIXING_TRIM_PITCH)
+
+/* Default collective trim */
+#ifndef SW_MIXING_TRIM_COLL
+#define SW_MIXING_TRIM_COLL 0
+#endif
+PRINT_CONFIG_VAR(SW_MIXING_TRIM_COLL)
+
+
+/**
+ * Initialize the motor mixing and calculate the trim values
+ */
+void swashplate_mixing_init()
+{
+ uint8_t i;
+
+ // Go trough all the motors and calculate the trim value and set the initial command
+ for (i = 0; i < SW_NB; i++) {
+ swashplate_mixing.commands[i] = 0;
+ swashplate_mixing.trim[i] =
+ roll_coef[i] * SW_MIXING_TRIM_ROLL +
+ pitch_coef[i] * SW_MIXING_TRIM_PITCH +
+ coll_coef[i] * SW_MIXING_TRIM_COLL;
+ }
+}
+
+/*
+ * Run the swashplate mixing
+ * This depends on the ROLL and PITCH command
+ * It also depends on the throttle_curve.collective
+ */
+void swashplate_mixing_run(pprz_t in_cmd[])
+{
+ uint8_t i;
+
+ // Go trough all the motors and calculate the command
+ for (i = 0; i < SW_NB; i++) {
+ swashplate_mixing.commands[i] = swashplate_mixing.trim[i] +
+ roll_coef[i] * in_cmd[COMMAND_ROLL] +
+ pitch_coef[i] * in_cmd[COMMAND_PITCH] +
+ coll_coef[i] * throttle_curve.collective;
+ BoundAbs(swashplate_mixing.commands[i], MAX_PPRZ);
+ }
+}
diff --git a/sw/airborne/modules/helicopter/swashplate_mixing.h b/sw/airborne/modules/helicopter/swashplate_mixing.h
new file mode 100644
index 0000000000..57c78ece2d
--- /dev/null
+++ b/sw/airborne/modules/helicopter/swashplate_mixing.h
@@ -0,0 +1,81 @@
+/*
+ * Copyright (C) 2015 C. De Wagter
+ * 2015 Freek van Tienen
+ *
+ * This file is part of paparazzi
+ *
+ * paparazzi is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * paparazzi is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with paparazzi; see the file COPYING. If not, see
+ * .
+ */
+/**
+ * @file "modules/helicopter/swashplate_mixing.h"
+ * @author C. De Wagter and Freek van Tienen
+ * Helicopter Swashplate Mixing
+ */
+
+#ifndef SWASHPLATE_MIXING_H
+#define SWASHPLATE_MIXING_H
+
+#include "std.h"
+#include "paparazzi.h"
+#include "generated/airframe.h"
+
+/* Different type of swashplate mixings */
+#define MECH 0
+#define H120 1
+#define HR120 2
+
+/**
+ * MECH (front/right/coll), H120 (front/rightback/leftback), HR120 (back/leftfront/rightfront)
+ */
+#if SW_MIXING_TYPE == MECH
+#define SW_NB 3
+#define SW_FRONT 0
+#define SW_RIGHT 1
+#define SW_COLL 2
+#define SW_MIXING_ROLL_COEF { 0, -1, 0 }
+#define SW_MIXING_PITCH_COEF { 1, 0, 0 }
+#define SW_MIXING_COLL_COEF { 0, 0, 1 }
+
+#elif SW_MIXING_TYPE == H120
+#define SW_NB 3
+#define SW_FRONT 0
+#define SW_RIGHTBACK 1
+#define SW_LEFTBACK 2
+#define SW_MIXING_ROLL_COEF { 0, -0.866, 0.866 }
+#define SW_MIXING_PITCH_COEF { 1, -0.5, -0.5 }
+#define SW_MIXING_COLL_COEF { 1, 1, 1 }
+
+#elif SW_MIXING_TYPE == HR120
+#define SW_NB 3
+#define SW_BACK 0
+#define SW_LEFTFRONT 1
+#define SW_RIGHTFRONT 2
+#define SW_MIXING_ROLL_COEF { 0, 0.866, -0.866 }
+#define SW_MIXING_PITCH_COEF { -1, 0.5, 0.5 }
+#define SW_MIXING_COLL_COEF { 1, 1, 1 }
+#endif
+
+/* Swashplate mixing structure */
+struct swashplate_mixing_t {
+ int32_t commands[SW_NB]; ///< The output commands
+ int32_t trim[SW_NB]; ///< Trim values for the different actuators
+};
+extern struct swashplate_mixing_t swashplate_mixing;
+
+/* External used functions */
+extern void swashplate_mixing_init(void);
+extern void swashplate_mixing_run(pprz_t in_cmd[]);
+
+#endif
diff --git a/sw/airborne/modules/helicopter/throttle_curve.c b/sw/airborne/modules/helicopter/throttle_curve.c
new file mode 100644
index 0000000000..b709d99e5f
--- /dev/null
+++ b/sw/airborne/modules/helicopter/throttle_curve.c
@@ -0,0 +1,82 @@
+/*
+ * Copyright (C) 2015 C. De Wagter
+ * 2015 Freek van Tienen
+ *
+ * This file is part of paparazzi
+ *
+ * paparazzi is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * paparazzi is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with paparazzi; see the file COPYING. If not, see
+ * .
+ */
+/**
+ * @file "modules/helicopter/throttle_curve.c"
+ * @author C. De Wagter and Freek van Tienen
+ * Throttle Curve Mixers
+ */
+
+#include "throttle_curve.h"
+
+/* The switching values for the Throttle Curve Mode switch */
+#define THROTTLE_CURVE_SWITCH_VAL (MAX_PPRZ*2/THROTTLE_CURVES_NB)
+
+/* Initialize the throttle curves from the airframe file */
+struct throttle_curve_t throttle_curve = {
+ .nb_curves = THROTTLE_CURVES_NB,
+ .curves = THROTTLE_CURVES
+};
+
+/**
+ * Initialize the default throttle curve values
+ */
+void throttle_curve_init(void)
+{
+ throttle_curve.mode = THROTTLE_CURVE_MODE_INIT;
+ throttle_curve.throttle = throttle_curve.curves[THROTTLE_CURVE_MODE_INIT].throttle[0];
+ throttle_curve.collective = throttle_curve.curves[THROTTLE_CURVE_MODE_INIT].collective[0];
+}
+
+/**
+ * Run the throttle curve and generate the output throttle and pitch
+ * This depends on the FMODE(flight mode) and TRHUST command
+ */
+void throttle_curve_run(bool_t motors_on, pprz_t in_cmd[])
+{
+ // Calculate the mode value from the switch
+ int8_t mode = ((float)(in_cmd[COMMAND_FMODE] + MAX_PPRZ) / THROTTLE_CURVE_SWITCH_VAL);
+ Bound(mode, 0, THROTTLE_CURVES_NB - 1);
+ throttle_curve.mode = mode;
+
+ // Check if we have multiple points or a single point
+ struct curve_t curve = throttle_curve.curves[mode];
+ if (curve.nb_points == 1) {
+ throttle_curve.throttle = curve.throttle[0];
+ throttle_curve.collective = curve.collective[0];
+ } else {
+ // Calculate the left point on the curve we need to use
+ uint16_t curve_range = (MAX_PPRZ / (curve.nb_points - 1));
+ int8_t curve_p = ((float)in_cmd[COMMAND_THRUST] / curve_range);
+ Bound(curve_p, 0, curve.nb_points - 1);
+
+ // Calculate the throttle and pitch value
+ uint16_t x = in_cmd[COMMAND_THRUST] - curve_p * curve_range;
+ throttle_curve.throttle = curve.throttle[curve_p]
+ + ((curve.throttle[curve_p + 1] - curve.throttle[curve_p]) * x / curve_range);
+ throttle_curve.collective = curve.collective[curve_p]
+ + ((curve.collective[curve_p + 1] - curve.collective[curve_p]) * x / curve_range);
+ }
+
+ // Only set throttle if motors are on
+ if (!motors_on) {
+ throttle_curve.throttle = 0;
+ }
+}
diff --git a/sw/airborne/modules/helicopter/throttle_curve.h b/sw/airborne/modules/helicopter/throttle_curve.h
new file mode 100644
index 0000000000..8fb4fef2f2
--- /dev/null
+++ b/sw/airborne/modules/helicopter/throttle_curve.h
@@ -0,0 +1,56 @@
+/*
+ * Copyright (C) 2015 C. De Wagter
+ * 2015 Freek van Tienen
+ *
+ * This file is part of paparazzi
+ *
+ * paparazzi is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * paparazzi is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with paparazzi; see the file COPYING. If not, see
+ * .
+ */
+/**
+ * @file "modules/helicopter/throttle_curve.h"
+ * @author C. De Wagter and Freek van Tienen
+ * Throttle Curve Mixers
+ */
+
+#ifndef THROTTLE_CURVE_H
+#define THROTTLE_CURVE_H
+
+#include "std.h"
+#include "paparazzi.h"
+#include "generated/airframe.h"
+
+/* Throttle and collective curve */
+struct curve_t {
+ uint8_t nb_points; ///< The number of points in the curve
+ uint16_t throttle[THROTTLE_POINTS_NB]; ///< Throttle points in the curve
+ int16_t collective[THROTTLE_POINTS_NB]; ///< The collective points in the curve
+};
+
+/* Main throttle curve structure */
+struct throttle_curve_t {
+ uint8_t mode; ///< Flight mode
+ uint8_t nb_curves; ///< The number of throttle/pitch curves
+ struct curve_t curves[THROTTLE_CURVES_NB]; ///< Throttle/pitch curves
+
+ uint16_t throttle; ///< Output thrust(throttle) of the throttle curve
+ int16_t collective; ///< Output collective of the throttle curve
+};
+extern struct throttle_curve_t throttle_curve;
+
+/* External functions */
+extern void throttle_curve_init(void);
+void throttle_curve_run(bool_t motors_on, pprz_t in_cmd[]);
+
+#endif
diff --git a/sw/tools/generators/gen_airframe.ml b/sw/tools/generators/gen_airframe.ml
index a2401ecab8..3a0a367fcf 100644
--- a/sw/tools/generators/gen_airframe.ml
+++ b/sw/tools/generators/gen_airframe.ml
@@ -262,6 +262,17 @@ let parse_command = fun command no ->
let failsafe_value = int_of_string (ExtXml.attrib command "failsafe_value") in
{ failsafe_value = failsafe_value; foo = 0}
+let parse_heli_curves = fun heli_surves ->
+ let a = fun s -> ExtXml.attrib heli_surves s in
+ match Xml.tag heli_surves with
+ "curve" ->
+ let throttle = a "throttle" in
+ let collective = a "collective" in
+ printf " {.nb_points = %i, \\\n" (List.length (Str.split (Str.regexp ",") throttle));
+ printf " .throttle = {%s}, \\\n" throttle;
+ printf " .collective = {%s}}, \\\n" collective
+ | _ -> xml_error "mixer"
+
let rec parse_section = fun ac_id s ->
match Xml.tag s with
"section" ->
@@ -315,6 +326,16 @@ let rec parse_section = fun ac_id s ->
List.iter parse_command_laws (Xml.children s);
printf " AllActuatorsCommit(); \\\n";
printf "}\n\n";
+ | "heli_curves" ->
+ let default = ExtXml.attrib_or_default s "default" "0" in
+ let curves = Xml.children s in
+ let nb_points = List.fold_right (fun s m -> Pervasives.max (List.length (Str.split (Str.regexp ",") (ExtXml.attrib s "throttle"))) m) curves 0 in
+ define "THROTTLE_CURVE_MODE_INIT" default;
+ define "THROTTLE_CURVES_NB" (string_of_int (List.length curves));
+ define "THROTTLE_POINTS_NB" (string_of_int nb_points);
+ printf "#define THROTTLE_CURVES { \\\n";
+ List.iter parse_heli_curves curves;
+ printf "}\n\n";
| "include" ->
let filename = Str.global_replace (Str.regexp "\\$AC_ID") ac_id (ExtXml.attrib s "href") in
let subxml = Xml.parse_file filename in