mirror of
https://github.com/paparazzi/paparazzi.git
synced 2026-05-26 08:22:43 +08:00
feat: add ANDI stabilization controller (#3578)
This commit is contained in:
@@ -0,0 +1,283 @@
|
||||
<!DOCTYPE airframe SYSTEM "../airframe.dtd">
|
||||
<airframe name="Cyclone2">
|
||||
<description>
|
||||
Cyclone 2 airframe
|
||||
|
||||
+ Model: Cyclone 2 is a tiltbody wing with a ~1m wingspan
|
||||
+ Autopilot: Cube orange
|
||||
+ Actuators: Feetech sts3032
|
||||
<!-- + GNSS Ublox F9P GNSS with RTK -->
|
||||
+ MAG ΡΜ3100
|
||||
+ ESC: KISS ECSs
|
||||
+ RCRX: ELRS RP1
|
||||
+ AIRSPEED: MS4525DO
|
||||
+ TELEMETRY: RFDesign 868X
|
||||
+ CURRENT: Standard FC Power sensor
|
||||
+ RANGER: None
|
||||
+ MOTOR: 2 x 1250KV Outrunner Brushless
|
||||
+ PROP: 2 blade thin electric 8 x 6
|
||||
+ BAT: Li-Po 4S1P 2300mAh
|
||||
|
||||
WARNING: Current PPRZ airspeed sensor driver has a bug,
|
||||
static and dynamic pressure defaults are swapped,
|
||||
so the airspeed is negative if you dont change your pitot leads
|
||||
|
||||
NOTES:
|
||||
+ Using oneloop ANDI
|
||||
+ Servos powered via external BEC (4s to 9 V)
|
||||
+ Flightcontroller powered via FC Powerboard
|
||||
+ Telemetry powerd via BEC of FC Powerboard
|
||||
</description>
|
||||
|
||||
<firmware name="rotorcraft">
|
||||
|
||||
<autopilot name="jpg_cyclone_andi.xml"/>
|
||||
|
||||
<configure name="PERIODIC_FREQUENCY" value="500"/>
|
||||
<configure name="NAVIGATION_FREQUENCY" value="50"/>
|
||||
|
||||
<target name="ap" board="cube_orange">
|
||||
|
||||
<module name="radio_control" type="sbus">
|
||||
<define name="RADIO_KILL_SWITCH" value="RADIO_AUX1"/>
|
||||
<define name="AP_MODE_SWITCH" value="RADIO_AUX3"/>
|
||||
</module>
|
||||
|
||||
<module name="sys_mon"/>
|
||||
|
||||
<module name="flight_recorder"/>
|
||||
|
||||
<!-- EKF EKF2 configure inputs -->
|
||||
<define name="INS_EKF2_MAG_ID" value="MAG_RM3100_SENDER_ID"/>
|
||||
<define name="INS_EKF2_IMU_ID" value="IMU_CUBE1_ID"/>
|
||||
<define name="INS_EKF2_GYRO_ID" value="IMU_CUBE1_ID"/>
|
||||
<define name="INS_EKF2_ACCEL_ID" value="IMU_CUBE1_ID"/>
|
||||
|
||||
<define name="INS_EKF2_OPTITRACK" value="TRUE"/> <!-- Not sure if it is actually using Optitrack here. Flies just fine with Optitrack Z-up instead of Y-up-->
|
||||
|
||||
</target>
|
||||
|
||||
<target name="nps" board="pc">
|
||||
<module name="fdm" type="jsbsim">
|
||||
<define name="NPS_JSBSIM_MODEL" value="cyclone" type="string"/>
|
||||
<define name="NPS_SENSORS_PARAMS" value="nps_sensors_params_default.h" type="string"/>
|
||||
<define name="NPS_USE_COMMANDS" value="TRUE"/>
|
||||
<define name="NPS_NO_MOTOR_MIXING" value="TRUE"/>
|
||||
|
||||
</module>
|
||||
<module name="radio_control" type="datalink">
|
||||
<define name="RADIO_KILL_SWITCH" value="RADIO_AUX1"/>
|
||||
<define name="AP_MODE_SWITCH" value="RADIO_AUX7"/>
|
||||
</module>
|
||||
</target>
|
||||
|
||||
<module name="imu" type="cube"/>
|
||||
<module name="air_data"/>
|
||||
<module name="ins" type="ekf2">
|
||||
</module>
|
||||
|
||||
<module name="actuators" type="t4"/>
|
||||
<module name="actuators_t4_uart">
|
||||
<configure name="ACTUATORS_T4_PORT" value="UART8"/>
|
||||
<configure name="ACTUATORS_T4_BAUD" value="B921600"/>
|
||||
</module>
|
||||
|
||||
<module name="telemetry" type="transparent">
|
||||
<configure name="MODEM_BAUD" value="B115200"/>
|
||||
</module>
|
||||
|
||||
<module name="gps" type="datalink"/>
|
||||
<!-- GPS has been removed, dont use this without reinstalling gps-->
|
||||
<!-- <module name="gps" type="ublox">
|
||||
<configure name="GPS_BAUD" value="B460800"/>
|
||||
</module> -->
|
||||
|
||||
<module name="mag" type="rm3100">
|
||||
<configure name="MAG_RM3100_I2C_DEV" value="i2c2"/>
|
||||
<define name="MODULE_RM3100_SYNC_SEND" value="TRUE"/>
|
||||
<define name="MODULE_RM3100_UPDATE_AHRS" value="TRUE"/>
|
||||
|
||||
<!-- 0:X, 1:Y, 2:Z; -->
|
||||
<define name="RM3100_CHAN_X" value="1"/>
|
||||
<define name="RM3100_CHAN_Y" value="0"/>
|
||||
<define name="RM3100_CHAN_Z" value="2"/>
|
||||
|
||||
<define name="RM3100_CHAN_X_SIGN" value="+"/>
|
||||
<define name="RM3100_CHAN_Y_SIGN" value="+"/>
|
||||
<define name="RM3100_CHAN_Z_SIGN" value="-"/>
|
||||
|
||||
<!--TODO: Set correct angles-->
|
||||
<!-- <define name="RM3100_MAG_TO_IMU_PHI" value="RadOfDeg\(0.0\)"/>
|
||||
<define name="RM3100_MAG_TO_IMU_THETA" value="RadOfDeg\(0.0\)"/>
|
||||
<define name="RM3100_MAG_TO_IMU_PSI" value="RadOfDeg\(0.0\)"/> -->
|
||||
</module>
|
||||
|
||||
<!-- Control -->
|
||||
<module name="stabilization" type="andi">
|
||||
<define name="WLS_N_U_MAX" value="4" />
|
||||
<define name="WLS_N_V_MAX" value="4" />
|
||||
</module>
|
||||
|
||||
<module name="guidance" type="indi_hybrid_tailsitter">
|
||||
<define name="GUIDANCE_INDI_RC_DEBUG" value="FALSE"/>
|
||||
<define name="NAV_HYBRID_POS_GAIN" value="0.2"/>
|
||||
<define name="GUIDANCE_INDI_POS_GAIN" value="0.2"/>
|
||||
<define name="GUIDANCE_INDI_SPEED_GAIN" value="1.0"/>
|
||||
<define name="GUIDANCE_INDI_POS_GAINZ" value="0.5"/>
|
||||
<define name="GUIDANCE_INDI_SPEED_GAINZ" value="1.8"/>
|
||||
<define name="GUIDANCE_INDI_LIFTD_ASQ" value="0.20"/>
|
||||
<define name="GUIDANCE_INDI_PITCH_EFF_SCALING" value="1.0"/>
|
||||
<define name="GUIDANCE_H_REF_MAX_SPEED" value="18.0"/>
|
||||
<!--not used-->
|
||||
<define name="GUIDANCE_INDI_MIN_THROTTLE" value="3000"/>
|
||||
<define name="GUIDANCE_INDI_MIN_THROTTLE_FWD" value="1500"/>
|
||||
<define name="GUIDANCE_INDI_MAX_AIRSPEED" value="16.0"/>
|
||||
<define name="GUIDANCE_INDI_HEADING_BANK_GAIN" value="15.0"/>
|
||||
<define name="GUIDANCE_INDI_SPECIFIC_FORCE_GAIN" value="-500.0"/>
|
||||
<define name="GUIDANCE_INDI_THRUST_DYNAMICS_FREQ" value="23.6"/>
|
||||
<define name="GUIDANCE_INDI_FILTER_CUTOFF" value="1.5"/>
|
||||
</module>
|
||||
|
||||
|
||||
<!-- <module name="nav" type="hybrid">
|
||||
<define name="GUIDANCE_H_USE_REF" value="FALSE"/>
|
||||
<define name="NAV_NO_CARROT" value="TRUE"/>
|
||||
</module> -->
|
||||
|
||||
|
||||
<module name="wls">
|
||||
<define name="WLS_N_U_MAX" value = "4"/>
|
||||
<define name="WLS_N_V_MAX" value = "4"/>
|
||||
</module>
|
||||
|
||||
</firmware>
|
||||
|
||||
<servos driver="T4">
|
||||
<servo name="S_ELEVON_LEFT" no="1" min="-5000" neutral="0" max="5000"/> <!-- [50.0 deg]-->
|
||||
<servo name="S_ELEVON_RIGHT" no="6" min="5000" neutral="0" max="-5000"/> <!-- [50.0 deg]-->
|
||||
<servo name="S_MOTOR_LEFT" no="13" min="0" neutral="0" max="1999"/> <!-- neutral is value when motor is not spinning, must be 0 -->
|
||||
<servo name="S_MOTOR_RIGHT" no="14" min="0" neutral="0" max="1999"/>
|
||||
</servos>
|
||||
|
||||
<commands>
|
||||
<!-- Real actuators commands -->
|
||||
<axis name="ELEVON_LEFT" group="REAL" failsafe_value="0"/>
|
||||
<axis name="ELEVON_RIGHT" group="REAL" failsafe_value="0"/>
|
||||
<axis name="MOTOR_LEFT" group="REAL" failsafe_value="0"/>
|
||||
<axis name="MOTOR_RIGHT" group="REAL" failsafe_value="0"/>
|
||||
<!-- Legacy commands-->
|
||||
<axis name="YAW" group="OTHER" failsafe_value="0"/>
|
||||
<axis name="THRUST" group="OTHER" failsafe_value="0"/>
|
||||
</commands>
|
||||
|
||||
<!-- Safety critical kill switch implementation, DO NOT REMOVE -->
|
||||
<command_laws>
|
||||
<set servo="S_ELEVON_LEFT" value="autopilot_get_motors_on()? commands[COMMAND_ELEVON_LEFT] : 0"/>
|
||||
<set servo="S_ELEVON_RIGHT" value="autopilot_get_motors_on()? commands[COMMAND_ELEVON_RIGHT] : 0"/>
|
||||
<set servo="S_MOTOR_LEFT" value="autopilot_get_motors_on()? commands[COMMAND_MOTOR_LEFT] : -MAX_PPRZ"/>
|
||||
<set servo="S_MOTOR_RIGHT" value="autopilot_get_motors_on()? commands[COMMAND_MOTOR_RIGHT] : -MAX_PPRZ"/>
|
||||
</command_laws>
|
||||
|
||||
<section name="MISC">
|
||||
<define name="TAILSITTER" value="TRUE"/>
|
||||
<define name="USE_AIRSPEED" value="FALSE"/>
|
||||
<define name="STABILIZATION_ATTITUDE_SP_MAX_PHI" value="45." unit="deg" />
|
||||
<define name="STABILIZATION_ATTITUDE_SP_MAX_THETA" value="45." unit="deg" />
|
||||
<define name="STABILIZATION_ATTITUDE_SP_MAX_R" value="90." unit="deg/s"/>
|
||||
<define name="STABILIZATION_ATTITUDE_DEADBAND_R" value="200" />
|
||||
<define name="AUTOPILOT_IN_FLIGHT_MIN_THRUST" value="1500" />
|
||||
<define name="AUTOPILOT_IN_FLIGHT_MIN_SPEED" value="0" />
|
||||
<define name="AUTOPILOT_IN_FLIGHT_MIN_ACCEL" value="0" />
|
||||
</section>
|
||||
|
||||
<section name="STABILIZATION_ANDI" prefix="STABILIZATION_ANDI_" >
|
||||
<define name="SCHEDULE_EFF" value="TRUE"/>
|
||||
<define name="USE_STATE_DYNAMICS" value="TRUE"/>
|
||||
<define name="RELAX_OBM" value="1.0f"/>
|
||||
|
||||
<!-- | EL | ER | ML^2 | MR^2 | -->
|
||||
<define name="ACT_IS_SERVO" value="{ 1, 1, 0, 0}"/>
|
||||
<define name="ACT_DYNAMICS" value="{ 20.0f, 20.0f, 35.0f, 35.0f}"/> <!-- [rad/s]-->
|
||||
<define name="ACT_DELAY" value="{ 0, 0, 0, 0}"/> <!-- [rad/s]-->
|
||||
<define name="ACT_USE_MEAS" value="{ true, true, true, true}"/>
|
||||
<define name="ACT_MIN" value="{ -0.87f, -0.87f, 40000.0f, 40000.0f}"/> <!-- [ rad | (rad/s)^2]-->
|
||||
<define name="ACT_MAX" value="{ 0.87f, 0.87f, 3534400.0f, 3534400.0f}"/> <!-- [ rad | (rad/s)^2]-->
|
||||
<define name="ACT_RATE_MIN" value="{ -10.0f, -10.0f, -90000000.0f, -90000000.0f}"/> <!-- [rad/s | (rad/s)^2/s]-->
|
||||
<define name="ACT_RATE_MAX" value="{ 10.0f, 10.0f, 90000000.0f, 90000000.0f}"/> <!-- [rad/s | (rad/s)^2/s]-->
|
||||
<define name="ACT_PREF" value="{ 0.00f, 0.00f, 705600.0f, 705600.0f}"/> <!-- [ rad | (rad/s)^2]--> <!-- Used as operating point when not scheduling-->
|
||||
<define name="WLS_WU" value="{ 0.0f, 0.0f, 0.0f, 0.0f}"/>
|
||||
|
||||
<!-- | P | Q | R | Tau | -->
|
||||
<define name="WLS_WV" value="{ 1000.0f, 100.0f, 1.0f, 10.0f}"/> <!-- Roll is more important than pitch, we do not want to sacrefice roll control in case failing to reach a certain pitch command -->
|
||||
|
||||
<!-- | P | Q | R | -->
|
||||
<define name="RC_RATE_MAX" value="{ 5.0f, 5.0f, 5.0f}"/> <!-- [rad/s]-->
|
||||
|
||||
<define name="THRUST_MIN" value="0.6f" /> <!-- [m/s^2]-->
|
||||
<define name="THRUST_MAX" value="52.0f" /> <!-- [m/s^2]-->
|
||||
|
||||
<define name="CUTOFF_FREQ_ACCEL" value=" 20.0f"/> <!-- [rad/s]-->
|
||||
<define name="CUTOFF_FREQ_VEL" value=" 80.0f"/> <!-- [rad/s]-->
|
||||
<define name="CUTOFF_FREQ_OMEGA_DOT" value=" 20.0f"/> <!-- [rad/s]-->
|
||||
<define name="CUTOFF_FREQ_OMEGA" value=" 80.0f"/> <!-- [rad/s]-->
|
||||
|
||||
</section>
|
||||
|
||||
<section name="BAT">
|
||||
<define name="MAX_BAT_CAPACITY" value="2300" unit="mAh"/>
|
||||
<!--<define name="MilliAmpereOfAdc(_adc)" value="(_adc-632)*4.14"/>-->
|
||||
<define name="VoltageOfAdc(_adc)" value="(0.000611456 * _adc)"/>
|
||||
<define name="MILLIAMP_AT_IDLE_THROTTLE" value="280" unit="mA"/>
|
||||
<define name="MILLIAMP_AT_FULL_THROTTLE" value="20000" unit="mA"/>
|
||||
<define name="MAX_BAT_LEVEL" value="16.8" unit="V"/>
|
||||
<define name="LOW_BAT_LEVEL" value="14.0" unit="V"/>
|
||||
<define name="CRITIC_BAT_LEVEL" value="13.5" unit="V"/>
|
||||
<define name="CATASTROPHIC_BAT_LEVEL" value="13.2" unit="V"/>
|
||||
<define name="CURRENT_ESTIMATION_NONLINEARITY" value="1.0"/>
|
||||
</section>
|
||||
|
||||
<section name="IMU" prefix="IMU_">
|
||||
<define name="MAG_CALIB" type="array">
|
||||
<field type="struct">
|
||||
<field name="abi_id" value="5"/>
|
||||
<field name="calibrated" type="struct">
|
||||
<field name="neutral" value="true"/>
|
||||
<field name="scale" value="true"/>
|
||||
<!-- <field name="rotation" value="true"/> -->
|
||||
</field>
|
||||
<field name="neutral" type="int[]" value="-2044,169,119"/>
|
||||
<field name="scale" type="int[][]" value="{{5666,15649,36949},{9069,27419,63039}}"/>
|
||||
<!-- <field name="body_to_sensor" value="{{0, 16384,0, 0, 0, -16384,-16384, 0, 0}}"/> -->
|
||||
</field>
|
||||
</define>
|
||||
|
||||
<!-- <define name="ACCEL_CALIB" type="array">
|
||||
<field type="struct">
|
||||
<field name="abi_id" value="20"/>
|
||||
<field name="calibrated" type="struct">
|
||||
<field name="neutral" value="false"/>
|
||||
<field name="scale" value="false"/>
|
||||
<field name="rotation" value="true"/>
|
||||
</field>
|
||||
<field name="body_to_sensor" value="{{0, 0, -16384, 0, 16384, 0, 0, 16384, 0}}"/>
|
||||
</field>
|
||||
</define> -->
|
||||
|
||||
<!-- Gyrometer calibration (NOT DONE!) -->
|
||||
<!-- <define name="GYRO_CALIB" type="array">
|
||||
<field type="struct">
|
||||
<field name="abi_id" value="20"/>
|
||||
<field name="calibrated" type="struct">
|
||||
<field name="neutral" value="false"/>
|
||||
<field name="scale" value="false"/>
|
||||
<field name="rotation" value="true"/>
|
||||
</field>
|
||||
<field name="body_to_sensor" value="{{0, 0, -16384, 0, 16384, 0, 0, 16384, 0}}"/>
|
||||
</field>
|
||||
</define> -->
|
||||
|
||||
<define name="BODY_TO_IMU_PHI" value="0." unit="deg"/>
|
||||
<define name="BODY_TO_IMU_THETA" value="90." unit="deg"/>
|
||||
<define name="BODY_TO_IMU_PSI" value="0." unit="deg"/>
|
||||
</section>
|
||||
</airframe>
|
||||
@@ -0,0 +1,194 @@
|
||||
<!DOCTYPE autopilot SYSTEM "autopilot.dtd">
|
||||
|
||||
<autopilot name="ANDI Autopilot Cyclone">
|
||||
<state_machine name="ap" freq="PERIODIC_FREQUENCY" gcs_mode="true" settings_mode="true" settings_handler="autopilot_generated|SetModeHandler">
|
||||
|
||||
<modules>
|
||||
<module name="actuators" type="t4_uart"/>
|
||||
<module name="stabilization" type="andi"/>
|
||||
</modules>
|
||||
|
||||
<includes>
|
||||
<include name="autopilot_rc_helpers.h"/>
|
||||
<define name="MODE_MANUAL" value="AP_MODE_ATTITUDE_DIRECT" cond="ifndef MODE_MANUAL"/>
|
||||
<define name="MODE_AUTO1" value="AP_MODE_RATE_DIRECT" cond="ifndef MODE_AUTO1"/>
|
||||
<define name="MODE_AUTO2" value="AP_MODE_RATE_DIRECT" cond="ifndef MODE_AUTO2"/>
|
||||
<define name="RCLost()" value="(radio_control.status == RC_REALLY_LOST)"/>
|
||||
</includes>
|
||||
|
||||
<settings>
|
||||
<dl_setting var="autopilot.kill_throttle" min="0" step="1" max="1" values="Resurrect|Kill"/> <!-- handler="KillThrottle" -->
|
||||
</settings>
|
||||
|
||||
<!-- Commit actuator commands. ANDI/INDI perform allocation themselves; retained so COMMAND_THRUST remains set -->
|
||||
<control_block name="set_commands">
|
||||
<call fun="SetRotorcraftCommands(stabilization.cmd, autopilot_in_flight(), autopilot_get_motors_on())"/>
|
||||
</control_block>
|
||||
|
||||
<control_block name="run_rate_control">
|
||||
<call fun="guidance_v_run(autopilot_in_flight())" store="struct ThrustSetpoint thrust_sp"/>
|
||||
<call fun="stabilization_andi_run(true, autopilot_in_flight(), &stabilization.rc_sp, &thrust_sp, stabilization.cmd)"/>
|
||||
</control_block>
|
||||
|
||||
<control_block name="run_attitude_control">
|
||||
<call fun="guidance_v_run(autopilot_in_flight())" store="struct ThrustSetpoint thrust_sp"/>
|
||||
<call fun="stabilization_andi_run(false, autopilot_in_flight(), &stabilization.rc_sp, &thrust_sp, stabilization.cmd)"/>
|
||||
</control_block>
|
||||
|
||||
<mode_selection>
|
||||
<mode_select cond="RCMode0()" mode="MODE_MANUAL"/>
|
||||
<mode_select cond="RCMode1()" mode="MODE_AUTO1"/>
|
||||
<mode_select cond="RCMode2()" mode="MODE_AUTO2"/>
|
||||
</mode_selection>
|
||||
|
||||
<!-- <exceptions>
|
||||
<exception cond="nav.too_far_from_home" deroute="HOME"/>
|
||||
<exception cond="kill_switch_is_on()" deroute="KILL"/>
|
||||
</exceptions> -->
|
||||
|
||||
<!-- KILL: 0 -->
|
||||
<mode name="KILL">
|
||||
<select cond="$DEFAULT_MODE"/>
|
||||
<select cond="kill_switch_is_on()"/>
|
||||
<on_enter>
|
||||
<call fun="guidance_h_mode_changed(GUIDANCE_H_MODE_NONE)"/>
|
||||
<call fun="stabilization_mode_changed(STABILIZATION_MODE_NONE, 0)"/>
|
||||
<call fun="guidance_v_mode_changed(GUIDANCE_V_MODE_KILL)"/>
|
||||
<call fun="autopilot_set_in_flight(false)"/>
|
||||
<call fun="autopilot_set_motors_on(false)"/>
|
||||
</on_enter>
|
||||
<control>
|
||||
<call fun="SetCommands(commands_failsafe)"/>
|
||||
</control>
|
||||
</mode>
|
||||
|
||||
<!-- FAILSAFE: 1 -->
|
||||
<mode name="FAILSAFE" shortname="FAIL">
|
||||
<!-- Failsafe does not work needs to be fixed-->
|
||||
</mode>
|
||||
|
||||
<!-- HOME: 2 (UNUSED) -->
|
||||
<mode name="HOME">
|
||||
<exception cond="GpsIsLost()" deroute="FAILSAFE"/>
|
||||
</mode>
|
||||
|
||||
<!-- RATE_DIRECT: 3 -->
|
||||
<mode name="RATE_DIRECT" shortname="RATE">
|
||||
<on_enter>
|
||||
<call fun="guidance_h_mode_changed(GUIDANCE_H_MODE_NONE)"/>
|
||||
<call fun="guidance_v_mode_changed(GUIDANCE_V_MODE_RC_DIRECT)"/>
|
||||
<call fun="stabilization_mode_changed(STABILIZATION_MODE_ATTITUDE, STABILIZATION_ATT_SUBMODE_HEADING)"/>
|
||||
<call fun="stabilization_andi_enter()"/>
|
||||
</on_enter>
|
||||
<control freq="NAVIGATION_FREQUENCY">
|
||||
<call fun="nav_periodic_task()"/>
|
||||
</control>
|
||||
<control>
|
||||
<call_block name="run_rate_control"/>
|
||||
<!-- <call_block name="set_commands"/> -->
|
||||
<call_block name="set_commands"/>
|
||||
</control>
|
||||
<exception cond="RCLost()" deroute="FAILSAFE"/>
|
||||
</mode>
|
||||
|
||||
<!-- ATITUDE_DIRECT: 4 -->
|
||||
<mode name="ATTITUDE_DIRECT" shortname="ATT">
|
||||
<on_enter>
|
||||
<call fun="guidance_h_mode_changed(GUIDANCE_H_MODE_NONE)"/>
|
||||
<call fun="guidance_v_mode_changed(GUIDANCE_V_MODE_RC_DIRECT)"/>
|
||||
<call fun="stabilization_mode_changed(STABILIZATION_MODE_ATTITUDE, STABILIZATION_ATT_SUBMODE_HEADING)"/>
|
||||
<call fun="stabilization_andi_enter()"/>
|
||||
</on_enter>
|
||||
<control freq="NAVIGATION_FREQUENCY">
|
||||
<call fun="nav_periodic_task()"/>
|
||||
</control>
|
||||
<control>
|
||||
<call_block name="run_attitude_control"/>
|
||||
<!-- <call fun="actuator_debug(true, false, 2)"/> For debugging actuators -->
|
||||
<call_block name="set_commands"/>
|
||||
</control>
|
||||
<exception cond="RCLost()" deroute="FAILSAFE"/>
|
||||
</mode>
|
||||
|
||||
<!-- RATE_RC_CLIMB: 5 (UNUSED) -->
|
||||
<mode name="RATE_RC_CLIMB" shortname="RRCC">
|
||||
<exception cond="RCLost()" deroute="FAILSAFE"/>
|
||||
</mode>
|
||||
|
||||
<!-- ATTITUDE_RC_CLIMB: 6 (UNUSED) -->
|
||||
<mode name="ATTITUDE_RC_CLIMB" shortname="ATTITUDE_RC_CLIMB">
|
||||
<exception cond="RCLost()" deroute="FAILSAFE"/>
|
||||
</mode>
|
||||
|
||||
<!-- ATTITUDE_CLIMB: 7 (UNUSED) -->
|
||||
<mode name="ATTITUDE_CLIMB" shortname="ATTITUDE_CLIMB">
|
||||
<exception cond="RCLost()" deroute="FAILSAFE"/>
|
||||
</mode>
|
||||
|
||||
<!-- RATE_Z_HOLD: 8 (UNUSED) -->
|
||||
<mode name="RATE_Z_HOLD" shortname="RATE_Z_HOLD">
|
||||
<exception cond="RCLost()" deroute="FAILSAFE"/>
|
||||
</mode>
|
||||
|
||||
<!-- ATTITUDE_Z_HOLD: (UNUSED) 9 -->
|
||||
<mode name="ATTITUDE_Z_HOLD" shortname="A_ZH">
|
||||
<exception cond="RCLost()" deroute="FAILSAFE"/>
|
||||
</mode>
|
||||
|
||||
<!-- HOVER_DIRECT: 10 (UNUSED) -->
|
||||
<mode name="HOVER_DIRECT" shortname="HOVER_DIRECT">
|
||||
<exception cond="RCLost()" deroute="FAILSAFE"/>
|
||||
</mode>
|
||||
|
||||
<!-- HOVER_CLIMB: 11 (UNUSED) -->
|
||||
<mode name="HOVER_CLIMB" shortname="HOVER_CLIMB">
|
||||
<exception cond="RCLost()" deroute="FAILSAFE"/>
|
||||
</mode>
|
||||
|
||||
<!-- HOVER_Z_HOLD: 12 (UNUSED) -->
|
||||
<mode name="HOVER_Z_HOLD" shortname="HOVER_Z_HOLD">
|
||||
<exception cond="RCLost()" deroute="FAILSAFE"/>
|
||||
</mode>
|
||||
|
||||
<!-- NAV: 13 -->
|
||||
<mode name="NAV" shortname="NAV">
|
||||
<exception cond="RCLost()" deroute="FAILSAFE"/>
|
||||
</mode>
|
||||
|
||||
<!-- RC_DIRECT: 14 (UNUSED) -->
|
||||
<mode name="RC_DIRECT" shortname="RC_DIRECT">
|
||||
<exception cond="RCLost()" deroute="FAILSAFE"/>
|
||||
</mode>
|
||||
|
||||
<!-- CARE_FREE_DIRECT: 15 (UNUSED) -->
|
||||
<mode name="CARE_FREE_DIRECT" shortname="CARE_FREE_DIRECT">
|
||||
<exception cond="RCLost()" deroute="FAILSAFE"/>
|
||||
</mode>
|
||||
|
||||
<!-- FORWARD: 16 (UNUSED) -->
|
||||
<mode name="FORWARD" shortname="FORWARD">
|
||||
<exception cond="RCLost()" deroute="FAILSAFE"/>
|
||||
</mode>
|
||||
|
||||
<!-- MODULE: 17 (UNUSED) -->
|
||||
<mode name="MODULE" shortname="MODULE">
|
||||
<exception cond="RCLost()" deroute="FAILSAFE"/>
|
||||
</mode>
|
||||
|
||||
<!-- FLIP: 18 (UNUSED) -->
|
||||
<mode name="FLIP" shortname="FLIP">
|
||||
<exception cond="RCLost()" deroute="FAILSAFE"/>
|
||||
</mode>
|
||||
|
||||
<!-- GUIDED: 19 (UNUSED) -->
|
||||
<mode name="GUIDED">
|
||||
<exception cond="RCLost()" deroute="FAILSAFE"/>
|
||||
</mode>
|
||||
|
||||
<!-- ATTITUDE_DIRECT_FWD: 20 (UNUSED) -->
|
||||
<mode name="ATTITUDE_DIRECT_FWD" shortname="ATT_Fwd">
|
||||
<exception cond="RCLost()" deroute="FAILSAFE"/>
|
||||
</mode>
|
||||
|
||||
</state_machine>
|
||||
</autopilot>
|
||||
@@ -0,0 +1,32 @@
|
||||
<!DOCTYPE flight_plan SYSTEM "../flight_plan.dtd">
|
||||
|
||||
<flight_plan alt="3.5" ground_alt="2" lat0="51.990634" lon0="4.376789" max_dist_from_home="20" name="Rotorcraft Cyberzoo (Delft) no GPS" security_height="0.3">
|
||||
<header>
|
||||
#include "autopilot.h"
|
||||
</header>
|
||||
<waypoints>
|
||||
<waypoint name="HOME" x="0.0" y="0.0"/>
|
||||
<waypoint name="CLIMB" x="1.2" y="-0.6"/>
|
||||
<waypoint name="GOAL" x="2.0" y="2.0"/>
|
||||
<waypoint name="STDBY" x="-0.7" y="-0.8"/>
|
||||
<waypoint name="TD" x="0.8" y="-1.7"/>
|
||||
<waypoint lat="51.9906213" lon="4.3768628" name="FA1"/>
|
||||
<waypoint lat="51.9905874" lon="4.3767766" name="FA2"/>
|
||||
<waypoint lat="51.9906409" lon="4.3767226" name="FA3"/>
|
||||
<waypoint lat="51.9906737" lon="4.3768074" name="FA4"/>
|
||||
</waypoints>
|
||||
<sectors>
|
||||
<sector color="red" name="Flight_Area">
|
||||
<corner name="FA4"/>
|
||||
<corner name="FA3"/>
|
||||
<corner name="FA2"/>
|
||||
<corner name="FA1"/>
|
||||
</sector>
|
||||
</sectors>
|
||||
<blocks>
|
||||
<block name="Holding point">
|
||||
<call_once fun="NavKillThrottle()"/>
|
||||
<attitude pitch="0" roll="0" throttle="0" until="FALSE" vmode="throttle"/>
|
||||
</block>
|
||||
</blocks>
|
||||
</flight_plan>
|
||||
@@ -0,0 +1,170 @@
|
||||
<!DOCTYPE module SYSTEM "module.dtd">
|
||||
|
||||
<module name="stabilization_andi" dir="stabilization" task="control">
|
||||
<doc>
|
||||
<description>
|
||||
Full ANDI stabilization controller for rotorcraft
|
||||
</description>
|
||||
|
||||
<configure name="ANDI_OUTPUTS" default="4"/>
|
||||
<configure name="ANDI_NUM_ACT" default="4"/>
|
||||
|
||||
<section name="STABILIZATION_ATTITUDE_ANDI" prefix="STABILIZATION_ANDI_">
|
||||
<define name="SCHEDULE_EFF" value="0" description="1 to schedule control effectiveness based on throttle command. 0 uses ACT_PREF to compute constant control effectiveness"/>
|
||||
<define name="USE_STATE_DYNAMICS" value="0" description="1 to use obm state derivative term, 0 to neglect this term."/>
|
||||
<define name="RELAX_OBM" value="1.0f" description="relaxation factor for obm state derivative contribution."/>
|
||||
|
||||
<define name="ACT_IS_SERVO" value="{0, 0, 0, 0}" description="1 for every actuator that is a servo"/>
|
||||
<define name="ACT_DYNAMICS" description="actuator bandwidth [rad/s]"/>
|
||||
<define name="ACT_DELAY" description="actuator transport delay [samples]"/>
|
||||
<define name="ACT_MAX" description="maximum actuator value [SI units]"/>
|
||||
<define name="ACT_MIN" description="maximum actuator value [SI units]"/>
|
||||
<define name="ACT_RATE_MAX" description="minimum actuator rate [SI units]"/>
|
||||
<define name="ACT_RATE_MIN" description="minimum actuator rate [SI units]"/>
|
||||
<define name="ACT_PREF" value="{0.0, 0.0, 0.0, 0.0}" description="preferred actuator value used for unscheduled control effectiveness"/>
|
||||
<define name="WLS_WV" value="{1000, 1000, 1, 100}" description="WLS control objective priorities: roll, pitch, yaw, thrust (size of ANDI_OUTPUTS)"/>
|
||||
<define name="WLS_WU" value="{1, 1, 1, 1}" description="WLS actuator cost (size of ANDI_NUM_ACT)"/>
|
||||
</section>
|
||||
</doc>
|
||||
<settings>
|
||||
<dl_settings>
|
||||
<dl_settings NAME="andi">
|
||||
<dl_setting var="andi_p_rate_rm.omega_a.x" min="0" step="0.25" max="100" shortname="pole_rate_rm/omega_a.x" param="STABILIZATION_ANDI_POLE_RATE_RM_OMEGA_A_X"/>
|
||||
<dl_setting var="andi_p_rate_rm.omega_a.y" min="0" step="0.25" max="100" shortname="pole_rate_rm/omega_a.y" param="STABILIZATION_ANDI_POLE_RATE_RM_OMEGA_A_Y"/>
|
||||
<dl_setting var="andi_p_rate_rm.omega_a.z" min="0" step="0.25" max="100" shortname="pole_rate_rm/omega_a.z" param="STABILIZATION_ANDI_POLE_RATE_RM_OMEGA_A_Z"/>
|
||||
|
||||
<dl_setting var="andi_p_rate_rm.zeta.x" min="0" step="0.25" max="5" shortname="pole_rate_rm/zeta.x" param="STABILIZATION_ANDI_POLE_RATE_RM_ZETA_X"/>
|
||||
<dl_setting var="andi_p_rate_rm.zeta.y" min="0" step="0.25" max="5" shortname="pole_rate_rm/zeta.y" param="STABILIZATION_ANDI_POLE_RATE_RM_ZETA_Y"/>
|
||||
<dl_setting var="andi_p_rate_rm.zeta.z" min="0" step="0.25" max="5" shortname="pole_rate_rm/zeta.z" param="STABILIZATION_ANDI_POLE_RATE_RM_ZETA_Z"/>
|
||||
|
||||
<dl_setting var="andi_p_att_rm.omega_n.x" min="0" step="0.25" max="100" shortname="pole_att_rm/omega_n.x" param="STABILIZATION_ANDI_POLE_ATT_RM_OMEGA_N_X"/>
|
||||
<dl_setting var="andi_p_att_rm.omega_n.y" min="0" step="0.25" max="100" shortname="pole_att_rm/omega_n.y" param="STABILIZATION_ANDI_POLE_ATT_RM_OMEGA_N_Y"/>
|
||||
<dl_setting var="andi_p_att_rm.omega_n.z" min="0" step="0.25" max="100" shortname="pole_att_rm/omega_n.z" param="STABILIZATION_ANDI_POLE_ATT_RM_OMEGA_N_Z"/>
|
||||
|
||||
<dl_setting var="andi_p_att_rm.zeta.x" min="0" step="0.25" max="5" shortname="pole_att_rm/zeta.x" param="STABILIZATION_ANDI_POLE_ATT_RM_ZETA_X"/>
|
||||
<dl_setting var="andi_p_att_rm.zeta.y" min="0" step="0.25" max="5" shortname="pole_att_rm/zeta.y" param="STABILIZATION_ANDI_POLE_ATT_RM_ZETA_Y"/>
|
||||
<dl_setting var="andi_p_att_rm.zeta.z" min="0" step="0.25" max="5" shortname="pole_att_rm/zeta.z" param="STABILIZATION_ANDI_POLE_ATT_RM_ZETA_Z"/>
|
||||
|
||||
<dl_setting var="andi_p_att_rm.omega_a.x" min="0" step="0.25" max="100" shortname="pole_att_rm/p1.x" param="STABILIZATION_ANDI_POLE_ATT_RM_OMEGA_A_X"/>
|
||||
<dl_setting var="andi_p_att_rm.omega_a.y" min="0" step="0.25" max="100" shortname="pole_att_rm/p1.y" param="STABILIZATION_ANDI_POLE_ATT_RM_OMEGA_A_Y"/>
|
||||
<dl_setting var="andi_p_att_rm.omega_a.z" min="0" step="0.25" max="100" shortname="pole_att_rm/p1.z" param="STABILIZATION_ANDI_POLE_ATT_RM_OMEGA_A_Z"/>
|
||||
|
||||
<dl_setting var="andi_p_thrust_rm" min="0" step="0.25" max="100" shortname="pole_thrust_rm" param="STABILIZATION_ANDI_POLE_THRUST_RM"/>
|
||||
|
||||
<dl_setting var="andi_p_rate_ec.omega_a.x" min="0" step="0.25" max="100" shortname="pole_rate_ec/omega_a.x" param="STABILIZATION_ANDI_POLE_RATE_EC_OMEGA_A_X"/>
|
||||
<dl_setting var="andi_p_rate_ec.omega_a.y" min="0" step="0.25" max="100" shortname="pole_rate_ec/omega_a.y" param="STABILIZATION_ANDI_POLE_RATE_EC_OMEGA_A_Y"/>
|
||||
<dl_setting var="andi_p_rate_ec.omega_a.z" min="0" step="0.25" max="100" shortname="pole_rate_ec/omega_a.z" param="STABILIZATION_ANDI_POLE_RATE_EC_OMEGA_A_Z"/>
|
||||
|
||||
<dl_setting var="andi_p_rate_ec.zeta.x" min="0" step="0.25" max="5" shortname="pole_rate_ec/zeta.x" param="STABILIZATION_ANDI_POLE_RATE_EC_ZETA_X"/>
|
||||
<dl_setting var="andi_p_rate_ec.zeta.y" min="0" step="0.25" max="5" shortname="pole_rate_ec/zeta.y" param="STABILIZATION_ANDI_POLE_RATE_EC_ZETA_Y"/>
|
||||
<dl_setting var="andi_p_rate_ec.zeta.z" min="0" step="0.25" max="5" shortname="pole_rate_ec/zeta.z" param="STABILIZATION_ANDI_POLE_RATE_EC_ZETA_Z"/>
|
||||
|
||||
<dl_setting var="andi_p_att_ec.omega_n.x" min="0" step="0.25" max="100" shortname="pole_att_ec/omega_n.x" param="STABILIZATION_ANDI_POLE_ATT_EC_OMEGA_N_X"/>
|
||||
<dl_setting var="andi_p_att_ec.omega_n.y" min="0" step="0.25" max="100" shortname="pole_att_ec/omega_n.y" param="STABILIZATION_ANDI_POLE_ATT_EC_OMEGA_N_Y"/>
|
||||
<dl_setting var="andi_p_att_ec.omega_n.z" min="0" step="0.25" max="100" shortname="pole_att_ec/omega_n.z" param="STABILIZATION_ANDI_POLE_ATT_EC_OMEGA_N_Z"/>
|
||||
|
||||
<dl_setting var="andi_p_att_ec.zeta.x" min="0" step="0.25" max="5" shortname="pole_att_ec/zeta.x" param="STABILIZATION_ANDI_POLE_ATT_EC_ZETA_X"/>
|
||||
<dl_setting var="andi_p_att_ec.zeta.y" min="0" step="0.25" max="5" shortname="pole_att_ec/zeta.y" param="STABILIZATION_ANDI_POLE_ATT_EC_ZETA_Y"/>
|
||||
<dl_setting var="andi_p_att_ec.zeta.z" min="0" step="0.25" max="5" shortname="pole_att_ec/zeta.z" param="STABILIZATION_ANDI_POLE_ATT_EC_ZETA_Z"/>
|
||||
|
||||
<dl_setting var="andi_p_att_ec.omega_a.x" min="0" step="0.25" max="100" shortname="pole_att_ec/p1.x" param="STABILIZATION_ANDI_POLE_ATT_EC_OMEGA_A_X"/>
|
||||
<dl_setting var="andi_p_att_ec.omega_a.y" min="0" step="0.25" max="100" shortname="pole_att_ec/p1.y" param="STABILIZATION_ANDI_POLE_ATT_EC_OMEGA_A_Y"/>
|
||||
<dl_setting var="andi_p_att_ec.omega_a.z" min="0" step="0.25" max="100" shortname="pole_att_ec/p1.z" param="STABILIZATION_ANDI_POLE_ATT_EC_OMEGA_A_Z"/>
|
||||
|
||||
<dl_setting var="andi_p_thrust_ec" min="0" step="0.25" max="100" shortname="pole_thrust_ec" param="STABILIZATION_ANDI_POLE_THRUST_EC"/>
|
||||
</dl_settings>
|
||||
</dl_settings>
|
||||
</settings>
|
||||
<dep>
|
||||
<depends>stabilization_rotorcraft,@attitude_command,wls</depends>
|
||||
<provides>commands</provides>
|
||||
</dep>
|
||||
<header>
|
||||
<file name="stabilization_andi.h"/>
|
||||
</header>
|
||||
<init fun="stabilization_andi_init()"/>
|
||||
<makefile target="ap|nps" firmware="rotorcraft">
|
||||
<file name="stabilization_andi.c" dir="$(SRC_FIRMWARE)/stabilization"/>
|
||||
<file name="obm_cyclone.c" dir="$(SRC_FIRMWARE)/stabilization"/>
|
||||
<configure name="ANDI_OUTPUTS" default="4"/>
|
||||
<configure name="ANDI_NUM_ACT" default="4"/>
|
||||
<define name="ANDI_OUTPUTS" value="$(ANDI_OUTPUTS)"/>
|
||||
<define name="ANDI_NUM_ACT" value="$(ANDI_NUM_ACT)"/>
|
||||
<define name="USE_STABILIZATION_RATE"/>
|
||||
|
||||
<configure name="STABILIZATION_ANDI_POLE_RATE_EC_OMEGA_A_X" default="35.0"/> <!-- Equivalent actuator bandwidth -->
|
||||
<configure name="STABILIZATION_ANDI_POLE_RATE_EC_OMEGA_A_Y" default="20.0"/> <!-- Equivalent actuator bandwidth -->
|
||||
<configure name="STABILIZATION_ANDI_POLE_RATE_EC_OMEGA_A_Z" default="20.0"/> <!-- Equivalent actuator bandwidth -->
|
||||
<configure name="STABILIZATION_ANDI_POLE_RATE_EC_ZETA_X" default="1.0"/>
|
||||
<configure name="STABILIZATION_ANDI_POLE_RATE_EC_ZETA_Y" default="1.0"/>
|
||||
<configure name="STABILIZATION_ANDI_POLE_RATE_EC_ZETA_Z" default="1.0"/>
|
||||
|
||||
<configure name="STABILIZATION_ANDI_POLE_RATE_RM_OMEGA_A_X" default="35.0"/>
|
||||
<configure name="STABILIZATION_ANDI_POLE_RATE_RM_OMEGA_A_Y" default="20.0"/>
|
||||
<configure name="STABILIZATION_ANDI_POLE_RATE_RM_OMEGA_A_Z" default="20.0"/>
|
||||
<configure name="STABILIZATION_ANDI_POLE_RATE_RM_ZETA_X" default="1.0"/>
|
||||
<configure name="STABILIZATION_ANDI_POLE_RATE_RM_ZETA_Y" default="1.0"/>
|
||||
<configure name="STABILIZATION_ANDI_POLE_RATE_RM_ZETA_Z" default="1.0"/>
|
||||
|
||||
<configure name="STABILIZATION_ANDI_POLE_ATT_EC_OMEGA_N_X" default="7.0"/> <!-- rad/s-->
|
||||
<configure name="STABILIZATION_ANDI_POLE_ATT_EC_OMEGA_N_Y" default="7.0"/> <!-- rad/s-->
|
||||
<configure name="STABILIZATION_ANDI_POLE_ATT_EC_OMEGA_N_Z" default="7.0"/> <!-- rad/s-->
|
||||
<configure name="STABILIZATION_ANDI_POLE_ATT_EC_ZETA_X" default="1.0"/>
|
||||
<configure name="STABILIZATION_ANDI_POLE_ATT_EC_ZETA_Y" default="1.0"/>
|
||||
<configure name="STABILIZATION_ANDI_POLE_ATT_EC_ZETA_Z" default="1.0"/>
|
||||
<configure name="STABILIZATION_ANDI_POLE_ATT_EC_OMEGA_A_X" default="35.0"/> <!-- Equivalent actuator bandwidth -->
|
||||
<configure name="STABILIZATION_ANDI_POLE_ATT_EC_OMEGA_A_Y" default="20.0"/> <!-- Equivalent actuator bandwidth -->
|
||||
<configure name="STABILIZATION_ANDI_POLE_ATT_EC_OMEGA_A_Z" default="20.0"/> <!-- Equivalent actuator bandwidth -->
|
||||
|
||||
<configure name="STABILIZATION_ANDI_POLE_ATT_RM_OMEGA_N_X" default="7.0"/>
|
||||
<configure name="STABILIZATION_ANDI_POLE_ATT_RM_OMEGA_N_Y" default="7.0"/>
|
||||
<configure name="STABILIZATION_ANDI_POLE_ATT_RM_OMEGA_N_Z" default="7.0"/>
|
||||
<configure name="STABILIZATION_ANDI_POLE_ATT_RM_ZETA_X" default="1.0"/>
|
||||
<configure name="STABILIZATION_ANDI_POLE_ATT_RM_ZETA_Y" default="1.0"/>
|
||||
<configure name="STABILIZATION_ANDI_POLE_ATT_RM_ZETA_Z" default="1.0"/>
|
||||
<configure name="STABILIZATION_ANDI_POLE_ATT_RM_OMEGA_A_X" default="35.0"/>
|
||||
<configure name="STABILIZATION_ANDI_POLE_ATT_RM_OMEGA_A_Y" default="20.0"/>
|
||||
<configure name="STABILIZATION_ANDI_POLE_ATT_RM_OMEGA_A_Z" default="20.0"/>
|
||||
|
||||
<configure name="STABILIZATION_ANDI_POLE_THRUST_EC" default="35.0"/> <!-- Equivalent actuator bandwidth -->
|
||||
<configure name="STABILIZATION_ANDI_POLE_THRUST_RM" default="35.0"/> <!-- Equivalent actuator bandwidth -->
|
||||
|
||||
|
||||
<define name="STABILIZATION_ANDI_POLE_RATE_EC_OMEGA_A_X" value="$(STABILIZATION_ANDI_POLE_RATE_EC_OMEGA_A_X)"/>
|
||||
<define name="STABILIZATION_ANDI_POLE_RATE_EC_OMEGA_A_Y" value="$(STABILIZATION_ANDI_POLE_RATE_EC_OMEGA_A_Y)"/>
|
||||
<define name="STABILIZATION_ANDI_POLE_RATE_EC_OMEGA_A_Z" value="$(STABILIZATION_ANDI_POLE_RATE_EC_OMEGA_A_Z)"/>
|
||||
<define name="STABILIZATION_ANDI_POLE_RATE_EC_ZETA_X" value="$(STABILIZATION_ANDI_POLE_RATE_EC_ZETA_X)"/>
|
||||
<define name="STABILIZATION_ANDI_POLE_RATE_EC_ZETA_Y" value="$(STABILIZATION_ANDI_POLE_RATE_EC_ZETA_Y)"/>
|
||||
<define name="STABILIZATION_ANDI_POLE_RATE_EC_ZETA_Z" value="$(STABILIZATION_ANDI_POLE_RATE_EC_ZETA_Z)"/>
|
||||
|
||||
<define name="STABILIZATION_ANDI_POLE_RATE_RM_OMEGA_A_X" value="$(STABILIZATION_ANDI_POLE_RATE_RM_OMEGA_A_X)"/>
|
||||
<define name="STABILIZATION_ANDI_POLE_RATE_RM_OMEGA_A_Y" value="$(STABILIZATION_ANDI_POLE_RATE_RM_OMEGA_A_Y)"/>
|
||||
<define name="STABILIZATION_ANDI_POLE_RATE_RM_OMEGA_A_Z" value="$(STABILIZATION_ANDI_POLE_RATE_RM_OMEGA_A_Z)"/>
|
||||
<define name="STABILIZATION_ANDI_POLE_RATE_RM_ZETA_X" value="$(STABILIZATION_ANDI_POLE_RATE_RM_ZETA_X)"/>
|
||||
<define name="STABILIZATION_ANDI_POLE_RATE_RM_ZETA_Y" value="$(STABILIZATION_ANDI_POLE_RATE_RM_ZETA_Y)"/>
|
||||
<define name="STABILIZATION_ANDI_POLE_RATE_RM_ZETA_Z" value="$(STABILIZATION_ANDI_POLE_RATE_RM_ZETA_Z)"/>
|
||||
|
||||
<define name="STABILIZATION_ANDI_POLE_ATT_EC_OMEGA_N_X" value="$(STABILIZATION_ANDI_POLE_ATT_EC_OMEGA_N_X)"/>
|
||||
<define name="STABILIZATION_ANDI_POLE_ATT_EC_OMEGA_N_Y" value="$(STABILIZATION_ANDI_POLE_ATT_EC_OMEGA_N_Y)"/>
|
||||
<define name="STABILIZATION_ANDI_POLE_ATT_EC_OMEGA_N_Z" value="$(STABILIZATION_ANDI_POLE_ATT_EC_OMEGA_N_Z)"/>
|
||||
<define name="STABILIZATION_ANDI_POLE_ATT_EC_ZETA_X" value="$(STABILIZATION_ANDI_POLE_ATT_EC_ZETA_X)"/>
|
||||
<define name="STABILIZATION_ANDI_POLE_ATT_EC_ZETA_Y" value="$(STABILIZATION_ANDI_POLE_ATT_EC_ZETA_Y)"/>
|
||||
<define name="STABILIZATION_ANDI_POLE_ATT_EC_ZETA_Z" value="$(STABILIZATION_ANDI_POLE_ATT_EC_ZETA_Z)"/>
|
||||
<define name="STABILIZATION_ANDI_POLE_ATT_EC_OMEGA_A_X" value="$(STABILIZATION_ANDI_POLE_ATT_EC_OMEGA_A_X)"/>
|
||||
<define name="STABILIZATION_ANDI_POLE_ATT_EC_OMEGA_A_Y" value="$(STABILIZATION_ANDI_POLE_ATT_EC_OMEGA_A_Y)"/>
|
||||
<define name="STABILIZATION_ANDI_POLE_ATT_EC_OMEGA_A_Z" value="$(STABILIZATION_ANDI_POLE_ATT_EC_OMEGA_A_Z)"/>
|
||||
|
||||
<define name="STABILIZATION_ANDI_POLE_ATT_RM_OMEGA_N_X" value="$(STABILIZATION_ANDI_POLE_ATT_RM_OMEGA_N_X)"/>
|
||||
<define name="STABILIZATION_ANDI_POLE_ATT_RM_OMEGA_N_Y" value="$(STABILIZATION_ANDI_POLE_ATT_RM_OMEGA_N_Y)"/>
|
||||
<define name="STABILIZATION_ANDI_POLE_ATT_RM_OMEGA_N_Z" value="$(STABILIZATION_ANDI_POLE_ATT_RM_OMEGA_N_Z)"/>
|
||||
<define name="STABILIZATION_ANDI_POLE_ATT_RM_ZETA_X" value="$(STABILIZATION_ANDI_POLE_ATT_RM_ZETA_X)"/>
|
||||
<define name="STABILIZATION_ANDI_POLE_ATT_RM_ZETA_Y" value="$(STABILIZATION_ANDI_POLE_ATT_RM_ZETA_Y)"/>
|
||||
<define name="STABILIZATION_ANDI_POLE_ATT_RM_ZETA_Z" value="$(STABILIZATION_ANDI_POLE_ATT_RM_ZETA_Z)"/>
|
||||
<define name="STABILIZATION_ANDI_POLE_ATT_RM_OMEGA_A_X" value="$(STABILIZATION_ANDI_POLE_ATT_RM_OMEGA_A_X)"/>
|
||||
<define name="STABILIZATION_ANDI_POLE_ATT_RM_OMEGA_A_Y" value="$(STABILIZATION_ANDI_POLE_ATT_RM_OMEGA_A_Y)"/>
|
||||
<define name="STABILIZATION_ANDI_POLE_ATT_RM_OMEGA_A_Z" value="$(STABILIZATION_ANDI_POLE_ATT_RM_OMEGA_A_Z)"/>
|
||||
|
||||
<define name="STABILIZATION_ANDI_POLE_THRUST_EC" value="$(STABILIZATION_ANDI_POLE_THRUST_EC)"/>
|
||||
<define name="STABILIZATION_ANDI_POLE_THRUST_RM" value="$(STABILIZATION_ANDI_POLE_THRUST_RM)"/>
|
||||
</makefile>
|
||||
</module>
|
||||
@@ -0,0 +1,27 @@
|
||||
<!--
|
||||
The order of the list below is of importance if you do not define a
|
||||
"no=" (order in the PPM frame) parameter.
|
||||
If you do not define this then the order of the PPM is the one of
|
||||
the order of the functon in the list
|
||||
-->
|
||||
|
||||
<!-- for example below function="AUX1" means that it defines RADIO_AUX1 as 4 (0 based counting)-->
|
||||
<!DOCTYPE radio SYSTEM "../radio.dtd">
|
||||
<radio name="Generic SBUS" data_min="986" data_max="2190" sync_min="5000" sync_max="15000" pulse_type="POSITIVE">
|
||||
<channel function="THROTTLE" min="986" neutral="987" max="1900" average="0"/>
|
||||
<channel function="ROLL" min="1100" neutral="1500" max="1900" average="0"/>
|
||||
<channel function="PITCH" min="1100" neutral="1500" max="1900" average="0"/>
|
||||
<channel function="YAW" min="1100" neutral="1500" max="1900" average="0"/>
|
||||
<channel function="AUX1" min="1100" neutral="1500" max="1900" average="0"/>
|
||||
<channel function="MODE" min="1100" neutral="1500" max="1900" average="3"/>
|
||||
<channel function="AUX2" min="1100" neutral="1500" max="1900" average="0"/>
|
||||
<channel function="AUX3" min="1100" neutral="1500" max="1900" average="0"/>
|
||||
<channel function="AUX4" min="1100" neutral="1500" max="1900" average="0"/>
|
||||
<channel function="AUX5" min="1100" neutral="1500" max="1900" average="0"/>
|
||||
<channel function="AUX6" min="1100" neutral="1500" max="1900" average="0"/>
|
||||
<channel function="AUX7" min="1100" neutral="1500" max="1900" average="0"/>
|
||||
<channel function="AUX8" min="1100" neutral="1500" max="1900" average="0"/>
|
||||
<channel function="AUX9" min="1100" neutral="1500" max="1900" average="0"/>
|
||||
<channel function="AUX10" min="1100" neutral="1500" max="1900" average="0"/>
|
||||
<channel function="AUX11" min="1100" neutral="1500" max="1900" average="0"/>
|
||||
</radio>
|
||||
@@ -0,0 +1,252 @@
|
||||
<?xml version="1.0"?>
|
||||
<!DOCTYPE telemetry SYSTEM "../telemetry.dtd">
|
||||
<telemetry>
|
||||
|
||||
|
||||
<process name="Main">
|
||||
|
||||
<mode name="default" key_press="d">
|
||||
<message name="AUTOPILOT_VERSION" period="11.1"/>
|
||||
<message name="DL_VALUE" period="1.1"/>
|
||||
<message name="ROTORCRAFT_STATUS" period="1.2"/>
|
||||
<message name="ROTORCRAFT_FP" period="0.25"/>
|
||||
<message name="ALIVE" period="2.1"/>
|
||||
<message name="INS_REF" period="5.1"/>
|
||||
<message name="ROTORCRAFT_NAV_STATUS" period="1.6"/>
|
||||
<message name="WP_MOVED" period="1.3"/>
|
||||
<message name="ROTORCRAFT_CAM" period="1."/>
|
||||
<message name="GPS_INT" period=".25"/>
|
||||
<message name="INS" period=".25"/>
|
||||
<message name="I2C_ERRORS" period="4.1"/>
|
||||
<message name="UART_ERRORS" period="3.1"/>
|
||||
<message name="ENERGY" period="2.5"/>
|
||||
<message name="DATALINK_REPORT" period="5.1"/>
|
||||
<message name="STATE_FILTER_STATUS" period="3.2"/>
|
||||
<message name="AIR_DATA" period="1.3"/>
|
||||
<message name="SURVEY" period="2.5"/>
|
||||
<message name="VISION_POSITION_ESTIMATE" period="0.1"/>
|
||||
<message name="LOGGER_STATUS" period="5.1"/>
|
||||
<message name="LIDAR" period="1.2"/>
|
||||
<message name="INS_EKF2" period=".25"/>
|
||||
<message name="WIND_INFO_RET" period="1."/>
|
||||
<message name="AHRS_REF_QUAT" period="0.5"/>
|
||||
<message name="STAB_ATTITUDE" period=".1"/>
|
||||
<!-- <message name="STAB_THRUST" period=".1"/> -->
|
||||
<!-- <message name="STAB_PSEUDO_COMMAND" period=".1"/> -->
|
||||
<message name="GUIDANCE" period=".25"/>
|
||||
<message name="ACTUATORS_T4_IN" period="0.1"/>
|
||||
<message name="ACTUATORS_T4_OUT" period="0.1"/>
|
||||
<message name="PPM" period="0.5"/>
|
||||
<message name="PAYLOAD_FLOAT" period="0.5"/>
|
||||
<message name="ROTORCRAFT_RADIO_CONTROL" period="0.1"/>
|
||||
<message name="WLS_V" period="0.1"/>
|
||||
<message name="WLS_U" period="0.1"/>
|
||||
<message name="SYS_MON" period="0.25"/>
|
||||
<message name="EXTERNAL_POSE_DOWN" period="0.1"/>
|
||||
<message name="AHRS_BIAS" period="1.0"/>
|
||||
<!-- <message name="DEBUG_VECT" period="0.1"/> -->
|
||||
<message name="COMMANDS" period="0.2"/>
|
||||
</mode>
|
||||
|
||||
<mode name="ppm">
|
||||
<message name="DL_VALUE" period="0.5"/>
|
||||
<message name="ALIVE" period="2.1"/>
|
||||
<message name="ROTORCRAFT_CMD" period=".05"/>
|
||||
<message name="PPM" period="0.5"/>
|
||||
<message name="RC" period="0.5"/>
|
||||
<message name="ROTORCRAFT_RADIO_CONTROL" period="0.5"/>
|
||||
<message name="ROTORCRAFT_STATUS" period="1.2"/>
|
||||
<message name="BEBOP_ACTUATORS" period="0.2"/>
|
||||
</mode>
|
||||
|
||||
<mode name="raw_sensors">
|
||||
<message name="ROTORCRAFT_STATUS" period="1.2"/>
|
||||
<message name="DL_VALUE" period="0.5"/>
|
||||
<message name="ALIVE" period="2.1"/>
|
||||
<message name="IMU_ACCEL_RAW" period=".05"/>
|
||||
<message name="IMU_GYRO_RAW" period=".05"/>
|
||||
<message name="IMU_MAG_RAW" period=".05"/>
|
||||
<message name="BARO_RAW" period=".1"/>
|
||||
<message name="IMU_MAG_CURRENT_CALIBRATION" period=".05"/>
|
||||
<message name="ARDRONE_NAVDATA" period=".05"/>
|
||||
<message name="AIRSPEED_RAW" period="0.1"/>
|
||||
</mode>
|
||||
|
||||
<mode name="scaled_sensors">
|
||||
<message name="ROTORCRAFT_STATUS" period="1.2"/>
|
||||
<message name="DL_VALUE" period="0.5"/>
|
||||
<message name="ALIVE" period="2.1"/>
|
||||
<message name="IMU_GYRO_SCALED" period=".075"/>
|
||||
<message name="IMU_ACCEL_SCALED" period=".075"/>
|
||||
<message name="IMU_MAG_SCALED" period=".1"/>
|
||||
</mode>
|
||||
|
||||
<mode name="ahrs">
|
||||
<message name="ROTORCRAFT_STATUS" period="1.2"/>
|
||||
<message name="DL_VALUE" period="0.5"/>
|
||||
<message name="ALIVE" period="2.1"/>
|
||||
<message name="FILTER_ALIGNER" period="2.2"/>
|
||||
<message name="FILTER" period=".5"/>
|
||||
<message name="GEO_MAG" period="5."/>
|
||||
<message name="AHRS_GYRO_BIAS_INT" period="0.08"/>
|
||||
<message name="AHRS_QUAT_INT" period=".25"/>
|
||||
<message name="AHRS_EULER_INT" period=".1"/>
|
||||
<message name="AHRS_EULER" period=".1"/>
|
||||
<!-- <message name="AHRS_RMAT_INT" period=".5"/> -->
|
||||
</mode>
|
||||
|
||||
<mode name="rate_loop">
|
||||
<message name="ROTORCRAFT_STATUS" period="1.2"/>
|
||||
<message name="DL_VALUE" period="0.5"/>
|
||||
<message name="ALIVE" period="2.1"/>
|
||||
<message name="RATE_LOOP" period=".02"/>
|
||||
</mode>
|
||||
|
||||
<mode name="attitude_setpoint_viz" key_press="v">
|
||||
<message name="ROTORCRAFT_STATUS" period="1.2"/>
|
||||
<message name="DL_VALUE" period="0.5"/>
|
||||
<message name="ALIVE" period="0.9"/>
|
||||
<message name="ROTORCRAFT_RADIO_CONTROL" period="0.1"/>
|
||||
<message name="AHRS_REF_QUAT" period="0.05"/>
|
||||
</mode>
|
||||
|
||||
<mode name="attitude_loop" key_press="a">
|
||||
<message name="ROTORCRAFT_STATUS" period="1.2"/>
|
||||
<message name="DL_VALUE" period="0.5"/>
|
||||
<message name="ALIVE" period="0.9"/>
|
||||
<message name="STAB_ATTITUDE_INT" period=".03"/>
|
||||
<message name="STAB_ATTITUDE_REF_INT" period=".03"/>
|
||||
<message name="STAB_ATTITUDE_FLOAT" period=".03"/>
|
||||
<message name="STAB_ATTITUDE_REF_FLOAT" period=".03"/>
|
||||
<message name="STAB_ATTITUDE" period=".25"/>
|
||||
<!-- <message name="STAB_THRUST" period=".25"/> -->
|
||||
<message name="EFF_MAT_STAB" period="2.0"/>
|
||||
</mode>
|
||||
|
||||
<mode name="vert_loop" key_press="v">
|
||||
<message name="ROTORCRAFT_STATUS" period="1.2"/>
|
||||
<message name="DL_VALUE" period="0.5"/>
|
||||
<message name="ALIVE" period="0.9"/>
|
||||
<message name="VFF" period=".05"/>
|
||||
<message name="VFF_EXTENDED" period=".05"/>
|
||||
<message name="VERT_LOOP" period=".05"/>
|
||||
<message name="INS_Z" period=".05"/>
|
||||
<message name="INS" period=".11"/>
|
||||
<message name="INS_REF" period="5.1"/>
|
||||
</mode>
|
||||
|
||||
<mode name="vel_guidance" key_press="q">
|
||||
<message name="ALIVE" period="0.9"/>
|
||||
<message name="HYBRID_GUIDANCE" period="0.062"/>
|
||||
<message name="GUIDANCE_INDI_HYBRID" period="0.1"/>
|
||||
<!--<message name="STAB_ATTITUDE_REF" period="0.4"/>-->
|
||||
<message name="ROTORCRAFT_FP" period="0.8"/>
|
||||
<message name="ROTORCRAFT_STATUS" period="1.2"/>
|
||||
<message name="ROTORCRAFT_NAV_STATUS" period="1.6"/>
|
||||
<message name="INS_REF" period="5.1"/>
|
||||
<message name="WP_MOVED" period="1.3"/>
|
||||
<message name="GPS_INT" period="1.0"/>
|
||||
<message name="INS" period="1.0"/>
|
||||
</mode>
|
||||
|
||||
<mode name="h_loop" key_press="h">
|
||||
<message name="ALIVE" period="0.9"/>
|
||||
<message name="HOVER_LOOP" period="0.062"/>
|
||||
<message name="GUIDANCE_H_REF_INT" period="0.062"/>
|
||||
<message name="STAB_ATTITUDE_INT" period="0.4"/>
|
||||
<message name="STAB_ATTITUDE_FLOAT" period="0.4"/>
|
||||
<!--<message name="STAB_ATTITUDE_REF_INT" period="0.4"/>-->
|
||||
<message name="ROTORCRAFT_FP" period="0.8"/>
|
||||
<message name="ROTORCRAFT_STATUS" period="1.2"/>
|
||||
<message name="ROTORCRAFT_NAV_STATUS" period="1.6"/>
|
||||
<message name="INS_REF" period="5.1"/>
|
||||
<!-- HFF messages are only sent if USE_HFF -->
|
||||
<message name="HFF" period=".05"/>
|
||||
<message name="HFF_GPS" period=".03"/>
|
||||
<message name="HFF_DBG" period=".2"/>
|
||||
</mode>
|
||||
|
||||
<mode name="aligner">
|
||||
<message name="ALIVE" period="0.9"/>
|
||||
<message name="FILTER_ALIGNER" period="0.02"/>
|
||||
</mode>
|
||||
|
||||
<mode name="tune_hover">
|
||||
<message name="DL_VALUE" period="1.1"/>
|
||||
<message name="ROTORCRAFT_STATUS" period="1.2"/>
|
||||
<message name="ALIVE" period="2.1"/>
|
||||
<message name="GUIDANCE_H_INT" period="0.05"/>
|
||||
<message name="ROTORCRAFT_TUNE_HOVER" period=".1"/>
|
||||
<!-- <message name="GPS_INT" period=".20"/> -->
|
||||
<!--<message name="INS2" period=".05"/>
|
||||
<message name="INS3" period=".20"/>-->
|
||||
<message name="INS_REF" period="5.1"/>
|
||||
</mode>
|
||||
|
||||
<mode name="RTCM3" >
|
||||
<message name="GPS_RXMRTCM" period="1"/>
|
||||
<message name="GPS_INT" period=".25"/>
|
||||
<message name="GPS_RELPOS" period="1"/>
|
||||
</mode>
|
||||
|
||||
</process>
|
||||
|
||||
<process name="FlightRecorder">
|
||||
<mode name="default">
|
||||
<message name="AUTOPILOT_VERSION" period="11.1"/>
|
||||
<message name="GPS" period="11.1"/>
|
||||
<!-- <message name="DL_VALUE" period="2.5"/> -->
|
||||
<message name="ROTORCRAFT_STATUS" period="0.02"/>
|
||||
<message name="ROTORCRAFT_FP" period="0.002"/>
|
||||
<message name="ROTORCRAFT_RADIO_CONTROL" period="0.20"/>
|
||||
<message name="COMMANDS" period="0.002"/>
|
||||
<message name="INS_REF" period="5.1"/>
|
||||
<message name="ROTORCRAFT_NAV_STATUS" period="1.6"/>
|
||||
<message name="WP_MOVED" period="1.3"/>
|
||||
<message name="GPS_INT" period=".1"/>
|
||||
<message name="INS" period=".02"/>
|
||||
<message name="INS_Z" period=".1"/>
|
||||
<!-- <message name="I2C_ERRORS" period="4.1"/> -->
|
||||
<!-- <message name="UART_ERRORS" period="3.1"/> -->
|
||||
<message name="ENERGY" period="0.1"/>
|
||||
<message name="DATALINK_REPORT" period="5.1"/>
|
||||
<message name="STATE_FILTER_STATUS" period="3.2"/>
|
||||
<message name="AIR_DATA" period="0.05"/>
|
||||
<!-- <message name="SURVEY" period="2.5"/> -->
|
||||
<message name="IMU_GYRO" period="0.002"/>
|
||||
<message name="IMU_GYRO_SCALED" period="0.002"/>
|
||||
|
||||
<message name="IMU_ACCEL" period="0.002"/>
|
||||
<message name="IMU_MAG_SCALED" period=".0125"/>
|
||||
<!-- <message name="LIDAR" period="0.05"/> -->
|
||||
<message name="INS_EKF2" period="0.05"/>
|
||||
<message name="INS_EKF2_EXT" period="0.1"/>
|
||||
<!-- <message name="WIND_INFO_RET" period="0.2"/> -->
|
||||
<message name="AHRS_BIAS" period="0.5"/>
|
||||
<message name="AHRS_REF_QUAT" period="0.002"/>
|
||||
<message name="GUIDANCE_H_REF_INT" period="0.02"/>
|
||||
<message name="GUIDANCE_INDI_HYBRID" period="0.2"/>
|
||||
<message name="HYBRID_GUIDANCE" period="0.02"/>
|
||||
<message name="ESC" period="0.02"/>
|
||||
<message name="STAB_ATTITUDE" period="0.01"/>
|
||||
<!-- <message name="STAB_THRUST" period="0.01"/> -->
|
||||
<!-- <message name="STAB_PSEUDO_COMMAND" period="0.01"/> -->
|
||||
<!-- <message name="ON_BOARD_MODEL" period="0.01"/> -->
|
||||
<message name="ACTUATORS_T4_IN" period="0.01"/>
|
||||
<message name="ACTUATORS_T4_OUT" period="0.01"/>
|
||||
<message name="GPS_RELPOS" period="0.1"/>
|
||||
<message name="IMU_HEATER" period="6.2"/>
|
||||
<!-- <message name="GUIDANCE" period="0.002"/> -->
|
||||
<!-- <message name="EXTERNAL_POSE_DOWN" period="0.002"/> -->
|
||||
<!-- <message name="DOUBLET" period="0.002"/> -->
|
||||
<message name="DEBUG" period="0.02"/> <!-- For the parachute module -->
|
||||
<message name="WLS_V" period="0.01"/>
|
||||
<message name="WLS_U" period="0.01"/>
|
||||
<message name="DEBUG_VECT" period="0.1"/>
|
||||
<message name="PPM" period="0.1"/>
|
||||
<message name="EXTERNAL_POSE_DOWN" period="0.02"/>
|
||||
<message name="AHRS_BIAS" period="0.5"/>
|
||||
</mode>
|
||||
</process>
|
||||
|
||||
</telemetry>
|
||||
@@ -0,0 +1,13 @@
|
||||
<conf>
|
||||
<aircraft
|
||||
name="Cyclone"
|
||||
ac_id="44"
|
||||
airframe="airframes/JPG/jpg_cyclone.xml"
|
||||
radio="radios/JPG/jpg_elrs.xml"
|
||||
telemetry="telemetry/JPG/jpg_cyclone.xml"
|
||||
flight_plan="flight_plans/JPG/jpg_cyberzoo_basic.xml"
|
||||
settings="settings/rotorcraft_basic.xml"
|
||||
settings_modules="modules/air_data.xml modules/electrical.xml modules/gps.xml modules/guidance_indi_hybrid.xml modules/guidance_pid_rotorcraft.xml modules/guidance_rotorcraft.xml modules/imu_common.xml modules/imu_heater.xml modules/ins_ekf2.xml modules/logger_sd_chibios.xml modules/nav_rotorcraft.xml modules/stabilization_andi.xml"
|
||||
gui_color="#b300c400ba00"
|
||||
/>
|
||||
</conf>
|
||||
@@ -0,0 +1,208 @@
|
||||
<control_panel name="paparazzi control panel">
|
||||
<section name="programs">
|
||||
<!-- Examples of custom configuration. -->
|
||||
<!--program name="Server" command="sw/ground_segment/tmtc/server">
|
||||
<arg flag="-b" constant="192.168.1.255:2010"/>
|
||||
</program>
|
||||
<program name="GCS" command="sw/ground_segment/cockpit/gcs" icon="gcs.svg" favorite="True">
|
||||
<arg flag="-layout" constant="large_left_col.xml"/>
|
||||
<arg flag="-osm"/>
|
||||
</program-->
|
||||
</section>
|
||||
<section name="sessions">
|
||||
<session name="Flight UDP/WiFi">
|
||||
<program name="Server"/>
|
||||
<program name="PprgGCS"/>
|
||||
<program name="Data Link">
|
||||
<arg flag="-udp"/>
|
||||
</program>
|
||||
</session>
|
||||
<session name="Flight USB-XBee-API@57600">
|
||||
<program name="Data Link">
|
||||
<arg flag="-d" constant="/dev/paparazzi/xbee"/>
|
||||
<arg flag="-transport" constant="xbee"/>
|
||||
<arg flag="-s" constant="57600"/>
|
||||
</program>
|
||||
<program name="Server"/>
|
||||
<program name="PprzGCS"/>
|
||||
</session>
|
||||
<session name="Flight USB-serial Redundant">
|
||||
<program name="Server"/>
|
||||
<program name="PprzGCS"/>
|
||||
<program name="Data Link">
|
||||
<arg flag="-d" constant="/dev/ttyUSB0"/>
|
||||
<arg flag="-id" constant="1"/>
|
||||
<arg flag="-redlink"/>
|
||||
</program>
|
||||
<program name="Data Link">
|
||||
<arg flag="-d" constant="/dev/ttyUSB1"/>
|
||||
<arg flag="-id" constant="2"/>
|
||||
<arg flag="-redlink"/>
|
||||
</program>
|
||||
<program name="Link Combiner"/>
|
||||
</session>
|
||||
<session name="Flight USB-serial@115200">
|
||||
<program name="Messages"/>
|
||||
<program name="Data Link">
|
||||
<arg flag="-d" constant="/dev/ttyUSB0"/>
|
||||
<arg flag="-s" constant="115200"/>
|
||||
</program>
|
||||
<program name="Server"/>
|
||||
<program name="PprzGCS"/>
|
||||
</session>
|
||||
<session name="Flight USB-serial@57600">
|
||||
<program name="Data Link">
|
||||
<arg flag="-d" constant="/dev/ttyUSB0"/>
|
||||
<arg flag="-s" constant="57600"/>
|
||||
</program>
|
||||
<program name="Server"/>
|
||||
<program name="PprzGCS"/>
|
||||
</session>
|
||||
<session name="Flight USB-serial@9600">
|
||||
<program name="Data Link">
|
||||
<arg flag="-d" constant="/dev/ttyUSB0"/>
|
||||
</program>
|
||||
<program name="Server"/>
|
||||
<program name="PprzGCS"/>
|
||||
</session>
|
||||
<session name="HITL demo">
|
||||
<program name="Hardware in the Loop">
|
||||
<arg flag="-a" constant="@AIRCRAFT"/>
|
||||
<arg flag="-t" constant="hitl"/>
|
||||
</program>
|
||||
<program name="Data Link">
|
||||
<arg flag="-d" constant="/dev/ttyACM1"/>
|
||||
</program>
|
||||
<program name="Server">
|
||||
<arg flag="-n"/>
|
||||
</program>
|
||||
<program name="GCS"/>
|
||||
</session>
|
||||
<session name="Messages and Settings">
|
||||
<program name="Data Link">
|
||||
<arg flag="-d" constant="/dev/ttyUSB0"/>
|
||||
<arg flag="-s" constant="57600"/>
|
||||
</program>
|
||||
<program name="Server">
|
||||
<arg flag="-n"/>
|
||||
</program>
|
||||
<program name="Messages"/>
|
||||
<program name="Settings">
|
||||
<arg flag="-ac" constant="@AIRCRAFT"/>
|
||||
</program>
|
||||
</session>
|
||||
<session name="Raw Sensors">
|
||||
<program name="Data Link">
|
||||
<arg flag="-d" constant="/dev/ttyUSB0"/>
|
||||
<arg flag="-s" constant="57600"/>
|
||||
</program>
|
||||
<program name="Server">
|
||||
<arg flag="-n"/>
|
||||
</program>
|
||||
<program name="Messages">
|
||||
<arg flag="-g" constant="300x400+0-220"/>
|
||||
</program>
|
||||
<program name="Settings">
|
||||
<arg flag="-ac" constant="@AIRCRAFT"/>
|
||||
<arg flag="-g" constant="800x200+0-0"/>
|
||||
</program>
|
||||
<program name="Real-time Plotter">
|
||||
<arg flag="-g" constant="1000x250-0+0"/>
|
||||
<arg flag="-t" constant="ACC"/>
|
||||
<arg flag="-u" constant="0.05"/>
|
||||
<arg flag="-c" constant="0.00"/>
|
||||
<arg flag="-c" constant="*:telemetry:IMU_ACCEL_RAW:ax"/>
|
||||
<arg flag="-c" constant="*:telemetry:IMU_ACCEL_RAW:ay"/>
|
||||
<arg flag="-c" constant="*:telemetry:IMU_ACCEL_RAW:az"/>
|
||||
<arg flag="-n"/>
|
||||
<arg flag="-g" constant="1000x250-0+250"/>
|
||||
<arg flag="-t" constant="GYRO"/>
|
||||
<arg flag="-u" constant="0.05"/>
|
||||
<arg flag="-c" constant="0.00"/>
|
||||
<arg flag="-c" constant="*:telemetry:IMU_GYRO_RAW:gp"/>
|
||||
<arg flag="-c" constant="*:telemetry:IMU_GYRO_RAW:gq"/>
|
||||
<arg flag="-c" constant="*:telemetry:IMU_GYRO_RAW:gr"/>
|
||||
<arg flag="-n"/>
|
||||
<arg flag="-g" constant="1000x250-0+500"/>
|
||||
<arg flag="-t" constant="MAG"/>
|
||||
<arg flag="-u" constant="0.05"/>
|
||||
<arg flag="-c" constant="0.00"/>
|
||||
<arg flag="-c" constant="*:telemetry:IMU_MAG_RAW:mx"/>
|
||||
<arg flag="-c" constant="*:telemetry:IMU_MAG_RAW:my"/>
|
||||
<arg flag="-c" constant="*:telemetry:IMU_MAG_RAW:mz"/>
|
||||
<arg flag="-n"/>
|
||||
<arg flag="-g" constant="1000x250-0+750"/>
|
||||
<arg flag="-t" constant="BARO"/>
|
||||
<arg flag="-u" constant="0.05"/>
|
||||
<arg flag="-c" constant="101325.0"/>
|
||||
<arg flag="-c" constant="*:telemetry:BARO_RAW:abs"/>
|
||||
</program>
|
||||
</session>
|
||||
<session name="Scaled Sensors">
|
||||
<program name="Data Link">
|
||||
<arg flag="-d" constant="/dev/ttyUSB0"/>
|
||||
<arg flag="-s" constant="57600"/>
|
||||
</program>
|
||||
<program name="Server">
|
||||
<arg flag="-n"/>
|
||||
</program>
|
||||
<program name="Messages">
|
||||
<arg flag="-g" constant="300x400+0-220"/>
|
||||
</program>
|
||||
<program name="Settings">
|
||||
<arg flag="-ac" constant="@AIRCRAFT"/>
|
||||
<arg flag="-g" constant="800x200+0-0"/>
|
||||
</program>
|
||||
<program name="Real-time Plotter">
|
||||
<arg flag="-g" constant="1000x250-0+0"/>
|
||||
<arg flag="-t" constant="ACC"/>
|
||||
<arg flag="-u" constant="0.05"/>
|
||||
<arg flag="-c" constant="9.81"/>
|
||||
<arg flag="-c" constant="0.00"/>
|
||||
<arg flag="-c" constant="-9.81"/>
|
||||
<arg flag="-c" constant="*:telemetry:IMU_ACCEL_SCALED:ax:0.0009766"/>
|
||||
<arg flag="-c" constant="*:telemetry:IMU_ACCEL_SCALED:ay:0.0009766"/>
|
||||
<arg flag="-c" constant="*:telemetry:IMU_ACCEL_SCALED:az:0.0009766"/>
|
||||
<arg flag="-n"/>
|
||||
<arg flag="-g" constant="1000x250-0+250"/>
|
||||
<arg flag="-t" constant="GYRO"/>
|
||||
<arg flag="-u" constant="0.05"/>
|
||||
<arg flag="-c" constant="0.00"/>
|
||||
<arg flag="-c" constant="*:telemetry:IMU_GYRO_SCALED:gp:0.0139882"/>
|
||||
<arg flag="-c" constant="*:telemetry:IMU_GYRO_SCALED:gq:0.0139882"/>
|
||||
<arg flag="-c" constant="*:telemetry:IMU_GYRO_SCALED:gr:0.0139882"/>
|
||||
<arg flag="-n"/>
|
||||
<arg flag="-g" constant="1000x250-0+500"/>
|
||||
<arg flag="-t" constant="MAG"/>
|
||||
<arg flag="-u" constant="0.05"/>
|
||||
<arg flag="-c" constant="0.00"/>
|
||||
<arg flag="-c" constant="*:telemetry:IMU_MAG_SCALED:mx:0.0004883"/>
|
||||
<arg flag="-c" constant="*:telemetry:IMU_MAG_SCALED:my:0.0004883"/>
|
||||
<arg flag="-c" constant="*:telemetry:IMU_MAG_SCALED:mz:0.0004883"/>
|
||||
</program>
|
||||
</session>
|
||||
<session name="SupperBitRF">
|
||||
<program name="Data Link">
|
||||
<arg flag="-d" constant="/dev/ttyACM0"/>
|
||||
</program>
|
||||
<program name="Server"/>
|
||||
<program name="PprzGCS"/>
|
||||
<program name="Messages"/>
|
||||
</session>
|
||||
<session name="SupperBitRF cable telemetry">
|
||||
<program name="Data Link">
|
||||
<arg flag="-d" constant="/dev/ttyACM1"/>
|
||||
<arg flag="-s" constant="57600"/>
|
||||
</program>
|
||||
<program name="Server"/>
|
||||
<program name="PprzGCS"/>
|
||||
<program name="Messages"/>
|
||||
<program name="Messages"/>
|
||||
</session>
|
||||
<session name="messages up down">
|
||||
<program name="Messages">
|
||||
<arg flag="-c" constant="ground"/>
|
||||
</program>
|
||||
</session>
|
||||
</section>
|
||||
</control_panel>
|
||||
+32
-5
@@ -10,13 +10,39 @@ if [ $# -eq 0 ]; then
|
||||
exit 1
|
||||
fi
|
||||
|
||||
ASTYLE_VERSION=`astyle --version 2>&1| awk '{print $4}'`
|
||||
ASTYLE_VERSION=${ASTYLE_VERSION:0:4}
|
||||
ASTYLE_VERSION=$(astyle --version 2>&1 | awk '{print $4}' | head -1)
|
||||
echo "Using astyle version $ASTYLE_VERSION"
|
||||
|
||||
set -f
|
||||
|
||||
if [ $(bc <<< "$ASTYLE_VERSION >= 2.03") -eq 1 ]; then
|
||||
# Safe version parsing with defaults
|
||||
major=${ASTYLE_VERSION%%.*}
|
||||
minor=$(echo "$ASTYLE_VERSION" | cut -d. -f2)
|
||||
|
||||
# Fix unary operator - quote variables and provide defaults
|
||||
major=${major:-0}
|
||||
minor=${minor:-0}
|
||||
|
||||
if [ "$major" -ge 3 ]; then
|
||||
echo "Using AStyle 3.x options"
|
||||
astyle --style=kr \
|
||||
--indent=spaces=2 \
|
||||
--convert-tabs \
|
||||
--indent-switches \
|
||||
--indent-preproc-block \
|
||||
--pad-oper \
|
||||
--pad-header \
|
||||
--unpad-paren \
|
||||
--keep-one-line-blocks \
|
||||
--keep-one-line-statements \
|
||||
--align-pointer=name \
|
||||
--suffix=none \
|
||||
--lineend=linux \
|
||||
--ignore-exclude-errors-x \
|
||||
--max-code-length=120 \
|
||||
"$@"
|
||||
elif [ "$major" -ge 2 ]; then
|
||||
echo "Using AStyle 2.x options"
|
||||
astyle --style=kr \
|
||||
--indent=spaces=2 \
|
||||
--convert-tabs \
|
||||
@@ -33,8 +59,9 @@ if [ $(bc <<< "$ASTYLE_VERSION >= 2.03") -eq 1 ]; then
|
||||
--add-brackets \
|
||||
--ignore-exclude-errors-x \
|
||||
--max-code-length=120 \
|
||||
$*
|
||||
"$@"
|
||||
else
|
||||
echo "Using AStyle 1.x options"
|
||||
astyle --style=kr \
|
||||
--indent=spaces=2 \
|
||||
--convert-tabs \
|
||||
@@ -49,5 +76,5 @@ else
|
||||
--suffix=none \
|
||||
--lineend=linux \
|
||||
--add-brackets \
|
||||
$*
|
||||
"$@"
|
||||
fi
|
||||
|
||||
@@ -0,0 +1,307 @@
|
||||
/*
|
||||
*
|
||||
* Copyright (C) 2025 Justin Dubois <j.p.g.dubois@student.tudelft.nl>
|
||||
*
|
||||
* This file is part of paparazzi
|
||||
*
|
||||
* paparazzi is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2, or (at your option)
|
||||
* any later version.
|
||||
*
|
||||
* paparazzi is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with paparazzi; see the file COPYING. If not, see
|
||||
* <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
/** @file filters/complementary_filter.h
|
||||
* @brief Implementation of complementary filters (first order, second order, and Butterworth variants)
|
||||
*
|
||||
* Provides structures and functions to initialize, update, reset, and get outputs from
|
||||
* first order and second order complementary filters, as well as Butterworth complementary filters.
|
||||
*
|
||||
* FIXME: This implementation of complementary filters forces user to first integrate or differentiate
|
||||
* the signals outside of the filter before passing them in. Consider extending the filter to handle integration
|
||||
* and differentiation internally. Maybe implement cascaded complementary filters for this purpose.
|
||||
*
|
||||
* @author Justin Dubois <j.p.g.dubois@student.tudelft.nl>
|
||||
*/
|
||||
|
||||
#ifndef COMPLEMENTARY_FILTER_H
|
||||
#define COMPLEMENTARY_FILTER_H
|
||||
|
||||
#include "std.h"
|
||||
#include "filters/low_pass_filter.h"
|
||||
|
||||
|
||||
/**
|
||||
* @brief First order complementary filter structure.
|
||||
*
|
||||
* This structure contains two first order low-pass filters,
|
||||
* one for the high-pass path and one for the low-pass path.
|
||||
*/
|
||||
struct FirstOrderComplementary {
|
||||
struct FirstOrderLowPass x_lp_filter; // Low pass filter instance for high pass path
|
||||
struct FirstOrderLowPass y_lp_filter; // Low pass filter instance for low pass path
|
||||
};
|
||||
|
||||
/** Initialize the first order complementary filter.
|
||||
*
|
||||
* @param filter Complementary filter struct
|
||||
* @param cut_off Time constant of the low-pass filter
|
||||
* @param sample_time Sampling period
|
||||
* @param value Initial value for filter history
|
||||
*/
|
||||
static inline void init_first_order_complementary(
|
||||
struct FirstOrderComplementary *filter,
|
||||
float cut_off, float sample_time,
|
||||
float value)
|
||||
{
|
||||
init_first_order_low_pass(&filter->x_lp_filter, 1.0f / cut_off, sample_time, value);
|
||||
init_first_order_low_pass(&filter->y_lp_filter, 1.0f / cut_off, sample_time, value);
|
||||
}
|
||||
|
||||
/** Update the first order complementary filter with new input values.
|
||||
* @param filter Complementary filter struct
|
||||
* @param value_x New input value from the high-pass path
|
||||
* @param value_y New input value from the low-pass path
|
||||
* @return New filtered output value
|
||||
*/
|
||||
static inline float update_first_order_complementary(
|
||||
struct FirstOrderComplementary *filter,
|
||||
float value_x, float value_y)
|
||||
{
|
||||
float x_lp_output = update_first_order_low_pass(&filter->x_lp_filter, value_x);
|
||||
float y_lp_output = update_first_order_low_pass(&filter->y_lp_filter, value_y);
|
||||
return filter->x_lp_filter.last_in - x_lp_output + y_lp_output;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Reset the first order complementary filter to a specific value.
|
||||
*
|
||||
* @param filter Complementary filter struct
|
||||
* @param value Value to reset the filter to
|
||||
* @return The reset value
|
||||
*/
|
||||
static inline float reset_first_order_complementary(
|
||||
struct FirstOrderComplementary *filter,
|
||||
float value)
|
||||
{
|
||||
reset_first_order_low_pass(&filter->x_lp_filter, value);
|
||||
reset_first_order_low_pass(&filter->y_lp_filter, value);
|
||||
return value;
|
||||
}
|
||||
|
||||
/** Get current value of the first order complementary filter.
|
||||
* @param filter Complementary filter struct
|
||||
* @return Current output value of the filter
|
||||
*/
|
||||
static inline float get_first_order_complementary(const struct FirstOrderComplementary *filter)
|
||||
{
|
||||
float x_lp_output = get_first_order_low_pass(&filter->x_lp_filter);
|
||||
float y_lp_output = get_first_order_low_pass(&filter->y_lp_filter);
|
||||
return filter->x_lp_filter.last_in - x_lp_output + y_lp_output;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Second order complementary filter structure.
|
||||
*
|
||||
* This structure contains two second order low-pass filters,
|
||||
* one for the high-pass path and one for the low-pass path.
|
||||
*/
|
||||
struct SecondOrderComplementary {
|
||||
struct SecondOrderLowPass x_lp_filter; // Low pass filter instance for high pass path
|
||||
struct SecondOrderLowPass y_lp_filter; // Low pass filter instance for low pass path
|
||||
};
|
||||
|
||||
/** Initialize the second order complementary filter.
|
||||
*
|
||||
* @param filter Complementary filter struct
|
||||
* @param cut_off Time constant of the low-pass filter
|
||||
* @param Q Q factor of the low-pass filter
|
||||
* @param sample_time Sampling period
|
||||
* @param value Initial value for filter history
|
||||
*/
|
||||
static inline void init_second_order_complementary(
|
||||
struct SecondOrderComplementary *filter,
|
||||
float cut_off, float Q, float sample_time,
|
||||
float value)
|
||||
{
|
||||
init_second_order_low_pass(&filter->x_lp_filter, 1.0f / cut_off, Q, sample_time, value);
|
||||
init_second_order_low_pass(&filter->y_lp_filter, 1.0f / cut_off, Q, sample_time, value);
|
||||
}
|
||||
|
||||
/** Update the second order complementary filter with new input values.
|
||||
*
|
||||
* @param filter Complementary filter struct
|
||||
* @param value_x New input value from the high-pass path
|
||||
* @param value_y New input value from the low-pass path
|
||||
* @return New filtered output value
|
||||
*/
|
||||
static inline float update_second_order_complementary(
|
||||
struct SecondOrderComplementary *filter,
|
||||
float value_x, float value_y)
|
||||
{
|
||||
float x_lp_output = update_second_order_low_pass(&filter->x_lp_filter, value_x);
|
||||
float y_lp_output = update_second_order_low_pass(&filter->y_lp_filter, value_y);
|
||||
return filter->x_lp_filter.i[0] - x_lp_output + y_lp_output;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Reset the second order complementary filter to a specific value.
|
||||
*
|
||||
* @param filter Complementary filter struct
|
||||
* @param value Value to reset the filter to
|
||||
* @return The reset value
|
||||
*/
|
||||
static inline float reset_second_order_complementary(
|
||||
struct SecondOrderComplementary *filter,
|
||||
float value)
|
||||
{
|
||||
reset_second_order_low_pass(&filter->x_lp_filter, value);
|
||||
reset_second_order_low_pass(&filter->y_lp_filter, value);
|
||||
return value;
|
||||
}
|
||||
|
||||
/** Get current value of the second order complementary filter.
|
||||
*
|
||||
* @param filter Complementary filter struct
|
||||
* @return Current output value of the filter
|
||||
*/
|
||||
static inline float get_second_order_complementary(const struct SecondOrderComplementary *filter)
|
||||
{
|
||||
float x_lp_output = get_second_order_low_pass(&filter->x_lp_filter);
|
||||
float y_lp_output = get_second_order_low_pass(&filter->y_lp_filter);
|
||||
return filter->x_lp_filter.i[0] - x_lp_output + y_lp_output;
|
||||
}
|
||||
|
||||
typedef struct SecondOrderComplementary Butterworth2Complementary;
|
||||
|
||||
/** Initialize the Butterworth 2nd order low-pass complementary filter.
|
||||
*
|
||||
* @param filter Complementary filter struct
|
||||
* @param cut_off Time constant of the low-pass filter
|
||||
* @param sample_time Sampling period
|
||||
* @param value Initial value for filter history
|
||||
*/
|
||||
static inline void init_butterworth_2_complementary(
|
||||
Butterworth2Complementary *filter,
|
||||
float cut_off, float sample_time,
|
||||
float value)
|
||||
{
|
||||
init_second_order_complementary(
|
||||
(struct SecondOrderComplementary *)filter,
|
||||
cut_off, 0.7071, sample_time,
|
||||
value);
|
||||
}
|
||||
|
||||
/** Update the Butterworth 2nd order low-pass complementary filter with new input values.
|
||||
*
|
||||
* @param filter Complementary filter struct
|
||||
* @param value_x New input value from the high-pass path
|
||||
* @param value_y New input value from the low-pass path
|
||||
* @return New filtered output value
|
||||
*/
|
||||
static inline float update_butterworth_2_complementary(Butterworth2Complementary *filter, float value_x, float value_y)
|
||||
{
|
||||
return update_second_order_complementary((struct SecondOrderComplementary *)filter, value_x, value_y);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Reset the Butterworth 2nd order complementary filter to a specific value.
|
||||
*
|
||||
* @param filter Complementary filter struct
|
||||
* @param value Value to reset the filter to
|
||||
*/
|
||||
static inline void reset_butterworth_2_complementary(Butterworth2Complementary *filter, float value)
|
||||
{
|
||||
reset_second_order_complementary((struct SecondOrderComplementary *)filter, value);
|
||||
}
|
||||
|
||||
/** Get current value of the Butterworth 2nd order low-pass complementary filter.
|
||||
*
|
||||
* @param filter Complementary filter struct
|
||||
* @return Current output value of the filter
|
||||
*/
|
||||
static inline float get_butterworth_2_complementary(const Butterworth2Complementary *filter)
|
||||
{
|
||||
return get_second_order_complementary((const struct SecondOrderComplementary *)filter);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 4th order Butterworth complementary filter structure.
|
||||
*
|
||||
* This structure contains two 4th order Butterworth low-pass filters,
|
||||
* one for the high-pass path and one for the low-pass path.
|
||||
*/
|
||||
typedef struct {
|
||||
Butterworth4LowPass x_lp_filter; // Low pass filter instance for high pass path
|
||||
Butterworth4LowPass y_lp_filter; // Low pass filter instance for low pass path
|
||||
} Butterworth4Complementary;
|
||||
|
||||
/** Initialize the Butterworth 4th order low-pass complementary filter.
|
||||
*
|
||||
* @param filter Complementary filter struct
|
||||
* @param cut_off Time constant of the low-pass filter
|
||||
* @param sample_time Sampling period
|
||||
* @param value Initial value for filter history
|
||||
*/
|
||||
static inline void init_butterworth_4_complementary(Butterworth4Complementary *filter, float cut_off, float sample_time,
|
||||
float value)
|
||||
{
|
||||
init_butterworth_4_low_pass(&filter->x_lp_filter, 1.0f / cut_off, sample_time, value);
|
||||
init_butterworth_4_low_pass(&filter->y_lp_filter, 1.0f / cut_off, sample_time, value);
|
||||
}
|
||||
|
||||
/** Update the Butterworth 4th order low-pass complementary filter with new input values.
|
||||
*
|
||||
* @param filter Complementary filter struct
|
||||
* @param value_x New input value from the high-pass path
|
||||
* @param value_y New input value from the low-pass path
|
||||
* @return New filtered output value
|
||||
*/
|
||||
static inline float update_butterworth_4_complementary(Butterworth4Complementary *filter, float value_x, float value_y)
|
||||
{
|
||||
float x_lp_output = update_butterworth_4_low_pass(&filter->x_lp_filter, value_x);
|
||||
float y_lp_output = update_butterworth_4_low_pass(&filter->y_lp_filter, value_y);
|
||||
return filter->x_lp_filter.lp1.i[0] - x_lp_output + y_lp_output;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Reset the Butterworth 4th order complementary filter to a specific value.
|
||||
*
|
||||
* @param filter Complementary filter struct
|
||||
* @param value Value to reset the filter to
|
||||
*/
|
||||
static inline void reset_butterworth_4_complementary(Butterworth4Complementary *filter, float value)
|
||||
{
|
||||
reset_butterworth_4_low_pass(&filter->x_lp_filter, value);
|
||||
reset_butterworth_4_low_pass(&filter->y_lp_filter, value);
|
||||
}
|
||||
|
||||
/** Get current value of the Butterworth 4th order low-pass complementary filter.
|
||||
*
|
||||
* @param filter Complementary filter struct
|
||||
* @return Current output value of the filter
|
||||
*/
|
||||
static inline float get_butterworth_4_complementary(const Butterworth4Complementary *filter)
|
||||
{
|
||||
float x_lp_output = get_butterworth_4_low_pass(&filter->x_lp_filter);
|
||||
float y_lp_output = get_butterworth_4_low_pass(&filter->y_lp_filter);
|
||||
return filter->x_lp_filter.lp1.i[0] - x_lp_output + y_lp_output;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
#endif /* COMPLEMENTARY_FILTER_H */
|
||||
File diff suppressed because it is too large
Load Diff
@@ -22,6 +22,9 @@
|
||||
/** @file filters/low_pass_filter.h
|
||||
* @brief Simple first order low pass filter with bilinear transform
|
||||
*
|
||||
* @FIXME: INT and FLOAT implementations are inconsistent, tau and cut_off freq are mixed.
|
||||
* Suggestion: Change everything to freq.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef LOW_PASS_FILTER_H
|
||||
@@ -54,7 +57,7 @@ struct FirstOrderLowPass {
|
||||
* @param sample_time sampling period of the signal
|
||||
* @param value initial value of the filter
|
||||
*/
|
||||
static inline void init_first_order_low_pass(struct FirstOrderLowPass *filter, float tau, float sample_time,
|
||||
static inline void init_first_order_low_pass(struct FirstOrderLowPass *filter, float tau, const float sample_time,
|
||||
float value)
|
||||
{
|
||||
filter->last_in = value;
|
||||
@@ -68,7 +71,7 @@ static inline void init_first_order_low_pass(struct FirstOrderLowPass *filter, f
|
||||
* @param value new input value of the filter
|
||||
* @return new filtered value
|
||||
*/
|
||||
static inline float update_first_order_low_pass(struct FirstOrderLowPass *filter, float value)
|
||||
static inline float update_first_order_low_pass(struct FirstOrderLowPass *filter, const float value)
|
||||
{
|
||||
float out = (value + filter->last_in + (filter->time_const - 1.0f) * filter->last_out) / (1.0f + filter->time_const);
|
||||
filter->last_in = value;
|
||||
@@ -76,12 +79,26 @@ static inline float update_first_order_low_pass(struct FirstOrderLowPass *filter
|
||||
return out;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Reset the first order low-pass filter to a specific value.
|
||||
*
|
||||
* @param filter first order low pass filter structure
|
||||
* @param value Value to reset the filter to
|
||||
* @return The reset value
|
||||
*/
|
||||
static inline float reset_first_order_low_pass(struct FirstOrderLowPass *filter, const float value)
|
||||
{
|
||||
filter->last_in = value;
|
||||
filter->last_out = value;
|
||||
return value;
|
||||
}
|
||||
|
||||
/** Get current value of the first order low pass filter.
|
||||
*
|
||||
* @param filter first order low pass filter structure
|
||||
* @return current value of the filter
|
||||
*/
|
||||
static inline float get_first_order_low_pass(struct FirstOrderLowPass *filter)
|
||||
static inline float get_first_order_low_pass(const struct FirstOrderLowPass *filter)
|
||||
{
|
||||
return filter->last_out;
|
||||
}
|
||||
@@ -92,7 +109,8 @@ static inline float get_first_order_low_pass(struct FirstOrderLowPass *filter)
|
||||
* @param tau time constant of the first order low pass filter
|
||||
* @param sample_time sampling period of the signal
|
||||
*/
|
||||
static inline void update_first_order_low_pass_tau(struct FirstOrderLowPass *filter, float tau, float sample_time)
|
||||
static inline void update_first_order_low_pass_tau(struct FirstOrderLowPass *filter, const float tau,
|
||||
const float sample_time)
|
||||
{
|
||||
filter->time_const = 2.0f * tau / sample_time;
|
||||
}
|
||||
@@ -149,7 +167,8 @@ struct SecondOrderLowPass {
|
||||
* @param sample_time sampling period of the signal
|
||||
* @param value initial value of the filter
|
||||
*/
|
||||
static inline void init_second_order_low_pass(struct SecondOrderLowPass *filter, float tau, float Q, float sample_time,
|
||||
static inline void init_second_order_low_pass(struct SecondOrderLowPass *filter, const float tau, const float Q,
|
||||
const float sample_time,
|
||||
float value)
|
||||
{
|
||||
float K = tanf(sample_time / (2.0f * tau));
|
||||
@@ -161,13 +180,26 @@ static inline void init_second_order_low_pass(struct SecondOrderLowPass *filter,
|
||||
filter->i[0] = filter->i[1] = filter->o[0] = filter->o[1] = value;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Reset the second order low-pass filter to a specific value.
|
||||
*
|
||||
* @param filter second order low pass filter structure
|
||||
* @param value Value to reset the filter to
|
||||
* @return The reset value
|
||||
*/
|
||||
static inline float reset_second_order_low_pass(struct SecondOrderLowPass *filter, const float value)
|
||||
{
|
||||
filter->i[0] = filter->i[1] = filter->o[0] = filter->o[1] = value;
|
||||
return value;
|
||||
}
|
||||
|
||||
/** Update second order low pass filter state with a new value.
|
||||
*
|
||||
* @param filter second order low pass filter structure
|
||||
* @param value new input value of the filter
|
||||
* @return new filtered value
|
||||
*/
|
||||
static inline float update_second_order_low_pass(struct SecondOrderLowPass *filter, float value)
|
||||
static inline float update_second_order_low_pass(struct SecondOrderLowPass *filter, const float value)
|
||||
{
|
||||
float out = filter->b[0] * value
|
||||
+ filter->b[1] * filter->i[0]
|
||||
@@ -186,7 +218,7 @@ static inline float update_second_order_low_pass(struct SecondOrderLowPass *filt
|
||||
* @param filter second order low pass filter structure
|
||||
* @return current value of the filter
|
||||
*/
|
||||
static inline float get_second_order_low_pass(struct SecondOrderLowPass *filter)
|
||||
static inline float get_second_order_low_pass(const struct SecondOrderLowPass *filter)
|
||||
{
|
||||
return filter->o[0];
|
||||
}
|
||||
@@ -207,7 +239,8 @@ struct SecondOrderLowPass_int {
|
||||
* @param sample_time sampling period of the signal
|
||||
* @param value initial value of the filter
|
||||
*/
|
||||
static inline void init_second_order_low_pass_int(struct SecondOrderLowPass_int *filter, float cut_off, float Q,
|
||||
static inline void init_second_order_low_pass_int(struct SecondOrderLowPass_int *filter, const float cut_off,
|
||||
const float Q,
|
||||
float sample_time, int32_t value)
|
||||
{
|
||||
struct SecondOrderLowPass filter_temp;
|
||||
@@ -236,7 +269,7 @@ static inline void init_second_order_low_pass_int(struct SecondOrderLowPass_int
|
||||
* @param value new input value of the filter
|
||||
* @return new filtered value
|
||||
*/
|
||||
static inline int32_t update_second_order_low_pass_int(struct SecondOrderLowPass_int *filter, int32_t value)
|
||||
static inline int32_t update_second_order_low_pass_int(struct SecondOrderLowPass_int *filter, const int32_t value)
|
||||
{
|
||||
int32_t out = filter->b[0] * value
|
||||
+ filter->b[1] * filter->i[0]
|
||||
@@ -256,7 +289,7 @@ static inline int32_t update_second_order_low_pass_int(struct SecondOrderLowPass
|
||||
* @param filter second order low pass filter structure
|
||||
* @return current value of the filter
|
||||
*/
|
||||
static inline int32_t get_second_order_low_pass_int(struct SecondOrderLowPass_int *filter)
|
||||
static inline int32_t get_second_order_low_pass_int(const struct SecondOrderLowPass_int *filter)
|
||||
{
|
||||
return filter->o[0];
|
||||
}
|
||||
@@ -277,7 +310,8 @@ typedef struct SecondOrderLowPass Butterworth2LowPass;
|
||||
* @param sample_time sampling period of the signal
|
||||
* @param value initial value of the filter
|
||||
*/
|
||||
static inline void init_butterworth_2_low_pass(Butterworth2LowPass *filter, float tau, float sample_time, float value)
|
||||
static inline void init_butterworth_2_low_pass(Butterworth2LowPass *filter, const float tau, const float sample_time,
|
||||
const float value)
|
||||
{
|
||||
init_second_order_low_pass((struct SecondOrderLowPass *)filter, tau, 0.7071, sample_time, value);
|
||||
}
|
||||
@@ -288,19 +322,31 @@ static inline void init_butterworth_2_low_pass(Butterworth2LowPass *filter, floa
|
||||
* @param value new input value of the filter
|
||||
* @return new filtered value
|
||||
*/
|
||||
static inline float update_butterworth_2_low_pass(Butterworth2LowPass *filter, float value)
|
||||
static inline float update_butterworth_2_low_pass(Butterworth2LowPass *filter, const float value)
|
||||
{
|
||||
return update_second_order_low_pass((struct SecondOrderLowPass *)filter, value);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Reset a Butterworth low-pass filter to a specific value.
|
||||
*
|
||||
* @param[out] filter Butterworth2LowPass filter instance to reset.
|
||||
* @param[in] value Value to reset the filter to.
|
||||
* @return The reset value.
|
||||
*/
|
||||
static inline float reset_butterworth_2_low_pass(Butterworth2LowPass *filter, const float value)
|
||||
{
|
||||
return reset_second_order_low_pass((struct SecondOrderLowPass *)filter, value);
|
||||
}
|
||||
|
||||
/** Get current value of the second order Butterworth low pass filter.
|
||||
*
|
||||
* @param filter second order Butterworth low pass filter structure
|
||||
* @return current value of the filter
|
||||
*/
|
||||
static inline float get_butterworth_2_low_pass(Butterworth2LowPass *filter)
|
||||
static inline float get_butterworth_2_low_pass(const Butterworth2LowPass *filter)
|
||||
{
|
||||
return filter->o[0];
|
||||
return get_second_order_low_pass((const struct SecondOrderLowPass *)filter);
|
||||
}
|
||||
|
||||
/** Second order Butterworth low pass filter(fixed point version).
|
||||
@@ -319,7 +365,8 @@ typedef struct SecondOrderLowPass_int Butterworth2LowPass_int;
|
||||
* @param sample_time sampling period of the signal
|
||||
* @param value initial value of the filter
|
||||
*/
|
||||
static inline void init_butterworth_2_low_pass_int(Butterworth2LowPass_int *filter, float cut_off, float sample_time,
|
||||
static inline void init_butterworth_2_low_pass_int(Butterworth2LowPass_int *filter, const float cut_off,
|
||||
const float sample_time,
|
||||
int32_t value)
|
||||
{
|
||||
init_second_order_low_pass_int((struct SecondOrderLowPass_int *)filter, cut_off, 0.7071, sample_time, value);
|
||||
@@ -331,7 +378,7 @@ static inline void init_butterworth_2_low_pass_int(Butterworth2LowPass_int *filt
|
||||
* @param value new input value of the filter
|
||||
* @return new filtered value
|
||||
*/
|
||||
static inline int32_t update_butterworth_2_low_pass_int(Butterworth2LowPass_int *filter, int32_t value)
|
||||
static inline int32_t update_butterworth_2_low_pass_int(Butterworth2LowPass_int *filter, const int32_t value)
|
||||
{
|
||||
return update_second_order_low_pass_int((struct SecondOrderLowPass_int *)filter, value);
|
||||
}
|
||||
@@ -341,7 +388,7 @@ static inline int32_t update_butterworth_2_low_pass_int(Butterworth2LowPass_int
|
||||
* @param filter second order Butterworth low pass filter structure
|
||||
* @return current value of the filter
|
||||
*/
|
||||
static inline int32_t get_butterworth_2_low_pass_int(Butterworth2LowPass_int *filter)
|
||||
static inline int32_t get_butterworth_2_low_pass_int(const Butterworth2LowPass_int *filter)
|
||||
{
|
||||
return filter->o[0];
|
||||
}
|
||||
@@ -368,7 +415,8 @@ typedef struct {
|
||||
* @param sample_time sampling period of the signal
|
||||
* @param value initial value of the filter
|
||||
*/
|
||||
static inline void init_butterworth_4_low_pass(Butterworth4LowPass *filter, float tau, float sample_time, float value)
|
||||
static inline void init_butterworth_4_low_pass(Butterworth4LowPass *filter, const float tau, const float sample_time,
|
||||
const float value)
|
||||
{
|
||||
init_second_order_low_pass(&filter->lp1, tau, 1.30651, sample_time, value);
|
||||
init_second_order_low_pass(&filter->lp2, tau, 0.51184, sample_time, value);
|
||||
@@ -382,7 +430,7 @@ static inline void init_butterworth_4_low_pass(Butterworth4LowPass *filter, floa
|
||||
* @param value new input value of the filter
|
||||
* @return new filtered value
|
||||
*/
|
||||
static inline float update_butterworth_4_low_pass(Butterworth4LowPass *filter, float value)
|
||||
static inline float update_butterworth_4_low_pass(Butterworth4LowPass *filter, const float value)
|
||||
{
|
||||
float tmp = update_second_order_low_pass(&filter->lp1, value);
|
||||
return update_second_order_low_pass(&filter->lp2, tmp);
|
||||
@@ -393,11 +441,23 @@ static inline float update_butterworth_4_low_pass(Butterworth4LowPass *filter, f
|
||||
* @param filter fourth order Butterworth low pass filter structure
|
||||
* @return current value of the filter
|
||||
*/
|
||||
static inline float get_butterworth_4_low_pass(Butterworth4LowPass *filter)
|
||||
static inline float get_butterworth_4_low_pass(const Butterworth4LowPass *filter)
|
||||
{
|
||||
return filter->lp2.o[0];
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Reset a Butterworth low-pass filter to a specific value.
|
||||
*
|
||||
* @param[out] filter Butterworth4LowPass filter instance to reset.
|
||||
* @param[in] value Value to reset the filter to.
|
||||
*/
|
||||
static inline void reset_butterworth_4_low_pass(Butterworth4LowPass *filter, const float value)
|
||||
{
|
||||
filter->lp1.i[0] = filter->lp1.i[1] = filter->lp1.o[0] = filter->lp1.o[1] = filter->lp2.i[0] = filter->lp2.i[1] =
|
||||
filter->lp2.o[0] = filter->lp2.o[1] = value;
|
||||
}
|
||||
|
||||
/** Fourth order Butterworth low pass filter(fixed point version).
|
||||
*
|
||||
* using two cascaded second order filters
|
||||
@@ -420,7 +480,8 @@ typedef struct {
|
||||
* @param sample_time sampling period of the signal
|
||||
* @param value initial value of the filter
|
||||
*/
|
||||
static inline void init_butterworth_4_low_pass_int(Butterworth4LowPass_int *filter, float cut_off, float sample_time,
|
||||
static inline void init_butterworth_4_low_pass_int(Butterworth4LowPass_int *filter, const float cut_off,
|
||||
const float sample_time,
|
||||
int32_t value)
|
||||
{
|
||||
init_second_order_low_pass_int(&filter->lp1, cut_off, 1.30651, sample_time, value);
|
||||
@@ -435,7 +496,7 @@ static inline void init_butterworth_4_low_pass_int(Butterworth4LowPass_int *filt
|
||||
* @param value new input value of the filter
|
||||
* @return new filtered value
|
||||
*/
|
||||
static inline int32_t update_butterworth_4_low_pass_int(Butterworth4LowPass_int *filter, int32_t value)
|
||||
static inline int32_t update_butterworth_4_low_pass_int(Butterworth4LowPass_int *filter, const int32_t value)
|
||||
{
|
||||
int32_t tmp = update_second_order_low_pass_int(&filter->lp1, value);
|
||||
return update_second_order_low_pass_int(&filter->lp2, tmp);
|
||||
@@ -446,7 +507,7 @@ static inline int32_t update_butterworth_4_low_pass_int(Butterworth4LowPass_int
|
||||
* @param filter fourth order Butterworth low pass filter structure
|
||||
* @return current value of the filter
|
||||
*/
|
||||
static inline int32_t get_butterworth_4_low_pass_int(Butterworth4LowPass_int *filter)
|
||||
static inline int32_t get_butterworth_4_low_pass_int(const Butterworth4LowPass_int *filter)
|
||||
{
|
||||
return filter->lp2.o[0];
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,116 @@
|
||||
/*
|
||||
* Copyright (C) 2025 Justin Dubois <j.p.g.dubois@student.tudelft.nl>
|
||||
*
|
||||
* This file is part of paparazzi
|
||||
*
|
||||
* paparazzi is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2, or (at your option)
|
||||
* any later version.
|
||||
*
|
||||
* paparazzi is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with paparazzi; see the file COPYING. If not, see
|
||||
* <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
/** @file low_pass_zoh_filter.h
|
||||
* @brief A first order low pass filter using Zero Order Hold (ZOH) discretization.
|
||||
*/
|
||||
|
||||
#ifndef LOW_PASS_ZOH_FILTER_H
|
||||
#define LOW_PASS_ZOH_FILTER_H
|
||||
|
||||
#include "std.h"
|
||||
#include "math/pprz_algebra_int.h"
|
||||
|
||||
|
||||
/**
|
||||
* @brief Zero Order Hold (ZOH) discrete first order low pass filter structure.
|
||||
*
|
||||
* This structure represents a first order low pass filter implemented using
|
||||
* the Zero Order Hold (ZOH) method for discretization. It maintains the necessary
|
||||
* state for filtering operations.
|
||||
*/
|
||||
struct FirstOrderZOHLowPass {
|
||||
float discrete_time_constant;
|
||||
float last_in;
|
||||
float last_out;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Init first order ZOH low pass filter.
|
||||
*
|
||||
* The ZOH discretization method is used to convert a continuous-time first order
|
||||
* low pass filter into its discrete-time equivalent which matches the continuous-time
|
||||
* behavior at the sampling instants exactly when holding the input constant between samples.
|
||||
*
|
||||
* @param[out] filter first order ZOH low pass filter structure
|
||||
* @param[in] tau time constant of the first order low pass filter [s]
|
||||
* @param[in] sample_time sampling period of the signal [s]
|
||||
* @param[in] value initial value of the filter
|
||||
*/
|
||||
static inline void init_first_order_zoh_low_pass(struct FirstOrderZOHLowPass *filter, const float tau,
|
||||
const float sample_time,
|
||||
float value)
|
||||
{
|
||||
filter->discrete_time_constant = exp(-sample_time / tau);
|
||||
filter->last_in = value;
|
||||
filter->last_out = value;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Update first order ZOH low pass filter state with a new value.
|
||||
*
|
||||
* @param[in,out] filter first order ZOH low pass filter structure
|
||||
* @param[in] value new input value of the filter
|
||||
* @return new filtered value
|
||||
*/
|
||||
static inline float update_first_order_zoh_low_pass(struct FirstOrderZOHLowPass *filter, const float value)
|
||||
{
|
||||
float out = (1.0f - filter->discrete_time_constant) * value + filter->discrete_time_constant * filter->last_out;
|
||||
filter->last_in = value;
|
||||
filter->last_out = out;
|
||||
return out;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Reset the first order ZOH low-pass filter to a specific value.
|
||||
*
|
||||
* @param[in,out] filter first order ZOH low pass filter structure
|
||||
* @param[in] value Value to reset the filter to
|
||||
* @return The reset value
|
||||
*/
|
||||
static inline float reset_first_order_zoh_low_pass(struct FirstOrderZOHLowPass *filter, const float value)
|
||||
{
|
||||
filter->last_in = value;
|
||||
filter->last_out = value;
|
||||
return value;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get current value of the first order ZOH low pass filter.
|
||||
*
|
||||
* @param[in] filter first order ZOH low pass filter structure
|
||||
* @return current value of the filter
|
||||
*/
|
||||
static inline float get_first_order_zoh_low_pass(const struct FirstOrderZOHLowPass *filter)
|
||||
{
|
||||
return filter->last_out;
|
||||
}
|
||||
|
||||
/** @brief Update time constant (tau parameter) for first order ZOH low pass filter
|
||||
* @param[in,out] filter first order ZOH low pass filter structure
|
||||
* @param[in] tau time constant of the first order low pass filter [s]
|
||||
* @param[in] sample_time sampling period of the signal [s]
|
||||
*/
|
||||
static inline void update_first_order_zoh_low_pass_tau(struct FirstOrderZOHLowPass *filter, const float tau,
|
||||
const float sample_time)
|
||||
{
|
||||
filter->discrete_time_constant = exp(-sample_time / tau);
|
||||
}
|
||||
|
||||
#endif // LOW_PASS_ZOH_FILTER_H
|
||||
@@ -0,0 +1,97 @@
|
||||
/*
|
||||
* Copyright (C) 2025 Justin Dubois <j.p.g.dubois@student.tudelft.nl>
|
||||
*
|
||||
* This file is part of paparazzi
|
||||
*
|
||||
* paparazzi is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2, or (at your option)
|
||||
* any later version.
|
||||
*
|
||||
* paparazzi is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with paparazzi; see the file COPYING. If not, see
|
||||
* <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
/** @file low_pass_zoh_filter.h
|
||||
* @brief A first order low pass filter using Zero Order Hold (ZOH) discretization.
|
||||
*/
|
||||
/** @file filters/low_pass_zoh_filter.h
|
||||
* @brief Definitions and inline functions for 1st order low-pass ZOH filter vector types
|
||||
*
|
||||
* Provides structures and functions to initialize, update, reset, and get outputs from
|
||||
* 1st order low-pass ZOH filter vectors.
|
||||
*
|
||||
* @author Justin Dubois <j.p.g.dubois@student.tudelft.nl>
|
||||
*/
|
||||
|
||||
#ifndef LOW_PASS_ZOH_FILTER_TYPES_H
|
||||
#define LOW_PASS_ZOH_FILTER_TYPES_H
|
||||
|
||||
#include "std.h"
|
||||
#include "filters/low_pass_zoh_filter.h"
|
||||
#include "math/pprz_algebra_float.h"
|
||||
|
||||
/**
|
||||
* @brief Initialize a set of first order ZOH low-pass filters to zero for 3D vector data.
|
||||
* @param[out] filter_array Array of FirstOrderZOHLowPass filters to initialize.
|
||||
* @param[in] omega Cut-off frequencies for the filters (rad/s).
|
||||
* @param[in] sample_time Sampling time interval (seconds).
|
||||
*/
|
||||
static inline void init_first_order_zoh_low_pass_array(const uint8_t n,
|
||||
struct FirstOrderZOHLowPass filter_array[restrict n], const float omega[restrict n], const float sample_time)
|
||||
{
|
||||
for (uint8_t i = 0; i < n; i++) {
|
||||
float tau = 1.0f / omega[i];
|
||||
init_first_order_zoh_low_pass(&filter_array[i], tau, sample_time, 0.0f);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Update an array of first order ZOH low-pass filters.
|
||||
* @param[in] n Number of filters in the array.
|
||||
* @param[in,out] filter_array Array of FirstOrderZOHLowPass filters to update.
|
||||
* @param[in] input_array Array of input values for the filters.
|
||||
*/
|
||||
static inline void update_first_order_zoh_low_pass_array(const uint8_t n,
|
||||
struct FirstOrderZOHLowPass filter_array[restrict n], const float input_array[restrict n])
|
||||
{
|
||||
for (uint8_t i = 0; i < n; i++) {
|
||||
update_first_order_zoh_low_pass(&filter_array[i], input_array[i]);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Reset an array of first order ZOH low-pass filters to specific values.
|
||||
* @param[in] n Number of filters in the array.
|
||||
* @param[out] filter_array Array of FirstOrderZOHLowPass filters to reset.
|
||||
* @param[in] value_array Array of values to reset the filters to.
|
||||
*/
|
||||
static inline void reset_first_order_zoh_low_pass_array(const uint8_t n,
|
||||
struct FirstOrderZOHLowPass filter_array[restrict n], const float value_array[restrict n])
|
||||
{
|
||||
for (uint8_t i = 0; i < n; i++) {
|
||||
filter_array[i].last_in = value_array[i];
|
||||
filter_array[i].last_out = value_array[i];
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Retrieve the filtered outputs from an array of first order ZOH low-pass filters.
|
||||
* @param[in] n Number of filters in the array.
|
||||
* @param[in] filter_array Array of FirstOrderZOHLowPass filters.
|
||||
* @param[out] output_array Array to store the filtered output values.
|
||||
*/
|
||||
static inline void get_first_order_zoh_low_pass_array(const uint8_t n,
|
||||
const struct FirstOrderZOHLowPass filter_array[restrict n], float output_array[restrict n])
|
||||
{
|
||||
for (uint8_t i = 0; i < n; i++) {
|
||||
output_array[i] = filter_array[i].last_out;
|
||||
}
|
||||
}
|
||||
|
||||
#endif // LOW_PASS_ZOH_FILTER_TYPES_H
|
||||
@@ -0,0 +1,104 @@
|
||||
/*
|
||||
* Copyright (C) 2025 Justin Dubois <j.p.g.dubois@student.tudelft.nl>
|
||||
*
|
||||
* This file is part of paparazzi
|
||||
*
|
||||
* paparazzi is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2, or (at your option)
|
||||
* any later version.
|
||||
*
|
||||
* paparazzi is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with paparazzi; see the file COPYING. If not, see
|
||||
* <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
/** @file transport_delay.h
|
||||
* @brief Transport delay filter implementation.
|
||||
*/
|
||||
|
||||
#ifndef TRANSPORT_DELAY_H
|
||||
#define TRANSPORT_DELAY_H
|
||||
|
||||
#include "paparazzi.h"
|
||||
|
||||
#define TRANSPORT_DELAY_BUFFER_SIZE 20
|
||||
|
||||
struct TransportDelay {
|
||||
uint8_t delay_samples; // Number of samples to delay
|
||||
uint8_t write_index; // Current write index
|
||||
float buffer[TRANSPORT_DELAY_BUFFER_SIZE];
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Initialize a transport delay buffer.
|
||||
*
|
||||
* @param[out] td Pointer to the transport_delay_t structure to initialize.
|
||||
* @param[in] delay_samples Number of samples to delay. If this value exceeds TRANSPORT_DELAY_BUFFER_SIZE,
|
||||
* it will be clamped to TRANSPORT_DELAY_BUFFER_SIZE.
|
||||
* @param[in] initial_value Initial value to fill the buffer with.
|
||||
*
|
||||
* @note: If delay_samples > TRANSPORT_DELAY_BUFFER_SIZE, it will be clamped to TRANSPORT_DELAY_BUFFER_SIZE
|
||||
* and the requested delay will not be fully honored.
|
||||
*/
|
||||
static inline void init_transport_delay(struct TransportDelay *td, uint8_t delay_samples, const float initial_value)
|
||||
{
|
||||
if (delay_samples > TRANSPORT_DELAY_BUFFER_SIZE) {
|
||||
delay_samples = TRANSPORT_DELAY_BUFFER_SIZE;
|
||||
}
|
||||
td->delay_samples = delay_samples;
|
||||
td->write_index = 0;
|
||||
for (uint8_t i = 0; i < TRANSPORT_DELAY_BUFFER_SIZE; i++) {
|
||||
td->buffer[i] = initial_value;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Propagate a new input value through the transport delay buffer.
|
||||
*
|
||||
* @param[in,out] td Pointer to the transport_delay_t structure.
|
||||
* @param[in] input New input value to add to the buffer.
|
||||
* @return Delayed output value from the buffer.
|
||||
*/
|
||||
static inline float update_transport_delay(struct TransportDelay *td, const float input)
|
||||
{
|
||||
td->buffer[td->write_index] = input;
|
||||
uint8_t read_index = (td->write_index + TRANSPORT_DELAY_BUFFER_SIZE - td->delay_samples) % TRANSPORT_DELAY_BUFFER_SIZE;
|
||||
float output = td->buffer[read_index];
|
||||
td->write_index = (td->write_index + 1) % TRANSPORT_DELAY_BUFFER_SIZE;
|
||||
return output;
|
||||
}
|
||||
|
||||
/**
|
||||
* Reset the transport delay buffer to a specific initial value.
|
||||
*
|
||||
* @param[in,out] td Pointer to the transport_delay_t structure.
|
||||
* @param[in] initial_value Value to reset the buffer elements to.
|
||||
*/
|
||||
static inline void reset_transport_delay(struct TransportDelay *td, const float initial_value)
|
||||
{
|
||||
td->write_index = 0;
|
||||
for (uint8_t i = 0; i < TRANSPORT_DELAY_BUFFER_SIZE; i++) {
|
||||
td->buffer[i] = initial_value;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the current output value from the transport delay buffer without updating it.
|
||||
*
|
||||
* @param td Pointer to the transport_delay_t structure.
|
||||
* @return Current delayed output value from the buffer.
|
||||
*/
|
||||
static inline float get_transport_delay(const struct TransportDelay *td)
|
||||
{
|
||||
uint8_t read_index = (td->write_index + TRANSPORT_DELAY_BUFFER_SIZE - td->delay_samples - 1) %
|
||||
TRANSPORT_DELAY_BUFFER_SIZE;
|
||||
return td->buffer[read_index];
|
||||
}
|
||||
|
||||
#endif // TRANSPORT_DELAY_H
|
||||
@@ -0,0 +1,88 @@
|
||||
/*
|
||||
* Copyright (C) 2025 Justin Dubois <j.p.g.dubois@student.tudelft.nl>
|
||||
*
|
||||
* This file is part of paparazzi
|
||||
*
|
||||
* paparazzi is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2, or (at your option)
|
||||
* any later version.
|
||||
*
|
||||
* paparazzi is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with paparazzi; see the file COPYING. If not, see
|
||||
* <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
/** @file transport_delay_types.h
|
||||
* @brief Transport delay filter type definitions and array operations.
|
||||
*/
|
||||
|
||||
#ifndef TRANSPORT_DELAY_TYPES_H
|
||||
#define TRANSPORT_DELAY_TYPES_H
|
||||
|
||||
#include "std.h"
|
||||
#include "paparazzi.h"
|
||||
#include "filters/transport_delay.h"
|
||||
|
||||
/**
|
||||
* @brief Initialize an array of TransportDelay structures.
|
||||
* @param[in] n Number of TransportDelay structures in the array.
|
||||
* @param[in,out] td_array Array of TransportDelay structures to initialize.
|
||||
* @param[in] delay_samples Array of delay samples for each TransportDelay structure.
|
||||
* @param[in] initial_value Array of initial values to fill the buffers.
|
||||
*/
|
||||
static inline void init_transport_delay_array(uint8_t n, struct TransportDelay td_array[restrict n],
|
||||
const uint8_t delay_samples[restrict n], float initial_value[restrict n])
|
||||
{
|
||||
for (uint8_t i = 0; i < n; i++) {
|
||||
init_transport_delay(&td_array[i], delay_samples[i], initial_value[i]);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Update an array of TransportDelay structures with input values.
|
||||
* @param[in] n Number of TransportDelay structures in the array.
|
||||
* @param[in,out] td_array Array of TransportDelay structures to update.
|
||||
* @param[in] input_array Array of input values for each TransportDelay structure.
|
||||
*/
|
||||
static inline void update_transport_delay_array(uint8_t n, struct TransportDelay td_array[restrict n],
|
||||
const float input_array[restrict n])
|
||||
{
|
||||
for (uint8_t i = 0; i < n; i++) {
|
||||
update_transport_delay(&td_array[i], input_array[i]);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Reset an array of TransportDelay structures to specific initial values.
|
||||
* @param[in] n Number of TransportDelay structures in the array.
|
||||
* @param[in,out] td_array Array of TransportDelay structures to reset.
|
||||
* @param[in] initial_value Array of initial values to reset the buffers to.
|
||||
*/
|
||||
static inline void reset_transport_delay_array(const uint8_t n, struct TransportDelay td_array[restrict n],
|
||||
const float initial_value[restrict n])
|
||||
{
|
||||
for (uint8_t i = 0; i < n; i++) {
|
||||
reset_transport_delay(&td_array[i], initial_value[i]);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get output values from an array of TransportDelay structures.
|
||||
* @param[in] n Number of TransportDelay structures in the array.
|
||||
* @param[in] td_array Array of TransportDelay structures to get outputs from.
|
||||
* @param[out] output_array Array to store the output values for each TransportDelay structure.
|
||||
*/
|
||||
static inline void get_transport_delay_array(const uint8_t n, const struct TransportDelay td_array[restrict n],
|
||||
float output_array[restrict n])
|
||||
{
|
||||
for (uint8_t i = 0; i < n; i++) {
|
||||
output_array[i] = get_transport_delay(&td_array[i]);
|
||||
}
|
||||
}
|
||||
|
||||
#endif // TRANSPORT_DELAY_TYPES_H
|
||||
@@ -0,0 +1,378 @@
|
||||
#include "firmwares/rotorcraft/stabilization/stabilization_andi.h"
|
||||
#include<math.h>
|
||||
|
||||
#if ANDI_NUM_ACT != 4
|
||||
#error Cyclone expects 4 actuators
|
||||
#endif
|
||||
|
||||
#if ANDI_OUTPUTS != 4
|
||||
#error The cyclone model provides 4 outputs
|
||||
#endif
|
||||
|
||||
union CycloneCoefficients {
|
||||
struct {
|
||||
// X-axis force coefficients (f_ff_x)
|
||||
float fx_motor_squared; // Motor thrust squared effect
|
||||
float fx_speed_forward; // Forward speed effect
|
||||
|
||||
// Y-axis force coefficients (f_ff_y)
|
||||
float fy_speed_lateral; // Lateral speed effect
|
||||
|
||||
// Z-axis force coefficients (f_ff_z)
|
||||
float fz_motor_squared; // Motor thrust squared effect
|
||||
float fz_speed_forward; // Forward speed effect
|
||||
float fz_speed_vertical; // Vertical speed effect
|
||||
float fz_elevon_speed; // Elevon-speed coupling
|
||||
float fz_elevon_motor; // Elevon-motor coupling
|
||||
|
||||
// X-axis moment coefficients (m_ff_x)
|
||||
float mx_elevon_motor_diff; // (ele_l * motor_l^2 - ele_r * motor_r^2)
|
||||
float mx_elevon_speed_diff; // (ele_l - ele_r) * speed * v_ff(1)
|
||||
float mx_angular_drag; // w_ff(1)^2
|
||||
float mx_angular_coupling; // w_ff(2) * w_ff(3)
|
||||
|
||||
// Y-axis moment coefficients (m_ff_y)
|
||||
float my_speed_forward; // speed * v_ff(1)
|
||||
float my_speed_vertical; // speed * v_ff(3)
|
||||
float my_motor_sum; // motor_l^2 + motor_r^2
|
||||
float my_elevon_motor_sum; // ele_l * motor_l^2 + ele_r * motor_r^2
|
||||
float my_elevon_speed_sum; // (ele_l + ele_r) * speed * v_ff(1)
|
||||
float my_angular_sum; // w_ff(1) + w_ff(3)
|
||||
|
||||
// Z-axis moment coefficients (m_ff_z)
|
||||
float mz_speed_lateral; // speed * v_ff(2)
|
||||
float mz_motor_diff; // motor_l^2 - motor_r^2
|
||||
float mz_speed_roll; // speed * w_ff(1)
|
||||
float mz_angular_coupling; // w_ff(1) * w_ff(2)
|
||||
|
||||
// Fixme: Move to x-axis moment coefficients
|
||||
};
|
||||
float data[22];
|
||||
};
|
||||
|
||||
// Model coefficinets
|
||||
union CycloneCoefficients obm_coefficients = {
|
||||
.fx_motor_squared = 0.00000735f,
|
||||
.fx_speed_forward = -0.03f,
|
||||
|
||||
.fy_speed_lateral = -0.008f,
|
||||
|
||||
.fz_motor_squared = 0.0f,
|
||||
.fz_speed_forward = 0.0f,
|
||||
.fz_speed_vertical = -0.144f,
|
||||
.fz_elevon_speed = 0.0f,
|
||||
.fz_elevon_motor = 0.0f,
|
||||
|
||||
.mx_elevon_motor_diff = 1.9e-05f,
|
||||
.mx_elevon_speed_diff = 0.344f,
|
||||
.mx_angular_drag = -0.4940217f,
|
||||
.mx_angular_coupling = -2.18f,
|
||||
|
||||
.my_speed_forward = 0.0f,
|
||||
.my_speed_vertical = -0.0888f,
|
||||
.my_motor_sum = 0.0f,
|
||||
.my_elevon_motor_sum = -0.0000424f,
|
||||
.my_elevon_speed_sum = 0.2525f,
|
||||
.my_angular_sum = 1.262f,
|
||||
|
||||
.mz_speed_lateral = -0.00371f,
|
||||
.mz_motor_diff = 0.000039f,
|
||||
.mz_speed_roll = -0.0129f,
|
||||
.mz_angular_coupling = -0.4827f,
|
||||
};
|
||||
|
||||
union CeMatrix {
|
||||
struct {
|
||||
float ce_11;
|
||||
float ce_12;
|
||||
float ce_13;
|
||||
float ce_14;
|
||||
float ce_21;
|
||||
float ce_22;
|
||||
float ce_23;
|
||||
float ce_24;
|
||||
float ce_31;
|
||||
float ce_32;
|
||||
float ce_33;
|
||||
float ce_34;
|
||||
float ce_41;
|
||||
float ce_42;
|
||||
float ce_43;
|
||||
float ce_44;
|
||||
|
||||
};
|
||||
float data[16];
|
||||
};
|
||||
|
||||
// Model coefficinets
|
||||
union CeMatrix ce_mat_tmp = {
|
||||
.ce_11 = 0.0f, .ce_12 = 0.0f, .ce_13 = 3.9e-5f, .ce_14 = -3.9e-5f, // Roll
|
||||
.ce_21 = -29.917439f, .ce_22 = -29.917439f, .ce_23 = 0.0f, .ce_24 = 0.0f, // Pitch
|
||||
.ce_31 = -19.968481f, .ce_32 = 19.968481f, .ce_33 = 0.0f, .ce_34 = 0.0f, // Yaw
|
||||
.ce_41 = 0.0f, .ce_42 = 0.0f, .ce_43 = 7e-6f, .ce_44 = 7e-6f, // Thrust
|
||||
};
|
||||
|
||||
|
||||
/* Function Definitions */
|
||||
static void cyclone_obm_forces(const float body_vel[3], const float u[4],
|
||||
const float coeff[22], float F_obm_forces[3])
|
||||
{
|
||||
float t2;
|
||||
float t7;
|
||||
t2 = u[2] + u[3];
|
||||
t7 = sqrtf((body_vel[0] * body_vel[0] + body_vel[1] * body_vel[1]) + body_vel[2] * body_vel[2]);
|
||||
F_obm_forces[0] = coeff[3] * t2
|
||||
+ coeff[7] * (u[0] * u[2] + u[1] * u[3])
|
||||
+ coeff[5] * t7 * body_vel[0]
|
||||
- coeff[4] * t7 * body_vel[2]
|
||||
- coeff[6] * t7 * body_vel[2] * (u[0] + u[1]);
|
||||
F_obm_forces[1] = coeff[2] * t7 * body_vel[1];
|
||||
F_obm_forces[2] = -coeff[0] * t2 + coeff[1] * t7 * body_vel[2];
|
||||
}
|
||||
|
||||
static void cyclone_obm_moments(const float rates[3],
|
||||
const float body_vel[3], const float u[4],
|
||||
const float coeff[22], float F_obm_moments[3])
|
||||
{
|
||||
float t2;
|
||||
float t3;
|
||||
float t8;
|
||||
t2 = u[0] * u[2];
|
||||
t3 = u[1] * u[3];
|
||||
t8 = sqrtf((body_vel[0] * body_vel[0] + body_vel[1] * body_vel[1]) + body_vel[2] * body_vel[2]);
|
||||
F_obm_moments[0] = coeff[19] * (u[2] - u[3])
|
||||
+ coeff[18] * t8 * body_vel[1]
|
||||
- coeff[20] * t8 * rates[2]
|
||||
- rates[1] * coeff[21] * rates[2];
|
||||
F_obm_moments[1] = coeff[15] * (t2 + t3)
|
||||
+ coeff[14] * (u[2] + u[3])
|
||||
+ coeff[13] * t8 * body_vel[0]
|
||||
- coeff[12] * t8 * body_vel[2]
|
||||
- rates[0] * coeff[17] * rates[2]
|
||||
- coeff[16] * t8 * body_vel[2] * (u[0] + u[1]);
|
||||
F_obm_moments[2] = -coeff[8] * (t2 - t3)
|
||||
+ coeff[10] * fabsf(rates[2]) * rates[2]
|
||||
- rates[0] * coeff[11] * rates[1]
|
||||
+ coeff[9] * t8 * body_vel[2] * (u[0] - u[1]);
|
||||
}
|
||||
|
||||
|
||||
static void cyclone_f_stb_u(const float body_vel[3],
|
||||
const float u[4], const float coeff[22], float F_stb_u[16])
|
||||
{
|
||||
float fv[16];
|
||||
float t6;
|
||||
float t7;
|
||||
int i;
|
||||
int i1;
|
||||
int i2;
|
||||
t6 = sqrtf((body_vel[0] * body_vel[0] + body_vel[1] * body_vel[1]) + body_vel[2] * body_vel[2]);
|
||||
t7 = coeff[9] * t6 * body_vel[2];
|
||||
t6 = coeff[16] * t6 * body_vel[2];
|
||||
fv[0] = 0.0F;
|
||||
fv[1] = -t6 + u[2] * coeff[15];
|
||||
fv[2] = t7 - u[2] * coeff[8];
|
||||
fv[3] = 0.0F;
|
||||
fv[4] = 0.0F;
|
||||
fv[5] = -t6 + u[3] * coeff[15];
|
||||
fv[6] = -t7 + u[3] * coeff[8];
|
||||
fv[7] = 0.0F;
|
||||
fv[8] = coeff[19];
|
||||
fv[9] = coeff[14] + u[0] * coeff[15];
|
||||
fv[10] = -coeff[8] * u[0];
|
||||
fv[11] = coeff[0];
|
||||
fv[12] = -coeff[19];
|
||||
fv[13] = coeff[14] + u[1] * coeff[15];
|
||||
fv[14] = u[1] * coeff[8];
|
||||
fv[15] = coeff[0];
|
||||
i = 0;
|
||||
i1 = 0;
|
||||
for (i2 = 0; i2 < 16; i2++) {
|
||||
F_stb_u[i1 + (i << 2)] = fv[i2];
|
||||
i++;
|
||||
if (i > 3) {
|
||||
i = 0;
|
||||
i1++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Function Definitions */
|
||||
void cyclone_f_stb_x(const float rates[3], const float ang_accel[3],
|
||||
const float vel_body[3], const float accel_body[3], const float u[4],
|
||||
const float coeff[22], float F_stb_x[4])
|
||||
{
|
||||
float F_stb_x_tmp;
|
||||
float b_F_stb_x_tmp;
|
||||
float c_F_stb_x_tmp;
|
||||
float d_F_stb_x_tmp;
|
||||
float et1_tmp;
|
||||
float t10;
|
||||
float t12;
|
||||
float t15;
|
||||
float t8;
|
||||
float t9;
|
||||
t8 = vel_body[0] * vel_body[0];
|
||||
t9 = vel_body[1] * vel_body[1];
|
||||
t10 = vel_body[2] * vel_body[2];
|
||||
t12 = u[0] - u[1];
|
||||
t15 = sqrtf((t8 + t9) + t10);
|
||||
et1_tmp = fmaxf(1.0E-8F, t15);
|
||||
F_stb_x[0] = -(
|
||||
-accel_body[1] * coeff[18] * t9
|
||||
- accel_body[0] * coeff[18] * vel_body[0] * vel_body[1]
|
||||
- accel_body[2] * coeff[18] * vel_body[1] * vel_body[2]
|
||||
+ accel_body[0] * coeff[20] * vel_body[0] * rates[2]
|
||||
+ accel_body[1] * coeff[20] * vel_body[1] * rates[2]
|
||||
+ accel_body[2] * coeff[20] * vel_body[2] * rates[2]
|
||||
- accel_body[1] * coeff[18] * t15 * et1_tmp
|
||||
+ coeff[20] * t15 * ang_accel[2] * et1_tmp
|
||||
+ rates[1] * coeff[21] * ang_accel[2] * et1_tmp
|
||||
+ rates[2] * coeff[21] * ang_accel[1] * et1_tmp
|
||||
) / et1_tmp;
|
||||
|
||||
t9 = accel_body[2] * coeff[12];
|
||||
F_stb_x_tmp = accel_body[2] * coeff[16];
|
||||
b_F_stb_x_tmp = accel_body[0] * coeff[16];
|
||||
c_F_stb_x_tmp = accel_body[1] * coeff[16];
|
||||
d_F_stb_x_tmp = F_stb_x_tmp * u[0];
|
||||
F_stb_x_tmp *= u[1];
|
||||
F_stb_x[1] = -(
|
||||
-accel_body[0] * coeff[13] * t8 + t9 * t10
|
||||
+ accel_body[0] * coeff[12] * vel_body[0] * vel_body[2]
|
||||
- accel_body[1] * coeff[13] * vel_body[0] * vel_body[1]
|
||||
+ accel_body[1] * coeff[12] * vel_body[1] * vel_body[2]
|
||||
- accel_body[1] * coeff[12] * vel_body[1] * vel_body[2]
|
||||
- accel_body[2] * coeff[13] * vel_body[0] * vel_body[2]
|
||||
- accel_body[0] * coeff[13] * t15 * et1_tmp
|
||||
+ t9 * t15 * et1_tmp
|
||||
+ rates[0] * coeff[17] * ang_accel[2] * et1_tmp
|
||||
+ rates[2] * coeff[17] * ang_accel[0] * et1_tmp
|
||||
+ d_F_stb_x_tmp * t10
|
||||
+ F_stb_x_tmp * t10
|
||||
+ b_F_stb_x_tmp * u[0] * vel_body[0] * vel_body[2]
|
||||
+ c_F_stb_x_tmp * u[0] * vel_body[1] * vel_body[2]
|
||||
+ b_F_stb_x_tmp * u[1] * vel_body[0] * vel_body[2]
|
||||
+ c_F_stb_x_tmp * u[1] * vel_body[1] * vel_body[2]
|
||||
+ d_F_stb_x_tmp * t15 * et1_tmp
|
||||
+ F_stb_x_tmp * t15 * et1_tmp
|
||||
) / et1_tmp;
|
||||
F_stb_x[2] = accel_body[2] * (coeff[9] * t12 * t15 + coeff[9] * t10 * t12 / et1_tmp)
|
||||
- rates[0] * coeff[11] * ang_accel[1]
|
||||
- rates[1] * coeff[11] * ang_accel[0]
|
||||
+ 2.0F * coeff[10] * fabsf(rates[2]) * ang_accel[2]
|
||||
+ accel_body[0] * coeff[9] * t12 * vel_body[0] * vel_body[2] / et1_tmp
|
||||
+ accel_body[1] * coeff[9] * t12 * vel_body[1] * vel_body[2] / et1_tmp;
|
||||
F_stb_x[3] = 0.0F;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* End of code generation (cyclone_f_stb_x.c) */
|
||||
|
||||
struct FloatVect3 evaluate_obm_forces(const struct FloatRates *rates, const struct FloatVect3 *vel_body,
|
||||
const float actuator_state[ANDI_NUM_ACT])
|
||||
{
|
||||
float vel_body_array[3];
|
||||
(void)rates;
|
||||
|
||||
vel_body_array[0] = vel_body->x;
|
||||
vel_body_array[1] = vel_body->y;
|
||||
vel_body_array[2] = vel_body->z;
|
||||
|
||||
float forces_array[3];
|
||||
cyclone_obm_forces(vel_body_array, actuator_state, obm_coefficients.data, forces_array);
|
||||
|
||||
struct FloatVect3 forces;
|
||||
forces.x = forces_array[0];
|
||||
forces.y = forces_array[1];
|
||||
forces.z = forces_array[2];
|
||||
|
||||
return forces;
|
||||
}
|
||||
|
||||
struct FloatVect3 evaluate_obm_moments(const struct FloatRates *rates, const struct FloatVect3 *vel_body,
|
||||
const float actuator_state[ANDI_NUM_ACT])
|
||||
{
|
||||
float vel_body_array[3];
|
||||
float rates_array[3];
|
||||
|
||||
vel_body_array[0] = vel_body->x;
|
||||
vel_body_array[1] = vel_body->y;
|
||||
vel_body_array[2] = vel_body->z;
|
||||
|
||||
rates_array[0] = rates->p;
|
||||
rates_array[1] = rates->q;
|
||||
rates_array[2] = rates->r;
|
||||
|
||||
float moments_array[3];
|
||||
cyclone_obm_moments(rates_array, vel_body_array, actuator_state, obm_coefficients.data, moments_array);
|
||||
struct FloatVect3 moments;
|
||||
moments.x = moments_array[0];
|
||||
moments.y = moments_array[1];
|
||||
moments.z = moments_array[2];
|
||||
|
||||
return moments;
|
||||
}
|
||||
|
||||
|
||||
void evaluate_obm_f_stb_u(float fu_mat[ANDI_NUM_ACT * ANDI_OUTPUTS], const struct FloatRates *rates,
|
||||
const struct FloatVect3 *vel_body, const float actuator_state[ANDI_NUM_ACT])
|
||||
{
|
||||
float vel_body_array[3];
|
||||
(void)rates;
|
||||
|
||||
vel_body_array[0] = vel_body->x;
|
||||
vel_body_array[1] = vel_body->y;
|
||||
vel_body_array[2] = vel_body->z;
|
||||
|
||||
// Bound min motor speed in actuator_state to prevent really low control effectiveness which may result in instabilities.
|
||||
// This should make "free fall" more stable at the cost of some model inaccuracy at very low thrust.
|
||||
// FIXME: Rethink this solution.
|
||||
// FIXME: Apply this bounding directly on the elevon effectiveness terms in the final matrix instead of modifying actuator_state.
|
||||
// FIXME: Would it be possible to dynamically identify or saturate the control effectiveness?
|
||||
float actuator_state_bounded[ANDI_NUM_ACT];
|
||||
actuator_state_bounded[0] = actuator_state[0];
|
||||
actuator_state_bounded[1] = actuator_state[1];
|
||||
actuator_state_bounded[2] = fmaxf(actuator_state[2], 360000.0f);
|
||||
actuator_state_bounded[3] = fmaxf(actuator_state[3], 360000.0f);
|
||||
|
||||
cyclone_f_stb_u(vel_body_array, actuator_state_bounded, obm_coefficients.data, fu_mat);
|
||||
|
||||
fu_mat = ce_mat_tmp.data; // FIXME: Temporary hack to use ce_mat instead of the real computed matrix
|
||||
}
|
||||
|
||||
void evaluate_obm_f_stb_x(float nu_obm[ANDI_OUTPUTS], const struct FloatRates *rates,
|
||||
const struct FloatVect3 *vel_body, const struct FloatVect3 *ang_accel, const struct FloatVect3 *accel_body,
|
||||
const float actuator_state[ANDI_NUM_ACT])
|
||||
{
|
||||
float rates_array[3];
|
||||
float ang_accel_array[3];
|
||||
float vel_body_array[3];
|
||||
float accel_body_array[3];
|
||||
|
||||
rates_array[0] = rates->p;
|
||||
rates_array[1] = rates->q;
|
||||
rates_array[2] = rates->r;
|
||||
|
||||
ang_accel_array[0] = ang_accel->x;
|
||||
ang_accel_array[1] = ang_accel->y;
|
||||
ang_accel_array[2] = ang_accel->z;
|
||||
|
||||
vel_body_array[0] = vel_body->x;
|
||||
vel_body_array[1] = vel_body->y;
|
||||
vel_body_array[2] = vel_body->z;
|
||||
|
||||
accel_body_array[0] = accel_body->x;
|
||||
accel_body_array[1] = accel_body->y;
|
||||
accel_body_array[2] = accel_body->z;
|
||||
|
||||
|
||||
cyclone_f_stb_x(rates_array, ang_accel_array, vel_body_array, accel_body_array, actuator_state, obm_coefficients.data,
|
||||
nu_obm);
|
||||
}
|
||||
|
||||
float evaluate_obm_thrust_z(const float actuator_state[ANDI_NUM_ACT])
|
||||
{
|
||||
return obm_coefficients.fx_motor_squared * (actuator_state[2] + actuator_state[3]);
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,277 @@
|
||||
/*
|
||||
*
|
||||
* Copyright (C) 2025 Justin Dubois <j.p.g.dubois@student.tudelft.nl>
|
||||
*
|
||||
* This file is part of paparazzi
|
||||
*
|
||||
* paparazzi is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2, or (at your option)
|
||||
* any later version.
|
||||
*
|
||||
* paparazzi is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with paparazzi; see the file COPYING. If not, see
|
||||
* <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file sw/airborne/firmwares/rotorcraft/stabilization/stabilization_andi.h
|
||||
* @brief ANDI stabilization controller for tiltbody rotorcraft.
|
||||
*
|
||||
* Provides declarations, configuration parameters, and interfaces for the ANDI controller implemented in stabilization_andi.c.
|
||||
*
|
||||
* @see stabilization_andi.c
|
||||
* @author Justin Dubois <j.p.g.dubois@student.tudelft.nl>
|
||||
*/
|
||||
|
||||
|
||||
#ifndef STABILIZATION_ANDI_H
|
||||
#define STABILIZATION_ANDI_H
|
||||
|
||||
#include "firmwares/rotorcraft/stabilization.h"
|
||||
#include "firmwares/rotorcraft/stabilization/stabilization_rate.h"
|
||||
#include "generated/airframe.h"
|
||||
#include <stdio.h>
|
||||
#include "filters/low_pass_filter.h"
|
||||
|
||||
|
||||
#ifndef ANDI_NUM_ACT
|
||||
#define ANDI_NUM_ACT COMMANDS_NB_REAL
|
||||
#endif
|
||||
|
||||
#ifndef ANDI_OUTPUTS
|
||||
#error "You must specify the number of controlled axis (outputs)"
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Structure representing attitude in quaternion form along with its first three derivatives, used for reference.
|
||||
*
|
||||
* This structure encapsulates the attitude represented as a quaternion,
|
||||
* its first derivative (angular rates), second derivative (angular accelerations),
|
||||
* and third derivative (angular jerks). It is primarily used for reference
|
||||
* representation in the ANDI controller.
|
||||
*/
|
||||
struct AttQuat {
|
||||
struct FloatQuat att;
|
||||
struct FloatRates att_d;
|
||||
struct FloatVect3 att_2d;
|
||||
struct FloatVect3 att_3d;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Structure representing attitude in quaternion form along with its first two derivatives, used for state.
|
||||
*
|
||||
* This structure encapsulates the attitude represented as a quaternion,
|
||||
* its first derivative (angular rates), and second derivative (angular accelerations).
|
||||
* It is primarily used for state representation in the ANDI controller.
|
||||
*/
|
||||
struct AttStateQuat {
|
||||
struct FloatQuat att;
|
||||
struct FloatRates att_d;
|
||||
struct FloatVect3 att_2d;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Structure representing linear state with velocity and acceleration vectors.
|
||||
*
|
||||
* This structure encapsulates the linear state of the vehicle,
|
||||
* including its velocity and acceleration as 3D vectors.
|
||||
*/
|
||||
struct LinState {
|
||||
struct FloatVect3 vel;
|
||||
struct FloatVect3 acc;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Structure representing (specific) thrust reference and its derivative.
|
||||
*
|
||||
* This structure encapsulates the thrust reference,
|
||||
* including the thrust value and its first derivative.
|
||||
*/
|
||||
struct ThrustRef {
|
||||
float thrust;
|
||||
float thrust_d;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Structure defining third-order pole parameters for vectorized 3D quantities.
|
||||
*
|
||||
* This structure holds the natural frequencies, damping ratios,
|
||||
* and the pseudo actuator dynamics.
|
||||
*/
|
||||
struct PolesOrder3Vect3 {
|
||||
struct FloatVect3 omega_n;
|
||||
struct FloatVect3 zeta;
|
||||
struct FloatVect3 omega_a;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Structure defining second-order pole parameters for vectorized 3D quantities.
|
||||
*
|
||||
* This structure holds the natural frequencies and damping ratios.
|
||||
*/
|
||||
struct PolesOrder2Vect3 {
|
||||
struct FloatVect3 omega_a;
|
||||
struct FloatVect3 zeta;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Structure defining second-order gain parameters for vectorized 3D quantities.
|
||||
*/
|
||||
struct GainsOrder2Vect3 {
|
||||
struct FloatVect3 k1;
|
||||
struct FloatVect3 k2;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Structure defining third-order gain parameters for vectorized 3D quantities.
|
||||
*/
|
||||
struct GainsOrder3Vect3 {
|
||||
struct FloatVect3 k1;
|
||||
struct FloatVect3 k2;
|
||||
struct FloatVect3 k3;
|
||||
};
|
||||
|
||||
/* Declaration of Reference Model and Error Controller Poles */
|
||||
extern struct PolesOrder2Vect3 andi_p_rate_ec;
|
||||
extern struct PolesOrder2Vect3 andi_p_rate_rm;
|
||||
extern struct PolesOrder3Vect3 andi_p_att_ec;
|
||||
extern struct PolesOrder3Vect3 andi_p_att_rm;
|
||||
extern float andi_p_thrust_ec;
|
||||
extern float andi_p_thrust_rm;
|
||||
|
||||
void stabilization_andi_init(void);
|
||||
void stabilization_andi_enter(void);
|
||||
void stabilization_andi_run(bool use_rate_control, bool in_flight, struct StabilizationSetpoint *stab_setpoint,
|
||||
struct ThrustSetpoint *thrust_setpoint, int32_t *cmd);
|
||||
// void actuator_debug(bool do_servo_step, bool do_motor_step, float step_rate);
|
||||
|
||||
/**
|
||||
* @brief Evaluate total force acting on the vehicle from the OBM
|
||||
*
|
||||
* Computes the full set of forces modeled by the on board model for
|
||||
* the given airframe as a function of the state and input.
|
||||
*
|
||||
* This function is used for complementary filtering in ANDI.
|
||||
*
|
||||
* @param[in] rates Current angular rates (p, q, r) used by the model (rad/s).
|
||||
* @param[in] vel_body Body-frame linear velocity vector (u, v, w) (m/s).
|
||||
* @param[in] actuator_state Current actuator commands/deflections array (length
|
||||
* ANDI_NUM_ACT). Units and normalization depend on the
|
||||
* airframe and actuator type (e.g. radians, throttle fraction).
|
||||
* @return Computed force vector produced by the actuators as per the OBM.
|
||||
*
|
||||
* @note Implementation is airframe-specific.
|
||||
* @see obm_cyclone.c
|
||||
*/
|
||||
struct FloatVect3 evaluate_obm_forces(const struct FloatRates *rates, const struct FloatVect3 *vel_body,
|
||||
const float actuator_state[ANDI_NUM_ACT]);
|
||||
|
||||
/**
|
||||
* @brief Evaluate total moments acting on the vehicle from the OBM
|
||||
*
|
||||
* Computes the full set of moments modeled by the on board model for
|
||||
* the given airframe as a function of the state and input.
|
||||
*
|
||||
* This function is used for complementary filtering in ANDI.
|
||||
*
|
||||
* @param[in] rates Current angular rates (p, q, r) used by the model (rad/s).
|
||||
* @param[in] vel_body Body-frame linear velocity vector (u, v, w) (m/s).
|
||||
* @param[in] actuator_state Current actuator commands/deflections array (length
|
||||
* ANDI_NUM_ACT). Units and normalization depend on the
|
||||
* airframe and actuator type (e.g. radians, throttle fraction).
|
||||
* @return Computed moment vector produced by the actuators as per the OBM.
|
||||
*
|
||||
* @note Implementation is airframe-specific.
|
||||
* @see obm_cyclone.c
|
||||
*/
|
||||
struct FloatVect3 evaluate_obm_moments(const struct FloatRates *rates, const struct FloatVect3 *vel_body,
|
||||
const float actuator_state[ANDI_NUM_ACT]);
|
||||
|
||||
/**
|
||||
* @brief Evaluate the state-dependent control effectiveness matrix F_u for stabilization.
|
||||
*
|
||||
* This function computes the mapping from actuator inputs to aerodynamic/motor outputs
|
||||
* for the stabilization model. The output is written into the provided, pre-allocated
|
||||
* array fu_mat of size ANDI_NUM_ACT * ANDI_OUTPUTS.
|
||||
*
|
||||
* The produced matrix represents the partial derivatives of the modeled outputs with
|
||||
* respect to actuator commands (∂f/∂u) evaluated at the current state and actuator
|
||||
* conditions. It is intended to be implemented per-airframe (see obm_cyclone for an
|
||||
* example).
|
||||
*
|
||||
* @param[out] fu_mat Pre-allocated array (size ANDI_NUM_ACT * ANDI_OUTPUTS) receiving
|
||||
* the flattened control-effectiveness matrix. Convention: element
|
||||
* for output i and actuator j should be written to
|
||||
* fu_mat[i * ANDI_NUM_ACT + j].
|
||||
* @param[in] rates Current angular rates (typically p, q, r) used by the model (rad/s).
|
||||
* @param[in] vel_body Body-frame linear velocity vector (u, v, w) (m/s).
|
||||
* @param[in] actuator_state Current actuator commands/deflections array (length
|
||||
* ANDI_NUM_ACT). Units and normalization depend on the
|
||||
* airframe and actuator type (e.g. radians, throttle fraction).
|
||||
*
|
||||
* @note Implementations are airframe-specific and must account for the particular
|
||||
* actuator layout and aerodynamic/motor characteristics of the platform.
|
||||
* @see obm_cyclone.c
|
||||
*/
|
||||
void evaluate_obm_f_stb_u(float fu_mat[ANDI_NUM_ACT * ANDI_OUTPUTS], const struct FloatRates *rates,
|
||||
const struct FloatVect3 *vel_body, const float actuator_state[ANDI_NUM_ACT]);
|
||||
|
||||
/**
|
||||
* @brief Evaluate the state-dependent contribution F_x * x_dot for stabilization.
|
||||
*
|
||||
* Computes nu_obm = F_x * x_dot, the portion of the open-body-model outputs that
|
||||
* depends on the current state rates/accelerations (i.e. the state-dependent term).
|
||||
* This is the term that captures how changes in state drive the modeled outputs
|
||||
* independent of actuator inputs.
|
||||
*
|
||||
* @note This contribution is often neglected for INDI, but can be included for ANDI.
|
||||
*
|
||||
* @param[out] nu_obm Pre-allocated output vector of length ANDI_OUTPUTS receiving
|
||||
* the computed F_x * x_dot values.
|
||||
* @param[in] rates Current angular rates (p, q, r) used by the model (rad/s).
|
||||
* @param[in] vel_body Body-frame velocity vector (u, v, w) (m/s).
|
||||
* @param[in] ang_accel Body angular accelerations (p_dot, q_dot, r_dot) (rad/s^2).
|
||||
* @param[in] accel_body Body-frame linear accelerations (ax, ay, az) (m/s^2).
|
||||
* @param[in] actuator_state Current actuator commands/deflections array (length
|
||||
* ANDI_NUM_ACT). Some terms of F_x may be actuator-state
|
||||
* dependent (e.g. rotor wake effects).
|
||||
*
|
||||
* @note The function computes only the state-dependent part of the model. The full
|
||||
* modeled output is typically nu_obm + F_u * delta_u (where F_u is provided by
|
||||
* evaluate_obm_f_stb_u). Implementations must be provided per airframe.
|
||||
* @see obm_cyclone.c
|
||||
*/
|
||||
void evaluate_obm_f_stb_x(float nu_obm[ANDI_OUTPUTS], const struct FloatRates *rates, const struct FloatVect3 *vel_body,
|
||||
const struct FloatVect3 *ang_accel, const struct FloatVect3 *accel_body, const float actuator_state[ANDI_NUM_ACT]);
|
||||
|
||||
|
||||
/**
|
||||
* @brief Compute total thrust produced by the current actuator state.
|
||||
*
|
||||
* Returns the aggregate thrust generated by the set of actuators described by
|
||||
* actuator_state. This value is typically used by the stabilization/obm code when
|
||||
* converting actuator commands to net force for direct thrust control.
|
||||
*
|
||||
* @note This function does not intend to accurately compute the thrust force;
|
||||
* it only returns an approximation of the total specific thrust in the body z-direction.
|
||||
* The intended use is as feedback for direct throttle control in ANDI stabilization.
|
||||
*
|
||||
* @param[in] actuator_state Current actuator commands/deflections array (length
|
||||
* ANDI_NUM_ACT). Units and normalization depend on the
|
||||
* airframe (e.g. rotor collective, throttle fraction).
|
||||
* @return Total specific thrust produced by the actuators (SI units, m/s^2). If
|
||||
* the airframe model uses a normalized thrust unit, document that convention
|
||||
* in the airframe implementation.
|
||||
*
|
||||
* @note Implementation is airframe-specific.
|
||||
* @see obm_cyclone.c
|
||||
*/
|
||||
float evaluate_obm_thrust_z(const float actuator_state[ANDI_NUM_ACT]);
|
||||
#endif // STABILIZATION_ANDI_H
|
||||
File diff suppressed because it is too large
Load Diff
@@ -104,7 +104,7 @@ struct FloatRates {
|
||||
/*
|
||||
* Returns the real part of the log of v in base of n
|
||||
*/
|
||||
static inline float float_log_n(float v, float n)
|
||||
static inline float float_log_n(const float v, const float n)
|
||||
{
|
||||
if (fabsf(v) < 1e-4) { // avoid inf
|
||||
return - 1.0E+30;
|
||||
@@ -131,12 +131,12 @@ static inline float float_log_n(float v, float n)
|
||||
/* macros also usable if _v is not a FloatVect2, but a different struct with x,y members */
|
||||
#define FLOAT_VECT2_NORM(_v) sqrtf(VECT2_NORM2(_v))
|
||||
|
||||
static inline float float_vect2_norm2(struct FloatVect2 *v)
|
||||
static inline float float_vect2_norm2(const struct FloatVect2 *v)
|
||||
{
|
||||
return v->x * v->x + v->y * v->y;
|
||||
}
|
||||
|
||||
static inline float float_vect2_norm(struct FloatVect2 *v)
|
||||
static inline float float_vect2_norm(const struct FloatVect2 *v)
|
||||
{
|
||||
return sqrtf(float_vect2_norm2(v));
|
||||
}
|
||||
@@ -163,12 +163,12 @@ static inline void float_vect2_normalize(struct FloatVect2 *v)
|
||||
/* macros also usable if _v is not a FloatVect3, but a different struct with x,y,z members */
|
||||
#define FLOAT_VECT3_NORM(_v) sqrtf(VECT3_NORM2(_v))
|
||||
|
||||
static inline float float_vect3_norm2(struct FloatVect3 *v)
|
||||
static inline float float_vect3_norm2(const struct FloatVect3 *v)
|
||||
{
|
||||
return v->x * v->x + v->y * v->y + v->z * v->z;
|
||||
}
|
||||
|
||||
static inline float float_vect3_norm(struct FloatVect3 *v)
|
||||
static inline float float_vect3_norm(const struct FloatVect3 *v)
|
||||
{
|
||||
return sqrtf(float_vect3_norm2(v));
|
||||
}
|
||||
@@ -201,14 +201,17 @@ static inline void float_vect3_normalize(struct FloatVect3 *v)
|
||||
}
|
||||
|
||||
|
||||
extern void float_vect3_integrate_fi(struct FloatVect3 *vec, struct FloatVect3 *dv,
|
||||
float dt);
|
||||
extern void float_vect3_integrate_fi(struct FloatVect3 *vec, const struct FloatVect3 *dv,
|
||||
const float dt);
|
||||
|
||||
extern void float_rates_integrate_fi(struct FloatRates *r, struct FloatRates *dr,
|
||||
float dt);
|
||||
extern void float_rates_integrate_fi(struct FloatRates *r, const struct FloatRates *dr,
|
||||
const float dt);
|
||||
|
||||
extern void float_rates_of_euler_dot(struct FloatRates *r, struct FloatEulers *e,
|
||||
struct FloatEulers *edot);
|
||||
extern void float_rates_vect3_integrate_fi(struct FloatRates *r, const struct FloatVect3 *dr,
|
||||
const float dt);
|
||||
|
||||
extern void float_rates_of_euler_dot(struct FloatRates *r, const struct FloatEulers *e,
|
||||
const struct FloatEulers *edot);
|
||||
|
||||
/* defines for backwards compatibility */
|
||||
#define FLOAT_VECT3_INTEGRATE_FI(_vo, _dv, _dt) WARNING("FLOAT_VECT3_INTEGRATE_FI macro is deprecated, use the lower case function instead") float_vect3_integrate_fi(&(_vo), &(_dv), _dt)
|
||||
@@ -260,61 +263,61 @@ static inline void float_rmat_identity(struct FloatRMat *rm)
|
||||
/** Inverse/transpose of a rotation matrix.
|
||||
* m_b2a = inv(_m_a2b) = transp(_m_a2b)
|
||||
*/
|
||||
extern void float_rmat_inv(struct FloatRMat *m_b2a, struct FloatRMat *m_a2b);
|
||||
extern void float_rmat_inv(struct FloatRMat *m_b2a, const struct FloatRMat *m_a2b);
|
||||
|
||||
/** Composition (multiplication) of two rotation matrices.
|
||||
* m_a2c = m_a2b comp m_b2c , aka m_a2c = m_b2c * m_a2b
|
||||
*/
|
||||
extern void float_rmat_comp(struct FloatRMat *m_a2c, struct FloatRMat *m_a2b,
|
||||
struct FloatRMat *m_b2c);
|
||||
extern void float_rmat_comp(struct FloatRMat *m_a2c, const struct FloatRMat *m_a2b,
|
||||
const struct FloatRMat *m_b2c);
|
||||
|
||||
/** Composition (multiplication) of two rotation matrices.
|
||||
* m_a2b = m_a2c comp_inv m_b2c , aka m_a2b = inv(_m_b2c) * m_a2c
|
||||
*/
|
||||
extern void float_rmat_comp_inv(struct FloatRMat *m_a2b, struct FloatRMat *m_a2c,
|
||||
struct FloatRMat *m_b2c);
|
||||
extern void float_rmat_comp_inv(struct FloatRMat *m_a2b, const struct FloatRMat *m_a2c,
|
||||
const struct FloatRMat *m_b2c);
|
||||
|
||||
/// Norm of a rotation matrix.
|
||||
extern float float_rmat_norm(struct FloatRMat *rm);
|
||||
extern float float_rmat_norm(const struct FloatRMat *rm);
|
||||
|
||||
/** rotate 3D vector by rotation matrix.
|
||||
* vb = m_a2b * va
|
||||
*/
|
||||
extern void float_rmat_vmult(struct FloatVect3 *vb, struct FloatRMat *m_a2b,
|
||||
struct FloatVect3 *va);
|
||||
extern void float_rmat_vmult(struct FloatVect3 *vb, const struct FloatRMat *m_a2b,
|
||||
const struct FloatVect3 *va);
|
||||
|
||||
/** rotate 3D vector by transposed rotation matrix.
|
||||
* vb = m_b2a^T * va
|
||||
*/
|
||||
extern void float_rmat_transp_vmult(struct FloatVect3 *vb, struct FloatRMat *m_b2a,
|
||||
struct FloatVect3 *va);
|
||||
extern void float_rmat_transp_vmult(struct FloatVect3 *vb, const struct FloatRMat *m_b2a,
|
||||
const struct FloatVect3 *va);
|
||||
|
||||
/** rotate angle by rotation matrix.
|
||||
* rb = m_a2b * ra
|
||||
*/
|
||||
extern void float_rmat_mult(struct FloatEulers *rb, struct FloatRMat *m_a2b,
|
||||
struct FloatEulers *ra);
|
||||
extern void float_rmat_mult(struct FloatEulers *rb, const struct FloatRMat *m_a2b,
|
||||
const struct FloatEulers *ra);
|
||||
|
||||
/** rotate angle by transposed rotation matrix.
|
||||
* rb = m_b2a^T * ra
|
||||
*/
|
||||
extern void float_rmat_transp_mult(struct FloatEulers *rb, struct FloatRMat *m_b2a,
|
||||
struct FloatEulers *ra);
|
||||
extern void float_rmat_transp_mult(struct FloatEulers *rb, const struct FloatRMat *m_b2a,
|
||||
const struct FloatEulers *ra);
|
||||
|
||||
/** rotate anglular rates by rotation matrix.
|
||||
* rb = m_a2b * ra
|
||||
*/
|
||||
extern void float_rmat_ratemult(struct FloatRates *rb, struct FloatRMat *m_a2b,
|
||||
struct FloatRates *ra);
|
||||
extern void float_rmat_ratemult(struct FloatRates *rb, const struct FloatRMat *m_a2b,
|
||||
const struct FloatRates *ra);
|
||||
|
||||
/** rotate anglular rates by transposed rotation matrix.
|
||||
* rb = m_b2a^T * ra
|
||||
*/
|
||||
extern void float_rmat_transp_ratemult(struct FloatRates *rb, struct FloatRMat *m_b2a,
|
||||
struct FloatRates *ra);
|
||||
extern void float_rmat_transp_ratemult(struct FloatRates *rb, const struct FloatRMat *m_b2a,
|
||||
const struct FloatRates *ra);
|
||||
|
||||
/** initialises a rotation matrix from unit vector axis and angle */
|
||||
extern void float_rmat_of_axis_angle(struct FloatRMat *rm, struct FloatVect3 *uv, float angle);
|
||||
extern void float_rmat_of_axis_angle(struct FloatRMat *rm, const struct FloatVect3 *uv, const float angle);
|
||||
|
||||
/** Rotation matrix from 321 Euler angles (float).
|
||||
* The Euler angles are interpreted as zy'x'' (intrinsic) rotation.
|
||||
@@ -328,13 +331,13 @@ extern void float_rmat_of_axis_angle(struct FloatRMat *rm, struct FloatVect3 *uv
|
||||
* @param[out] rm pointer to rotation matrix
|
||||
* @param[in] e pointer to Euler angles
|
||||
*/
|
||||
extern void float_rmat_of_eulers_321(struct FloatRMat *rm, struct FloatEulers *e);
|
||||
extern void float_rmat_of_eulers_312(struct FloatRMat *rm, struct FloatEulers *e);
|
||||
extern void float_rmat_of_eulers_321(struct FloatRMat *rm, const struct FloatEulers *e);
|
||||
extern void float_rmat_of_eulers_312(struct FloatRMat *rm, const struct FloatEulers *e);
|
||||
#define float_rmat_of_eulers float_rmat_of_eulers_321
|
||||
|
||||
extern void float_rmat_of_quat(struct FloatRMat *rm, struct FloatQuat *q);
|
||||
extern void float_rmat_of_quat(struct FloatRMat *rm, const struct FloatQuat *q);
|
||||
/** in place first order integration of a rotation matrix */
|
||||
extern void float_rmat_integrate_fi(struct FloatRMat *rm, struct FloatRates *omega, float dt);
|
||||
extern void float_rmat_integrate_fi(struct FloatRMat *rm, const struct FloatRates *omega, const float dt);
|
||||
extern float float_rmat_reorthogonalize(struct FloatRMat *rm);
|
||||
|
||||
/* defines for backwards compatibility */
|
||||
@@ -372,7 +375,7 @@ static inline void float_quat_identity(struct FloatQuat *q)
|
||||
|
||||
#define FLOAT_QUAT_NORM2(_q) (SQUARE((_q).qi) + SQUARE((_q).qx) + SQUARE((_q).qy) + SQUARE((_q).qz))
|
||||
|
||||
static inline float float_quat_norm(struct FloatQuat *q)
|
||||
static inline float float_quat_norm(const struct FloatQuat *q)
|
||||
{
|
||||
return sqrtf(SQUARE(q->qi) + SQUARE(q->qx) + SQUARE(q->qy) + SQUARE(q->qz));
|
||||
}
|
||||
@@ -388,7 +391,7 @@ static inline void float_quat_normalize(struct FloatQuat *q)
|
||||
}
|
||||
}
|
||||
|
||||
static inline void float_quat_invert(struct FloatQuat *qo, struct FloatQuat *qi)
|
||||
static inline void float_quat_invert(struct FloatQuat *qo, const struct FloatQuat *qi)
|
||||
{
|
||||
QUAT_INVERT(*qo, *qi);
|
||||
}
|
||||
@@ -406,72 +409,75 @@ static inline void float_quat_wrap_shortest(struct FloatQuat *q)
|
||||
/** Composition (multiplication) of two quaternions.
|
||||
* a2c = a2b comp b2c , aka a2c = a2b * b2c
|
||||
*/
|
||||
extern void float_quat_comp(struct FloatQuat *a2c, struct FloatQuat *a2b, struct FloatQuat *b2c);
|
||||
extern void float_quat_comp(struct FloatQuat *a2c, const struct FloatQuat *a2b, const struct FloatQuat *b2c);
|
||||
|
||||
/** Composition (multiplication) of two quaternions.
|
||||
* a2b = a2c comp_inv b2c , aka a2b = a2c * inv(b2c)
|
||||
*/
|
||||
extern void float_quat_comp_inv(struct FloatQuat *a2b, struct FloatQuat *a2c, struct FloatQuat *b2c);
|
||||
extern void float_quat_comp_inv(struct FloatQuat *a2b, const struct FloatQuat *a2c, const struct FloatQuat *b2c);
|
||||
|
||||
/** Composition (multiplication) of two quaternions.
|
||||
* b2c = a2b inv_comp a2c , aka b2c = inv(_a2b) * a2c
|
||||
*/
|
||||
extern void float_quat_inv_comp(struct FloatQuat *b2c, struct FloatQuat *a2b, struct FloatQuat *a2c);
|
||||
extern void float_quat_inv_comp(struct FloatQuat *b2c, const struct FloatQuat *a2b, const struct FloatQuat *a2c);
|
||||
|
||||
/** Composition (multiplication) of two quaternions with normalization.
|
||||
* a2c = a2b comp b2c , aka a2c = a2b * b2c
|
||||
*/
|
||||
extern void float_quat_comp_norm_shortest(struct FloatQuat *a2c, struct FloatQuat *a2b, struct FloatQuat *b2c);
|
||||
extern void float_quat_comp_norm_shortest(struct FloatQuat *a2c, const struct FloatQuat *a2b,
|
||||
const struct FloatQuat *b2c);
|
||||
|
||||
/** Composition (multiplication) of two quaternions with normalization.
|
||||
* a2b = a2c comp_inv b2c , aka a2b = a2c * inv(b2c)
|
||||
*/
|
||||
extern void float_quat_comp_inv_norm_shortest(struct FloatQuat *a2b, struct FloatQuat *a2c, struct FloatQuat *b2c);
|
||||
extern void float_quat_comp_inv_norm_shortest(struct FloatQuat *a2b, const struct FloatQuat *a2c,
|
||||
const struct FloatQuat *b2c);
|
||||
|
||||
/** Composition (multiplication) of two quaternions with normalization.
|
||||
* b2c = a2b inv_comp a2c , aka b2c = inv(_a2b) * a2c
|
||||
*/
|
||||
extern void float_quat_inv_comp_norm_shortest(struct FloatQuat *b2c, struct FloatQuat *a2b, struct FloatQuat *a2c);
|
||||
extern void float_quat_inv_comp_norm_shortest(struct FloatQuat *b2c, const struct FloatQuat *a2b,
|
||||
const struct FloatQuat *a2c);
|
||||
|
||||
/** Quaternion derivative from rotational velocity.
|
||||
* qd = -0.5*omega(r) * q
|
||||
* or equally:
|
||||
* qd = 0.5 * q * omega(r)
|
||||
*/
|
||||
extern void float_quat_derivative(struct FloatQuat *qd, struct FloatRates *r, struct FloatQuat *q);
|
||||
extern void float_quat_derivative(struct FloatQuat *qd, const struct FloatRates *r, const struct FloatQuat *q);
|
||||
|
||||
/** Quaternion derivative from rotational velocity with Lagrange multiplier.
|
||||
* qd = -0.5*omega(r) * q
|
||||
* or equally:
|
||||
* qd = 0.5 * q * omega(r)
|
||||
*/
|
||||
extern void float_quat_derivative_lagrange(struct FloatQuat *qd, struct FloatRates *r, struct FloatQuat *q);
|
||||
extern void float_quat_derivative_lagrange(struct FloatQuat *qd, const struct FloatRates *r, const struct FloatQuat *q);
|
||||
|
||||
/** Delta rotation quaternion with constant angular rates.
|
||||
*/
|
||||
extern void float_quat_differential(struct FloatQuat *q_out, struct FloatRates *w, float dt);
|
||||
extern void float_quat_differential(struct FloatQuat *q_out, const struct FloatRates *w, const float dt);
|
||||
|
||||
/** in place first order quaternion integration with constant rotational velocity */
|
||||
extern void float_quat_integrate_fi(struct FloatQuat *q, struct FloatRates *omega, float dt);
|
||||
extern void float_quat_integrate_fi(struct FloatQuat *q, const struct FloatRates *omega, const float dt);
|
||||
|
||||
/** in place quaternion integration with constant rotational velocity */
|
||||
extern void float_quat_integrate(struct FloatQuat *q, struct FloatRates *omega, float dt);
|
||||
extern void float_quat_integrate(struct FloatQuat *q, const struct FloatRates *omega, const float dt);
|
||||
|
||||
/** rotate 3D vector by quaternion.
|
||||
* vb = q_a2b * va * q_a2b^-1
|
||||
*/
|
||||
extern void float_quat_vmult(struct FloatVect3 *v_out, struct FloatQuat *q, const struct FloatVect3 *v_in);
|
||||
extern void float_quat_vmult(struct FloatVect3 *v_out, const struct FloatQuat *q, const struct FloatVect3 *v_in);
|
||||
|
||||
/// Quaternion from Euler angles.
|
||||
extern void float_quat_of_eulers(struct FloatQuat *q, struct FloatEulers *e);
|
||||
extern void float_quat_of_eulers_zxy(struct FloatQuat *q, struct FloatEulers *e);
|
||||
extern void float_quat_of_eulers_yxz(struct FloatQuat *q, struct FloatEulers *e);
|
||||
extern void float_quat_of_eulers(struct FloatQuat *q, const struct FloatEulers *e);
|
||||
extern void float_quat_of_eulers_zxy(struct FloatQuat *q, const struct FloatEulers *e);
|
||||
extern void float_quat_of_eulers_yxz(struct FloatQuat *q, const struct FloatEulers *e);
|
||||
|
||||
/** Quaternion from unit vector and angle.
|
||||
* Output quaternion is not normalized.
|
||||
* It will be a unit quaternion only if the input vector is also unitary.
|
||||
*/
|
||||
extern void float_quat_of_axis_angle(struct FloatQuat *q, const struct FloatVect3 *uv, float angle);
|
||||
extern void float_quat_of_axis_angle(struct FloatQuat *q, const struct FloatVect3 *uv, const float angle);
|
||||
|
||||
/** Quaternion from orientation vector.
|
||||
* Length/norm of the vector is the angle.
|
||||
@@ -479,10 +485,10 @@ extern void float_quat_of_axis_angle(struct FloatQuat *q, const struct FloatVect
|
||||
extern void float_quat_of_orientation_vect(struct FloatQuat *q, const struct FloatVect3 *ov);
|
||||
|
||||
/// Quaternion from rotation matrix.
|
||||
extern void float_quat_of_rmat(struct FloatQuat *q, struct FloatRMat *rm);
|
||||
extern void float_quat_of_rmat(struct FloatQuat *q, const struct FloatRMat *rm);
|
||||
|
||||
/// Tilt twist decomposition of quaternion
|
||||
extern void float_quat_tilt_twist(struct FloatQuat *tilt, struct FloatQuat *twist, struct FloatQuat *quat);
|
||||
extern void float_quat_tilt_twist(struct FloatQuat *tilt, struct FloatQuat *twist, const struct FloatQuat *quat);
|
||||
|
||||
|
||||
/* defines for backwards compatibility */
|
||||
@@ -518,14 +524,14 @@ extern void float_quat_tilt_twist(struct FloatQuat *tilt, struct FloatQuat *twis
|
||||
|
||||
#define FLOAT_EULERS_ZERO(_e) EULERS_ASSIGN(_e, 0., 0., 0.);
|
||||
|
||||
static inline float float_eulers_norm(struct FloatEulers *e)
|
||||
static inline float float_eulers_norm(const struct FloatEulers *e)
|
||||
{
|
||||
return sqrtf(SQUARE(e->phi) + SQUARE(e->theta) + SQUARE(e->psi));
|
||||
}
|
||||
extern void float_eulers_of_rmat(struct FloatEulers *e, struct FloatRMat *rm);
|
||||
extern void float_eulers_of_quat(struct FloatEulers *e, struct FloatQuat *q);
|
||||
extern void float_eulers_of_quat_zxy(struct FloatEulers *e, struct FloatQuat *q);
|
||||
extern void float_eulers_of_quat_yxz(struct FloatEulers *e, struct FloatQuat *q);
|
||||
extern void float_eulers_of_rmat(struct FloatEulers *e, const struct FloatRMat *rm);
|
||||
extern void float_eulers_of_quat(struct FloatEulers *e, const struct FloatQuat *q);
|
||||
extern void float_eulers_of_quat_zxy(struct FloatEulers *e, const struct FloatQuat *q);
|
||||
extern void float_eulers_of_quat_yxz(struct FloatEulers *e, const struct FloatQuat *q);
|
||||
|
||||
/* defines for backwards compatibility */
|
||||
#define FLOAT_EULERS_OF_RMAT(_e, _rm) WARNING("FLOAT_EULERS_OF_RMAT macro is deprecated, use the lower case function instead") float_eulers_of_rmat(&(_e), &(_rm))
|
||||
@@ -642,12 +648,12 @@ static inline float float_vect_dot_product(const float *a, const float *b, const
|
||||
for (__i = 0; __i < _rows; __i++) { _ptr[__i] = &_mat[__i][0]; } \
|
||||
}
|
||||
|
||||
extern void float_mat_invert(float **o, float **mat, int n);
|
||||
extern void float_mat_exp(float **a, float **o, int n);
|
||||
extern float float_mat_norm_li(float **o, int m, int n);
|
||||
extern void float_mat_invert(float **o, float **mat, const int n);
|
||||
extern void float_mat_exp(float **a, float **o, const int n);
|
||||
extern float float_mat_norm_li(float **o, const int m, const int n);
|
||||
|
||||
/** a = 0 */
|
||||
static inline void float_mat_zero(float **a, int m, int n)
|
||||
static inline void float_mat_zero(float **a, const int m, const int n)
|
||||
{
|
||||
int i, j;
|
||||
for (i = 0; i < m; i++) {
|
||||
@@ -656,7 +662,7 @@ static inline void float_mat_zero(float **a, int m, int n)
|
||||
}
|
||||
|
||||
/** a = b */
|
||||
static inline void float_mat_copy(float **a, float **b, int m, int n)
|
||||
static inline void float_mat_copy(float **a, float **b, const int m, const int n)
|
||||
{
|
||||
int i, j;
|
||||
for (i = 0; i < m; i++) {
|
||||
@@ -667,7 +673,7 @@ static inline void float_mat_copy(float **a, float **b, int m, int n)
|
||||
|
||||
|
||||
/** o = a + b */
|
||||
static inline void float_mat_sum(float **o, float **a, float **b, int m, int n)
|
||||
static inline void float_mat_sum(float **o, float **a, float **b, const int m, const int n)
|
||||
{
|
||||
int i, j;
|
||||
for (i = 0; i < m; i++) {
|
||||
@@ -676,7 +682,7 @@ static inline void float_mat_sum(float **o, float **a, float **b, int m, int n)
|
||||
}
|
||||
|
||||
/** o = a - b */
|
||||
static inline void float_mat_diff(float **o, float **a, float **b, int m, int n)
|
||||
static inline void float_mat_diff(float **o, float **a, float **b, const int m, const int n)
|
||||
{
|
||||
int i, j;
|
||||
for (i = 0; i < m; i++) {
|
||||
@@ -685,7 +691,7 @@ static inline void float_mat_diff(float **o, float **a, float **b, int m, int n)
|
||||
}
|
||||
|
||||
/** transpose square matrix */
|
||||
static inline void float_mat_transpose_square(float **a, int n)
|
||||
static inline void float_mat_transpose_square(float **a, const int n)
|
||||
{
|
||||
int i, j;
|
||||
for (i = 0; i < n; i++) {
|
||||
@@ -699,7 +705,7 @@ static inline void float_mat_transpose_square(float **a, int n)
|
||||
|
||||
|
||||
/** transpose non-square matrix */
|
||||
static inline void float_mat_transpose(float **o, float **a, int n, int m)
|
||||
static inline void float_mat_transpose(float **o, float **a, const int n, const int m)
|
||||
{
|
||||
int i, j;
|
||||
for (i = 0; i < n; i++) {
|
||||
@@ -715,7 +721,7 @@ static inline void float_mat_transpose(float **o, float **a, int n, int m)
|
||||
* b: [n x l]
|
||||
* o: [m x l]
|
||||
*/
|
||||
static inline void float_mat_mul(float **o, float **a, float **b, int m, int n, int l)
|
||||
static inline void float_mat_mul(float **o, float **a, float **b, const int m, const int n, const int l)
|
||||
{
|
||||
int i, j, k;
|
||||
for (i = 0; i < m; i++) {
|
||||
@@ -734,7 +740,7 @@ static inline void float_mat_mul(float **o, float **a, float **b, int m, int n,
|
||||
* b: [l x n]
|
||||
* o: [m x l]
|
||||
*/
|
||||
static inline void float_mat_mul_transpose(float **o, float **a, float **b, int m, int n, int l)
|
||||
static inline void float_mat_mul_transpose(float **o, float **a, float **b, const int m, const int n, const int l)
|
||||
{
|
||||
int i, j, k;
|
||||
for (i = 0; i < m; i++) {
|
||||
@@ -758,7 +764,7 @@ static inline void float_mat_mul_transpose(float **o, float **a, float **b, int
|
||||
* of the input matrices when this function is used, which is useful for consecutive multiplications
|
||||
* (e.g. when doing matrix exponentiation), at the cost of some copy overhead.
|
||||
*/
|
||||
static inline void float_mat_mul_copy(float **o, float **a, float **b, int m, int n, int l)
|
||||
static inline void float_mat_mul_copy(float **o, float **a, float **b, const int m, const int n, const int l)
|
||||
{
|
||||
float temp[m][l];
|
||||
int i, j, k;
|
||||
@@ -782,7 +788,7 @@ static inline void float_mat_mul_copy(float **o, float **a, float **b, int m, in
|
||||
* b: [n x 1]
|
||||
* o: [m x 1]
|
||||
*/
|
||||
static inline void float_mat_vect_mul(float *o, float **a, float *b, int m, int n)
|
||||
static inline void float_mat_vect_mul(float *o, float **a, const float *b, const int m, const int n)
|
||||
{
|
||||
int i, j;
|
||||
for (i = 0; i < m; i++) {
|
||||
@@ -798,7 +804,7 @@ static inline void float_mat_vect_mul(float *o, float **a, float *b, int m, int
|
||||
* a: [m x n]
|
||||
* k: [1 x 1]
|
||||
*/
|
||||
static inline void float_mat_scale(float **a, float k, int m, int n)
|
||||
static inline void float_mat_scale(float **a, float k, const int m, const int n)
|
||||
{
|
||||
int i, j;
|
||||
for (i = 0; i < m; i++) {
|
||||
@@ -814,7 +820,7 @@ static inline void float_mat_scale(float **a, float k, int m, int n)
|
||||
* b: [m x n]
|
||||
* k: [1 x 1]
|
||||
*/
|
||||
static inline void float_mat_sum_scaled(float **a, float **b, float k, int m, int n)
|
||||
static inline void float_mat_sum_scaled(float **a, float **b, const float k, const int m, const int n)
|
||||
{
|
||||
int i, j;
|
||||
for (i = 0; i < m; i++) {
|
||||
@@ -831,7 +837,7 @@ static inline void float_mat_sum_scaled(float **a, float **b, float k, int m, in
|
||||
* o: [I(d,d) 0 ]
|
||||
* [ 0 a(d,m:d,n)]
|
||||
*/
|
||||
static inline void float_mat_minor(float **o, float **a, int m, int n, int d)
|
||||
static inline void float_mat_minor(float **o, float **a, const int m, const int n, const int d)
|
||||
{
|
||||
int i, j;
|
||||
float_mat_zero(o, m, n);
|
||||
@@ -844,7 +850,7 @@ static inline void float_mat_minor(float **o, float **a, int m, int n, int d)
|
||||
}
|
||||
|
||||
/** o = I - v v^T */
|
||||
static inline void float_mat_vmul(float **o, float *v, int n)
|
||||
static inline void float_mat_vmul(float **o, const float *v, const int n)
|
||||
{
|
||||
int i, j;
|
||||
for (i = 0; i < n; i++) {
|
||||
@@ -858,7 +864,7 @@ static inline void float_mat_vmul(float **o, float *v, int n)
|
||||
}
|
||||
|
||||
/** o = c-th column of matrix a[m x n] */
|
||||
static inline void float_mat_col(float *o, float **a, int m, int c)
|
||||
static inline void float_mat_col(float *o, float **a, const int m, const int c)
|
||||
{
|
||||
int i;
|
||||
for (i = 0; i < m; i++) {
|
||||
@@ -867,7 +873,7 @@ static inline void float_mat_col(float *o, float **a, int m, int c)
|
||||
}
|
||||
|
||||
/** Make an n x n identity matrix (for matrix passed as array) */
|
||||
static inline void float_mat_diagonal_scal(float **o, float v, int n)
|
||||
static inline void float_mat_diagonal_scal(float **o, float v, const int n)
|
||||
{
|
||||
int i, j;
|
||||
for (i = 0 ; i < n; i++) {
|
||||
@@ -883,41 +889,40 @@ static inline void float_mat_diagonal_scal(float **o, float v, int n)
|
||||
|
||||
|
||||
/** Divide a matrix by a scalar */
|
||||
static inline void float_mat_div_scalar(float **o, float **a, float scalar, int m, int n)
|
||||
static inline void float_mat_div_scalar(float **o, float **a, const float scalar, const int m, const int n)
|
||||
{
|
||||
int i, j;
|
||||
for (i = 0; i < m; i++) {
|
||||
for (j = 0; j < n; j++) {
|
||||
o[i][j] = a[i][j] / scalar;
|
||||
}
|
||||
}
|
||||
int i, j;
|
||||
for (i = 0; i < m; i++) {
|
||||
for (j = 0; j < n; j++) {
|
||||
o[i][j] = a[i][j] / scalar;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/** Multiply a matrix by a scalar */
|
||||
static inline void float_mat_mul_scalar(float **o, float **a, float scalar, int m, int n)
|
||||
static inline void float_mat_mul_scalar(float **o, float **a, const float scalar, const int m, const int n)
|
||||
{
|
||||
int i, j;
|
||||
for (i = 0; i < m; i++) {
|
||||
for (j = 0; j < n; j++) {
|
||||
o[i][j] = a[i][j] * scalar;
|
||||
}
|
||||
}
|
||||
int i, j;
|
||||
for (i = 0; i < m; i++) {
|
||||
for (j = 0; j < n; j++) {
|
||||
o[i][j] = a[i][j] * scalar;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
extern bool float_mat_inv_2d(float inv_out[4], float mat_in[4]);
|
||||
extern void float_mat2_mult(struct FloatVect2 *vect_out, float mat[4], struct FloatVect2 vect_in);
|
||||
extern bool float_mat_inv_3d(float inv_out[3][3], float mat_in[3][3]);
|
||||
extern void float_mat3_mult(struct FloatVect3 *vect_out, float mat[3][3], struct FloatVect3 vect_in);
|
||||
extern bool float_mat_inv_4d(float invOut[4][4], float mat_in[4][4]);
|
||||
|
||||
extern void float_vect3_bound_in_2d(struct FloatVect3 *vect3, float bound);
|
||||
extern void float_vect3_bound_in_3d(struct FloatVect3 *vect3, float bound);
|
||||
extern void float_vect3_scale_in_2d(struct FloatVect3 *vect3, float norm_des);
|
||||
extern void float_vect2_bound_in_2d(struct FloatVect2 *vect2, float bound);
|
||||
extern void float_vect2_scale_in_2d(struct FloatVect2 *vect2, float norm_des);
|
||||
extern bool float_mat_inv_2d(float inv_out[4], const float mat_in[4]);
|
||||
extern void float_mat2_mult(struct FloatVect2 *vect_out, const float mat[4], const struct FloatVect2 vect_in);
|
||||
extern bool float_mat_inv_3d(float inv_out[3][3], const float mat_in[3][3]);
|
||||
extern void float_mat3_mult(struct FloatVect3 *vect_out, const float mat[3][3], const struct FloatVect3 vect_in);
|
||||
extern bool float_mat_inv_4d(float invOut[4][4], const float mat_in[4][4]);
|
||||
|
||||
extern void float_vect3_bound_in_2d(struct FloatVect3 *vect3, const float bound);
|
||||
extern void float_vect3_bound_in_3d(struct FloatVect3 *vect3, const float bound);
|
||||
extern void float_vect3_scale_in_2d(struct FloatVect3 *vect3, const float norm_des);
|
||||
extern void float_vect2_bound_in_2d(struct FloatVect2 *vect2, const float bound);
|
||||
extern void float_vect2_scale_in_2d(struct FloatVect2 *vect2, const float norm_des);
|
||||
#ifdef __cplusplus
|
||||
} /* extern "C" */
|
||||
#endif
|
||||
|
||||
@@ -1097,6 +1097,14 @@ static inline struct Int32Vect3 *stateGetAccelBody_i(void)
|
||||
}
|
||||
/** @}*/
|
||||
|
||||
static inline struct FloatVect3 *stateGetAccelBody_f(void)
|
||||
{
|
||||
static struct FloatVect3 body_accel_f;
|
||||
body_accel_f.x = FLOAT_OF_BFP(state.body_accel_i.x, INT32_ACCEL_FRAC);
|
||||
body_accel_f.y = FLOAT_OF_BFP(state.body_accel_i.y, INT32_ACCEL_FRAC);
|
||||
body_accel_f.z = FLOAT_OF_BFP(state.body_accel_i.z, INT32_ACCEL_FRAC);
|
||||
return &body_accel_f;
|
||||
}
|
||||
|
||||
|
||||
/******************************************************************************
|
||||
|
||||
+22
-21
@@ -31,7 +31,7 @@
|
||||
#include <math.h>
|
||||
|
||||
#ifdef SITL
|
||||
#include <stdio.h> // for debuging in simulation
|
||||
#include <stdio.h> // for debuging in simulation
|
||||
#endif
|
||||
|
||||
/* some convenience macros to print debug/config messages at compile time */
|
||||
@@ -44,46 +44,46 @@
|
||||
#define PTR(_f) &_f
|
||||
|
||||
#ifndef FALSE
|
||||
#define FALSE false
|
||||
#define FALSE false
|
||||
#endif
|
||||
#ifndef TRUE
|
||||
#define TRUE true
|
||||
#define TRUE true
|
||||
#endif
|
||||
|
||||
#ifndef NULL
|
||||
#ifdef __cplusplus
|
||||
#define NULL 0
|
||||
#else
|
||||
#define NULL ((void *)0)
|
||||
#endif
|
||||
#ifdef __cplusplus
|
||||
#define NULL 0
|
||||
#else
|
||||
#define NULL ((void *)0)
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/* Unit (void) values */
|
||||
typedef uint8_t unit_t;
|
||||
|
||||
#ifndef M_PI
|
||||
#define M_PI 3.14159265358979323846
|
||||
#define M_PI 3.14159265358979323846
|
||||
#endif
|
||||
|
||||
#ifndef M_PI_6
|
||||
#define M_PI_6 (M_PI/6)
|
||||
#define M_PI_6 (M_PI/6)
|
||||
#endif
|
||||
|
||||
#ifndef M_PI_4
|
||||
#define M_PI_4 (M_PI/4)
|
||||
#define M_PI_4 (M_PI/4)
|
||||
#endif
|
||||
|
||||
#ifndef M_PI_2
|
||||
#define M_PI_2 (M_PI/2)
|
||||
#define M_PI_2 (M_PI/2)
|
||||
#endif
|
||||
|
||||
|
||||
#ifndef bit_is_set
|
||||
#define bit_is_set(x, b) ((x >> b) & 0x1)
|
||||
#define bit_is_set(x, b) ((x >> b) & 0x1)
|
||||
#endif
|
||||
|
||||
#ifndef _BV
|
||||
#define _BV(bit) (1 << (bit))
|
||||
#define _BV(bit) (1 << (bit))
|
||||
#endif
|
||||
|
||||
#define SetBit(a, n) a |= (1 << n)
|
||||
@@ -122,6 +122,7 @@ typedef uint8_t unit_t;
|
||||
#define DeciDegOfRad(x) ((x) * (1800./ M_PI))
|
||||
#define RadOfDeg(x) ((x) * (M_PI/180.))
|
||||
#define RadOfDeciDeg(x) ((x) * (M_PI/1800.))
|
||||
#define RadOfCentiDeg(x) ((x) * (M_PI/18000.))
|
||||
|
||||
#define MOfCm(_x) (((float)(_x))/100.)
|
||||
#define MOfMm(_x) (((float)(_x))/1000.)
|
||||
@@ -134,7 +135,7 @@ typedef uint8_t unit_t;
|
||||
#define MoreThan(_x, _y) ((_x) > (_y))
|
||||
|
||||
#ifndef ABS
|
||||
#define ABS(val) ((val) < 0 ? -(val) : (val))
|
||||
#define ABS(val) ((val) < 0 ? -(val) : (val))
|
||||
#endif
|
||||
|
||||
#define BoundUpper(_x, _max) { if (_x > (_max)) _x = (_max);}
|
||||
@@ -270,17 +271,17 @@ static inline bool str_equal(const char *a, const char *b)
|
||||
}
|
||||
|
||||
#ifdef __GNUC__
|
||||
# define UNUSED __attribute__((__unused__))
|
||||
# define WEAK __attribute__((weak))
|
||||
#define UNUSED __attribute__((__unused__))
|
||||
#define WEAK __attribute__((weak))
|
||||
#else
|
||||
# define UNUSED
|
||||
# define WEAK
|
||||
#define UNUSED
|
||||
#define WEAK
|
||||
#endif
|
||||
|
||||
#if __GNUC__ >= 7
|
||||
# define INTENTIONAL_FALLTHRU __attribute__ ((fallthrough));
|
||||
#define INTENTIONAL_FALLTHRU __attribute__ ((fallthrough));
|
||||
#else
|
||||
# define INTENTIONAL_FALLTHRU
|
||||
#define INTENTIONAL_FALLTHRU
|
||||
#endif
|
||||
|
||||
#endif /* STD_H */
|
||||
|
||||
Reference in New Issue
Block a user