Path: blob/master/Tools/simulink/arducopter/sid_sim_init.m
9660 views
% Initialization of the Simulink model. The script loads all important1% signals and parameter to the workspace.2%3% Fabian Bredemeier - IAV GmbH4% License: GPL v35%% Define log index and start + stop time6if ~exist('log_idx', 'var')7log_idx = 1;8end9tStart = 0;10tEnd = inf;1112%% Setting simMode13% 0 = Model validation - Identified models are used and full control loop14% is active15% 1 = Rate Controller validation - No models used, measured input signals16% of rate controller are used17% 2 = Attitude Controller validation - No models used, measured input18% signals of attitude controller are used19% 3 = Altitude Controller validation - No models used, measured input20% signals of attitude controller are used21% 4 = Optimization of controller - Not implemented yet22if ~exist('simMode', 'var')23simMode = 0;24end2526%% Check for existance of data2728% Check if sid data is existing29if exist('sidLogs', 'var') % in Workspace30disp('.mat file already loaded. Reading parameter and signals...');31elseif exist('sid.mat', 'file') % in a .mat file with all other axis tests32load('sid.mat');33disp('Loaded data from sid.mat');34elseif ~exist(loadedDataConfig)35error('Could not find configuration struct. Aborting script.')36else37error('Could not find data. Aborting script.')38end3940%% Config and variable declaration4142% Sample rate of simInulation43Fs = 400;44dt = 0.0025;45simIn.param.dt = 0.0025;4647% Load data48sid = sidLogs(log_idx).data;49% Check if relevant messages are defined50if (numel(sid) == 0)51error('Ardupilog object sid is empty. Aborting.');52end5354% Get mode of current test run55mode = loadedDataConfig.modes(log_idx);56% Get manual throttle flag for current test run57thr_man = loadedDataConfig.modesConfig(log_idx).thr_man;58% Get filter messages of current test run59msgs = loadedDataConfig.modesConfig(log_idx).filter_msgs;60% Set axis61axis = loadedDataConfig.axisList(log_idx);62% Check if config parameters are complete63if (isempty(mode) || isempty(thr_man) || isempty(msgs))64error('Config variables (mode, thr_man, msgs) not complete. Aborting.');65end6667% Define validation and optimization flag of simInulation68simIn.param.mdlVal = simMode == 0;69simIn.param.rateCtrlVal = simMode == 1;70simIn.param.attCtrlVal = simMode == 2 || simMode == 3;71simIn.param.altCtrlVal = simMode == 3 || mode == 2;72simIn.param.optCtrl = simMode == 4;7374%% General Copter settings75simIn.param.LOOP_RATE = getParamVal(sid, 'SCHED_LOOP_RATE');76simIn.param.dt = round(double(1 / simIn.param.LOOP_RATE), 4); % Sample time resulting from loop rate. Round to four decimal digits77simIn.param.FRAME_CLASS = getParamVal(sid, 'FRAME_CLASS');78simIn.param.FRAME_TYPE = getParamVal(sid, 'FRAME_TYPE');79[simIn.param.NUM_MOTORS, simIn.param.AXIS_FAC_MOTORS] = getMotorMixerFactors(simIn.param.FRAME_CLASS, simIn.param.FRAME_TYPE);80simIn.param.EKF_TYPE = getParamVal(sid, 'AHRS_EKF_TYPE');81simIn.param.GRAVITY_MSS = single(9.80665);82simIn.param.dt_THR_LOOP = 1 / 50; % Sample time of throttle loop in Copter.cpp. Defined in Copter.cpp, line 9483simIn.param.ANGLE_MAX = getParamVal(sid, 'ANGLE_MAX'); % Maximum lean angle in all flight modes84simIn.param.PILOT_Y_EXPO = getParamVal(sid, 'PILOT_Y_EXPO'); % Acro yaw expo to allow faster rotation when stick at edges85simIn.param.PILOT_Y_RATE = getParamVal(sid, 'PILOT_Y_RATE');86simIn.param.PILOT_Y_RATE_TC = getParamVal(sid, 'PILOT_Y_RATE_TC'); % Pilot yaw rate control input time constant87simIn.param.MODE.ModeNr = mode; % Flight mode8889% Abort script if frame configuration is not defined yet90if (isempty(simIn.param.AXIS_FAC_MOTORS) || simIn.param.NUM_MOTORS == 0)91error("Body configuration of copter is not defined yet!");92end9394%% Simulation duration95% Define end time of simInulation96if simIn.param.mdlVal || simIn.param.rateCtrlVal || simIn.param.attCtrlVal || simIn.param.altCtrlVal97if isinf(tEnd) % Run full data98simIn.param.timeEnd = sid.RATE.TimeS(end);99else % Only run part of data100duration = tEnd-tStart;101iEnd = int16(duration/dt);102simIn.param.timeEnd = sid.RATE.TimeS(iEnd);103clear duration iEnd104end105elseif simIn.param.optCtrl106simIn.param.timeEnd = OPT.tEndOpt;107end108109%% Inertial Sensor110simIn.param.INS.GYRO_FILTER = getParamVal(sid, 'INS_GYRO_FILTER'); % Filter cutoff frequency for gyro lowpass filter111simIn.param.INS.GYRO_RATE = 400; % Gyro sampling rate. Actually define by INS_GYRO_RATE, but simInulation is run with 400 Hz112113%% AHRS114trim_x = getParamVal(sid, 'AHRS_TRIM_X');115trim_y = getParamVal(sid, 'AHRS_TRIM_Y');116simIn.param.AHRS.FC2BF = single(dcmFromEuler(trim_x, trim_y, 0)); % Rotation matrix from FC to Body Frame based on AP_AHRS constructor117simIn.param.AHRS.BF2FC = simIn.param.AHRS.FC2BF';118119clear trim_x trim_y120%% RCIN - Radio Input and parameters for Attitude Control121rollCh = getParamVal(sid, 'RCMAP_ROLL');122pitchCh = getParamVal(sid, 'RCMAP_PITCH');123yawCh = getParamVal(sid, 'RCMAP_YAW');124thrCh = getParamVal(sid, 'RCMAP_THROTTLE');125126simIn.param.RCIN.DZ_RLL = getParamVal(sid, ['RC' num2str(rollCh) '_DZ']);127simIn.param.RCIN.MIN_RLL = getParamVal(sid, ['RC' num2str(rollCh) '_MIN']);128simIn.param.RCIN.MAX_RLL = getParamVal(sid, ['RC' num2str(rollCh) '_MAX']);129simIn.param.RCIN.TRIM_RLL = getParamVal(sid, ['RC' num2str(rollCh) '_TRIM']);130simIn.param.RCIN.REVERSED_RLL = getParamVal(sid, ['RC' num2str(rollCh) '_REVERSED']);131simIn.param.RCIN.DZ_PIT = getParamVal(sid, ['RC' num2str(pitchCh) '_DZ']);132simIn.param.RCIN.MIN_PIT = getParamVal(sid, ['RC' num2str(pitchCh) '_MIN']);133simIn.param.RCIN.MAX_PIT = getParamVal(sid, ['RC' num2str(pitchCh) '_MAX']);134simIn.param.RCIN.TRIM_PIT = getParamVal(sid, ['RC' num2str(pitchCh) '_TRIM']);135simIn.param.RCIN.REVERSED_PIT = getParamVal(sid, ['RC' num2str(pitchCh) '_REVERSED']);136simIn.param.RCIN.DZ_YAW = getParamVal(sid, ['RC' num2str(yawCh) '_DZ']);137simIn.param.RCIN.MIN_YAW = getParamVal(sid, ['RC' num2str(yawCh) '_MIN']);138simIn.param.RCIN.MAX_YAW = getParamVal(sid, ['RC' num2str(yawCh) '_MAX']);139simIn.param.RCIN.TRIM_YAW = getParamVal(sid, ['RC' num2str(yawCh) '_TRIM']);140simIn.param.RCIN.REVERSED_YAW = getParamVal(sid, ['RC' num2str(yawCh) '_REVERSED']);141simIn.param.RCIN.DZ_THR = getParamVal(sid, ['RC' num2str(thrCh) '_DZ']);142simIn.param.RCIN.MIN_THR = getParamVal(sid, ['RC' num2str(thrCh) '_MIN']);143simIn.param.RCIN.MAX_THR = getParamVal(sid, ['RC' num2str(thrCh) '_MAX']);144simIn.param.RCIN.TRIM_THR = getParamVal(sid, ['RC' num2str(thrCh) '_TRIM']);145simIn.param.RCIN.REVERSED_THR = getParamVal(sid, ['RC' num2str(thrCh) '_REVERSED']);146147simIn.param.RCIN.ROLL_PITCH_YAW_INPUT_MAX = 4500; % Yaw, roll, pitch input range, defined in config.h148149% Check if RCIN log is available150if simIn.param.mdlVal || simIn.param.attCtrlVal || simIn.param.altCtrlVal151if isfield(sid, 'RCIN')152iVec = (sid.RCIN.TimeS >= tStart & sid.RCIN.TimeS <= tEnd);153simIn.signals.RCIN.Time = single(sid.RCIN.TimeS(iVec)-tStart);154simIn.signals.RCIN.RollInput = eval(['single(sid.RCIN.C' num2str(rollCh) '(iVec))']);155simIn.signals.RCIN.PitchInput = eval(['single(sid.RCIN.C' num2str(pitchCh) '(iVec))']);156simIn.signals.RCIN.YawInput = eval(['single(sid.RCIN.C' num2str(yawCh) '(iVec))']);157simIn.signals.RCIN.ThrottleInput = eval(['single(sid.RCIN.C' num2str(thrCh) '(iVec))']);158else159if ~isfield(sid, 'RCIN') && axis == 13160warning(['RCIN message cannot be found in log ' num2str(log_idx) '! Validating vertical motion model.']);161else162warning(['RCIN message cannot be found in log ' num2str(log_idx) '! Ommiting attitude controller and models in simInulation. Only rate controller is validated']);163simIn.param.rateCtrlVal = 1;164simIn.param.mdlVal = 0;165end166% Set RCIN signals to zero167simIn.signals.RCIN.Time = single(0:0.1:simIn.param.timeEnd);168simIn.signals.RCIN.RollInput = single(zeros(length(simIn.signals.RCIN.Time),1));169simIn.signals.RCIN.PitchInput = single(zeros(length(simIn.signals.RCIN.Time),1));170simIn.signals.RCIN.YawInput = single(zeros(length(simIn.signals.RCIN.Time),1));171simIn.signals.RCIN.ThrottleInput = single(zeros(length(simIn.signals.RCIN.Time),1));172end173end174175%% Attitude176% Yaw Angle signals are a modulo of 360°, so this operation has to be177% inverted178iVec = (sid.ATT.TimeS >= tStart & sid.ATT.TimeS <= tEnd);179simIn.signals.ATT.Time = single(sid.ATT.TimeS(iVec)-tStart);180simIn.signals.ATT.Roll = single(sid.ATT.Roll(iVec));181simIn.signals.ATT.Pitch = single(sid.ATT.Pitch(iVec));182simIn.signals.ATT.Yaw = single(demodYawAngle(sid.ATT.Yaw(iVec)));183simIn.signals.ATT.DesRoll = single(sid.ATT.DesRoll(iVec));184simIn.signals.ATT.DesPitch = single(sid.ATT.DesPitch(iVec));185simIn.signals.ATT.DesYaw = single(demodYawAngle(sid.ATT.DesYaw(iVec)));186187% The actual yaw angle is calculated from the DCM with188% Matrix3<T>::to_euler() with the four-quadrant arcus tangens atan2(), for189% example in AP_AHRS_View::update(), so the controller can only handle190% values in the range [-pi, pi].191simIn.signals.ATT.Yaw = simIn.signals.ATT.Yaw - 360 * (simIn.signals.ATT.Yaw > 180);192simIn.signals.ATT.DesYaw = simIn.signals.ATT.DesYaw - 360 * (simIn.signals.ATT.DesYaw > 180);193194% Initial DCM matrix based on initial Euler angles195% Calculation based on Matrix3<T>::from_euler()196for i=1:length(iVec)197if iVec(i) == 1198iInit = i;199break;200end201end202rollAngInit = single(sid.ATT.Roll(iInit))*pi/180;203pitchAngInit = single(sid.ATT.Pitch(iInit))*pi/180;204yawAngInit = single(simIn.signals.ATT.Yaw(1))*pi/180;205simIn.init.ATT.Roll = rollAngInit;206simIn.init.ATT.Pitch = pitchAngInit;207simIn.init.ATT.Yaw = yawAngInit;208simIn.init.ATT.DCM = dcmFromEuler(rollAngInit, pitchAngInit, yawAngInit);209210% Initialize attitudeTarget according to211% AC_AttitudeControl::reset_yaw_target_and_rate(), which is called in212% ModeStabilize::run() when copter is landed213attitudeTargetUpdate = fromAxisAngle([0;0;yawAngInit]);214simIn.init.ATT.attitudeTarget = quatMult(attitudeTargetUpdate, [1;0;0;0]);215simIn.init.ATT.eulerRateTar = [0;0;0];216217% Test signals in SITL218% Attitude Controller Targets219% simIn.signals.ATT.attTarMeasW = single(sid.ATAR.attW);220% simIn.signals.ATT.attTarMeasX = single(sid.ATAR.attX);221% simIn.signals.ATT.attTarMeasY = single(sid.ATAR.attY);222% simIn.signals.ATT.attTarMeasZ = single(sid.ATAR.attZ);223% simIn.signals.ATT.eulerAngTarMeasX = single(sid.ATAR.angX);224% simIn.signals.ATT.eulerAngTarMeasY = single(sid.ATAR.angY);225% simIn.signals.ATT.eulerAngTarMeasZ = single(sid.ATAR.angZ);226% simIn.signals.ATT.eulerRatTarMeasX = single(sid.ATAR.ratX);227% simIn.signals.ATT.eulerRatTarMeasY = single(sid.ATAR.ratY);228% simIn.signals.ATT.eulerRatTarMeasZ = single(sid.ATAR.ratZ);229%230% simIn.signals.ATT.CtrlRollIn = single(sid.CTIN.rllCtrl);231% simIn.signals.ATT.CtrlPitchIn = single(sid.CTIN.pitCtrl);232% simIn.signals.ATT.CtrlYawIn = single(sid.CTIN.yawCtrl);233% simIn.signals.ATT.yawRateDesMeas = single(sid.ATIN.yawDes);234235clear rollAngInit pitchAngInit yawAngInit attitudeTargetUpdate iInit236237%% Attitude Controller General238simIn.param.ATC.RATE_FF_ENAB = getParamVal(sid, 'ATC_RATE_FF_ENAB');239simIn.param.ATC.INPUT_TC = getParamVal(sid, 'ATC_INPUT_TC'); % Attitude control input time constant240simIn.param.ATC.ANGLE_LIMIT_MIN = single(10); % Min lean angle so that vehicle can maintain limited control, defined in AC_AttitudeControl.cpp as AC_ATTITUDE_CONTROL_ANGLE_LIMIT_MIN241simIn.param.ATC.ANGLE_LIMIT_THROTTLE_MAX = single(0.8); % Max throttle used to limit lean angle so that vehicle does not lose altitude, defined in AC_AttitudeControl.h as AC_ATTITUDE_CONTROL_ANGLE_LIMIT_THROTTLE_MAX242simIn.param.ATC.ANG_LIM_TC = getParamVal(sid, 'ATC_ANG_LIM_TC'); % Angle Limit (to maintain altitude) Time Constant243% Roll Angle Controller244simIn.param.ATC.ANG_RLL_P = getParamVal(sid, 'ATC_ANG_RLL_P');245simIn.param.ATC.ACCEL_R_MAX = getParamVal(sid, 'ATC_ACCEL_R_MAX');246simIn.param.ATC.RATE_R_MAX = getParamVal(sid, 'ATC_RATE_R_MAX');247simIn.param.ATC.ACCEL_RP_CONTROLLER_MIN_RADSS = 40*pi/180; % Maximum body-frame acceleration limit for the stability controller, defined in AC_AttitudeControl.h248simIn.param.ATC.ACCEL_RP_CONTROLLER_MAX_RADSS = 720*pi/180;249% Pitch Angle Controller250simIn.param.ATC.ANG_PIT_P = getParamVal(sid, 'ATC_ANG_PIT_P');251simIn.param.ATC.ACCEL_P_MAX = getParamVal(sid, 'ATC_ACCEL_P_MAX');252simIn.param.ATC.RATE_P_MAX = getParamVal(sid, 'ATC_RATE_P_MAX');253% Yaw Angle Controller254simIn.param.ATC.ANG_YAW_P = getParamVal(sid, 'ATC_ANG_YAW_P');255simIn.param.ATC.ACCEL_Y_MAX = getParamVal(sid, 'ATC_ACCEL_Y_MAX');256simIn.param.ATC.RATE_Y_MAX = getParamVal(sid, 'ATC_RATE_Y_MAX');257simIn.param.ATC.ACCEL_Y_CONTROLLER_MAX_RADSS = single(120*pi/180); % Maximum body-frame acceleration limit for the stability controller, defined in AC_AttitudeControl.h258simIn.param.ATC.ACCEL_Y_CONTROLLER_MIN_RADSS = single(10*pi/180);259simIn.param.ATC.THRUST_ERROR_ANGLE = single(30*pi/180); % Thrust angle error above which yaw corrections are limited. Defined in AC_AttitudeControl.h260simIn.param.ATC.YAW_MAX_ERROR_ANGLE = single(45*pi/180); % Thrust angle error above which yaw corrections are limited261262% Thrust and throttle calculation parameters263simIn.param.MODE.THR_MAN_FLG = thr_man; % Flag for manual throttle, which depends on the current mode.264if thr_man265simIn.param.ATC.THR_FILT_CUTOFF = getParamVal(sid, 'PILOT_THR_FILT'); % Cutoff frequency of throttle filter for modes with manual throttle. parameter is given to function call of AC_AttitudeControl_Multi::set_throttle_out().266else267simIn.param.ATC.THR_FILT_CUTOFF = 2.0; % Cutoff frequency of throttle filter for modes with z position control (Defined in AC_PosControl.h, line 33)268end269simIn.param.ATC.ANGLE_BOOST = getParamVal(sid, 'ATC_ANGLE_BOOST'); % Enabling of angle boost to increase output throttle. Used in AC_AttitudeConrtol_Multi::get_throttle_boosted()270simIn.param.ATC.THR_MIX_MAN = getParamVal(sid, 'ATC_THR_MIX_MAN'); % Throttle vs. attitude priorisation during manual flight271simIn.param.ATC.THR_MIX_MIN = getParamVal(sid, 'ATC_THR_MIX_MIN'); % Throttle vs. attitude priorisation used when landing272simIn.param.ATC.THR_MIX_MAX = getParamVal(sid, 'ATC_THR_MIX_MAX'); % Throttle vs. attitude priorisation during active flights273simIn.param.ATC.THR_G_BOOST = getParamVal(sid, 'ATC_THR_G_BOOST'); % Throttle-gain boost ratio. A value of 0 means no boosting is applied, a value of 1 means full boosting is applied. Describes the ratio increase that is applied to angle P and PD on pitch and roll.274simIn.param.ATC.THR_MIX_DFLT = single(0.5); % Default value for the priorization of throttle use between attitude control and throttle demand by pilot (or autopilot). Defined in AC_AttitudeControl.h, line 44275if thr_man276simIn.init.ATC.THR_MIX = simIn.param.ATC.THR_MIX_MAN;277else278simIn.init.ATC.THR_MIX = simIn.param.ATC.THR_MIX_DFLT;279end280simIn.param.MOT.HOVER_LEARN = getParamVal(sid, 'MOT_HOVER_LEARN'); % Enable/Disable automatic learning of hover throttle (0=Disabled, 1=Learn, 2=Learn and Save281simIn.param.MOT.THST_HOVER = getParamVal(sid, 'MOT_THST_HOVER'); % Motor thrust needed to hover. Default value of _throttle_hover.282simIn.param.MOT.THST_HOVER = simIn.param.MOT.THST_HOVER(1); % Assign first value of array to default value which is the correct value in the case, that the parameter is defined twice in the param file.283simIn.param.MOT.THST_HOVER_TC = single(10.0); % Time constant used to update estimated hover throttle, found as AP_MOTORS_THST_HOVER_TC in AP_MotorsMulticopter.h284simIn.param.MOT.THST_HOVER_MIN = single(0.125); % Minimum possible hover throttle, found as AP_MOTORS_THST_HOVER_MIN in AP_MotorsMulticopter.h285simIn.param.MOT.THST_HOVER_MAX = single(0.6875); % Maximum possible hover throttle, found as AP_MOTORS_THST_HOVER_MAX in AP_MotorsMulticopter.h286simIn.param.MOT.BAT_VOLT_MAX = getParamVal(sid, 'MOT_BAT_VOLT_MAX'); % Maximum voltage above which no additional scaling on thrust is performed287simIn.param.MOT.BAT_VOLT_MIN = getParamVal(sid, 'MOT_BAT_VOLT_MIN'); % Minimum voltage below which no additional scaling on thrust is performed288simIn.param.MOT.BAT_CURR_MAX = getParamVal(sid, 'MOT_BAT_CURR_MAX'); % Maximum current over which maximum throttle is limited (and no further scaling is performed)289simIn.param.MOT.THST_EXPO = getParamVal(sid, 'MOT_THST_EXPO'); % Motor thrust curve exponent (0.0 for linear to 1.0 for second order curve)290simIn.param.MOT.BAT_CURR_TC = getParamVal(sid, 'MOT_BAT_CURR_TC'); % Time constant used to limit the maximum current291simIn.param.MOT.YAW_HEADROOM = getParamVal(sid, 'MOT_YAW_HEADROOM'); % Yaw control is goven at least this PWM in microseconds range292293% Throttle inputs294iVec = (sid.CTUN.TimeS >= tStart & sid.CTUN.TimeS <= tEnd);295simIn.signals.CTUN.Time = single(sid.CTUN.TimeS(iVec)--tStart);296simIn.signals.CTUN.ThrIn = single(sid.CTUN.ThI(iVec)); % Throttle In, pilots input to Attitude Control (attitude_control->get_throttle_in())297simIn.signals.CTUN.ThrOut = single(sid.CTUN.ThO(iVec)); % Throttle Out, throttle given to motor mixer after filtering (motors->get_throttle())298simIn.signals.CTUN.AngBst = single(sid.CTUN.ABst(iVec)); % Extra amount of throttle, added to throttle_in in AC_AttitudeControl_Multi::get_throttle_boosted()299simIn.signals.CTUN.ThrHov = single(sid.CTUN.ThH(iVec)); % Estimated throttle required to hover throttle in range 0-1 (AP_MotorsMulticopter::get_throttle_hover())300301% Throttle inital values302if simIn.param.rateCtrlVal || simIn.param.attCtrlVal || simIn.param.mdlVal || simIn.param.altCtrlVal303simIn.init.CTUN.ThrOut = single(sid.CTUN.ThO(1));304simIn.init.CTUN.ThrHov = single(sid.CTUN.ThH(1));305else306simIn.init.CTUN.ThrOut = single(0);307simIn.init.CTUN.ThrHov = single(simIn.param.MOT.THST_HOVER);308end309310% Altitude signals311simIn.signals.CTUN.DSAlt = single(sid.CTUN.DSAlt(iVec)); % Desired rangefinder altitude312simIn.signals.CTUN.DAlt = single(sid.CTUN.DAlt(iVec)); % Desired altitude313simIn.signals.CTUN.Alt = single(sid.CTUN.Alt(iVec)); % Achieved altitude (inav)314simIn.signals.CTUN.SAlt = single(sid.CTUN.SAlt(iVec)); % Achieved rangefinder altitude315simIn.signals.CTUN.TAlt = single(sid.CTUN.TAlt(iVec)); % Terrain altitude316simIn.signals.CTUN.BAlt = single(sid.CTUN.BAlt(iVec)); % Barometric altitude317simIn.signals.CTUN.CRt = single(sid.CTUN.CRt(iVec)); % Climb rate inav318simIn.signals.CTUN.DCRt = single(sid.CTUN.DCRt(iVec)); % Desired climb rate319320% Altitude inital values321simIn.init.CTUN.Alt = single(sid.CTUN.Alt(1));322simIn.init.CTUN.CRt = single(sid.CTUN.CRt(1)*0.01);323324% Intermediate throttle calculation quantities - only read if message325% exists326if isfield(sid, 'MOTQ')327iVec = (sid.MOTQ.TimeS >= tStart & sid.MOTQ.TimeS <= tEnd);328simIn.signals.MOTQ.Time = single(sid.MOTQ.TimeS(iVec)-tStart);329simIn.signals.MOTQ.ThrAvgMax = single(sid.MOTQ.ThAvgMax(iVec));330simIn.signals.MOTQ.ThrThstMaxMeas = single(sid.MOTQ.ThThstMax(iVec));331simIn.signals.MOTQ.CompGain = single(sid.MOTQ.CompGain(iVec));332simIn.signals.MOTQ.AirDensityRatio = single(sid.MOTQ.AirDensRat(iVec));333simIn.signals.MOTQ.ThrMixOut = single(sid.MOTQ.ThrOut(iVec));334else335iVec = (sid.CTUN.TimeS >= tStart & sid.CTUN.TimeS <= tEnd);336simIn.signals.MOTQ.Time = single(sid.CTUN.TimeS(iVec)-tStart);337simIn.signals.MOTQ.ThrAvgMax = single(zeros(length(simIn.signals.MOTQ.Time),1));338simIn.signals.MOTQ.ThrThstMaxMeas = single(zeros(length(simIn.signals.MOTQ.Time),1));339simIn.signals.MOTQ.CompGain = single(zeros(length(simIn.signals.MOTQ.Time),1));340simIn.signals.MOTQ.AirDensityRatio = single(zeros(length(simIn.signals.MOTQ.Time),1));341simIn.signals.MOTQ.ThrMixOut = single(zeros(length(simIn.signals.MOTQ.Time),1));342end343344345% Battery inputs346iVec = (sid.BAT.TimeS >= tStart & sid.BAT.TimeS <= tEnd);347simIn.signals.BAT.Time = single(sid.BAT.TimeS(iVec)-tStart);348simIn.signals.BAT.RestVoltEst = single(sid.BAT.VoltR(iVec)); % Estimated resting voltage of the battery349simIn.signals.BAT.Curr = single(sid.BAT.Curr(iVec)); % Measured battery current350simIn.signals.BAT.Res = single(sid.BAT.Res(iVec)); % Estimated battery resistance351simIn.signals.BAT.Volt = single(sid.BAT.Volt(iVec)); % Measured voltage resistance352353% Battery inital values354if simIn.param.rateCtrlVal || simIn.param.attCtrlVal || simIn.param.mdlVal || simIn.param.altCtrlVal355simIn.init.BAT.RestVoltEst = single(sid.BAT.VoltR(1));356else357simIn.init.BAT.RestVoltEst = single(0);358end359360% Baro inputs361iVec = (sid.BARO.TimeS >= tStart & sid.BARO.TimeS <= tEnd);362simIn.signals.BARO.Time = single(sid.BARO.TimeS(iVec)-tStart);363simIn.signals.BARO.Alt = single(sid.BARO.Alt(iVec)); % Calculated altitude by the barometer364simIn.signals.BARO.AirPress = single(sid.BARO.Press(iVec)); % Measured atmospheric pressure by the barometer365simIn.signals.BARO.GndTemp = single(sid.BARO.GndTemp(iVec)); % Temperature on ground, specified by parameter or measured while on ground366367% Attitude controller outputs368iVec = (sid.MOTB.TimeS >= tStart & sid.MOTB.TimeS <= tEnd);369simIn.signals.MOTB.Time = single(sid.MOTB.TimeS(iVec)-tStart);370simIn.signals.MOTB.LiftMax = single(sid.MOTB.LiftMax(iVec)); % Maximum motor compensation gain, calculated in AP_MotorsMulticopter::update_lift_max_from_batt_voltage()371simIn.signals.MOTB.ThrLimit = single(sid.MOTB.ThLimit(iVec)); % Throttle limit set due to battery current limitations, calculated in AP_MotorsMulticopter::get_current_limit_max_throttle()372simIn.signals.MOTB.ThrAvMx = single(sid.MOTB.ThrAvMx(iVec)); % Throttle average max373374% SID Inputs375% Create array for sid signals, each element containing the signal struct376if (mode == 25)377iVec = (sid.SIDD.TimeS >= tStart & sid.SIDD.TimeS <= tEnd);378for i=1:13379simIn.signals.SIDD.Time{i} = single(sid.SIDD.TimeS(iVec)-tStart);380if (i == axis)381simIn.signals.SIDD.Chirp{i} = single(sid.SIDD.Targ(iVec)); % SID test signal382else383simIn.signals.SIDD.Chirp{i} = single(zeros(length(simIn.signals.SIDD.Time{i}),1));384end385end386simIn.signals.SIDD.AccX = single(sid.SIDD.Ax(iVec));387simIn.signals.SIDD.AccY = single(sid.SIDD.Ay(iVec));388simIn.signals.SIDD.AccZ = single(sid.SIDD.Az(iVec));389simIn.signals.SIDD.GyrX = single(sid.SIDD.Gx(iVec));390simIn.signals.SIDD.GyrY = single(sid.SIDD.Gy(iVec));391simIn.signals.SIDD.GyrZ = single(sid.SIDD.Gz(iVec));392else393iVec = (sid.RATE.TimeS >= tStart & sid.RATE.TimeS <= tEnd);394for i=1:13395simIn.signals.SIDD.Time{i} = single(sid.RATE.TimeS(iVec)-tStart);396simIn.signals.SIDD.Chirp{i} = single(zeros(length(simIn.signals.SIDD.Time{i}),1));397end398simIn.signals.SIDD.AccX = single(zeros(length(simIn.signals.SIDD.Time{1}),1));399simIn.signals.SIDD.AccY = single(zeros(length(simIn.signals.SIDD.Time{1}),1));400simIn.signals.SIDD.AccZ = single(zeros(length(simIn.signals.SIDD.Time{1}),1));401simIn.signals.SIDD.GyrX = single(zeros(length(simIn.signals.SIDD.Time{1}),1));402simIn.signals.SIDD.GyrY = single(zeros(length(simIn.signals.SIDD.Time{1}),1));403simIn.signals.SIDD.GyrZ = single(zeros(length(simIn.signals.SIDD.Time{1}),1));404end405406% PID Notch Filter407simIn.param.FiltEnabled = 1;408409%% Roll Rate Controller410iVec = (sid.PIDR.TimeS >= tStart & sid.PIDR.TimeS <= tEnd);411simIn.signals.PIDR.Time = single(sid.PIDR.TimeS(iVec)-tStart);412% Inputs413simIn.signals.PIDR.Tar = single(sid.PIDR.Tar(iVec)); % target values filtered414simIn.signals.PIDR.Act = single(sid.PIDR.Act(iVec)); % actual values415simIn.signals.PIDR.Err = single(sid.PIDR.Err(iVec)); % error values416if simIn.param.rateCtrlVal || simIn.param.attCtrlVal || simIn.param.mdlVal417% Clock of Slew Limiter in ms418% Use tracked logging time of PID message in validation modes419simIn.signals.PIDR.ClockDMod = single(1000*simIn.signals.PIDR.Time);420else421simIn.signals.PIDR.ClockDMod = single(1000 * simIn.param.dt * (0:length(simIn.signals.PIDR.Time)-1)');422end423424% Outputs425simIn.signals.PIDR.FF = single(sid.PIDR.FF(iVec));426simIn.signals.PIDR.P = single(sid.PIDR.P(iVec));427simIn.signals.PIDR.I = single(sid.PIDR.I(iVec));428simIn.signals.PIDR.D = single(sid.PIDR.D(iVec));429simIn.signals.PIDR.DMod = single(sid.PIDR.Dmod(iVec));430%simIn.signals.PIDR.ILimit = single(sid.PIDR.Limit(iVec)); % comment out because variable goes to terminator block431simIn.signals.PIDR.SRate = single(sid.PIDR.SRate(iVec)); % Output slew rate of the slew limiter, stored in _output_slew_rate in AC_PID.cpp, line 161432433% parameters - Read from PARM.Value cell array with logical indexing434simIn.param.PIDR.TC = getParamVal(sid, 'ATC_INPUT_TC');435simIn.param.PIDR.FLTT_f = getParamVal(sid, 'ATC_RAT_RLL_FLTT');436simIn.param.PIDR.FLTE_f = getParamVal(sid, 'ATC_RAT_RLL_FLTE');437simIn.param.PIDR.FLTD_f = getParamVal(sid, 'ATC_RAT_RLL_FLTD');438simIn.param.PIDR.P = getParamVal(sid, 'ATC_RAT_RLL_P');439simIn.param.PIDR.I = getParamVal(sid, 'ATC_RAT_RLL_I');440simIn.param.PIDR.D = getParamVal(sid, 'ATC_RAT_RLL_D');441simIn.param.PIDR.IMAX = getParamVal(sid, 'ATC_RAT_RLL_IMAX');442simIn.param.PIDR.PDMX = getParamVal(sid, 'ATC_RAT_RLL_PDMX');443simIn.param.PIDR.FF = getParamVal(sid, 'ATC_RAT_RLL_FF'); %0.05;444simIn.param.PIDR.DFF = getParamVal(sid, 'ATC_RAT_RLL_D_FF');445simIn.param.PIDR.SR_MAX = getParamVal(sid, 'ATC_RAT_RLL_SMAX'); %5.0;446simIn.param.PIDR.SR_TAU = single(1.0); % Slew Rate Tau - not yet available as a parameter of the copter. Set to 1.0 by default (AC_PID.h, line 24).447simIn.param.PIDR.SR_FLT_f = single(25.0); % Slew Rate lowpass filter cutoff frequency. Defined in SlewLimiter.h, line 14.448449% Inital inputs450if simIn.param.rateCtrlVal || simIn.param.attCtrlVal || simIn.param.mdlVal451simIn.init.PIDR.P = single(sid.PIDR.P(1));452simIn.init.PIDR.I = single(sid.PIDR.I(1));453simIn.init.PIDR.D = single(sid.PIDR.D(1));454simIn.init.PIDR.Tar = single(sid.RATE.RDes(1)*pi/180); % Convert to radian due to conversion to degree for logging (AP_AHRS_View::Write_Rate)455simIn.init.PIDR.TarFilt = single(sid.PIDR.Tar(1));456simIn.init.PIDR.ErrFilt = single(sid.PIDR.Err(1));457simIn.init.PIDR.SROut = single(sid.PIDR.SRate(1)); % Initial value of the slew rate determined by the slew limiter. Used for both modifier_slew_rate and output_slew_rate.458if (sid.PIDR.D(1) ~= 0) % Prevent division by zero459simIn.init.PIDR.DerFilt = single(sid.PIDR.D(1))/simIn.param.PIDR.D;460else461simIn.init.PIDR.DerFilt = single(0);462end463else % Set to zero if we do not want to validate model with test run464simIn.init.PIDR.P = single(0);465simIn.init.PIDR.I = single(0);466simIn.init.PIDR.D = single(0);467simIn.init.PIDR.Tar = single(0);468simIn.init.PIDR.TarFilt = single(0);469simIn.init.PIDR.ErrFilt = single(0);470simIn.init.PIDR.DerFilt = single(0);471simIn.init.PIDR.SROut = single(0);472end473474%% Pitch Rate Controller475iVec = (sid.PIDP.TimeS >= tStart & sid.PIDP.TimeS <= tEnd);476simIn.signals.PIDP.Time = single(sid.PIDP.TimeS(iVec)-tStart);477% Inputs478simIn.signals.PIDP.Tar = single(sid.PIDP.Tar(iVec)); % target values filtered479simIn.signals.PIDP.Act = single(sid.PIDP.Act(iVec)); % actual values480simIn.signals.PIDP.Err = single(sid.PIDP.Err(iVec)); % error values481if simIn.param.rateCtrlVal || simIn.param.attCtrlVal || simIn.param.mdlVal482% Clock of Slew Limiter483% Use tracked logging time of PID message in validation modes484simIn.signals.PIDP.ClockDMod = single(1000 * simIn.signals.PIDP.Time);485else486simIn.signals.PIDP.ClockDMod = single(1000 * simIn.param.dt * (0:length(simIn.signals.PIDP.Time)-1)');487end488489% Outputs490simIn.signals.PIDP.FF = single(sid.PIDP.FF(iVec));491simIn.signals.PIDP.P = single(sid.PIDP.P(iVec));492simIn.signals.PIDP.I = single(sid.PIDP.I(iVec));493simIn.signals.PIDP.D = single(sid.PIDP.D(iVec));494simIn.signals.PIDP.DMod = single(sid.PIDP.Dmod(iVec));495%simIn.signals.PIDP.ILimit = single(sid.PIDP.Limit(iVec)); % comment out because variable goes to terminator block496simIn.signals.PIDP.SRate = single(sid.PIDP.SRate(iVec)); % Output slew rate of the slew limiter, stored in _output_slew_rate in AC_PID.cpp, line 161497498% Parameters - Read from PARM.Value cell array with logical indexing499simIn.param.PIDP.TC = getParamVal(sid, 'ATC_INPUT_TC');500simIn.param.PIDP.FLTT_f = getParamVal(sid, 'ATC_RAT_PIT_FLTT');501simIn.param.PIDP.FLTE_f = getParamVal(sid, 'ATC_RAT_PIT_FLTE');502simIn.param.PIDP.FLTD_f = getParamVal(sid, 'ATC_RAT_PIT_FLTD');503simIn.param.PIDP.P = getParamVal(sid, 'ATC_RAT_PIT_P');504simIn.param.PIDP.I = getParamVal(sid, 'ATC_RAT_PIT_I');505simIn.param.PIDP.D = getParamVal(sid, 'ATC_RAT_PIT_D');506simIn.param.PIDP.IMAX = getParamVal(sid, 'ATC_RAT_PIT_IMAX');507simIn.param.PIDP.PDMX = getParamVal(sid, 'ATC_RAT_PIT_PDMX');508simIn.param.PIDP.FF = getParamVal(sid, 'ATC_RAT_PIT_FF');509simIn.param.PIDP.DFF = getParamVal(sid, 'ATC_RAT_PIT_D_FF');510simIn.param.PIDP.SR_MAX = getParamVal(sid, 'ATC_RAT_PIT_SMAX');511simIn.param.PIDP.SR_TAU = single(1.0); % Slew Rate Tau - not yet available as a parameter of the copter. Set to 1.0 by default (AC_PID.h, line 24).512simIn.param.PIDP.SR_FLT_f = single(25.0); % Slew Rate lowpass filter cutoff frequency. Defined in SlewLimiter.h, line 14.513514% Inital inputs515if simIn.param.rateCtrlVal || simIn.param.attCtrlVal || simIn.param.mdlVal516simIn.init.PIDP.P = single(sid.PIDP.P(1));517simIn.init.PIDP.I = single(sid.PIDP.I(1));518simIn.init.PIDP.D = single(sid.PIDP.D(1));519simIn.init.PIDP.Tar = single(sid.RATE.PDes(1)*pi/180); % Convert to radian due to conversion to degree for logging (AP_AHRS_View::Write_Rate)520simIn.init.PIDP.TarFilt = single(sid.PIDP.Tar(1));521simIn.init.PIDP.ErrFilt = single(sid.PIDP.Err(1));522simIn.init.PIDP.SROut = single(sid.PIDP.SRate(1)); % Initial value of the slew rate determined by the slew limiter. Used for both modifier_slew_rate and output_slew_rate.523if (simIn.param.PIDP.D ~= 0)524simIn.init.PIDP.DerFilt = single(sid.PIDP.D(1))/simIn.param.PIDP.D;525else526simIn.init.PIDP.DerFilt = single(0);527end528else529simIn.init.PIDP.P = single(0);530simIn.init.PIDP.I = single(0);531simIn.init.PIDP.D = single(0);532simIn.init.PIDP.Tar = single(0);533simIn.init.PIDP.TarFilt = single(0);534simIn.init.PIDP.ErrFilt = single(0);535simIn.init.PIDP.DerFilt = single(0);536simIn.init.PIDP.SROut = single(0);537end538539%% Yaw Rate Controller540iVec = (sid.PIDY.TimeS >= tStart & sid.PIDY.TimeS <= tEnd);541simIn.signals.PIDY.Time = single(sid.PIDY.TimeS(iVec)-tStart);542% Inputs543simIn.signals.PIDY.Tar = single(sid.PIDY.Tar(iVec)); % target values filtered544simIn.signals.PIDY.Act = single(sid.PIDY.Act(iVec)); % actual values545simIn.signals.PIDY.Err = single(sid.PIDY.Err(iVec)); % error values546if simIn.param.rateCtrlVal || simIn.param.attCtrlVal || simIn.param.mdlVal547% Clock of Slew Limiter548% Use tracked logging time of PID message in validation modes549simIn.signals.PIDY.ClockDMod = single(1000 * simIn.signals.PIDY.Time);550else551simIn.signals.PIDY.ClockDMod = single(1000 * simIn.param.dt * (0:length(simIn.signals.PIDY.Time)-1)');552end553554% Outputs555simIn.signals.PIDY.FF = single(sid.PIDY.FF(iVec));556simIn.signals.PIDY.P = single(sid.PIDY.P(iVec));557simIn.signals.PIDY.I = single(sid.PIDY.I(iVec));558simIn.signals.PIDY.D = single(sid.PIDY.D(iVec));559simIn.signals.PIDY.DMod = single(sid.PIDY.Dmod(iVec));560%simIn.signals.PIDY.ILimit = single(sid.PIDY.Limit(iVec)); % comment out because variable goes to terminator block561simIn.signals.PIDY.SRate = single(sid.PIDY.SRate(iVec)); % Output slew rate of the slew limiter, stored in _output_slew_rate in AC_PID.cpp, line 161562563% Parameters - Read from PARM.Value cell array with logical indexing564simIn.param.PIDY.TC = getParamVal(sid, 'ATC_INPUT_TC');565simIn.param.PIDY.FLTT_f = getParamVal(sid, 'ATC_RAT_YAW_FLTT');566simIn.param.PIDY.FLTE_f = getParamVal(sid, 'ATC_RAT_YAW_FLTE');567simIn.param.PIDY.FLTD_f = getParamVal(sid, 'ATC_RAT_YAW_FLTD');568simIn.param.PIDY.P = getParamVal(sid, 'ATC_RAT_YAW_P');569simIn.param.PIDY.I = getParamVal(sid, 'ATC_RAT_YAW_I');570simIn.param.PIDY.D = getParamVal(sid, 'ATC_RAT_YAW_D');571simIn.param.PIDY.IMAX = getParamVal(sid, 'ATC_RAT_YAW_IMAX');572simIn.param.PIDY.PDMX = getParamVal(sid, 'ATC_RAT_YAW_PDMX');573simIn.param.PIDY.FF = getParamVal(sid, 'ATC_RAT_YAW_FF');574simIn.param.PIDY.DFF = getParamVal(sid, 'ATC_RAT_YAW_D_FF');575simIn.param.PIDY.SR_MAX = getParamVal(sid, 'ATC_RAT_YAW_SMAX');576simIn.param.PIDY.SR_TAU = single(1.0); % Slew Rate Tau - not yet available as a parameter of the copter. Set to 1.0 by default (AC_PID.h, line 24).577simIn.param.PIDY.SR_FLT_f = single(25.0); % Slew Rate lowpass filter cutoff frequency. Defined in SlewLimiter.h, line 14.578579% Inital inputs580if simIn.param.rateCtrlVal || simIn.param.attCtrlVal || simIn.param.mdlVal581simIn.init.PIDY.P = single(sid.PIDY.P(1));582simIn.init.PIDY.I = single(sid.PIDY.I(1));583simIn.init.PIDY.D = single(sid.PIDY.D(1));584simIn.init.PIDY.Tar = single(sid.RATE.PDes(1)*pi/180); % Convert to radian due to conversion to degree for logging (AP_AHRS_View::Write_Rate)585simIn.init.PIDY.TarFilt = single(sid.PIDY.Tar(1));586simIn.init.PIDY.ErrFilt = single(sid.PIDY.Err(1));587simIn.init.PIDY.SROut = single(sid.PIDY.SRate(1)); % Initial value of the slew rate determined by the slew limiter. Used for both modifier_slew_rate and output_slew_rate.588if (simIn.param.PIDY.D ~= 0)589simIn.init.PIDY.DerFilt = single(sid.PIDY.D(1))/simIn.param.PIDY.D;590else591simIn.init.PIDY.DerFilt = single(0);592end593else594simIn.init.PIDY.P = single(0);595simIn.init.PIDY.I = single(0);596simIn.init.PIDY.D = single(0);597simIn.init.PIDY.Tar = single(0);598simIn.init.PIDY.TarFilt = single(0);599simIn.init.PIDY.ErrFilt = single(0);600simIn.init.PIDY.DerFilt = single(0);601simIn.init.PIDY.SROut = single(0);602end603604%% RATE message605iVec = (sid.RATE.TimeS >= tStart & sid.RATE.TimeS <= tEnd);606simIn.signals.RATE.Time = single(sid.RATE.TimeS(iVec)-tStart);607608% Roll609simIn.signals.RATE.ROut = single(sid.RATE.ROut(iVec)); % Rate Controller total output (except FF)610% Rate Controller target (deg/s): Logged signal in val phase, step in opt phase.611if simIn.param.rateCtrlVal || simIn.param.attCtrlVal || simIn.param.mdlVal612simIn.signals.RATE.RDes = single(sid.RATE.RDes(iVec));613elseif simIn.param.optCtrl && axis == 10614simIn.signals.RATE.RDes = single((simIn.signals.RATE.Time > OPT.stepTime)'*OPT.stepMag); % Step at 5s615else616simIn.signals.RATE.RDes = single(zeros(numel(simIn.signals.RATE.Time), 1)); % Set to zero if axis not optimized617end618619% Pitch620simIn.signals.RATE.POut = single(sid.RATE.POut(iVec));621% Rate Controller target (deg/s): Logged signal in val phase, step in opt phase622if simIn.param.rateCtrlVal || simIn.param.attCtrlVal || simIn.param.mdlVal623simIn.signals.RATE.PDes = single(sid.RATE.PDes(iVec));624elseif simIn.param.optCtrl && axis == 11625simIn.signals.RATE.PDes = single((simIn.signals.RATE.Time > OPT.stepTime)'*OPT.stepMag); % Step at 5s626else627simIn.signals.RATE.PDes = single(zeros(numel(simIn.signals.RATE.Time), 1)); % Set to zero if axis not optimized628end629630% Yaw631simIn.signals.RATE.YOut = single(sid.RATE.YOut(iVec));632% Rate Controller target (deg/s): Logged signal in val phase, step in opt phase633if simIn.param.rateCtrlVal || simIn.param.attCtrlVal || simIn.param.mdlVal634simIn.signals.RATE.YDes = single(sid.RATE.YDes(iVec));635elseif simIn.param.optCtrl && axis == 12636simIn.signals.RATE.YDes = single((simIn.signals.RATE.Time > OPT.stepTime)'*OPT.stepMag); % Step at 5s637else638simIn.signals.RATE.YDes = single(zeros(numel(simIn.signals.RATE.Time), 1)); % Set to zero if axis not optimized639end640641% Throttle642simIn.signals.RATE.AOut = single(sid.RATE.AOut(iVec)); % Throttle command to motors643simIn.signals.RATE.A = single(sid.RATE.A(iVec)); % Vertical acceleration in earth frame644645%% Position Controller646% Default definitions647simIn.param.PSCD.THR_DZ = getParamVal(sid, 'THR_DZ'); % Deadzone above and below mid throttle in PWM microseconds. Used in Althold, Loiter, PosHold. Defined in Parameters.cpp648simIn.param.PSCD.VEL_MAX_DOWN_DFLT = single(-150); % Default descent rate in cm/s, defined in AC_PosControl.h, line 27649simIn.param.PSCD.VEL_MAX_UP_DFLT = single(250); % Default climb rate in cm/s, defined in AC_PosControl.h, line 28650simIn.param.PSCD.ACC_MAX_Z_DFLT = single(250); % Default vertical acceleration cm/s/s, defined in AC_PosControl.h, line 30651simIn.param.PSCD.JERK_MAX_Z_DFLT = single(500); % Default vertical jerk, defined as m/s/s/s in AC_PosControl.h, line 31. Converted to cm/s/s/s in AC_PosControl.cpp, line 318.652653simIn.param.PSCD.VEL_MAX_DN = getParamVal(sid, 'PILOT_SPEED_DN'); % Maximum vertical descending velocity in cm/s, defined in parameters.cpp, line 906654simIn.param.PSCD.VEL_MAX_UP = getParamVal(sid, 'PILOT_SPEED_UP'); % Maximum vertical ascending velocity in cm/s, defined in parameters.cpp, line 223655simIn.param.PSCD.ACC_MAX_Z = getParamVal(sid, 'PILOT_ACCEL_Z'); % Maximum vertical acceleration used when pilot is controlling the altitude, parameters.cpp, line 232656simIn.param.PSCD.JERK_MAX_Z = getParamVal(sid, 'PSC_JERK_D'); % Jerk limit of vertical kinematic path generation in m/s^3. Determines how quickly aircraft changes acceleration target657simIn.param.PSCD.OVERSPEED_GAIN_Z = single(2); % gain controlling rate at which z-axis speed is brought back within SPEED_UP and SPEED_DOWN range, defined in AC_PosControl.h658%% Position Controller z659660% Parameters z position controller661simIn.param.PSCD.P_POS = getParamVal(sid, 'PSC_D_POS_P'); % P gain of the vertical position controller662663% Parameters z velocity controller664simIn.param.PSCD.P_VEL = getParamVal(sid, 'PSC_D_VEL_P'); % P gain of the vertical velocity controller665simIn.param.PSCD.I_VEL = getParamVal(sid, 'PSC_D_VEL_I'); % I gain of the vertical velocity controller666simIn.param.PSCD.D_VEL = getParamVal(sid, 'PSC_D_VEL_D'); % D gain of the vertical velocity controller667simIn.param.PSCD.IMAX_VEL = getParamVal(sid, 'PSC_D_VEL_IMAX'); % I gain maximu vertical velocity controller668simIn.param.PSCD.FF_VEL = getParamVal(sid, 'PSC_D_VEL_FF'); % Feed Forward gain of the vertical velocity controller669simIn.param.PSCD.FLTE_VEL = getParamVal(sid, 'PSC_D_VEL_FLTE'); % Cutoff frequency of the error filter (in Hz)670simIn.param.PSCD.FLTD_VEL = getParamVal(sid, 'PSC_D_VEL_FLTD'); % Cutoff frequency of the D term filter (in Hz)671simIn.param.PSCD.CTRL_RATIO_INIT = single(2.0); % Initial value of _vel_z_control_ratio, defined in PosControl.h, line 456672673% Parameters z acceleration controller674simIn.param.PIDA.P = getParamVal(sid, 'PSC_D_ACC_P'); % P gain of the vertical acceleration controller675simIn.param.PIDA.I = getParamVal(sid, 'PSC_D_ACC_I'); % I gain of the vertical acceleration controller676simIn.param.PIDA.D = getParamVal(sid, 'PSC_D_ACC_D'); % D gain of the vertical acceleration controller677simIn.param.PIDA.IMAX = getParamVal(sid, 'PSC_D_ACC_IMAX'); % I gain maximu vertical acceleration controller678simIn.param.PIDA.PDMX = getParamVal(sid, 'PSC_D_ACC_PDMX');679simIn.param.PIDA.FF = getParamVal(sid, 'PSC_D_ACC_FF'); % Feed Forward gain of the vertical acceleration controller680simIn.param.PIDA.DFF = getParamVal(sid, 'PSC_D_ACC_D_FF'); % Derivative Feed Forward gain of the vertical acceleration controller681simIn.param.PIDA.FLTE_f = getParamVal(sid, 'PSC_D_ACC_FLTE'); % Cutoff frequency of the error filter (in Hz)682simIn.param.PIDA.FLTD_f = getParamVal(sid, 'PSC_D_ACC_FLTD'); % Cutoff frequency of the D term filter (in Hz)683simIn.param.PIDA.FLTT_f = getParamVal(sid, 'PSC_D_ACC_FLTT'); % Cutoff frequency of the target filter (in Hz)684simIn.param.PIDA.SR_MAX = getParamVal(sid, 'PSC_D_ACC_SMAX'); % Upper limit of the slew rate produced by combined P and D gains685simIn.param.PIDA.SR_TAU = single(1.0); % Slew Rate Tau - not yet available as a parameter of the copter. Set to 1.0 by default (AC_PID.h, line 24).686simIn.param.PIDA.SR_FLT_f = single(25.0); % Slew Rate lowpass filter cutoff frequency. Defined in SlewLimiter.h, line 14.687688% Read signals for z position controller if PSCD message was logged689if isfield(sid, 'PSCD')690% Signals of PSCD message691iVec = (sid.PSCD.TimeS >= tStart & sid.PSCD.TimeS <= tEnd);692simIn.signals.PSCD.Time = single(sid.PSCD.TimeS(iVec)-tStart);693% Inputs - Multiply by 100 to get cm as used in controller694% Inversion of signals necessary due to inverted logging695simIn.signals.PSCD.zPosTar = single(-sid.PSCD.TPD(iVec)*100); % Target z-Position, calculated in set_pos_target_z_from_climb_rate_cm()696simIn.signals.PSCD.zPosAct = single(-sid.PSCD.PD(iVec)*100); % Actual z-Position, obtained from INAV697simIn.signals.PSCD.zVelDes = single(-sid.PSCD.DVD(iVec)*100); % Desired z-Velocity, calculated in set_pos_target_z_from_climb_rate_cm()698simIn.signals.PSCD.zVelAct = single(-sid.PSCD.VD(iVec)*100); % Actual z-Velocity, obtained from INAV699simIn.signals.PSCD.zVelTar = single(-sid.PSCD.TVD(iVec)*100); % Target z-Velocity, calculated in update_z_controller()700simIn.signals.PSCD.zAccDes = single(-sid.PSCD.DAD(iVec)*100); % Desired z-Acceleration, calculated in set_pos_target_z_from_climb_rate_cm()701simIn.signals.PSCD.zAccAct = single(-sid.PSCD.AD(iVec)*100); % Actual z-Acceleration, obtained from AHRS702simIn.signals.PSCD.zAccTar = single(-sid.PSCD.TAD(iVec)*100); % Target z-Acceleration, calculated in update_z_controller()703704% Signals of PIDA message705iVec = (sid.PIDA.TimeS >= tStart & sid.PIDA.TimeS <= tEnd);706simIn.signals.PIDA.Time = single(sid.PIDA.TimeS(iVec)-tStart);707% Inputs PID z acceleration708simIn.signals.PIDA.Err = single(sid.PIDA.Err(iVec)); % Error between target and actual z-acceleration709simIn.signals.PIDA.Tar = single(sid.PIDA.Tar(iVec));710simIn.signals.PIDA.Act = single(sid.PIDA.Act(iVec));711if simIn.param.rateCtrlVal || simIn.param.attCtrlVal || simIn.param.mdlVal || simIn.param.altCtrlVal712% Clock of Slew Limiter713% Use tracked logging time of PID message in validation modes714simIn.signals.PIDA.ClockDMod = single(1000 * simIn.signals.PIDA.Time);715else716simIn.signals.PIDA.ClockDMod = single(1000 * simIn.param.dt * (0:length(simIn.signals.PIDA.Time)-1)');717end718% Outputs PID z acceleration719simIn.signals.PIDA.FF = single(sid.PIDA.FF(iVec));720simIn.signals.PIDA.P = single(sid.PIDA.P(iVec));721simIn.signals.PIDA.I = single(sid.PIDA.I(iVec));722simIn.signals.PIDA.D = single(sid.PIDA.D(iVec));723simIn.signals.PIDA.DMod = single(sid.PIDA.Dmod(iVec));724%simIn.signals.PIDA.ILimit = single(sid.PIDA.Limit(iVec)); % comment out because variable goes to terminator block725simIn.signals.PIDA.SRate = single(sid.PIDA.SRate(iVec));726727% Inital inputs728if simIn.param.rateCtrlVal || simIn.param.attCtrlVal || simIn.param.mdlVal || simIn.param.altCtrlVal729% Initial actual values - in meter730simIn.init.PSCD.posAct = single(-sid.PSCD.PD(1));731simIn.init.PSCD.velAct = single(-sid.PSCD.VD(1));732simIn.init.PSCD.accAct = single(-sid.PSCD.AD(1));733734% Init the position controller to the current position, velocity735% and acceleration (from AC_PosControl::init_z()) in cm736simIn.init.PIDA.posTar = single(-sid.PSCD.TPD(1)*100);737simIn.init.PIDA.velDes = single(-sid.PSCD.DVD(1)*100);738simIn.init.PIDA.accDes = single(min(max(-sid.PSCD.DAD(1)*100, -simIn.param.PSCD.ACC_MAX_Z_DFLT) ,simIn.param.PSCD.ACC_MAX_Z_DFLT));739740simIn.init.PIDA.P = single(sid.PIDA.P(1));741simIn.init.PIDA.I = single(simIn.signals.CTUN.ThrIn(1) - simIn.signals.CTUN.ThrHov(1)) * 1000 ...742- simIn.param.PIDA.P * (-sid.PSCD.TAD(1)*100 - (-sid.PSCD.AD(1))*100) ...743- simIn.param.PIDA.FF * sid.PIDA.Tar(1); % Integrator init. according to AC_PosControl::init_z_controller()744simIn.init.PIDA.D = single(sid.PIDA.D(1));745simIn.init.PIDA.TarFilt = single(sid.PIDA.Tar(1));746simIn.init.PIDA.ErrFilt = single(sid.PIDA.Err(1));747simIn.init.PIDA.SROut = single(sid.PIDA.SRate(1)); % Initial value of the slew rate determined by the slew limiter. Used for both modifier_slew_rate and output_slew_rate.748if (simIn.param.PIDA.D ~= 0)749simIn.init.PIDA.DerFilt = single(sid.PIDA.D(1))/PSC_ACC_Z.param.D; % Divide through D gain to obtain inital D input750else751simIn.init.PIDA.DerFilt = single(0);752end753else754% Initial actual values755simIn.init.PSCD.posAct = single(0);756simIn.init.PSCD.velAct = single(0);757simIn.init.PSCD.accAct = single(0);758759simIn.init.PIDA.posTar = single(0);760simIn.init.PIDA.velDes = single(0);761simIn.init.PIDA.accDes = single(0);762763simIn.init.PIDA.P = single(0);764simIn.init.PIDA.I = single(0);765simIn.init.PIDA.D = single(0);766simIn.init.PIDA.TarFilt = single(0);767simIn.init.PIDA.ErrFilt = single(0);768simIn.init.PIDA.DerFilt = single(0);769simIn.init.PIDA.SROut = single(0);770end771else772% Set all signals to zero, if PSCD message was not logged and z773% controller has been deactivated774iVec = (sid.RATE.TimeS >= tStart & sid.RATE.TimeS <= tEnd);775simIn.signals.PSCD.Time = single(sid.RATE.TimeS(iVec)-tStart);776simIn.signals.PSCD.zPosTar = single(zeros(length(simIn.signals.PSCD.Time),1)); % Target z-Position, calculated in set_pos_target_z_from_climb_rate_cm()777simIn.signals.PSCD.zPosAct = single(zeros(length(simIn.signals.PSCD.Time),1)); % Actual z-Position, obtained from INAV778simIn.signals.PSCD.zVelDes = single(zeros(length(simIn.signals.PSCD.Time),1)); % Desired z-Velocity, calculated in set_pos_target_z_from_climb_rate_cm()779simIn.signals.PSCD.zVelAct = single(zeros(length(simIn.signals.PSCD.Time),1)); % Actual z-Velocity, obtained from INAV780simIn.signals.PSCD.zVelTar = single(zeros(length(simIn.signals.PSCD.Time),1)); % Target z-Velocity, calculated in update_z_controller()781simIn.signals.PSCD.zAccDes = single(zeros(length(simIn.signals.PSCD.Time),1)); % Desired z-Acceleration, calculated in set_pos_target_z_from_climb_rate_cm()782simIn.signals.PSCD.zAccAct = single(zeros(length(simIn.signals.PSCD.Time),1)); % Actual z-Acceleration, obtained from AHRS783simIn.signals.PSCD.zAccTar = single(zeros(length(simIn.signals.PSCD.Time),1)); % Target z-Acceleration, calculated in update_z_controller()784785% Signals of PIDA message786simIn.signals.PIDA.Time = single(simIn.signals.RATE.Time)-tStart;787% Inputs PID z acceleration788simIn.signals.PIDA.Err = single(zeros(length(simIn.signals.PIDA.Time),1)); % Error between target and actual z-acceleration789simIn.signals.PIDA.ClockDMod = single(zeros(length(simIn.signals.PIDA.Time),1)); % Clock of Slew Limiter790791% Outputs PID z acceleration792simIn.signals.PIDA.FF = single(zeros(length(simIn.signals.PIDA.Time),1));793simIn.signals.PIDA.P = single(zeros(length(simIn.signals.PIDA.Time),1));794simIn.signals.PIDA.I = single(zeros(length(simIn.signals.PIDA.Time),1));795simIn.signals.PIDA.D = single(zeros(length(simIn.signals.PIDA.Time),1));796simIn.signals.PIDA.DMod = single(zeros(length(simIn.signals.PIDA.Time),1));797simIn.signals.PIDA.ILimit = single(zeros(length(simIn.signals.PIDA.Time),1));798simIn.signals.PIDA.SRate = single(zeros(length(simIn.signals.PIDA.Time),1));799simIn.signals.PIDA.Act = single(zeros(length(simIn.signals.PIDA.Time),1));800simIn.signals.PIDA.Tar = single(zeros(length(simIn.signals.PIDA.Time),1));801802% Initial inputs803% Initial actual values804simIn.init.PSCD.posAct = single(0);805simIn.init.PSCD.velAct = single(0);806simIn.init.PSCD.accAct = single(0);807808simIn.init.PIDA.posTar = single(0);809simIn.init.PIDA.velDes = single(0);810simIn.init.PIDA.accDes = single(0);811812simIn.init.PIDA.P = single(0);813simIn.init.PIDA.I = single(0);814simIn.init.PIDA.D = single(0);815simIn.init.PIDA.TarFilt = single(0);816simIn.init.PIDA.ErrFilt = single(0);817simIn.init.PIDA.DerFilt = single(0);818simIn.init.PIDA.SROut = single(0);819end820821822% Real Flight Signals of PID z velocity - only load if log messages823% exists824if isfield(sid, 'PCVZ')825iVec = (sid.PCVZ.TimeS >= tStart & sid.PCVZ.TimeS <= tEnd);826simIn.signals.PCVZ.Time = single(sid.PCVZ.TimeS(iVec)-tStart);827simIn.signals.PCVZ.Err = single(sid.PCVZ.Err(iVec));828simIn.signals.PCVZ.P = single(sid.PCVZ.P(iVec));829simIn.signals.PCVZ.I = single(sid.PCVZ.I(iVec));830simIn.signals.PCVZ.D = single(sid.PCVZ.D(iVec));831simIn.signals.PCVZ.FF = single(sid.PCVZ.FF(iVec));832else % Set to zero otherwise833iVec = (sid.RATE.TimeS >= tStart & sid.RATE.TimeS <= tEnd);834simIn.signals.PCVZ.Time = single(sid.RATE.TimeS(iVec)-tStart);835simIn.signals.PCVZ.Err = single(zeros(length(simIn.signals.PCVZ.Time),1));836simIn.signals.PCVZ.P = single(zeros(length(simIn.signals.PCVZ.Time),1));837simIn.signals.PCVZ.I = single(zeros(length(simIn.signals.PCVZ.Time),1));838simIn.signals.PCVZ.D = single(zeros(length(simIn.signals.PCVZ.Time),1));839simIn.signals.PCVZ.FF = single(zeros(length(simIn.signals.PCVZ.Time),1));840end841842%% Load identified plant models data843if simIn.param.optCtrl || simIn.param.mdlVal && exist('idModel', 'var')844% Roll845if isempty(findobj(idModel, 'axis', 'RLL'))846simIn.models.RollAxis = idpoly(tf(1, [1 1], simIn.param.dt));847else848model = findobj(idModel, 'axis', 'RLL');849% If more than one model is found, let user choose850if length(model) > 1851mdlIdx = input('More than one model found for the roll axis. Input index of desired model: ');852else853mdlIdx = 1;854end855simIn.models.RollAxis = idss(c2d(model(mdlIdx).tfModel, simIn.param.dt));856% Decrease delay to account for the additional feedback delay857simIn.models.RollAxis.InputDelay = simIn.models.RollAxis.InputDelay-1;858end859% Pitch860if isempty(findobj(idModel, 'axis', 'PIT'))861simIn.models.PitchAxis = idpoly(tf(1, [1 1], simIn.param.dt));862else863model = findobj(idModel, 'axis', 'PIT');864% If more than one model is found, let user choose865if length(model) > 1866mdlIdx = input('More than one model found for the pitch axis. Input index of desired model: ');867else868mdlIdx = 1;869end870simIn.models.PitchAxis = idss(c2d(model(mdlIdx).tfModel, simIn.param.dt));871simIn.models.PitchAxis.InputDelay = simIn.models.PitchAxis.InputDelay-1;872end873% Yaw874if isempty(findobj(idModel, 'axis', 'YAW'))875simIn.models.YawAxis = idpoly(tf(1, [1 1], simIn.param.dt));876else877model = findobj(idModel, 'axis', 'YAW');878% If more than one model is found, let user choose879if length(model) > 1880mdlIdx = input('More than one model found for the yaw axis. Input index of desired model: ');881else882mdlIdx = 1;883end884simIn.models.YawAxis = idss(c2d(model(mdlIdx).tfModel, simIn.param.dt));885simIn.models.YawAxis.InputDelay = simIn.models.YawAxis.InputDelay-1;886end887% Vertical Motion - Throttle888if isempty(findobj(idModel, 'axis', 'THR'))889simIn.models.RollAxis = idpoly(tf(1, [1 1], simIn.param.dt));890else891model = findobj(idModel, 'axis', 'THR');892% If more than one model is found, let user choose893if length(model) > 1894mdlIdx = input('More than one model found for the vertical axis. Input index of desired model: ');895else896mdlIdx = 1;897end898simIn.models.VerticalAxis = idss(c2d(model(mdlIdx).tfModel, simIn.param.dt));899% Decrease delay to account for the additional feedback delay900simIn.models.VerticalAxis.InputDelay = simIn.models.VerticalAxis.InputDelay-1;901end902else % Create dummy models of optimization is not active903simIn.models.RollAxis = idpoly(tf(1, [1 1], simIn.param.dt));904simIn.models.PitchAxis = idpoly(tf(1, [1 1], simIn.param.dt));905simIn.models.YawAxis = idpoly(tf(1, [1 1], simIn.param.dt));906simIn.models.VerticalAxis = idpoly(tf(1, [1 1], simIn.param.dt));907end908909% Initial values910if simIn.param.mdlVal && mode == 25911simIn.models.RollInit = single(sid.SIDD.Gx(1)*pi/180);912simIn.models.PitchInit = single(sid.SIDD.Gy(1)*pi/180);913simIn.models.YawInit = single(sid.SIDD.Gz(1)*pi/180);914simIn.models.VerticalOutInit = single(sid.SIDD.Az(1));915simIn.models.VerticalInInit = single(sid.RATE.AOut(1));916else917simIn.models.RollInit = single(0);918simIn.models.PitchInit = single(0);919simIn.models.YawInit = single(0);920simIn.models.VerticalOutInit = single(-9.81);921simIn.models.VerticalInInit = single(sid.RATE.AOut(1));922end923924%% Delete all irrelevant data925clear i dist start thr_man rel_msg mode param_names msgs tEnd tStart simMode926clear phase_des runOutsideLoop mdlIdx pitchCh rollCh yawCh iVec Fs axis dt927clear simMode thrCh928929930