From 623b9512d5de0d80426d8d12f9b2236c13ed1921 Mon Sep 17 00:00:00 2001 From: George Zogopoulos-Papaliakos Date: Fri, 5 Apr 2024 12:28:05 +0200 Subject: [PATCH] Feature/mode annotations (#94) Now vertical lines signifying the instances where flight mode transitions occurred are plotted by default. Thanks to JadeLogan over at the Ardupilot Discuss who submitted a draft of the feature! --- Ardupilog.m | 258 +++++++++++++++++++++++++++++++++++++++++++++++++++- README.md | 28 ++++-- cover.png | Bin 0 -> 32761 bytes 3 files changed, 278 insertions(+), 8 deletions(-) create mode 100644 cover.png diff --git a/Ardupilog.m b/Ardupilog.m index 0453363..7b1b4ea 100644 --- a/Ardupilog.m +++ b/Ardupilog.m @@ -21,6 +21,7 @@ FMTLen = 89; valid_msgheader_cell = cell(0); % A cell array for reconstructing LineNo (line-number) for all entries bootDatenumUTC = NaN; % The MATLAB datenum (days since Jan 00, 0000) at APM microcontroller boot (TimeUS = 0) + flagPlotModes = true; end methods @@ -821,7 +822,53 @@ function delete(obj) label = ''; end end + + + function enableModePlot(obj) + % Enable plotting of flight mode change indications. + obj.flagPlotModes = true; + end + + + function disableModePlot(obj) + % Enable plotting of flight mode change indications. + obj.flagPlotModes = false; + end + + function ht = PlotModeChanges(obj, modeTime, mode, axh) + % PlotModeChanges Plot vertical lines when control mode changes using flight + % data from ArduCopter + % + % Inputs: + % modeTime : [vector] (sec) time when mode change occurs + % mode : [vector] numerical value indicating mode + % axh : [scalar] axis handle for plotting - if empty use current figure + % varargin(2:end) : Name-value pair arguments to format the vertical lines + % indicating mode change + % + % Outputs: + % ht : handle to graphics indicating mode change + % + % Get the map of control mode for the correct platform + if isempty(obj.platform) + return + end + modesStruct = FlightModes(obj.platform); + numModeChanges = length(mode); + + hold(axh,'on') + ylim = get(axh, 'Ylim'); + for idx = 1:numModeChanges + ht = plot(axh, modeTime(idx)*ones(1,2), ylim); + ht.Color = [getModeColour(modesStruct, mode(idx)), 0.5]; + ht.Tag = getModeName(modesStruct, mode(idx)); + end + % set the data cursor to display the mode type + figh = GetFigureHandle(axh); + CustomDataCursor(figh); + + end function newAxisHandle = plot(obj, msgFieldName, style, axisHandle) % Plot a timeseries of a message field @@ -866,6 +913,10 @@ function delete(obj) plot(axisHandle, obj.(messageName).TimeS, obj.(messageName).(fieldName), style); newAxisHandle = axisHandle; end + + if obj.flagPlotModes + obj.PlotModeChanges(obj.MODE.TimeS, obj.MODE.Mode, newAxisHandle); + end end @@ -924,8 +975,7 @@ function delete(obj) end end - end - + end methods(Access=protected) @@ -974,3 +1024,207 @@ function delete(obj) return; end + +function modeStruct = FlightModes(v_type) + % Return the flight mode number used in ArduCopter + % + % INPUTS: + % v_type: String with the vehicle type. One of {ArduPlane, ArduCopter, + % ArduRover, ArduSub, ArduBlimp} + % + % OUTPUTS: + % modeStruct: A struct containing mode information. + + % ref: https://github.com/ArduPilot/ardupilot/blob/master/ArduPlane/mode.h + PlaneModes = { + 'MANUAL' , 0, [0.00 0 1.00]; + 'CIRCLE' , 1, [0.75 0.75 0]; + 'STABILIZE' , 2, [1.00 0 0]; + 'TRAINING' , 3, [0.00 0 0]; + 'ACRO' , 4, [0.25 0.25 0.25]; + 'FLY_BY_WIRE_A', 5, [0 0.75 0.75]; + 'FLY_BY_WIRE_B', 6, [0.75 0.25 0.25]; + 'CRUISE' , 7, [0.95 0.95 0]; + 'AUTOTUNE' , 8, [0.25 0.25 0.75]; + 'AUTO' , 10, [0.75 0.75 0.75]; + 'RTL' , 11, [0.00 1 0]; + 'LOITER' , 12, [0.76 0.57 0.17]; + 'TAKEOFF' , 13, [0.75 0 0.75]; + 'AVOID_ADSB' , 14, [0 0.5 0]; + 'GUIDED' , 15, [0.54 0.63 0.22]; + 'INITIALISING' , 16, [0.34 0.57 0.92]; + 'QSTABILIZE' , 17, [1.00 0.1 0.6]; + 'QHOVER' , 18, [0.88 0.75 0.73]; + 'QLOITER' , 19, [0.10 0.49 0.47]; + 'QLAND' , 20, [0.66 0.34 0.65]; + 'QRTL' , 21, [0.99 0.41 0.23]; + 'QAUTOTUNE' , 22, [0.58 0.49 0.25]; + 'QACRO' , 23, [0.10 0.49 0.47]; + 'THERMAL' , 24, [0.66 0.34 0.65]; + 'LOITER_ALT_QLAND', 25, [0.99 0.41 0.23]; + }; + + % ref: https://github.com/ArduPilot/ardupilot/blob/master/ArduCopter/mode.h + CopterModes = { + % name, index, colour + 'STABILIZE', 0, [0.00 0 1.00]; % blue, manual airframe angle with manual throttle + 'ACRO', 1, [0.75 0.75 0]; % yellowish gold, manual body-frame angular rate with manual throttle + 'ALT_HOLD', 2, [1.00 0 0]; % red, manual airframe angle with automatic throttle + 'AUTO', 3, [0.00 0 0]; % black, fully automatic waypoint control using mission commands + 'GUIDED', 4, [0.25 0.25 0.25]; % fully automatic fly to coordinate or fly at velocity/direction using GCS immediate commands + 'LOITER', 5, [0 0.75 0.75]; % teal, automatic horizontal acceleration with automatic throttle + 'RTL', 6, [0.75 0.25 0.25]; % brick red, automatic return to launching point + 'CIRCLE', 7, [0.95 0.95 0]; % yellow, automatic circular flight with automatic throttle + 'LAND', 9, [0.25 0.25 0.75]; % automatic landing with horizontal position control + 'DRIFT', 11, [0.75 0.75 0.75]; % semi-autonomous position, yaw and throttle control + 'SPORT', 13, [0.00 1 0]; % bright green, manual earth-frame angular rate control with manual throttle + 'FLIP', 14, [0.76 0.57 0.17]; % automatically flip the vehicle on the roll axis + 'AUTOTUNE', 15, [0.75 0 0.75]; % purple, automatically tune the vehicle's roll and pitch gains + 'POSHOLD', 16, [0 0.5 0]; % dark green, automatic position hold with manual override, with automatic throttle + 'BRAKE', 17, [0.54 0.63 0.22]; % full-brake using inertial/GPS system, no pilot input + 'THROW', 18, [0.34 0.57 0.92]; % throw to launch mode using inertial/GPS system, no pilot input + 'AVOID_ADSB', 19, [1.00 0.1 0.6]; % automatic avoidance of obstacles in the macro scale - e.g. full-sized aircraft + 'GUIDED_NOGPS', 20, [0.88 0.75 0.73]; % guided mode but only accepts attitude and altitude + 'SMART_RTL', 21, [0.10 0.49 0.47]; % SMART_RTL returns to home by retracing its steps + 'FLOWHOLD ', 22, [0.66 0.34 0.65]; % FLOWHOLD holds position with optical flow without rangefinder + 'FOLLOW ', 23, [0.99 0.41 0.23]; % follow attempts to follow another vehicle or ground station + 'ZIGZAG ', 24, [0.58 0.49 0.25]; % ZIGZAG mode is able to fly in a zigzag manner with predefined point A and point B + 'SYSTEMID ', 25, [0.10 0.49 0.47]; % System ID mode produces automated system identification signals in the controllers + 'AUTOROTATE', 26, [0.66 0.34 0.65]; % Autonomous autorotation + 'AUTO_RTL', 27, [0.99 0.41 0.23]; % Auto RTL, this is not a true mode, AUTO will report as this mode if entered to perform a DO_LAND_START Landing sequence + 'TURTLE', 28, [0.23 0.77 1.00]; % Flip over after crash + }; + + % ref: https://github.com/ArduPilot/ardupilot/blob/master/Rover/mode.h + RoverModes = { + 'MANUAL' , 0, [0.00 0 1.00]; + 'ACRO' , 1, [0.75 0.75 0]; + 'STEERING' , 3, [1.00 0 0]; + 'HOLD' , 4, [0.00 0 0]; + 'LOITER' , 5, [0.25 0.25 0.25]; + 'FOLLOW' , 6, [0 0.75 0.75]; + 'SIMPLE' , 7, [0.75 0.25 0.25]; + 'DOCK' , 8, [0.95 0.95 0]; + 'CIRCLE' , 9, [0.25 0.25 0.75]; + 'AUTO' , 10, [0.75 0.75 0.75]; + 'RTL' , 11, [0.00 1 0]; + 'SMART_RTL' , 12, [0.76 0.57 0.17]; + 'GUIDED' , 15, [0.75 0 0.75]; + 'INITIALISING', 16, [0 0.5 0]; + }; + + % ref: https://github.com/ArduPilot/ardupilot/blob/master/ArduSub/mode.h + SubModes = { + 'STABILIZE', 0, [0.00 0 1.00]; % manual angle with manual depth/throttle + 'ACRO', 1, [0.75 0.75 0]; % manual body-frame angular rate with manual depth/throttle + 'ALT_HOLD', 2, [1.00 0 0]; % manual angle with automatic depth/throttle + 'AUTO', 3, [0.00 0 0]; % fully automatic waypoint control using mission commands + 'GUIDED', 4, [0.25 0.25 0.25]; % fully automatic fly to coordinate or fly at velocity/direction using GCS immediate commands + 'CIRCLE', 7, [0 0.75 0.75]; % automatic circular flight with automatic throttle + 'SURFACE', 9, [0.75 0.25 0.25]; % automatically return to surface, []; pilot maintains horizontal control + 'POSHOLD', 16, [0.95 0.95 0]; % automatic position hold with manual override, []; with automatic throttle + 'MANUAL', 19, [0.25 0.25 0.75]; % Pass-through input with no stabilization + 'MOTOR_DETECT', 20, [0.75 0.75 0.75]; % Automatically detect motors orientation + 'SURFTRAK', 21, [0.00 1 0]; % Track distance above seafloor (hold range) + }; + + % ref: https://github.com/ArduPilot/ardupilot/blob/master/Blimp/mode.h + BlimpModes = { + 'LAND', 0, [0.00 0 1.00]; % currently just stops moving + 'MANUAL', 1, [0.75 0.75 0]; % manual control + 'VELOCITY', 2, [1.00 0 0]; % velocity mode + 'LOITER', 3, [0.00 0 0]; % loiter mode (position hold) + 'RTL', 4, [0.25 0.25 0.25]; % rtl + }; + + switch v_type + case 'ArduCopter' + modeStruct = CopterModes; + case 'ArduPlane' + modeStruct = PlaneModes; + case 'ArduRover' + modeStruct = RoverModes; + case 'ArduSub' + modeStruct = SubModes; + case 'ArduBlimp' + modeStruct = BlimpModes; + otherwise + error('Unsupported mode map for vehicle type %s', v_type); + end +end + + +function modeName = getModeName(modeStruct, modeNo) +% Retrieve the mode name from the mode map. +% +% INPUTS: +% modeStruct: The output of FlightModes(). +% +% OUTPUTS: +% modeName: A string with the mode name. + names = modeStruct(:,1); + indices = cell2mat(modeStruct(:,2)); + index = find(indices==modeNo, 1); + modeName = names{index}; +end + +function modeColour = getModeColour(modeStruct, modeNo) +% Retrieve the mode name from the mode map. +% +% INPUTS: +% modeStruct: The output of FlightModes(). +% +% OUTPUTS: +% modeColour: An array with an RGB specification. + colours = modeStruct(:,3); + indices = cell2mat(modeStruct(:,2)); + index = find(indices==modeNo, 1); + modeColour = colours{index}; +end + + +function figh = GetFigureHandle(ob) + % Obtain the figure handle of an axis handle. + temp = ob.Parent; + if ~isa(temp, 'matlab.ui.Figure') + temp = GetFigureHandle(temp); + end + figh = temp; +end + + +function CustomDataCursor(fh, varargin) +% Assign a custom data tip message for a Figure. + +dcm_obj = datacursormode(fh); +set(dcm_obj,'UpdateFcn',{@myupdatefcn}) +end + + +function txt = myupdatefcn(~,event_obj) +% Customizes text of data tips. + pos = get(event_obj,'Position'); + + % If the tag field of the selected object is not blank, it means that + % we are clicking on a mode change line. + if ~isempty(event_obj.Target.Tag) + txt = {['Time: ',num2str(pos(1))],... + ['Mode: ', event_obj.Target.Tag] + }; + else % This is just a normal datapoint. + txt = {['X: ',num2str(pos(1))],... + ['Y: ',num2str(pos(2))] + }; + + % If there is a Z-coordinate in the position, display it as well + if length(pos) > 2 + txt{end+1} = ['Z: ',num2str(pos(3))]; + end + end + + % If the userdata field is not blank, display it + temp = event_obj.Target.UserData; + if ~isempty(temp) + txt{end+1} = ['T: ' num2str(temp,'%.2f')]; + end +end \ No newline at end of file diff --git a/README.md b/README.md index b035f4f..2200dff 100644 --- a/README.md +++ b/README.md @@ -3,6 +3,8 @@ An Ardupilot log to MATLAB converter. Primarily intended to facilitate processin It is very efficient: The time required to parse large logs is in the order of seconds. +![cover](cover.png) + ## Supported log formats Currently, only Dataflash logs (.bin files) are supported. @@ -32,7 +34,7 @@ Each `LogMsgGroup` under a log contains the following members: ### Plotting To plot a specific numerical data field from a specific message, you can enter: ```matlab -log.plot('/'); +log.plot('/') ``` The full command allows for passnig a Matlab-style line style and an existing Axes Handle to plot in. @@ -43,26 +45,40 @@ ah = log.plot('/',,) For example, to plot the `Pitch` field from the `AHR2` message in red, enter: ```matlab -log.plot('AHR2/Pitch', 'r'); +log.plot('AHR2/Pitch', 'r') ``` and to plot more than one series in the same figure, you can capture the axis handle of the first plot: ```matlab -ah = log.plot('AHR2/Roll'); -log.plot('AHR2/Pitch', 'r', ah); +ah = log.plot('AHR2/Roll') +log.plot('AHR2/Pitch', 'r', ah) ``` +#### Mode change lines + +By default `ardupilog` plots vertical lines that signify mode changes. +You can inspect the mode name by clicking on them with the Data Cursor. + +You can disable mode line plotting with `log.disableModePlot();` + +You can re-enable mode line plotting with `log.enableModePlot();` + ### Message Filter You can optionally filter the log file for specific message types: ```matlab log_filtered = log.filterMsgs() -log_filtered = Ardupilog(') +log_filtered = Ardupilog('', ) ``` `msgFilter` can be: * Either a vector of integers, representing the message IDs you want to convert. * Or a cell array of strings. Each string is the literal name of the message type. +**Example** +```matlab +log_filtered = log.filterMsgs({'POS', 'AHR2'}) +``` + ### Slicing Typically, only a small portion of the flight log is of interest. Ardupilog supports *slicing* logs to a specific start-end interval with: ```matlab @@ -86,7 +102,7 @@ requires the `ardupilog` library to exist in the current MATLAB path. Creating a more basic struct file, free of the `ardupilog` dependency, is possible with: ```matlab -log_struct = log.getStruct(); +log_struct = log.getStruct() ``` `log_struct` does not need the `ardupilog` source code accompanying it to be shared. diff --git a/cover.png b/cover.png new file mode 100644 index 0000000000000000000000000000000000000000..b61b60e09f22d1b1ffba638da7f7c8f7a26cbe48 GIT binary patch literal 32761 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 z zk00|178e$t%j-6`vLZ@INcaY1X#49_IZFT_(c7>Xz`;RwqdPbF;)~_2QKA3oX7!VCvWC z1-i&gG@-^azlS_ne%S3xZ>3Tp))$0RK1)Rz$1~cu_!|5}%x03r^2@ zcfU3FhNh;2HU{>*1w}>IY-~t;e0;u@IB{sC%0|F>A|Ki^l$^HLoyZR##y~DAFE0no z=)mxJSucbeIHr*$xUqujX3ZaLj41-Ik|Q@KKCz^3F_AA$8?JH-I{t=$_$t>-a|g9w zJE>fLKA7KX{bP{EaW2D$tt@yz$!~Bl_&c(_u!29%SL_-1qP@*CgUX!M1mh!$%dSN=0Wk(~3R#sLJ|KZ`Q7cN{t;wx|Y0|@`}MeD4k$JfEZO4?!mGnv#{ zFLvXXq}ys!vh@ah57AsfkZCgfu% z#VC{|67I9ifRncQ0^#0blxn!JxzDn)@DT8qzBb?&PPp)`!1h6j3@qT{8?{rX)bQ=Xs8?>KR)VI2F6caUAo7Q zAK#CU$F;R-L(vC)ZCh77=hzS zGM>|MEbj2LVVNN5nRY7giny_Jar6ugJkrR8@Q*hvRINy>+~nT_*jk03W-Q^B9T$hDzt&JjI^>18&Wb0`2`& z!24Vh3#Nh#A#k&lR}ajx|D2l(J)f~~W03BI-q6n4AVrBb*12lU%3JKjnPj); z6~JFi#KFM<<)xCZukZ7_-00bhp5w;C2+~^E_Y1v)yL!g%!_|b+(AZiDwp)g7_=3`G`G@;6&d_HT)+#9}kaz=XFI}TV9CX zp%5Pr#IuQWKxs`odD%2YqnqN{r?btZiaWHD^qmR?R;@>ovryRXPWbH-=jZ3M+tUKl zZ-!)%L``O@5;DEJTj7xQ78g(mS@U+7+$GniYx0$D=D-FROr*-Hup>tRKjbvu=jN@u(eBLCG%B$~fy^4Q( z=UUT3XV*{be#Z-H(Kl3PEumh=a&pH^vj3c&t;;bgPU^BBtY85;d&JquhzZ1BD=Vw} z2?=54UTYXZ!B6J5Wn^TIFf(I8O$Skx{#7v)jKBdzS+o-OQv%cr*Z)2f zM*Yi7nDZ(+no37se-v&rF#Fp9q}ulO0&p>8P~PNqkDbR#r#>2a0obi~0wBcPWroTV zImXRR{OHjm*5XrQVowSRXkq*zf)pA?jEr21zrY3Nafx3q+ox`V_1mWKJK^-(9y_!J zQzJ>@4#X{d1W-e0@u08K1)O(b7#i(DEq+j5=BEcV_#`jyv%Qh3>cI56>)UPS8+&du%w`05DZ4duvhq86)1nnb|5KW6-7}*Nmv8+! zy{M?m`ifDJ9UkJnyD`zw*ocQLudW_I&MPVHTyK}(FaK5v)FXFy6^6W=RxZX{_Z(m9VZp-r*%b1PC2KKiu@SPhxpkqn*p)%oR0$o zO`N$;oyeN_1_$k+N?;X|;Uq&IB2sK0y)4=HJLd)$d7pFR{hv6uq$Vg>ssLC=LlFd6 zx3B`5RlwXsEVt39IUmTjjleKV36~$_Kq-1;7@FD}DuZk=REemFp3U4G#j9N?E#4X9 z`d0M$w}iOEV}09C)7e+kJFMedtbkx9wJL=x?<3V>m~CC<=dj~bzT|EztF4{u?s&;; z++(T!+YgP_y<5_jrZCE7zo@L&S8AI0vfvmyD!1IGOs!xQNs~%=?yQOmDG?Eo@TpV5 zJw2CobaaMl8BA;5nAhKg)rA%x(27YD`u5$scQ0chUYL3g`618LMk*;v-O>Tzz8zkmn+pxc;B7xh35olTs4kL0!Mxv%lQ= zW7ek!dU|*@ZnCnmDZ%CdGZ{O{0fKX90rM|=mP-s~m6x+v((K5xMT0% zO9N~VpJqCG)a;GHYnW++d>9%!1}YsT4NYKL8aofW_(z-w3 z!o*Os_BPM}6Z4;?WhG5b3fM65lvhff2>}j4%nt>s(7j@bX8#{M_fKg%V{n`_ z!2i=HjV#w(KH&p{Kq?BN&j{!~?m3kiH~&>lNZ=is5}-_uri{K-no`kpM&7GV&;w)Z zB(2w)>={xoxEMxCC18^lNU}G7X0$3+*^oI(J2#A~O`g-~yUc#16hVuO^yl?Ku+4Gl ztbZliAU^(F;6J%&yTph;bK2->@Ir?d#&+cLlQ9Y|>{ut{1bOHBY32G$b74=z_MYCa zl(0a9Cdw+p*SAF4U-5r%l7IcVq72ZG>@_D_akw!!Hf`KZc`mAG?|(Ro^y76#o|IH7 zY=3(|@VbK{DW1Up$pI%Rk8^>JrZHaezC-g$?(V0-H!@z}u(kS2SzVnjuJ`+Q7{e=a z@?;9swVZ;xd+|Du40Ofaot?ug-KL?2IdxE&h5^nS8jmwwH9(8#?3XXoAf&>l z6HdR%$*GO<+cuY8sG$J~_yc$b?*eCazaG6p!`$Jl7z6^?IZMmTdiz6%4)OdmVMAl< z=PfB_saqt5Ic`<&Af$r7&7X!_!)$G~AMtmc?i&78Ja`^FNXjGVEu6ZqNI``d{6EC# ze6wmG-7%yw>J-{HZkzzU;7fORDCpWFFr-^qO${Fbjfl2Bime{5AMD_^-d?gCJ+feV z_KE=;u@Q)AK>Dm)?goAxLBQoC>Fn%`AW*R≪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 literal 0 HcmV?d00001