Copter: merge the latest 2.9 changes into master
This commit is contained in:
parent
c9fe7fe932
commit
860f4b2605
@ -375,12 +375,21 @@ static struct AP_System{
|
||||
uint8_t nav_ok : 1; // 4 // deprecated
|
||||
uint8_t CH7_flag : 1; // 5 // manages state of the ch7 toggle switch
|
||||
uint8_t usb_connected : 1; // 6 // true if APM is powered from USB connection
|
||||
uint8_t run_50hz_loop : 1; // 7 // toggles the 100hz loop for 50hz
|
||||
uint8_t alt_sensor_flag : 1; // 8 // used to track when to read sensors vs estimate alt
|
||||
uint8_t yaw_stopped : 1; // 9 // Used to manage the Yaw hold capabilities
|
||||
uint8_t alt_sensor_flag : 1; // 7 // used to track when to read sensors vs estimate alt
|
||||
uint8_t yaw_stopped : 1; // 8 // Used to manage the Yaw hold capabilities
|
||||
|
||||
} ap_system;
|
||||
|
||||
/*
|
||||
what navigation updated are needed
|
||||
*/
|
||||
static struct nav_updates {
|
||||
uint8_t need_velpos : 1;
|
||||
uint8_t need_dist_bearing : 1;
|
||||
uint8_t need_nav_controllers : 1;
|
||||
uint8_t need_nav_pitch_roll : 1;
|
||||
} nav_updates;
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// velocity in lon and lat directions calculated from GPS position and accelerometer data
|
||||
@ -448,6 +457,8 @@ MOTOR_CLASS motors(&g.rc_1, &g.rc_2, &g.rc_3, &g.rc_4);
|
||||
static Vector3f omega;
|
||||
// This is used to hold radio tuning values for in-flight CH6 tuning
|
||||
float tuning_value;
|
||||
// used to limit the rate that the pid controller output is logged so that it doesn't negatively affect performance
|
||||
static uint8_t pid_log_counter;
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// LED output
|
||||
@ -814,14 +825,10 @@ static int16_t gps_fix_count;
|
||||
// --------------
|
||||
// Time in microseconds of main control loop
|
||||
static uint32_t fast_loopTimer;
|
||||
// Time in microseconds of 50hz control loop
|
||||
static uint32_t fiftyhz_loopTimer;
|
||||
// Counters for branching from 10 hz control loop
|
||||
static uint8_t medium_loopCounter;
|
||||
// Counters for branching from 3 1/3hz control loop
|
||||
static uint8_t slow_loopCounter;
|
||||
// Counters for branching at 1 hz
|
||||
static uint8_t counter_one_herz;
|
||||
// Counter of main loop executions. Used for performance monitoring and failsafe processing
|
||||
static uint16_t mainLoop_count;
|
||||
// Delta Time in milliseconds for navigation computations, updated with every good GPS read
|
||||
@ -928,15 +935,130 @@ void setup() {
|
||||
}
|
||||
|
||||
/*
|
||||
return true if the main loop is ready to run. This is used by
|
||||
potentially expensive functions that are not timing critical, to
|
||||
defer the expensive processing until after the main loop has run.
|
||||
if the compass is enabled then try to accumulate a reading
|
||||
*/
|
||||
static bool main_loop_ready(void)
|
||||
static void compass_accumulate(void)
|
||||
{
|
||||
return ins.num_samples_available() >= 2;
|
||||
if (g.compass_enabled) {
|
||||
compass.accumulate();
|
||||
}
|
||||
}
|
||||
|
||||
// enable this to get console logging of scheduler performance
|
||||
#define SCHEDULER_DEBUG 0
|
||||
|
||||
static void perf_update(void)
|
||||
{
|
||||
if (g.log_bitmask & MASK_LOG_PM)
|
||||
Log_Write_Performance();
|
||||
#if SCHEDULER_DEBUG
|
||||
cliSerial->printf_P(PSTR("PERF: %u/%u %lu\n"),
|
||||
(unsigned)perf_info_get_num_long_running(),
|
||||
(unsigned)perf_info_get_num_loops(),
|
||||
(unsigned long)perf_info_get_max_time());
|
||||
#endif
|
||||
perf_info_reset();
|
||||
gps_fix_count = 0;
|
||||
}
|
||||
|
||||
/*
|
||||
return number of micros until the main loop will want to run again
|
||||
*/
|
||||
static int16_t main_loop_time_available(void)
|
||||
{
|
||||
uint32_t dt = (micros() - fast_loopTimer);
|
||||
if (dt > 10000) {
|
||||
return 0;
|
||||
}
|
||||
return 10000 - dt;
|
||||
}
|
||||
|
||||
typedef void (*event_fn_t)(void);
|
||||
|
||||
struct timer_event_table {
|
||||
event_fn_t func;
|
||||
uint16_t time_interval_10ms;
|
||||
uint16_t min_time_usec;
|
||||
};
|
||||
|
||||
#define NUM_TIMER_EVENTS 14
|
||||
|
||||
/*
|
||||
scheduler table - all regular events apart from the fast_loop()
|
||||
should be listed here, along with how often they should be called
|
||||
(in 10ms units) and the maximum time they are expected to take
|
||||
*/
|
||||
static const struct timer_event_table PROGMEM timer_events[NUM_TIMER_EVENTS] = {
|
||||
{ update_GPS, 2, 900 },
|
||||
{ update_navigation, 2, 500 },
|
||||
{ medium_loop, 2, 700 },
|
||||
{ update_altitude_est, 2, 900 },
|
||||
{ fifty_hz_loop, 2, 800 },
|
||||
{ run_nav_updates, 2, 500 },
|
||||
{ slow_loop, 10, 500 },
|
||||
{ gcs_check_input, 2, 700 },
|
||||
{ gcs_send_heartbeat, 100, 700 },
|
||||
{ gcs_data_stream_send, 2, 1100 },
|
||||
{ gcs_send_deferred, 2, 700 },
|
||||
{ compass_accumulate, 2, 600 },
|
||||
{ super_slow_loop, 100, 1100 },
|
||||
{ perf_update, 1000, 500 }
|
||||
};
|
||||
static uint16_t timer_counters[NUM_TIMER_EVENTS];
|
||||
|
||||
static uint16_t tick_counter;
|
||||
static uint32_t event_time_started;
|
||||
static uint16_t event_time_allowed;
|
||||
|
||||
/*
|
||||
return number of micros until the current event reaches its deadline
|
||||
*/
|
||||
static uint16_t event_time_available(void)
|
||||
{
|
||||
uint32_t dt = micros() - event_time_started;
|
||||
if (dt > event_time_allowed) {
|
||||
return 0;
|
||||
}
|
||||
return event_time_allowed - dt;
|
||||
}
|
||||
|
||||
/*
|
||||
run as many scheduler events as we can
|
||||
*/
|
||||
static void run_events(uint16_t time_available_usec)
|
||||
{
|
||||
for (uint8_t i=0; i<NUM_TIMER_EVENTS; i++) {
|
||||
if (tick_counter - timer_counters[i] >= pgm_read_word(&timer_events[i].time_interval_10ms)) {
|
||||
// this event is due to run. Do we have enough time to run it?
|
||||
event_time_allowed = pgm_read_word(&timer_events[i].min_time_usec);
|
||||
if (event_time_allowed <= time_available_usec) {
|
||||
// run it
|
||||
event_time_started = micros();
|
||||
event_fn_t func = (event_fn_t)pgm_read_pointer(&timer_events[i].func);
|
||||
func();
|
||||
|
||||
// record the tick counter when we ran. This drives
|
||||
// when we next run the event
|
||||
timer_counters[i] = tick_counter;
|
||||
|
||||
// work out how long the event actually took
|
||||
uint32_t time_taken = micros() - event_time_started;
|
||||
|
||||
if (time_taken > event_time_allowed) {
|
||||
// the event overran!
|
||||
#if SCHEDULER_DEBUG
|
||||
cliSerial->printf_P(PSTR("overrun in event %u (%u/%u)\n"),
|
||||
(unsigned)i,
|
||||
(unsigned)time_taken,
|
||||
(unsigned)event_time_allowed);
|
||||
#endif
|
||||
return;
|
||||
}
|
||||
time_available_usec -= time_taken;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void loop()
|
||||
{
|
||||
@ -944,17 +1066,7 @@ void loop()
|
||||
|
||||
// We want this to execute fast
|
||||
// ----------------------------
|
||||
if (main_loop_ready()) {
|
||||
|
||||
#if 0
|
||||
uint16_t num_samples = ins.num_samples_available();
|
||||
static uint16_t counter;
|
||||
if (num_samples != 2 || (counter++ % 200 == 0)) {
|
||||
cliSerial->printf_P(PSTR("num_samples=%u dt=%u\n"),
|
||||
(unsigned)num_samples,
|
||||
(unsigned)(timer - fast_loopTimer));
|
||||
}
|
||||
#endif
|
||||
if (ins.num_samples_available() >= 2) {
|
||||
|
||||
#if DEBUG_FAST_LOOP == ENABLED
|
||||
Log_Write_Data(DATA_FAST_LOOP, (int32_t)(timer - fast_loopTimer));
|
||||
@ -963,8 +1075,8 @@ void loop()
|
||||
// check loop time
|
||||
perf_info_check_loop_time(timer - fast_loopTimer);
|
||||
|
||||
G_Dt = (float)(timer - fast_loopTimer) / 1000000.f; // used by PI Loops
|
||||
fast_loopTimer = timer;
|
||||
G_Dt = (float)(timer - fast_loopTimer) / 1000000.f; // used by PI Loops
|
||||
fast_loopTimer = timer;
|
||||
|
||||
// for mainloop failure monitoring
|
||||
mainLoop_count++;
|
||||
@ -973,68 +1085,20 @@ void loop()
|
||||
// ---------------------
|
||||
fast_loop();
|
||||
|
||||
// run the 50hz loop 1/2 the time
|
||||
ap_system.run_50hz_loop = !ap_system.run_50hz_loop;
|
||||
|
||||
if(ap_system.run_50hz_loop) {
|
||||
|
||||
#if DEBUG_MED_LOOP == ENABLED
|
||||
Log_Write_Data(DATA_MED_LOOP, (int32_t)(timer - fiftyhz_loopTimer));
|
||||
#endif
|
||||
|
||||
// store the micros for the 50 hz timer
|
||||
fiftyhz_loopTimer = timer;
|
||||
|
||||
// check for new GPS messages
|
||||
// --------------------------
|
||||
update_GPS();
|
||||
|
||||
// run navigation routines
|
||||
update_navigation();
|
||||
|
||||
// perform 10hz tasks
|
||||
// ------------------
|
||||
medium_loop();
|
||||
|
||||
// Stuff to run at full 50hz, but after the med loops
|
||||
// --------------------------------------------------
|
||||
fifty_hz_loop();
|
||||
|
||||
counter_one_herz++;
|
||||
|
||||
// trgger our 1 hz loop
|
||||
if(counter_one_herz >= 50) {
|
||||
super_slow_loop();
|
||||
counter_one_herz = 0;
|
||||
}
|
||||
perf_mon_counter++;
|
||||
if (perf_mon_counter >= 500 ) { // 500 iterations at 50hz = 10 seconds
|
||||
if (g.log_bitmask & MASK_LOG_PM)
|
||||
Log_Write_Performance();
|
||||
perf_info_reset();
|
||||
gps_fix_count = 0;
|
||||
perf_mon_counter = 0;
|
||||
}
|
||||
}else{
|
||||
// process communications with the GCS
|
||||
gcs_check();
|
||||
}
|
||||
tick_counter++;
|
||||
} else {
|
||||
if (timer - fast_loopTimer < 9000) {
|
||||
// we have some spare cycles available
|
||||
// less than 10ms has passed. We have at least one millisecond
|
||||
// of free time. The most useful thing to do with that time is
|
||||
// to accumulate some sensor readings, specifically the
|
||||
// compass, which is often very noisy but is not interrupt
|
||||
// driven, so it can't accumulate readings by itself
|
||||
if (g.compass_enabled) {
|
||||
compass.accumulate();
|
||||
}
|
||||
uint16_t time_to_next_loop;
|
||||
uint16_t dt = timer - fast_loopTimer;
|
||||
if (dt > 10000) {
|
||||
time_to_next_loop = 0;
|
||||
} else {
|
||||
time_to_next_loop = 10000 - dt;
|
||||
}
|
||||
run_events(time_to_next_loop);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
// Main loop - 100hz
|
||||
static void fast_loop()
|
||||
{
|
||||
@ -1078,6 +1142,7 @@ static void fast_loop()
|
||||
// update targets to rate controllers
|
||||
update_rate_contoller_targets();
|
||||
|
||||
// agmatthews - USERHOOKS
|
||||
#ifdef USERHOOK_FASTLOOP
|
||||
USERHOOK_FASTLOOP
|
||||
#endif
|
||||
@ -1178,6 +1243,7 @@ static void medium_loop()
|
||||
// -----------------------
|
||||
arm_motors();
|
||||
|
||||
// agmatthews - USERHOOKS
|
||||
#ifdef USERHOOK_MEDIUMLOOP
|
||||
USERHOOK_MEDIUMLOOP
|
||||
#endif
|
||||
@ -1185,8 +1251,6 @@ static void medium_loop()
|
||||
#if COPTER_LEDS == ENABLED
|
||||
update_copter_leds();
|
||||
#endif
|
||||
|
||||
slow_loop();
|
||||
break;
|
||||
|
||||
default:
|
||||
@ -1201,10 +1265,6 @@ static void medium_loop()
|
||||
// ---------------------------
|
||||
static void fifty_hz_loop()
|
||||
{
|
||||
// read altitude sensors or estimate altitude
|
||||
// ------------------------------------------
|
||||
update_altitude_est();
|
||||
|
||||
// Update the throttle ouput
|
||||
// -------------------------
|
||||
update_throttle_mode();
|
||||
@ -1307,6 +1367,7 @@ static void slow_loop()
|
||||
camera_mount2.update_mount_type();
|
||||
#endif
|
||||
|
||||
// agmatthews - USERHOOKS
|
||||
#ifdef USERHOOK_SLOWLOOP
|
||||
USERHOOK_SLOWLOOP
|
||||
#endif
|
||||
@ -1368,7 +1429,7 @@ static void super_slow_loop()
|
||||
static void update_optical_flow(void)
|
||||
{
|
||||
static uint32_t last_of_update = 0;
|
||||
static int log_counter = 0;
|
||||
static uint8_t of_log_counter = 0;
|
||||
|
||||
// if new data has arrived, process it
|
||||
if( optflow.last_update != last_of_update ) {
|
||||
@ -1376,9 +1437,9 @@ static void update_optical_flow(void)
|
||||
optflow.update_position(ahrs.roll, ahrs.pitch, cos_yaw_x, sin_yaw_y, current_loc.alt); // updates internal lon and lat with estimation based on optical flow
|
||||
|
||||
// write to log at 5hz
|
||||
log_counter++;
|
||||
if( log_counter >= 4 ) {
|
||||
log_counter = 0;
|
||||
of_log_counter++;
|
||||
if( of_log_counter >= 4 ) {
|
||||
of_log_counter = 0;
|
||||
if (g.log_bitmask & MASK_LOG_OPTFLOW) {
|
||||
Log_Write_Optflow();
|
||||
}
|
||||
@ -1772,16 +1833,21 @@ bool set_throttle_mode( uint8_t new_throttle_mode )
|
||||
case THROTTLE_MANUAL:
|
||||
case THROTTLE_MANUAL_TILT_COMPENSATED:
|
||||
throttle_accel_deactivate(); // this controller does not use accel based throttle controller
|
||||
altitude_error = 0; // clear altitude error reported to GCS
|
||||
throttle_initialised = true;
|
||||
break;
|
||||
|
||||
case THROTTLE_ACCELERATION: // pilot inputs the desired acceleration
|
||||
if( g.throttle_accel_enabled ) { // this throttle mode requires use of the accel based throttle controller
|
||||
altitude_error = 0; // clear altitude error reported to GCS
|
||||
throttle_initialised = true;
|
||||
}
|
||||
break;
|
||||
|
||||
case THROTTLE_RATE:
|
||||
altitude_error = 0; // clear altitude error reported to GCS
|
||||
throttle_initialised = true;
|
||||
break;
|
||||
case THROTTLE_STABILIZED_RATE:
|
||||
case THROTTLE_DIRECT_ALT:
|
||||
throttle_initialised = true;
|
||||
@ -1850,7 +1916,7 @@ void update_throttle_mode(void)
|
||||
}
|
||||
|
||||
#if FRAME_CONFIG == HELI_FRAME
|
||||
if (roll_pitch_mode == ROLL_PITCH_STABLE){
|
||||
if (control_mode == STABILIZE){
|
||||
motors.stab_throttle = true;
|
||||
} else {
|
||||
motors.stab_throttle = false;
|
||||
@ -1935,6 +2001,7 @@ void update_throttle_mode(void)
|
||||
if(g.rc_3.control_in <= 0){
|
||||
set_throttle_out(0, false);
|
||||
throttle_accel_deactivate(); // do not allow the accel based throttle to override our command
|
||||
altitude_error = 0; // clear altitude error reported to GCS - normally underlying alt hold controller updates altitude error reported to GCS
|
||||
}else{
|
||||
pilot_climb_rate = get_pilot_desired_climb_rate(g.rc_3.control_in);
|
||||
get_throttle_rate_stabilized(pilot_climb_rate);
|
||||
@ -1946,8 +2013,8 @@ void update_throttle_mode(void)
|
||||
if(g.rc_3.control_in <= 0){
|
||||
set_throttle_out(0, false);
|
||||
throttle_accel_deactivate(); // do not allow the accel based throttle to override our command
|
||||
altitude_error = 0; // clear altitude error reported to GCS - normally underlying alt hold controller updates altitude error reported to GCS
|
||||
}else{
|
||||
// To-Do: this should update the global desired altitude variable next_WP.alt
|
||||
int32_t desired_alt = get_pilot_desired_direct_alt(g.rc_3.control_in);
|
||||
get_throttle_althold(desired_alt, g.auto_velocity_z_min, g.auto_velocity_z_max);
|
||||
}
|
||||
@ -1991,7 +2058,7 @@ static void read_AHRS(void)
|
||||
//-----------------------------------------------
|
||||
#if HIL_MODE != HIL_MODE_DISABLED
|
||||
// update hil before ahrs update
|
||||
gcs_update();
|
||||
gcs_check_input();
|
||||
#endif
|
||||
|
||||
ahrs.update();
|
||||
|
@ -74,12 +74,11 @@ get_stabilize_yaw(int32_t target_angle)
|
||||
#endif
|
||||
|
||||
#if LOGGING_ENABLED == ENABLED
|
||||
static int8_t log_counter = 0; // used to slow down logging of PID values to dataflash
|
||||
// log output if PID logging is on and we are tuning the yaw
|
||||
if( g.log_bitmask & MASK_LOG_PID && (g.radio_tuning == CH6_YAW_KP || g.radio_tuning == CH6_YAW_RATE_KP) ) {
|
||||
log_counter++;
|
||||
if( log_counter >= 10 ) { // (update rate / desired output rate) = (100hz / 10hz) = 10
|
||||
log_counter = 0;
|
||||
if( g.log_bitmask & MASK_LOG_PID && g.radio_tuning == CH6_YAW_KP ) {
|
||||
pid_log_counter++;
|
||||
if( pid_log_counter >= 10 ) { // (update rate / desired output rate) = (100hz / 10hz) = 10
|
||||
pid_log_counter = 0;
|
||||
Log_Write_PID(CH6_YAW_KP, angle_error, target_rate, i_term, 0, output, tuning_value);
|
||||
}
|
||||
}
|
||||
@ -333,13 +332,11 @@ get_heli_rate_roll(int32_t target_rate)
|
||||
output = constrain(output, -4500, 4500);
|
||||
|
||||
#if LOGGING_ENABLED == ENABLED
|
||||
static int8_t log_counter = 0; // used to slow down logging of PID values to dataflash
|
||||
|
||||
// log output if PID logging is on and we are tuning the rate P, I or D gains
|
||||
if( g.log_bitmask & MASK_LOG_PID && (g.radio_tuning == CH6_RATE_KP || g.radio_tuning == CH6_RATE_KI || g.radio_tuning == CH6_RATE_KD) ) {
|
||||
log_counter++;
|
||||
if( log_counter >= 10 ) { // (update rate / desired output rate) = (100hz / 10hz) = 10
|
||||
log_counter = 0;
|
||||
pid_log_counter++;
|
||||
if( pid_log_counter >= 10 ) { // (update rate / desired output rate) = (100hz / 10hz) = 10
|
||||
pid_log_counter = 0;
|
||||
Log_Write_PID(CH6_RATE_KP, rate_error, p, i, d, output, tuning_value);
|
||||
}
|
||||
}
|
||||
@ -387,12 +384,9 @@ get_heli_rate_pitch(int32_t target_rate)
|
||||
output = constrain(output, -4500, 4500);
|
||||
|
||||
#if LOGGING_ENABLED == ENABLED
|
||||
static int8_t log_counter = 0; // used to slow down logging of PID values to dataflash
|
||||
// log output if PID logging is on and we are tuning the rate P, I or D gains
|
||||
if( g.log_bitmask & MASK_LOG_PID && (g.radio_tuning == CH6_RATE_KP || g.radio_tuning == CH6_RATE_KI || g.radio_tuning == CH6_RATE_KD) ) {
|
||||
log_counter++;
|
||||
if( log_counter >= 10 ) { // (update rate / desired output rate) = (100hz / 10hz) = 10
|
||||
log_counter = 0;
|
||||
if( pid_log_counter == 0 ) { // relies on get_heli_rate_roll to update pid_log_counter
|
||||
Log_Write_PID(CH6_RATE_KP+100, rate_error, p, i, 0, output, tuning_value);
|
||||
}
|
||||
}
|
||||
@ -432,12 +426,11 @@ get_heli_rate_yaw(int32_t target_rate)
|
||||
output = constrain(output, -4500, 4500);
|
||||
|
||||
#if LOGGING_ENABLED == ENABLED
|
||||
static int8_t log_counter = 0; // used to slow down logging of PID values to dataflash
|
||||
// log output if PID loggins is on and we are tuning the yaw
|
||||
if( g.log_bitmask & MASK_LOG_PID && (g.radio_tuning == CH6_YAW_KP || g.radio_tuning == CH6_YAW_RATE_KP) ) {
|
||||
log_counter++;
|
||||
if( log_counter >= 10 ) { // (update rate / desired output rate) = (100hz / 10hz) = 10
|
||||
log_counter = 0;
|
||||
if( g.log_bitmask & MASK_LOG_PID && (g.radio_tuning == CH6_YAW_RATE_KP || g.radio_tuning == CH6_YAW_RATE_KD) ) {
|
||||
pid_log_counter++;
|
||||
if( pid_log_counter >= 10 ) { // (update rate / desired output rate) = (100hz / 10hz) = 10
|
||||
pid_log_counter = 0;
|
||||
Log_Write_PID(CH6_YAW_RATE_KP, rate_error, p, i, d, output, tuning_value);
|
||||
}
|
||||
}
|
||||
@ -479,14 +472,12 @@ get_rate_roll(int32_t target_rate)
|
||||
output = constrain(output, -5000, 5000);
|
||||
|
||||
#if LOGGING_ENABLED == ENABLED
|
||||
static int8_t log_counter = 0; // used to slow down logging of PID values to dataflash
|
||||
|
||||
// log output if PID logging is on and we are tuning the rate P, I or D gains
|
||||
if( g.log_bitmask & MASK_LOG_PID && (g.radio_tuning == CH6_RATE_KP || g.radio_tuning == CH6_RATE_KI || g.radio_tuning == CH6_RATE_KD) ) {
|
||||
log_counter++;
|
||||
if( log_counter >= 10 ) { // (update rate / desired output rate) = (100hz / 10hz) = 10
|
||||
log_counter = 0;
|
||||
Log_Write_PID(CH6_RATE_KP, rate_error, p, i, d /*-rate_d_dampener*/, output, tuning_value);
|
||||
pid_log_counter++; // Note: get_rate_pitch pid logging relies on this function to update pid_log_counter so if you change the line above you must change the equivalent line in get_rate_pitch
|
||||
if( pid_log_counter >= 10 ) { // (update rate / desired output rate) = (100hz / 10hz) = 10
|
||||
pid_log_counter = 0;
|
||||
Log_Write_PID(CH6_RATE_KP, rate_error, p, i, d, output, tuning_value);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
@ -522,13 +513,10 @@ get_rate_pitch(int32_t target_rate)
|
||||
output = constrain(output, -5000, 5000);
|
||||
|
||||
#if LOGGING_ENABLED == ENABLED
|
||||
static int8_t log_counter = 0; // used to slow down logging of PID values to dataflash
|
||||
// log output if PID logging is on and we are tuning the rate P, I or D gains
|
||||
if( g.log_bitmask & MASK_LOG_PID && (g.radio_tuning == CH6_RATE_KP || g.radio_tuning == CH6_RATE_KI || g.radio_tuning == CH6_RATE_KD) ) {
|
||||
log_counter++;
|
||||
if( log_counter >= 10 ) { // (update rate / desired output rate) = (100hz / 10hz) = 10
|
||||
log_counter = 0;
|
||||
Log_Write_PID(CH6_RATE_KP+100, rate_error, p, i, d/*-rate_d_dampener*/, output, tuning_value);
|
||||
if( pid_log_counter == 0 ) { // relies on get_rate_roll having updated pid_log_counter
|
||||
Log_Write_PID(CH6_RATE_KP+100, rate_error, p, i, d, output, tuning_value);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
@ -561,12 +549,11 @@ get_rate_yaw(int32_t target_rate)
|
||||
output = constrain(output, -4500, 4500);
|
||||
|
||||
#if LOGGING_ENABLED == ENABLED
|
||||
static int8_t log_counter = 0; // used to slow down logging of PID values to dataflash
|
||||
// log output if PID loggins is on and we are tuning the yaw
|
||||
if( g.log_bitmask & MASK_LOG_PID && (g.radio_tuning == CH6_YAW_KP || g.radio_tuning == CH6_YAW_RATE_KP) ) {
|
||||
log_counter++;
|
||||
if( log_counter >= 10 ) { // (update rate / desired output rate) = (100hz / 10hz) = 10
|
||||
log_counter = 0;
|
||||
if( g.log_bitmask & MASK_LOG_PID && g.radio_tuning == CH6_YAW_RATE_KP ) {
|
||||
pid_log_counter++;
|
||||
if( pid_log_counter >= 10 ) { // (update rate / desired output rate) = (100hz / 10hz) = 10
|
||||
pid_log_counter = 0;
|
||||
Log_Write_PID(CH6_YAW_RATE_KP, rate_error, p, i, d, output, tuning_value);
|
||||
}
|
||||
}
|
||||
@ -619,12 +606,11 @@ get_of_roll(int32_t input_roll)
|
||||
of_roll = constrain(new_roll, (of_roll-20), (of_roll+20));
|
||||
|
||||
#if LOGGING_ENABLED == ENABLED
|
||||
static int8_t log_counter = 0; // used to slow down logging of PID values to dataflash
|
||||
// log output if PID logging is on and we are tuning the rate P, I or D gains
|
||||
if( g.log_bitmask & MASK_LOG_PID && (g.radio_tuning == CH6_OPTFLOW_KP || g.radio_tuning == CH6_OPTFLOW_KI || g.radio_tuning == CH6_OPTFLOW_KD) ) {
|
||||
log_counter++;
|
||||
if( log_counter >= 5 ) { // (update rate / desired output rate) = (100hz / 10hz) = 10
|
||||
log_counter = 0;
|
||||
pid_log_counter++; // Note: get_of_pitch pid logging relies on this function updating pid_log_counter so if you change the line above you must change the equivalent line in get_of_pitch
|
||||
if( pid_log_counter >= 5 ) { // (update rate / desired output rate) = (100hz / 10hz) = 10
|
||||
pid_log_counter = 0;
|
||||
Log_Write_PID(CH6_OPTFLOW_KP, tot_x_cm, p, i, d, of_roll, tuning_value);
|
||||
}
|
||||
}
|
||||
@ -674,12 +660,9 @@ get_of_pitch(int32_t input_pitch)
|
||||
of_pitch = constrain(new_pitch, (of_pitch-20), (of_pitch+20));
|
||||
|
||||
#if LOGGING_ENABLED == ENABLED
|
||||
static int8_t log_counter = 0; // used to slow down logging of PID values to dataflash
|
||||
// log output if PID logging is on and we are tuning the rate P, I or D gains
|
||||
if( g.log_bitmask & MASK_LOG_PID && (g.radio_tuning == CH6_OPTFLOW_KP || g.radio_tuning == CH6_OPTFLOW_KI || g.radio_tuning == CH6_OPTFLOW_KD) ) {
|
||||
log_counter++;
|
||||
if( log_counter >= 5 ) { // (update rate / desired output rate) = (100hz / 10hz) = 10
|
||||
log_counter = 0;
|
||||
if( pid_log_counter == 0 ) { // relies on get_of_roll having updated the pid_log_counter
|
||||
Log_Write_PID(CH6_OPTFLOW_KP+100, tot_y_cm, p, i, d, of_pitch, tuning_value);
|
||||
}
|
||||
}
|
||||
@ -829,13 +812,12 @@ get_throttle_accel(int16_t z_target_accel)
|
||||
output = constrain(p+i+d+g.throttle_cruise, g.throttle_min, g.throttle_max);
|
||||
|
||||
#if LOGGING_ENABLED == ENABLED
|
||||
static int8_t log_counter = 0; // used to slow down logging of PID values to dataflash
|
||||
// log output if PID loggins is on and we are tuning the yaw
|
||||
if( g.log_bitmask & MASK_LOG_PID && (g.radio_tuning == CH6_THR_ACCEL_KD || g.radio_tuning == CH6_THROTTLE_KP) ) {
|
||||
log_counter++;
|
||||
if( log_counter >= 10 ) { // (update rate / desired output rate) = (50hz / 10hz) = 5hz
|
||||
log_counter = 0;
|
||||
Log_Write_PID(CH6_THR_ACCEL_KD, z_accel_error, p, i, d, output, tuning_value);
|
||||
if( g.log_bitmask & MASK_LOG_PID && (g.radio_tuning == CH6_THR_ACCEL_KP || g.radio_tuning == CH6_THR_ACCEL_KI || g.radio_tuning == CH6_THR_ACCEL_KD) ) {
|
||||
pid_log_counter++;
|
||||
if( pid_log_counter >= 10 ) { // (update rate / desired output rate) = (50hz / 10hz) = 5hz
|
||||
pid_log_counter = 0;
|
||||
Log_Write_PID(CH6_THR_ACCEL_KP, z_accel_error, p, i, d, output, tuning_value);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
@ -956,12 +938,11 @@ get_throttle_rate(int16_t z_target_speed)
|
||||
output = p+i+d;
|
||||
|
||||
#if LOGGING_ENABLED == ENABLED
|
||||
static uint8_t log_counter = 0; // used to slow down logging of PID values to dataflash
|
||||
// log output if PID loggins is on and we are tuning the yaw
|
||||
if( g.log_bitmask & MASK_LOG_PID && (g.radio_tuning == CH6_THROTTLE_KP || g.radio_tuning == CH6_THROTTLE_KI || g.radio_tuning == CH6_THROTTLE_KD) ) {
|
||||
log_counter++;
|
||||
if( log_counter >= 10 ) { // (update rate / desired output rate) = (50hz / 10hz) = 5hz
|
||||
log_counter = 0;
|
||||
pid_log_counter++;
|
||||
if( pid_log_counter >= 10 ) { // (update rate / desired output rate) = (50hz / 10hz) = 5hz
|
||||
pid_log_counter = 0;
|
||||
Log_Write_PID(CH6_THROTTLE_KP, z_rate_error, p, i, d, output, tuning_value);
|
||||
}
|
||||
}
|
||||
@ -988,21 +969,22 @@ get_throttle_rate(int16_t z_target_speed)
|
||||
static void
|
||||
get_throttle_althold(int32_t target_alt, int16_t min_climb_rate, int16_t max_climb_rate)
|
||||
{
|
||||
int32_t alt_error;
|
||||
int16_t desired_rate;
|
||||
int32_t linear_distance; // the distace we swap between linear and sqrt.
|
||||
|
||||
// calculate altitude error
|
||||
altitude_error = target_alt - current_loc.alt;
|
||||
alt_error = target_alt - current_loc.alt;
|
||||
|
||||
// check kP to avoid division by zero
|
||||
if( g.pi_alt_hold.kP() != 0 ) {
|
||||
linear_distance = 250/(2*g.pi_alt_hold.kP()*g.pi_alt_hold.kP());
|
||||
if( altitude_error > 2*linear_distance ) {
|
||||
desired_rate = sqrt(2*250*(altitude_error-linear_distance));
|
||||
}else if( altitude_error < -2*linear_distance ) {
|
||||
desired_rate = -sqrt(2*250*(-altitude_error-linear_distance));
|
||||
if( alt_error > 2*linear_distance ) {
|
||||
desired_rate = sqrt(2*250*(alt_error-linear_distance));
|
||||
}else if( alt_error < -2*linear_distance ) {
|
||||
desired_rate = -sqrt(2*250*(-alt_error-linear_distance));
|
||||
}else{
|
||||
desired_rate = g.pi_alt_hold.get_p(altitude_error);
|
||||
desired_rate = g.pi_alt_hold.get_p(alt_error);
|
||||
}
|
||||
}else{
|
||||
desired_rate = 0;
|
||||
@ -1013,6 +995,9 @@ get_throttle_althold(int32_t target_alt, int16_t min_climb_rate, int16_t max_cli
|
||||
// call rate based throttle controller which will update accel based throttle controller targets
|
||||
get_throttle_rate(desired_rate);
|
||||
|
||||
// update altitude error reported to GCS
|
||||
altitude_error = alt_error;
|
||||
|
||||
// TO-DO: enabled PID logging for this controller
|
||||
}
|
||||
|
||||
|
@ -11,6 +11,9 @@ static mavlink_statustext_t pending_status;
|
||||
// true when we have received at least 1 MAVLink packet
|
||||
static bool mavlink_active;
|
||||
|
||||
// true if we are out of time in our event timeslice
|
||||
static bool gcs_out_of_time;
|
||||
|
||||
|
||||
// check if a message will fit in the payload space available
|
||||
#define CHECK_PAYLOAD_SIZE(id) if (payload_space < MAVLINK_MSG_ID_ ## id ## _LEN) return false
|
||||
@ -18,30 +21,35 @@ static bool mavlink_active;
|
||||
// prototype this for use inside the GCS class
|
||||
static void gcs_send_text_fmt(const prog_char_t *fmt, ...);
|
||||
|
||||
// gcs_check - throttles communication with ground station.
|
||||
// should be called regularly
|
||||
// returns true if it has sent a message to the ground station
|
||||
static bool gcs_check()
|
||||
|
||||
|
||||
// gcs_check_delay - keep GCS communications going
|
||||
// in our delay callback
|
||||
static void gcs_check_delay()
|
||||
{
|
||||
static uint32_t last_1hz, last_50hz;
|
||||
bool sent_message = false;
|
||||
|
||||
uint32_t tnow = millis();
|
||||
if (tnow - last_1hz > 1000) {
|
||||
last_1hz = tnow;
|
||||
gcs_send_message(MSG_HEARTBEAT);
|
||||
sent_message = true;
|
||||
gcs_send_heartbeat();
|
||||
}
|
||||
if (tnow - last_50hz > 20 && !sent_message) {
|
||||
if (tnow - last_50hz > 20) {
|
||||
last_50hz = tnow;
|
||||
gcs_update();
|
||||
gcs_check_input();
|
||||
gcs_data_stream_send();
|
||||
sent_message = true;
|
||||
gcs_send_deferred();
|
||||
}
|
||||
}
|
||||
|
||||
gcs_send_message(MSG_RETRY_DEFERRED);
|
||||
static void gcs_send_heartbeat(void)
|
||||
{
|
||||
gcs_send_message(MSG_HEARTBEAT);
|
||||
}
|
||||
|
||||
return sent_message;
|
||||
static void gcs_send_deferred(void)
|
||||
{
|
||||
gcs_send_message(MSG_RETRY_DEFERRED);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -483,18 +491,6 @@ static void NOINLINE send_raw_imu3(mavlink_channel_t chan)
|
||||
accel_offsets.z);
|
||||
}
|
||||
|
||||
static void NOINLINE send_gps_status(mavlink_channel_t chan)
|
||||
{
|
||||
mavlink_msg_gps_status_send(
|
||||
chan,
|
||||
g_gps->num_sats,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL);
|
||||
}
|
||||
|
||||
static void NOINLINE send_current_waypoint(mavlink_channel_t chan)
|
||||
{
|
||||
mavlink_msg_mission_current_send(
|
||||
@ -545,10 +541,11 @@ static bool mavlink_try_send_message(mavlink_channel_t chan, enum ap_message id,
|
||||
return false;
|
||||
}
|
||||
|
||||
// if the ins has new data for the main loop then don't send a
|
||||
// mavlink message. We want to prioritise the main flight control
|
||||
// loop over communications
|
||||
if (main_loop_ready()) {
|
||||
// if we don't have at least 1ms remaining before the main loop
|
||||
// wants to fire then don't send a mavlink message. We want to
|
||||
// prioritise the main flight control loop over communications
|
||||
if (event_time_available() < 500) {
|
||||
gcs_out_of_time = true;
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -556,7 +553,7 @@ static bool mavlink_try_send_message(mavlink_channel_t chan, enum ap_message id,
|
||||
case MSG_HEARTBEAT:
|
||||
CHECK_PAYLOAD_SIZE(HEARTBEAT);
|
||||
send_heartbeat(chan);
|
||||
return true;
|
||||
break;
|
||||
|
||||
case MSG_EXTENDED_STATUS1:
|
||||
CHECK_PAYLOAD_SIZE(SYS_STATUS);
|
||||
@ -680,6 +677,7 @@ static bool mavlink_try_send_message(mavlink_channel_t chan, enum ap_message id,
|
||||
case MSG_RETRY_DEFERRED:
|
||||
break; // just here to prevent a warning
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -968,6 +966,8 @@ GCS_MAVLINK::data_stream_send(void)
|
||||
return;
|
||||
}
|
||||
|
||||
gcs_out_of_time = false;
|
||||
|
||||
if (_queued_parameter != NULL) {
|
||||
if (streamRateParams.get() <= 0) {
|
||||
streamRateParams.set(50);
|
||||
@ -979,6 +979,8 @@ GCS_MAVLINK::data_stream_send(void)
|
||||
return;
|
||||
}
|
||||
|
||||
if (gcs_out_of_time) return;
|
||||
|
||||
if (in_mavlink_delay) {
|
||||
// don't send any other stream types while in the delay callback
|
||||
return;
|
||||
@ -991,6 +993,8 @@ GCS_MAVLINK::data_stream_send(void)
|
||||
//cliSerial->printf("mav1 %d\n", (int)streamRateRawSensors.get());
|
||||
}
|
||||
|
||||
if (gcs_out_of_time) return;
|
||||
|
||||
if (stream_trigger(STREAM_EXTENDED_STATUS)) {
|
||||
send_message(MSG_EXTENDED_STATUS1);
|
||||
send_message(MSG_EXTENDED_STATUS2);
|
||||
@ -1000,32 +1004,44 @@ GCS_MAVLINK::data_stream_send(void)
|
||||
send_message(MSG_LIMITS_STATUS);
|
||||
}
|
||||
|
||||
if (gcs_out_of_time) return;
|
||||
|
||||
if (stream_trigger(STREAM_POSITION)) {
|
||||
send_message(MSG_LOCATION);
|
||||
}
|
||||
|
||||
if (gcs_out_of_time) return;
|
||||
|
||||
if (stream_trigger(STREAM_RAW_CONTROLLER)) {
|
||||
send_message(MSG_SERVO_OUT);
|
||||
//cliSerial->printf("mav4 %d\n", (int)streamRateRawController.get());
|
||||
}
|
||||
|
||||
if (gcs_out_of_time) return;
|
||||
|
||||
if (stream_trigger(STREAM_RC_CHANNELS)) {
|
||||
send_message(MSG_RADIO_OUT);
|
||||
send_message(MSG_RADIO_IN);
|
||||
//cliSerial->printf("mav5 %d\n", (int)streamRateRCChannels.get());
|
||||
}
|
||||
|
||||
if (gcs_out_of_time) return;
|
||||
|
||||
if (stream_trigger(STREAM_EXTRA1)) {
|
||||
send_message(MSG_ATTITUDE);
|
||||
send_message(MSG_SIMSTATE);
|
||||
//cliSerial->printf("mav6 %d\n", (int)streamRateExtra1.get());
|
||||
}
|
||||
|
||||
if (gcs_out_of_time) return;
|
||||
|
||||
if (stream_trigger(STREAM_EXTRA2)) {
|
||||
send_message(MSG_VFR_HUD);
|
||||
//cliSerial->printf("mav7 %d\n", (int)streamRateExtra2.get());
|
||||
}
|
||||
|
||||
if (gcs_out_of_time) return;
|
||||
|
||||
if (stream_trigger(STREAM_EXTRA3)) {
|
||||
send_message(MSG_AHRS);
|
||||
send_message(MSG_HWSTATUS);
|
||||
@ -1452,21 +1468,22 @@ void GCS_MAVLINK::handleMessage(mavlink_message_t* msg)
|
||||
if (mavlink_check_target(packet.target_system,packet.target_component)) break;
|
||||
enum ap_var_type p_type;
|
||||
AP_Param *vp;
|
||||
char param_name[AP_MAX_NAME_SIZE];
|
||||
if (packet.param_index != -1) {
|
||||
vp = AP_Param::find_by_index(packet.param_index, &p_type);
|
||||
if (vp == NULL) {
|
||||
gcs_send_text_fmt(PSTR("Unknown parameter index %d"), packet.param_index);
|
||||
break;
|
||||
}
|
||||
vp->copy_name(param_name, sizeof(param_name), true);
|
||||
} else {
|
||||
vp = AP_Param::find(packet.param_id, &p_type);
|
||||
if (vp == NULL) {
|
||||
gcs_send_text_fmt(PSTR("Unknown parameter %.16s"), packet.param_id);
|
||||
break;
|
||||
}
|
||||
strncpy(param_name, packet.param_id, AP_MAX_NAME_SIZE);
|
||||
}
|
||||
char param_name[AP_MAX_NAME_SIZE];
|
||||
vp->copy_name(param_name, sizeof(param_name), true);
|
||||
|
||||
float value = vp->cast_to_float(p_type);
|
||||
mavlink_msg_param_value_send(
|
||||
@ -2090,7 +2107,7 @@ GCS_MAVLINK::queued_param_send()
|
||||
value = vp->cast_to_float(_queued_parameter_type);
|
||||
|
||||
char param_name[AP_MAX_NAME_SIZE];
|
||||
vp->copy_name(param_name, sizeof(param_name), true);
|
||||
vp->copy_name_token(&_queued_parameter_token, param_name, sizeof(param_name), true);
|
||||
|
||||
mavlink_msg_param_value_send(
|
||||
chan,
|
||||
@ -2138,13 +2155,14 @@ static void mavlink_delay_cb()
|
||||
uint32_t tnow = millis();
|
||||
if (tnow - last_1hz > 1000) {
|
||||
last_1hz = tnow;
|
||||
gcs_send_message(MSG_HEARTBEAT);
|
||||
gcs_send_heartbeat();
|
||||
gcs_send_message(MSG_EXTENDED_STATUS1);
|
||||
}
|
||||
if (tnow - last_50hz > 20) {
|
||||
last_50hz = tnow;
|
||||
gcs_update();
|
||||
gcs_check_input();
|
||||
gcs_data_stream_send();
|
||||
gcs_send_deferred();
|
||||
}
|
||||
if (tnow - last_5s > 5000) {
|
||||
last_5s = tnow;
|
||||
@ -2182,7 +2200,7 @@ static void gcs_data_stream_send(void)
|
||||
/*
|
||||
* look for incoming commands on the GCS links
|
||||
*/
|
||||
static void gcs_update(void)
|
||||
static void gcs_check_input(void)
|
||||
{
|
||||
gcs0.update();
|
||||
if (gcs3.initialised) {
|
||||
|
@ -41,20 +41,14 @@ static void update_navigation()
|
||||
}
|
||||
#endif
|
||||
|
||||
// calc various navigation values and run controllers if we've received a position update
|
||||
// setup to calculate new navigation values and run controllers if
|
||||
// we've received a position update
|
||||
if( pos_updated ) {
|
||||
|
||||
// calculate velocity
|
||||
calc_velocity_and_position();
|
||||
|
||||
// calculate distance, angles to target
|
||||
calc_distance_and_bearing();
|
||||
|
||||
// run navigation controllers
|
||||
run_navigation_contollers();
|
||||
|
||||
// Rotate the nav_lon and nav_lat vectors based on Yaw
|
||||
calc_nav_pitch_roll();
|
||||
nav_updates.need_velpos = 1;
|
||||
nav_updates.need_dist_bearing = 1;
|
||||
nav_updates.need_nav_controllers = 1;
|
||||
nav_updates.need_nav_pitch_roll = 1;
|
||||
|
||||
// update log
|
||||
if (log_output && (g.log_bitmask & MASK_LOG_NTUN) && motors.armed()) {
|
||||
@ -71,6 +65,28 @@ static void update_navigation()
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
run navigation updates from nav_updates. Only run one at a time to
|
||||
prevent too much cpu usage hurting the main loop
|
||||
*/
|
||||
static void run_nav_updates(void)
|
||||
{
|
||||
if (nav_updates.need_velpos) {
|
||||
calc_velocity_and_position();
|
||||
nav_updates.need_velpos = 0;
|
||||
} else if (nav_updates.need_dist_bearing) {
|
||||
calc_distance_and_bearing();
|
||||
nav_updates.need_dist_bearing = 0;
|
||||
} else if (nav_updates.need_nav_controllers) {
|
||||
run_navigation_contollers();
|
||||
nav_updates.need_nav_controllers = 0;
|
||||
} else if (nav_updates.need_nav_pitch_roll) {
|
||||
calc_nav_pitch_roll();
|
||||
nav_updates.need_nav_pitch_roll = 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//*******************************************************************************************************
|
||||
// calc_velocity_and_filtered_position - velocity in lon and lat directions calculated from GPS position
|
||||
// and accelerometer data
|
||||
|
Loading…
Reference in New Issue
Block a user