branch for tests with T265

Dependencies:   Lib_Cntrl AHRS Lib_Misc

Revision:
0:a479dc61e931
Child:
1:d8c9f6b16279
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Sources/main.cpp	Wed Oct 02 15:31:12 2019 +0000
@@ -0,0 +1,478 @@
+#define PI 3.141592653589793
+#include "mbed.h"
+#define _MBED_
+#include "LinearCharacteristics.h"
+#include "UAV.h"
+#include "RCin.h"
+#include "define_constants.h"
+#include "PID_Cntrl.h"
+#include "IIR_filter.h"
+#include "data_structs.h"
+#include "Signal.h"
+#include "data_logger.h"
+#include "RangeFinder.h"
+#include "AHRS.h"
+#include "PX4Flow.h"
+#include "TFmini.h"
+
+// ----------------------------------------------------------------------------
+// ----------------------------------------------------------------------------
+// define IOs
+Serial pc(SERIAL_TX, SERIAL_RX,115200);        // serial connection via USB - programmer
+RawSerial uart4lidar(PA_0, PA_1);
+PwmOut motor_pwms[4];
+motor_pwms[0] = new PwmOut(PC_6);
+motor_pwms[1] = new PwmOut(PC_8);
+motor_pwms[2] = new PwmOut(PB_14);
+motor_pwms[3] = new PwmOut(PB_9);
+// ----------------------------------------------------------------------------
+RCin myRC(PB_6);                // read PWM of RC (Graupner Hott)
+// ----------------------------------------------------------------------------
+// Ultrasonic Range finder (US), read up to 4 signals 
+RangeFinder rf(PA_10, PB_3, PB_5, PB_4 , 10, 5782.0, 0.02, 12000); // 20 Hz parametrization
+TFmini tfmini(uart4lidar);
+// ----------------------------------------------------------------------------
+// PX4 Optical flow (OF), use same i2c like imu
+I2C i2c(PC_9, PA_8);
+PX4Flow optical_flow(i2c);
+// -----------------------------------------------------------------------------
+// Timers
+Timer global_timer;             // in main loop
+// -----------------------------------------------------------------------------
+// The copter!
+UAV copter(QUAD2,AIRGEAR350);
+
+// -----------------------------------------------------------------------------
+// Characteristic for thrust, 
+//LinearCharacteristics PM1_2_F_Thrust;       // map +-1 to Thrust
+float PM1_2_F_Thrust(float);    // replace linear char. with nonlinear below
+
+// -----------------------------------------------------------------------------
+// States and communication
+char Message[150];
+
+// -----------------------------------------------------------------------------
+// sample rates
+float Ts200 = 0.005f;
+float Ts100 = 0.01f;
+float Ts50 = 0.02f;
+float Ts25 = 0.04f;
+float Ts10 = 0.1f;
+float Ts4 = 0.25f;
+// -----------------------------------
+float TsCntrl = Ts200;
+float TsSDLog = Ts50;
+// -----------------------------------
+// some stuff
+float Mxy_limit = 0.0f;
+uint8_t CS=INIT;                // for main state machine
+float motorspeed[8];            // motor speeds in rad/sec
+AHRS ahrs(1,Ts100,true);        // ahrs filter, 1=EKF,,true=do recalibration of imu
+
+float Kv = 4.0;
+// -----------------------------------------------------------------------------
+// use pottis for scaling (temporarily)
+LinearCharacteristics map_pwm_2_P(864,1600,0.35,1.5);
+LinearCharacteristics map_pwm_2_I(864,1600,2.0, 8.0);
+LinearCharacteristics map_pwm_2_PX(864,1600,1.0, 4.0);  // RP-Winkelregler
+LinearCharacteristics map_pwm_2_scale(864,1600,1.0,2.0);
+
+// -----------------------------------------------------------------------------
+// my functions (below)
+void updateLoop(void);          // THE MAIN LOOP!!!!
+void motor_mix(float *,float ,float *);    // map torques Mx,My,Mz and thrust to motor speeds
+void read_US_OF_sensors(void);  // read extra sensors (low frequency)
+//
+void RPY_controller(float *, uint8_t , uint8_t, float *);   // the main controller for Stabilized and Acro mode
+// -----------------------------------------------------------------------------
+// - some extra functions
+float limit_minmax(float ,float ,float );
+float deadzone(float,float,float);
+void sendSignal_mainLoop(void);
+void sendSignal_read_US_OF_sensors(void);
+void sendSignal_Output(void);
+// -----------------------------------------------------------------------------
+// some values needed
+float dt;               // time elapsed in current state
+float Mxyz[3];          // torques
+float cur_pos[3];
+bool disarm_flag=false;
+bool flipm = false;     // used while arming motors
+float F_thrust;         // Thrust of motors
+float z_des = 0.0;
+// -----------------------------------------------------------------------------
+// ----------- MBED OS ----------------------------
+Thread thread_mainLoop(osPriorityNormal, 4096);
+Thread thread_read_US_OF_sensors(osPriorityBelowNormal, 4096);
+Thread thread_UAV_state(osPriorityLow, 4096);
+Thread thread_Output(osPriorityIdle, 4096);
+// Signals
+Signal signal_mainLoop;
+Signal signal_read_US_OF_sensors;
+Signal signal_read_OF_sensors;
+Signal signal_UAV_state;
+Signal signal_Output;
+// tickers
+Ticker mainLoop;                // Main loop at 100Hz
+Ticker US_OF_sensors_loop;
+Ticker UAV_state;               // check if UAV crashed / flying / landed etc.
+Ticker Output;             // Output loop at 4Hz (Writing and saving)
+
+// -----------------------------------------------------------------------------
+// data logger:
+data_logger my_logger(35);      // number shows # of logged data columns
+// -----------------------------------------------------------------------------
+//          MAIN     MAIN     MAIN     MAIN     MAIN     MAIN     MAIN     MAIN 
+// -----------------------------------------------------------------------------
+int main() {
+    i2c.frequency(400000);
+    att_cntrl.P_Roll = Kv;   // was 8      // p-controller different attitudes
+    att_cntrl.P_Pitch = Kv;
+    // --- initialize PWMS
+    wait(1);
+    uint32_t pwm_init_us = 500;
+    PWMOut1.period_ms(5);
+    PWMOut1.pulsewidth_us(pwm_init_us);
+    PWMOut2.period_ms(5);
+    PWMOut2.pulsewidth_us(pwm_init_us);
+    PWMOut3.period_ms(5);
+    PWMOut3.pulsewidth_us(pwm_init_us);
+    PWMOut4.period_ms(5);
+    PWMOut4.pulsewidth_us(pwm_init_us);
+    copter.calc_copter(myMotor);
+    myRC.map_Channels();
+    myRC.cou=0;
+    myMotor.calc_n2pwm_9k5();
+    //myMotor.calc_n2pwm_8k4();
+    global_timer.reset();
+    global_timer.start();
+    wait(1);
+    while(!myRC.isAlive) 
+        {
+        wait(.5);
+        pc.printf("Failed to receive RC - signal!\r\n");
+        }
+    pc.printf("RC - signal on!\r\n");
+    wait(.5);
+    if(1){
+        // start main threads:
+        thread_mainLoop.start(&updateLoop);
+        mainLoop.attach(&sendSignal_mainLoop, TsCntrl);
+        thread_read_US_OF_sensors.start(&read_US_OF_sensors);
+        US_OF_sensors_loop.attach(&sendSignal_read_US_OF_sensors,Ts50);
+        my_logger.start_logging(TsSDLog);
+        my_logger.pause_logging();
+        }
+}
+// -----------------------------------------------------------------------------
+// main loop with state handling and controllers
+// -----------------------------------------------------------------------------
+void updateLoop(void){
+    pc.printf("Start Main loop...\r\n");
+    bool flightmode_changed = false;
+    float old_dt=0;
+    uint8_t flm_temp = 1;
+    uint8_t flm_loc = 1;
+    float des_values[3];    // temporary variable for desired values
+    des_values[0]=0.0;    // temporary variable for desired values
+    des_values[1]=0.0;    // temporary variable for desired values
+    des_values[2]=0.0;    // temporary variable for desired values
+    while(1){
+        thread_mainLoop.signal_wait(signal_mainLoop);
+        old_dt = dt;
+        dt  = global_timer.read();              // time elapsed in current state
+        my_logger.data_vector[24] = dt - old_dt;    // time delta for analyses 
+        if(myRC.flightmode_changed){            // This is triggered bei RC-PWM readout
+            flm_temp = myRC.get_flightmode();
+            if(flm_temp == VEL_OF_Z_POS & optical_flow.avg_scaled_quality() <150) // do not change to that flightmode, if OF quality ist too low
+                {
+                 myRC.flightmode_changed = false;   // set flag back, but do nothing else! 
+                }
+            else{
+                flm_loc = flm_temp;
+                pc.printf("Changed FM to %d \r\n",flm_loc);
+                my_logger.data_vector[23]=(float)flm_loc;
+                myRC.flightmode_changed = false;
+                flightmode_changed = true;
+                }
+            }   
+        switch(CS)  {
+            case INIT:                      // at very beginning
+                if (dt > 5.0f && (myRC.PM1[1]<-0.9f) && (myRC.PM1[4]>0.9f)){
+                    CS = INIT_MOTORS;              // switch to FLAT state
+                    global_timer.reset(); 
+                    printf("INIT_MOTORS\r\n");
+                    }
+                    break;      // CS: INIT
+            case INIT_MOTORS:                      // 
+                if(dt < 2.0f && flipm){   // after 2 sec armed
+                    for(uint8_t m=1;m <= copter.nb_motors;m++)
+                        motorspeed[m]=100.0;
+                    flipm = false;     
+                    }
+                else if(dt < 2.0f){   // after 2 sec armed
+                    for(uint8_t m=1;m <= copter.nb_motors;m++)
+                        motorspeed[m]=0.0f;
+                    flipm = true; 
+                    }
+                else{
+                    CS = WAIT_ARMING;
+                    global_timer.reset();
+                    pc.printf("Motors initialized\r\n");
+                    }
+                break;      // CS: INIT_MOTORS
+            case WAIT_ARMING:                      // 
+                if(flm_loc == RTL)    // HACK!: update scaled Parameters
+                    {
+                    /*rate_cntrl_Roll.scale_PID_param(map_pwm_2_scale(myRC.pwms[10]));
+                    rate_cntrl_Pitch.scale_PID_param(map_pwm_2_scale(myRC.pwms[10]));
+                    att_cntrl.P_Roll = map_pwm_2_scale(myRC.pwms[11]) * Kv;
+                    att_cntrl.P_Pitch = map_pwm_2_scale(myRC.pwms[11]) * Kv;*/
+                    my_logger.continue_logging();
+                    }
+                if((myRC.PM1[1] < -.9) && (myRC.PM1[4]>0.9f) ){      // use CH1 (Roll) and CH4 (Yaw) to arm (stick to middle)
+                    CS = ARMING;
+                    my_logger.continue_logging();
+                    pc.printf("Rate Cntrl P: %2.3f\r\n",rate_cntrl_Roll.get_P_gain());
+                    pc.printf("Att Cntrl P: %2.3f\r\n",att_cntrl.P_Roll);
+                    global_timer.reset();
+                    }
+                break;      // CS: WAIT_ARMING
+            case ARMING:                      // 
+                if((myRC.PM1[1] >= -.9) || (myRC.PM1[4]<.9f)){
+                    CS = WAIT_ARMING;
+                    global_timer.reset();
+                    }
+                else if(dt > 1.0f){   // after 1 sec armed
+                    CS = START_MOTORS;
+                    global_timer.reset();
+                    pc.printf("Armed, start motors at %3.0f rad/s \r\n",copter.static_thrust_n*0.1f);
+                    }
+                break;      // CS: ARMING
+            case START_MOTORS:                      // 
+                for(uint8_t m=1;m <= copter.nb_motors;m++)
+                    motorspeed[m]=copter.static_thrust_n*0.1f;
+                if (dt > 1.5f){
+                    CS = FLIGHT;
+                    global_timer.reset();
+                    Mxy_limit = copter.max_Mxy;        
+                    rate_cntrl_Roll.reset(0.0);
+                    rate_cntrl_Roll.set_limits(-Mxy_limit,Mxy_limit);
+                    rate_cntrl_Pitch.reset(0.0);
+                    rate_cntrl_Pitch.set_limits(-Mxy_limit,Mxy_limit);
+                    // rate_cntrl_Roll_rolloff.reset(0.0);
+                    // rate_cntrl_Pitch_rolloff.reset(0.0);
+                    rate_cntrl_Yaw.reset(0.0);
+                    rate_cntrl_Yaw.set_limits(-copter.max_Mz,copter.max_Mz);
+                    pos_cntrl_z.reset(0.0);
+                    z_des = 0.0;
+                    }
+                break;      // CS: START_MOTORS
+            case FLIGHT:
+                // 2nd SWITCH-CASE
+                switch(flm_loc){
+                    case STABILIZED:         // STABILIZED: Control RP-Angles with Sticks, Yaw-Rate with Sticks, Thrust with Sticks
+                        des_values[0] = myRC.PM1[1] * 0.5f; // +- 1 correspond to +-0.5 rad desired angle 
+                        des_values[1] = myRC.PM1[2] * 0.5f; // +- 1 correspond to +-0.5 rad desired angle
+                        des_values[2] = -myRC.PM1[4]* 0.8f;//integrate_CH4_2_yaw_angle(myRC.PM1[4]);; // integrate +- 1 to yaw angle
+                        F_thrust = PM1_2_F_Thrust(myRC.PM1[3]);    // desired thrust
+                        RPY_controller(des_values, 1,1,Mxyz);
+                        break;      // flm_loc: STABILIZED
+                    case ACRO:       // ACRO: Control Rates with sticks, Thrust with Sticks
+                        des_values[0] = myRC.PM1[1]*2.5f; // +- 1 correspond to +-1 rad/s desired rate
+                        des_values[1] = myRC.PM1[2]*2.5f; // +- 1 correspond to +-1 rad/s desired rate
+                        des_values[2] = -myRC.PM1[4]*1.5f; // +- 1 correspond to +-1 rad/s desired rate
+                        F_thrust = PM1_2_F_Thrust(myRC.PM1[3]);    // desired thrust
+                        RPY_controller(des_values, 0,1,Mxyz);
+                        break;      // flm_loc: ACRO
+                    case ALT_HOLD:   // Altitde Hold (with US Sensor)
+                        if(flightmode_changed){
+                            cur_pos[2] = ahrs.xyzUS[2];
+                            pos_cntrl_z.reset(F_thrust);
+                            flightmode_changed = false;
+                    //        pc.printf("Initialized z:%1.3f\r\n",cur_pos[2]);
+                            }
+                        des_values[0] = myRC.PM1[1] * 0.5f; // +- 1 correspond to +-0.5 rad desired angle 
+                        des_values[1] = myRC.PM1[2] * 0.5f; // +- 1 correspond to +-0.5 rad desired angle
+                        des_values[2] = -myRC.PM1[4]* 0.8f; //integrate_CH4_2_yaw_angle(myRC.PM1[4]);; // integrate +- 1 to yaw angle
+    //                    cur_pos[2] += 0.8 * TsCntrl * deadzone(myRC.PM1[3],-0.15,0.15); 
+    //                    cur_pos[2] = limit_minmax(cur_pos[2],-1.0,0.8);
+                        //F_thrust = pos_cntrl_z(cur_pos[2] - ahrs.xyzUS[2]);
+                        F_thrust = pos_cntrl_z(0.8f - ahrs.xyzLIDAR[2]);  // use fixed value here and use analog Sensor
+                        RPY_controller(des_values, 1,1,Mxyz);
+                        break;      // flm_loc: ALT_HOLD
+                    case VEL_OF_Z_POS:       // This is the velocity mode with optical flow sensor
+                        if(flightmode_changed){
+                            vel_cntrl_x.reset(0.0);
+                            vel_cntrl_y.reset(0.0);
+                            // pos_cntrl_z.reset(F_thrust);     // carfull!!! only valid if this state comes from ALT_HOLD
+                            flightmode_changed = false;
+                            }
+                        des_values[1] = vel_cntrl_x(1.5f * myRC.PM1[2] - ahrs.v_xyzOF[0]);    // Pitchachse: korrekt: positices pitchen führt zu Bewegung in +x
+                        des_values[0] = -vel_cntrl_y(-1.5f * myRC.PM1[1] - ahrs.v_xyzOF[1]);;    // Rollachse: Diese ist gedreht: Positives Rollen fuehrt zu Bewegung -y, Hebel nach recht ebenfalls!!!
+                        des_values[2] = -myRC.PM1[4]* 0.8f;
+                        F_thrust = pos_cntrl_z(0.8f - ahrs.xyzLIDAR[2]);  // use fixed value here and use analog Sensor
+                        RPY_controller(des_values, 1,1,Mxyz);
+                        break;      // flm_loc: VEL_OF_Z_POS
+                    default: break;
+                    }       // end of switch(flm_loc)
+                // ... continue FLIGHT case
+                motor_mix(Mxyz,F_thrust,motorspeed);    // MAp TOrques to Motor speeds
+                if((myRC.PM1[1] > 0.8f) && (myRC.PM1[4]<-0.8f) && (myRC.PM1[3]<-0.8f) && disarm_flag == false){      // use CH1 (Roll) and CH4 (Yaw) to disarm (stick to leftright)
+                    disarm_flag=true;
+                    global_timer.reset();
+                    }
+                if(disarm_flag == true && dt > 0.8f){
+                    disarm_flag=false;
+                    global_timer.reset();
+                    CS = MOTOR_STOPPED;
+                    my_logger.pause_logging();
+                    pc.printf("UAV disarmed\r\n");
+                    }
+                break;  // case FLIGHT
+            case MOTOR_STOPPED:
+                for(uint8_t m=1;m <= copter.nb_motors;m++)
+                    motorspeed[m]=0.0f;
+                if(dt>1){
+                    global_timer.reset();
+                    CS = WAIT_ARMING;
+                    }   // case MOTOR_STOPPED
+                break;
+        default: break;
+        }           // end of switch(CS)
+        // ------- Datalogger
+        my_logger.data_vector[15] = Mxyz[0];
+        my_logger.data_vector[16] = Mxyz[1];
+        my_logger.data_vector[17] = Mxyz[2];
+        my_logger.data_vector[18]=F_thrust;
+        my_logger.data_vector[19]=motorspeed[1];
+        my_logger.data_vector[20]=motorspeed[2];
+        my_logger.data_vector[21]=motorspeed[3];
+        my_logger.data_vector[22]=motorspeed[4];
+        my_logger.data_vector[25]=des_values[0];
+        my_logger.data_vector[26]=des_values[1];
+        my_logger.data_vector[27]=des_values[2];
+ //       pc.printf("%3.3f %3.3f %3.3f \r\n",des_values[0],des_values[1],des_values[2]);
+        }   // of while(1) (the thread)
+}
+//-----------------------------------------------------------------------------
+// Read Ultrasonic range finder Sensors (via PWM) and Optcal Flow Sensors
+// WARNING: US-Sensors interfere each other, thus the sensorw are read sequentially
+void read_US_OF_sensors(void){
+    while(1)
+    {
+        thread_read_US_OF_sensors.signal_wait(signal_read_US_OF_sensors);
+        /*
+        rf.read_and_filter(rf.current_sensor++);
+        if(rf.current_sensor >= rf.n_sensors)   // loop over 4 Sensors from step to step.(only 1/4 sampling rate)
+            rf.current_sensor = 0;
+        //for(uint8_t k=0;k<rf.n_sensors;k++)printf("S%d: %1.3f ",k,rf.val[k]);printf("\r\n");
+        ahrs.xyzUS[0] = 1.0f-(rf.val[2]+rf.val[3])/2; // mind x positive! If Sensors measure larger distance, it is towards -x !!!
+                    // distance 1m is the origin!
+        ahrs.xyzUS[1] = rf.val[1]; // larger position of sensor 1 means +y (correct direction)             
+        ahrs.xyzUS[2] = rf.val[0]; // z-sensor
+        ahrs.rxryrzUS[2] = (rf.val[3]-rf.val[2])/0.4;   // Yaw axis
+        my_logger.data_vector[18]=rf.val[0];
+        */
+        ahrs.xyzAS[2] = 2.311f *exp(-6.5514f*ai1.read())+0.2017f;
+        ahrs.xyzLIDAR[2] = tfmini()*0.001f;
+        my_logger.data_vector[14]=ahrs.xyzLIDAR[2];
+        //my_logger.data_vector[22]=ahrs.xyzAS[2];
+        if(optical_flow.update_integral()) {
+            ahrs.v_xyzOF[0]= vel_cntrl_x_rolloff(-optical_flow.avg_flowx()*0.001f + ahrs.raw_gy2gy(ahrs.imu.gyroY) * ahrs.xyzLIDAR[2]);
+            ahrs.v_xyzOF[1]= vel_cntrl_y_rolloff( optical_flow.avg_flowy()*0.001f - ahrs.raw_gx2gx(ahrs.imu.gyroX) * ahrs.xyzLIDAR[2]);
+            ahrs.xyzOF[2]= 0.0f;//((float)optical_flow.ground_distance())*0.001f;         
+            my_logger.data_vector[10]=ahrs.v_xyzOF[0];
+            my_logger.data_vector[11]=ahrs.v_xyzOF[1];
+            my_logger.data_vector[13]=(float)optical_flow.avg_scaled_quality();
+            my_logger.data_vector[28]=optical_flow.gyro_x_rate();
+            my_logger.data_vector[29]=optical_flow.gyro_y_rate();
+            my_logger.data_vector[30]=optical_flow.gyro_z_rate();
+            }
+        }
+}
+
+
+/* ****************************************************************************
+void RPY_controller(float *des_values, uint8_t rate_and_att,float* Mxyz){
+ Roll/Pitch/Yaw Controller,
+ INPUT:
+        des_values      desired angle ( mode stabilized aso), rotation rates (acro) 
+        rate_and_att    logic for flight mode (1 = cascade control)
+        *Mxyz           resulting values
+***************************************************************************** */ 
+void RPY_controller(float *des_values, uint8_t rate_and_att,uint8_t filtertype,float* Mxyz){
+    float rate_des[4];        
+//--------------------------------       
+    if(rate_and_att ==1){       // this is for Mode STABILIZED (and Loiter aso)
+            rate_des[1] = att_cntrl.P_Roll * (des_values[0] - ahrs.getRoll(filtertype)); 
+            rate_des[2] = att_cntrl.P_Pitch * (des_values[1] - ahrs.getPitch(filtertype));
+            rate_des[3] = des_values[2];//att_cntrl.P_Yaw * (des_values[2] - ahrs.getYawRadians());
+            }
+    else{                       // this is for Mode ACRO
+            rate_des[1] = des_values[0]; 
+            rate_des[2] = des_values[1]; 
+            rate_des[3] = des_values[2]; 
+        }
+    // Mxyz[0]= rate_cntrl_Roll_rolloff( rate_cntrl_Roll(rate_des[1] - ahrs.raw_gx2gx(ahrs.imu.gyroX)) );
+    // Mxyz[1]= rate_cntrl_Pitch_rolloff( rate_cntrl_Pitch(rate_des[2] - ahrs.raw_gy2gy(ahrs.imu.gyroY)) );
+    float gx = ahrs.raw_gx2gx(ahrs.imu.gyroX);
+    float gy = ahrs.raw_gy2gy(ahrs.imu.gyroY);
+    Mxyz[0]= rate_cntrl_Roll(rate_des[1] - gx, gx);
+    Mxyz[1]= rate_cntrl_Pitch(rate_des[2] - gy, gy);
+    Mxyz[2]= rate_cntrl_Yaw(rate_des[3] - ahrs.raw_gz2gz(ahrs.imu.gyroZ));
+    }
+// *****************************************************************************
+// *****************************************************************************
+float limit_minmax(float val,float mi,float ma){
+    if(val < mi)
+        val = mi;
+    if(val > ma)
+        val = ma;
+    return val;
+}
+
+// *****************************************************************************
+// Dead zone, from lo ... hi
+float deadzone(float x,float lo,float hi){
+return (x>hi)*(x-hi)+(x<lo)*(x-lo);
+}
+
+// *****************************************************************************
+// nonlinear characteristics for thrust
+float PM1_2_F_Thrust(float x)
+{
+    return 9.81f*copter.weight*(0.5f*x+1.1f - 0.06f/(x+1.1f));         // y=0.5*x+1.1-0.06./(x+1.1);
+}
+   
+
+void sendSignal_mainLoop(void){
+    thread_mainLoop.signal_set(signal_mainLoop);
+}
+void sendSignal_read_US_OF_sensors(void){
+    thread_read_US_OF_sensors.signal_set(signal_read_US_OF_sensors);
+}
+
+void sendSignal_UAV_state(void){
+    thread_UAV_state.signal_set(signal_UAV_state);
+}
+void sendSignal_Output(void){
+    thread_Output.signal_set(signal_Output);
+}
+
+/*
+Thread thread_mainLoop(osPriorityNormal, 4096);
+Thread thread_AHRS(osPriorityBelowNormal, 4096);
+Thread thread_UAV_state(osPriorityLow, 4096);
+Thread thread_Output(osPriorityIdle, 4096);
+
+Signal signal_mainLoop;
+Signal signal_AHRS;
+Signal signal_UAV_state;
+Signal signal_Output;
+
+Ticker AHRS;                   // Madgwick filter for AHRS
+Ticker mainLoop;                // Main loop at 200Hz
+Ticker UAV_state;               // check if UAV crashed / flying / landed etc.
+Ticker Output;             // Output loop at 10Hz (Writing and saving
+*/
\ No newline at end of file