Merged in f5soh/librepilot/update_credits (pull request #529)
[librepilot.git] / ground / gcs / src / plugins / uavobjects / uavobject.m.template
blobb12bea0a718e0c6916569196417a3e2a9c866704
1 function [] = OPLogConvert(varargin)
2 %% Define indices and arrays of structures to hold data
3 % THIS FILE IS AUTOMATICALLY GENERATED.
5 outputType='mat'; %Default output is a .mat file
6 checkCRC = false;
7 wrongSyncByte=0;
8 wrongMessageByte=0;
9 lastWrongSyncByte=0;
10 lastWrongMessageByte=0;
11 str1=[];
12 str2=[];
13 str3=[];
14 str4=[];
15 str5=[];
17 fprintf('\n\n***OpenPilot log parser***\n\n');
18 global crc_table;
19 crc_table = [ ...
20     hex2dec('00'),hex2dec('07'),hex2dec('0e'),hex2dec('09'),hex2dec('1c'),hex2dec('1b'),hex2dec('12'),hex2dec('15'),hex2dec('38'),hex2dec('3f'),hex2dec('36'),hex2dec('31'),hex2dec('24'),hex2dec('23'),hex2dec('2a'),hex2dec('2d'), ...
21     hex2dec('70'),hex2dec('77'),hex2dec('7e'),hex2dec('79'),hex2dec('6c'),hex2dec('6b'),hex2dec('62'),hex2dec('65'),hex2dec('48'),hex2dec('4f'),hex2dec('46'),hex2dec('41'),hex2dec('54'),hex2dec('53'),hex2dec('5a'),hex2dec('5d'), ...
22     hex2dec('e0'),hex2dec('e7'),hex2dec('ee'),hex2dec('e9'),hex2dec('fc'),hex2dec('fb'),hex2dec('f2'),hex2dec('f5'),hex2dec('d8'),hex2dec('df'),hex2dec('d6'),hex2dec('d1'),hex2dec('c4'),hex2dec('c3'),hex2dec('ca'),hex2dec('cd'), ...
23     hex2dec('90'),hex2dec('97'),hex2dec('9e'),hex2dec('99'),hex2dec('8c'),hex2dec('8b'),hex2dec('82'),hex2dec('85'),hex2dec('a8'),hex2dec('af'),hex2dec('a6'),hex2dec('a1'),hex2dec('b4'),hex2dec('b3'),hex2dec('ba'),hex2dec('bd'), ...
24     hex2dec('c7'),hex2dec('c0'),hex2dec('c9'),hex2dec('ce'),hex2dec('db'),hex2dec('dc'),hex2dec('d5'),hex2dec('d2'),hex2dec('ff'),hex2dec('f8'),hex2dec('f1'),hex2dec('f6'),hex2dec('e3'),hex2dec('e4'),hex2dec('ed'),hex2dec('ea'), ...
25     hex2dec('b7'),hex2dec('b0'),hex2dec('b9'),hex2dec('be'),hex2dec('ab'),hex2dec('ac'),hex2dec('a5'),hex2dec('a2'),hex2dec('8f'),hex2dec('88'),hex2dec('81'),hex2dec('86'),hex2dec('93'),hex2dec('94'),hex2dec('9d'),hex2dec('9a'), ...
26     hex2dec('27'),hex2dec('20'),hex2dec('29'),hex2dec('2e'),hex2dec('3b'),hex2dec('3c'),hex2dec('35'),hex2dec('32'),hex2dec('1f'),hex2dec('18'),hex2dec('11'),hex2dec('16'),hex2dec('03'),hex2dec('04'),hex2dec('0d'),hex2dec('0a'), ...
27     hex2dec('57'),hex2dec('50'),hex2dec('59'),hex2dec('5e'),hex2dec('4b'),hex2dec('4c'),hex2dec('45'),hex2dec('42'),hex2dec('6f'),hex2dec('68'),hex2dec('61'),hex2dec('66'),hex2dec('73'),hex2dec('74'),hex2dec('7d'),hex2dec('7a'), ...
28     hex2dec('89'),hex2dec('8e'),hex2dec('87'),hex2dec('80'),hex2dec('95'),hex2dec('92'),hex2dec('9b'),hex2dec('9c'),hex2dec('b1'),hex2dec('b6'),hex2dec('bf'),hex2dec('b8'),hex2dec('ad'),hex2dec('aa'),hex2dec('a3'),hex2dec('a4'), ...
29     hex2dec('f9'),hex2dec('fe'),hex2dec('f7'),hex2dec('f0'),hex2dec('e5'),hex2dec('e2'),hex2dec('eb'),hex2dec('ec'),hex2dec('c1'),hex2dec('c6'),hex2dec('cf'),hex2dec('c8'),hex2dec('dd'),hex2dec('da'),hex2dec('d3'),hex2dec('d4'), ...
30     hex2dec('69'),hex2dec('6e'),hex2dec('67'),hex2dec('60'),hex2dec('75'),hex2dec('72'),hex2dec('7b'),hex2dec('7c'),hex2dec('51'),hex2dec('56'),hex2dec('5f'),hex2dec('58'),hex2dec('4d'),hex2dec('4a'),hex2dec('43'),hex2dec('44'), ...
31     hex2dec('19'),hex2dec('1e'),hex2dec('17'),hex2dec('10'),hex2dec('05'),hex2dec('02'),hex2dec('0b'),hex2dec('0c'),hex2dec('21'),hex2dec('26'),hex2dec('2f'),hex2dec('28'),hex2dec('3d'),hex2dec('3a'),hex2dec('33'),hex2dec('34'), ...
32     hex2dec('4e'),hex2dec('49'),hex2dec('40'),hex2dec('47'),hex2dec('52'),hex2dec('55'),hex2dec('5c'),hex2dec('5b'),hex2dec('76'),hex2dec('71'),hex2dec('78'),hex2dec('7f'),hex2dec('6a'),hex2dec('6d'),hex2dec('64'),hex2dec('63'), ...
33     hex2dec('3e'),hex2dec('39'),hex2dec('30'),hex2dec('37'),hex2dec('22'),hex2dec('25'),hex2dec('2c'),hex2dec('2b'),hex2dec('06'),hex2dec('01'),hex2dec('08'),hex2dec('0f'),hex2dec('1a'),hex2dec('1d'),hex2dec('14'),hex2dec('13'), ...
34     hex2dec('ae'),hex2dec('a9'),hex2dec('a0'),hex2dec('a7'),hex2dec('b2'),hex2dec('b5'),hex2dec('bc'),hex2dec('bb'),hex2dec('96'),hex2dec('91'),hex2dec('98'),hex2dec('9f'),hex2dec('8a'),hex2dec('8d'),hex2dec('84'),hex2dec('83'), ...
35     hex2dec('de'),hex2dec('d9'),hex2dec('d0'),hex2dec('d7'),hex2dec('c2'),hex2dec('c5'),hex2dec('cc'),hex2dec('cb'),hex2dec('e6'),hex2dec('e1'),hex2dec('e8'),hex2dec('ef'),hex2dec('fa'),hex2dec('fd'),hex2dec('f4'),hex2dec('f3')  ...
36     ];
38 if nargin==0
39         %%
40         if (exist('uigetfile')) %#ok<EXIST>
41                 [FileName, PathName]=uigetfile('*.opl');
42                 logfile=fullfile(PathName, FileName);
43                 
44         else
45                 error('Your technical computing program does not support file choosers. Please input the file name in the argument. ')
46         end     
47 elseif nargin>0
48         logfile=varargin{1};
49         if nargin>1
50                 outputType=varargin{2};
51         end
52 end
54 if ~strcmpi(outputType,'mat') && ~strcmpi(outputType,'csv')
55         error('Incorrect file format specified. Second argument must be ''mat'' or ''csv''.');
56 end
58 $(INSTANTIATIONCODE)
61 fid = fopen(logfile);
62 buffer=fread(fid,Inf,'uchar=>uint8');
63 fseek(fid, 0, 'bof');
64 bufferlen = size(buffer);
66 correctMsgByte=hex2dec('20');
67 correctTimestampedByte=hex2dec('A0');
68 correctSyncByte=hex2dec('3C');
69 unknownObjIDList=zeros(1,2);
70 headerLen = 1 + 1 + 2 + 4 + 2; % sync type len id inst
71 timestampLen = 4;
72 crcLen = 1;
73 oplHeaderLen = 8 + 4;
75 last_print = -1e10;
77 bufferIdx=1;
78 headerIdx=oplHeaderLen + 1;
80 startTime=clock;
82 while (1)
83         try
84         %% Read message header
85         % get sync field (0x3C, 1 byte)
86         if (bufferlen < headerIdx + 12); break; end
87         sync = buffer(headerIdx);
88         % printf('%x ', sync);
89         headerIdx = headerIdx + 1;
90         if sync ~= correctSyncByte
91                 wrongSyncByte = wrongSyncByte + 1;
92                 continue
93         end
95         % printf('\n %u:',headerIdx - 1);
96         % get the opl timestamp and datablock size
97         oplTimestamp = typecast(uint8(buffer(headerIdx - 1 - 8 - 4:headerIdx - 1 - 8 - 1)), 'uint32'); 
98         oplSize = typecast(uint8(buffer(headerIdx - 1 - 8:headerIdx - 1 - 1)), 'uint64'); 
100         % get msg type (quint8 1 byte ) should be 0x20/0xA0, ignore the rest
101         msgType = buffer(headerIdx);
102         headerIdx = headerIdx + 1;
103         if msgType ~= correctMsgByte && msgType ~= correctTimestampedByte
104                 % fixme: it should read the whole message payload instead of skipping and blindly searching for next sync byte.
105                 fprintf('\nSkipping message type: %x \n', msgType);
106                 continue
107         end
109         % get msg size (quint16 2 bytes) excludes crc, include msg header and data payload
110         msgSize = uint32(typecast(buffer(headerIdx:headerIdx + 1), 'uint16'));
111         headerIdx = headerIdx + 2;
113         % get obj id (quint32 4 bytes)
114         objID = typecast(uint8(buffer(headerIdx:headerIdx + 3)), 'uint32'); 
115         headerIdx = headerIdx + 4;
117         % get instance id (quint16 2 bytes)
118         instID = typecast(uint8(buffer(headerIdx:headerIdx + 1)),  'uint16');
119         % printf('Id %x type %x size %u Inst %x ', objID, msgType, msgSize, instID);
120         headerIdx = headerIdx + 2;
122         % get timestamp if needed (quint32 4 bytes)
123         if msgType == correctMsgByte
124                 datasize = msgSize - headerLen;
125         elseif msgType == correctTimestampedByte
126                 timestamp = typecast(uint8(buffer(headerIdx:headerIdx + 3)),  'uint32');
127         %       printf('ts %u');
128                 headerIdx = headerIdx + 4;
129                 datasize = msgSize - headerLen - timestampLen;
130         end
131         % printf('\n');
132         bufferIdx = headerIdx;
133         headerIdx = headerIdx + datasize + crcLen + oplHeaderLen;
135         %% Read object
137         switch objID
138 $(SWITCHCODE)
139                 otherwise
140                         unknownObjIDListIdx=find(unknownObjIDList(:,1)==objID, 1, 'first');
141                         if isempty(unknownObjIDListIdx)
142                                 unknownObjIDList=[unknownObjIDList; uint32(objID) 1]; %#ok<AGROW>
143                         else
144                                 unknownObjIDList(unknownObjIDListIdx,2)=unknownObjIDList(unknownObjIDListIdx,2)+1; 
145                         end
147                         msgBytesLeft = msgSize - 1 - 1 - 2 - 4;
148                         if msgBytesLeft > 255
149                                 msgBytesLeft = 0;
150                         end
151                         bufferIdx=bufferIdx+double(msgBytesLeft);
152         end
153         catch
154                 % One of the reads failed - indicates EOF
155                 break;
156         end
158         if (wrongSyncByte ~= lastWrongSyncByte || wrongMessageByte~=lastWrongMessageByte ) ||...
159                         bufferIdx - last_print > 5e4 %Every 50,000 bytes show the status update
161                 lastWrongSyncByte=wrongSyncByte;
162                 lastWrongMessageByte=wrongMessageByte;
164                 str1=[];
165                 for i=1:length([str2 str3 str4 str5]);
166                         str1=[str1 sprintf('\b')]; %#ok<AGROW>
167                 end
168                 str2=sprintf('wrongSyncByte instances:    % 10d\n', wrongSyncByte );
169                 str3=sprintf('wrongMessageByte instances: % 10d\n\n', wrongMessageByte );
170                 
171                 str4=sprintf('Completed bytes: % 9d of % 9d\n', bufferIdx, length(buffer));
172                 
173                 % Arbitrary times two so that it is at least as long    
174                 estTimeRemaining=(length(buffer)-bufferIdx)/(bufferIdx/etime(clock,startTime)) * 2;
175                 h=floor(estTimeRemaining/3600);
176                 m=floor((estTimeRemaining-h*3600)/60);
177                 s=ceil(estTimeRemaining-h*3600-m*60);
178                 
179                 str5=sprintf('Est. time remaining, %02dh:%02dm:%02ds \n', h,m,s);
181                 last_print = bufferIdx;
182                 
183                 fprintf([str1 str2 str3 str4 str5]);
184         end
186         %Check if at end of file. If not, load next prebuffer
187         if bufferIdx+12-1 > length(buffer)
188                 break;
189         end
190 %       bufferIdx=bufferIdx+12;
195 for i=2:size(unknownObjIDList,1) %Don't show the first one, as it was simply a dummy placeholder
196    disp(['Unknown object ID: 0x' dec2hex(unknownObjIDList(i,1),8) ' appeared ' int2str(unknownObjIDList(i,2)) ' times.']);
199 %% Clean Up and Save mat file
200 fclose(fid);
202 %% Prune vectors
203 $(CLEANUPCODE)
206 %% Perform typecasting on vectors
207 $(ALLOCATIONCODE)
209 %% Save data to file
210 if strcmpi(outputType,'mat')
211         [path, name]=fileparts(logfile);
212         matfile = fullfile(path,[name '.mat']);
213         save(matfile $(SAVEOBJECTSCODE));
214 else
215 $(EXPORTCSVCODE)
218 fprintf('%d records in %0.2f seconds.\n', length(buffer), etime(clock,startTime));
222         
223 function        OPLog2csv(structIn, structName, logfile)
224         %Get each field name from the structure
225         fieldNames = fieldnames(structIn);
226         
227         %Create a text string with the field names
228         headerOut=sprintf('%s,',fieldNames{:});
229         headerOut=headerOut(1:end-1); %Trim off last `,` and `\t`
230         
231         %Assign the structure arrays to a matrix.
232         matOut=zeros(max(size(structIn.(fieldNames{1}))), length(fieldNames));
233         
234         if      isempty(structIn.(fieldNames{1}));
235                 matOut=[];
236         else
237                 for i=1:length(fieldNames)
238                         matOut(:,i)=structIn.(fieldNames{i});
239                 end
240         end     
241         % Create filename by replacing opl by csv
242         [path, name] = fileparts(logfile);
243         csvDirName=[name '_csv'];
244         [dummyA, dummyB]=mkdir(fullfile(path, csvDirName)); %Dummy outputs so the program doens't throw warnings about "Directory already exists"
245         csvfile=fullfile(path, csvDirName , [name '.csv']);
246         
247         %Write to csv.
248         dlmwrite(csvfile, headerOut, '');
249         dlmwrite(csvfile, matOut, '-append');
251 function crc = compute_crc(data)
252     global crc_table;
253     crc = 0;
254     for i = 1:length(data)
255         crc = crc_table(1+bitxor(data(i),crc));
256     end
258 function out=mcolon(inStart, inFinish)
259 %% This function was inspired by Bruno Luong's 'mcolon'. The name is kept the same as his 'mcolon'
260 % function, found on Matlab's file exchange. The two functions return identical
261 % results, although his is much faster. Unfortunately, C-compiled mex
262 % code would make this function non-cross-platform, so a Matlab scripted
263 % version is provided here.
264         if size(inStart,1) > 1 || size(inFinish,1) > 1
265                 if size(inStart,2) > 1 || size(inFinish,2) > 1
266                         error('Inputs must be vectors, i.e just one column wide.')              
267                 else
268                         inStart=inStart';
269                         inFinish=inFinish';
270                 end
271         end
272         
273         diffIn=diff([inStart; inFinish]);
274         numElements=sum(diffIn)+length(inStart);
275         
276         out=zeros(1,numElements);
277         
278         idx=1;
279         for i=1:length(inStart)
280                 out(idx:idx+diffIn(i))=inStart(i):inFinish(i);
281                 idx=idx+diffIn(i)+1;
282         end