Master Thesis Code
by Simon Moser
Loading...
Searching...
No Matches
trajectoryGenerationApp.m
Go to the documentation of this file.
1% =========================================================================== %
2%> @brief app that helps to generate a trajectory.
3%>
4%> This app is mainly a graphical interface to the Trajectory class. It allows
5%> to define waypoints, set the sampling frequency and the interpolation methods
6%> and to generate the trajectory.
7%>
8%> The app can be called with no arguments:
9%> @code
11%> @endcode
12%>
13%> or with a Trajectory object as argument:
14%> @code
15%> myTraj = Trajectory;
17%> @endcode
18%> in the second case, the app will be initialized with the given Trajectory
19%> object. Also, every change made in the app will be reflected in the given
20%> Trajectory object since is is passed by reference. If you want to keep the
21%> original Trajectory object, you should pass a copy of it to the app. You can
22%> do this by calling the copy method of the Trajectory object:
23%> @code
24%> myTraj = Trajectory;
25%> myTrajCopy = myTraj.copy;
26%> trajectoryGenerationApp(myTrajCopy);
27%> @endcode
28%>
29%> @copyright see the file @ref LICENSE in the root directory of the repository
30%>
31%> \par Example Usage
32%>
33%> \image html trajectoryGenerationApp.gif
34% =========================================================================== %
35
36classdef trajectoryGenerationApp < matlab.apps.AppBase
37
38 % Properties that correspond to app components
39 properties (Access = public)
40 TrajectoryAppUIFigure matlab.ui.Figure
41 gridMain matlab.ui.container.GridLayout
42 mossFeb2024Label matlab.ui.control.Label
43 Image matlab.ui.control.Image
44 gridTrajMenu matlab.ui.container.GridLayout
45 GridLayout matlab.ui.container.GridLayout
46 PlayButton matlab.ui.control.Button
47 GenerateButton matlab.ui.control.Button
48 TrajectoryGenerationLabel matlab.ui.control.Label
49 gridInterpolationMenu matlab.ui.container.GridLayout
50 SetSamplingFrequencyInputLabel matlab.ui.control.Label
51 SetSamplingFrequencyInput matlab.ui.control.NumericEditField
52 OrientationDropDown matlab.ui.control.DropDown
53 OrientationDropDownLabel matlab.ui.control.Label
54 PositionDropDown matlab.ui.control.DropDown
55 PositionDropDownLabel matlab.ui.control.Label
56 InterpolationSettingsLabel matlab.ui.control.Label
57 gridWaypointTableMenu matlab.ui.container.GridLayout
58 AutomaticallyCheckandSortCheckBox matlab.ui.control.CheckBox
59 btnPlotWaypoints matlab.ui.control.Button
60 CheckandSortButton matlab.ui.control.Button
61 WaypointTableSettingsLabel matlab.ui.control.Label
62 gridImportExportMenu matlab.ui.container.GridLayout
63 NewButton matlab.ui.control.Button
64 ExportButton matlab.ui.control.Button
65 ImportButton matlab.ui.control.Button
66 ImportandExportLabel matlab.ui.control.Label
67 lblTrajGen matlab.ui.control.Label
68 lblTrajDefinition matlab.ui.control.Label
69 gridTable matlab.ui.container.GridLayout
70 lblOrientationHelper matlab.ui.control.Label
71 gridTabLbls matlab.ui.container.GridLayout
72 lblTabOrientation matlab.ui.control.Label
73 lblTabPosition matlab.ui.control.Label
74 lblTabTimeInfo matlab.ui.control.Label
75 tabPoints matlab.ui.control.Table
76 end
78
79 properties (Access = private)
80
81 appTrajectory = Trajectory; % Description
82 end
84 properties (Access = public)
85 appReturnValue % Return Value from a SubApp
86 end
88 methods (Access = private)
90 function tabPointsAddRow(app)
92 if height(app.tabPoints.Data) > 0
93 thisTStart = duration(app.tabPoints.Data.t_start(end),"InputFormat","mm:ss.SSS") + seconds(1);
94 thisTStart = string(thisTStart,"mm:ss.SSS");
95 else
96 thisTStart = "00:00.000";
97 end
98
99 app.tabPoints.Data = [app.tabPoints.Data; {thisTStart,string(seconds(0),"mm:ss.SSS"),0,0,0,1,0,0,0}];
100 end
102 function tabPointsEditCell(app, row, col)
104 inputSize = [1,45];
105 cellData = app.tabPoints.Data{row,col};
106
107 switch col
108 case 1 % start time
109 prompt = "Enter a new Start Time (mm:ss.SSS)";
110 title = "Starttime";
112 val = inputdlg(prompt,title,inputSize,string(cellData));
114 if isempty(val)
115 return
116 end
117
118 try
119 val = duration(val{1,1},"Format","mm:ss.SSS");
120 catch
121 errordlg("Wrong Format");
122 return
123 end
124
125 case 2 % duration
126 prompt = "Enter a new Durartion (mm:ss.SSS)";
127 title = "Duration";
128
129 val = inputdlg(prompt,title,inputSize,string(cellData));
130
131 if isempty(val)
132 return
133 end
134
135 try
136 val = duration(val{1,1},"Format","mm:ss.SSS");
137 catch
138 errordlg("Wrong Format");
139 return
140 end
141
142 case 3 % position
143 prompt = ["X [m]","Y [m]","Z [m]"];
144 title = "Position";
145
146 val = inputdlg(prompt,title,inputSize,string(cellData));
147
148 if isempty(val)
149 return
150 end
151
152 try
153 val = str2double(val);
154 assert(numel(val)==3);
155 assert(any(isnan(val))==false);
156 val = reshape(val,[1,3]);
157 catch
158 errordlg("Wrong Format");
159 return
160 end
161
162
163 case 4 % orientation
164 ui = getOrientationApp(app,cellData);
165 uiwait(ui.UIFigure);
166 val = app.appReturnValue;
167 end
168
169
170 app.tabPoints.Data{row,col} = val;
171
172 end
173
174 function app = tabPointsUpdate(app)
175 % convert to Trajectory Instance
176 app.uiTableToTraj;
177
178 % clean the table
179 if app.AutomaticallyCheckandSortCheckBox.Value
180 try
181 app.appTrajectory.cleanTab;
182 catch err
183 e = errordlg(err.message);
184 uiwait(e)
185 end
186 end
187
188 % convert from Trajectory Instance
189 app.trajToUiTable;
190 end
191
192
193 function trajToUiTable(app)
194 app.tabPoints.Data = app.appTrajectory.reduce;
195 end
196
197 function uiTableToTraj(app)
198 app.appTrajectory.importTab(app.tabPoints.Data);
199 end
200 end
201
202
203 % Callbacks that handle component events
204 methods (Access = private)
205
206 % Code that executes after component creation
207 function startupFcn(app, traj)
208 arguments
209 app
210 traj (1,1) {mustBeA(traj,"Trajectory")} = Trajectory;
211 end
212
213 % setup table
214 app.appTrajectory = traj;
215 app.trajToUiTable;
216
217 % setup sampling frequency
218 app.SetSamplingFrequencyInput.Value = app.appTrajectory.getSamplingFrequency;
219 app.SetSamplingFrequencyInput.ValueChangedFcn = createCallbackFcn(app, @SamplingFrequencyChanged, false);
220
221 % setup interpolation methods
222 methods = app.appTrajectory.getInterpMethods;
223 app.PositionDropDown.Items = methods.pos;
224 app.PositionDropDown.Value = methods.posCurrent;
225 app.OrientationDropDown.Items = methods.ori;
226 app.OrientationDropDown.Value = methods.oriCurrent;
227
228 % setup import button
229 app.ImportButton.ButtonPushedFcn = createCallbackFcn(app, @ImportButtonPushed, false);
230
231 % setup export button
232 app.ExportButton.ButtonPushedFcn = createCallbackFcn(app, @ExportButtonPushed, false);
233
234 % setup new button
235 app.NewButton.ButtonPushedFcn = createCallbackFcn(app, @NewButtonPushed, false);
236
237 % setup check and sort button
238 app.CheckandSortButton.ButtonPushedFcn = createCallbackFcn(app, @tabPointsCheckandSort, false);
239
240 % setup plot waypoints button
241 app.btnPlotWaypoints.ButtonPushedFcn = createCallbackFcn(app, @btnPlotWaypointsPushed, false);
243 % setup generate button
244 app.GenerateButton.ButtonPushedFcn = createCallbackFcn(app, @GenerateButtonPushed, false);
245
246 % setup play button
247 app.PlayButton.ButtonPushedFcn = createCallbackFcn(app, @PlayButtonPushed, false);
248
249 end
250
251 % Double-clicked callback: tabPoints
252 function tabPointsDoubleClicked(app, event)
254 if isempty(event.InteractionInformation.Row) && isempty(event.InteractionInformation.Column)
255 app.tabPointsAddRow();
256 end
257
258 end
259
260 % Key release function: tabPoints
261 function tabPointsKeyRelease(app, event)
262 key = event.Key;
263 selection = event.Source.Selection;
264
265 switch key
266 case 'delete' %delete row
267 answer = questdlg("Delete all the Row(s) in the selection?","Delete?","Yes","Cancel","Cancel");
268 if strcmp(answer,"Yes")
269 rows = selection(:,1);
270 event.Source.Data(rows,:) = [];
271 if height(event.Source.Data) == 0
272 app.tabPointsAddRow;
273 end
274 end
275
276 case 'q' %open orientation helper app
277 try
278 row = selection(:,1);
279 assert(numel(row) == 1); %make sure only one row is selected
280
281 % open app and wait for it
282 orientApp = getOrientationApp(app,app.tabPoints.Data{row,6:9});
283 uiwait(orientApp.OrientationAppUIFigure);
284
285 % insert the new value
286 app.tabPoints.Data{row,6:9} = app.appReturnValue;
287 catch
288 e = errordlg("Select only one Row!");
289 uiwait(e);
290 end
291
292
293 end
294 end
295
296 % Cell edit callback: tabPoints
297 function tabPointsCellEdit(app, event)
298 indices = event.Indices;
299 newData = event.NewData;
300
301 try
302 switch indices(2)
303 case {1,2} %start time, duration
304 if contains(newData,':')
305 newTime = duration(newData,"Format","mm:ss.SSS");
306 else
307 newTime = seconds(str2double(newData));
308 end
309 assert(~isnan(newTime));
310 assert(~ismissing(newTime));
311 newData = string(newTime,"mm:ss.SSS");
312
313 case {3,4,5} % x,y,z
314 assert(~isnan(newData))
315
316 case {6,7,8,9}
317
318 if event.EditData == 'q' % special case where the app is called
319 app.tabPoints.Data{indices(1),indices(2)} = event.PreviousData;
320 return;
321 end
322
323 assert(~isnan(newData))
324
325 % generate new valid quaternion
326 newQuat = quaternion(app.tabPoints.Data{indices(1),6:9});
327 app.tabPoints.Data{indices(1),6:9} = newQuat.compact;
328
329 end
330 app.tabPoints.Data{indices(1),indices(2)} = newData;
331 catch
332 e = errordlg("Wrong Input Format","Error","modal");
333 uiwait(e);
334 app.tabPoints.Data{indices(1),indices(2)} = event.PreviousData;
335 end
336
337 app.tabPointsUpdate;
338
339 end
340
341 % Key press function: tabPoints
342 function tabPointsKeyPress(app, event)
343 key = event.Key;
344
345 tabSize = size(app.tabPoints.Data);
346 selection = event.Source.Selection;
347
348 switch key
349 case 'tab' % next cell
350 try
351 if numel(selection) == 2 %only one cell selected
352 if selection(2) < tabSize(2)
353 %if possible, one cell to the right
354 event.Source.Selection(2) = selection(2) + 1;
355 else
356 %first cell of next row
357 event.Source.Selection(1) = selection(1) + 1;
358 event.Source.Selection(2) = 1;
359 end
360 end
361 catch
362 app.tabPointsAddRow;
363 %first cell of new row
364 event.Source.Selection(1) = selection(1) + 1;
365 event.Source.Selection(2) = 1;
366 end
367 end
368
369 end
370
371 % Value changed function: SamplingFrequencyInput
372 function SamplingFrequencyChanged(app)
373 app.appTrajectory.setSamplingFrequency(app.SetSamplingFrequencyInput.Value);
374 end
375
376 % Value changed function: OrientationDropDown, PositionDropDown
377 function InterpolationDropDownValueChanged(app)
378 methods.pos = app.PositionDropDown.Value;
379 methods.ori = app.OrientationDropDown.Value;
380 app.appTrajectory.setInterpMethods(methods);
381
382 end
383
384 % Button pushed function: ImportButton
385 function ImportButtonPushed(app)
386 [file,path] = uigetfile('*.mat');
387 if file == 0
388 return
389 end
390
391 try
392 traj = load(fullfile(path,file));
393 assert(isfield(traj,"traj"));
394 assert(isa(traj.traj,"Trajectory"));
395 app.appTrajectory = traj.traj;
396 app.trajToUiTable;
397 catch
398 e = errordlg("File is not a valid Trajectory Object","Error","modal");
399 uiwait(e);
400 end
401 end
402
403 % Button pushed function: ExportButton
404 function ExportButtonPushed(app)
405 [file,path] = uiputfile('*.mat');
406 if file == 0
407 return
408 end
409
410 traj = app.appTrajectory;
411
412 try
413 save(fullfile(path,file),"traj","-v7.3");
414 catch
415 e = errordlg("Error while saving the Trajectory Object","Error","modal");
416 uiwait(e);
417 end
418 end
419
420 % Button pushed function: NewButton
421 function NewButtonPushed(app)
422 app.appTrajectory = Trajectory;
423 app.trajToUiTable;
424 end
425
426 % Button pushed function: CheckandSortButton
427 function tabPointsCheckandSort(app)
428 app.uiTableToTraj;
429 app.appTrajectory.cleanTab;
430 app.trajToUiTable;
431 end
432
433 % Button pushed function: btnPlotWaypoints
434 function btnPlotWaypointsPushed(app)
435 app.tabPointsCheckandSort;
436 fig = figure("Name","Waypoints","NumberTitle","off");
437 ax = axes(fig);
438 app.appTrajectory.plotWaypoints(ax);
439 uiwait(fig);
440 end
441
442 % Button pushed function: GenerateButton
443 function GenerateButtonPushed(app)
444 app.GenerateButton.Enable = false;
445
446
447 try
448 assert(height(app.tabPoints.Data) > 0);
449 catch
450 e = errordlg("No Waypoints defined","Error","modal");
451 uiwait(e);
452 app.GenerateButton.Enable = true;
453 return
454 end
455
456 app.uiTableToTraj;
457 app.appTrajectory.generateTrajectory;
458 app.trajToUiTable;
459
460 m = msgbox("Trajectory generated","Success","modal");
461 uiwait(m);
462
463 app.GenerateButton.Enable = true;
464 end
465
466 % Button pushed function: PlayButton
467 function PlayButtonPushed(app)
468 app.PlayButton.Enable = false;
469
470 try
471 assert(app.appTrajectory.getIsGenerated);
472 catch
473 e = errordlg("Trajectory not generated","Error","modal");
474 uiwait(e);
475 app.PlayButton.Enable = true;
476 return
477 end
478
479 trajPlayer = trajectoryVisualizationApp(app.appTrajectory);
480
481 uiwait(trajPlayer.TrajectoryVisualizationUIFigure);
482
483 app.PlayButton.Enable = true;
484 end
485 end
486
487 % Component initialization
488 methods (Access = private)
489
490 % Create UIFigure and components
491 function createComponents(app)
492
493 % Create TrajectoryAppUIFigure and hide until all components are created
494 app.TrajectoryAppUIFigure = uifigure('Visible', 'off');
495 app.TrajectoryAppUIFigure.Position = [100 100 900 650];
496 app.TrajectoryAppUIFigure.Name = 'Trajectory App';
497 app.TrajectoryAppUIFigure.Icon = 'logo_zhaw.png';
498
499 % Create gridMain
500 app.gridMain = uigridlayout(app.TrajectoryAppUIFigure);
501 app.gridMain.ColumnWidth = {550, '1x'};
502 app.gridMain.RowHeight = {'2x', 'fit', '1x', 60};
503 app.gridMain.Padding = [25 25 25 25];
504
505 % Create gridTable
506 app.gridTable = uigridlayout(app.gridMain);
507 app.gridTable.ColumnWidth = {'fit'};
508 app.gridTable.RowHeight = {'fit', 300, 'fit'};
509 app.gridTable.Padding = [0 0 0 0];
510 app.gridTable.Layout.Row = 2;
511 app.gridTable.Layout.Column = 1;
512
513 % Create tabPoints
514 app.tabPoints = uitable(app.gridTable);
515 app.tabPoints.ColumnName = {'t start'; 'duration'; 'x'; 'y'; 'z'; '1'; 'i'; 'j'; 'k'};
516 app.tabPoints.ColumnWidth = {70, 80, 50, 50, 50, 50, 50, 50, 50};
517 app.tabPoints.RowName = {};
518 app.tabPoints.ColumnSortable = [true false false false false false false false false];
519 app.tabPoints.ColumnEditable = true;
520 app.tabPoints.CellEditCallback = createCallbackFcn(app, @tabPointsCellEdit, true);
521 app.tabPoints.DoubleClickedFcn = createCallbackFcn(app, @tabPointsDoubleClicked, true);
522 app.tabPoints.KeyPressFcn = createCallbackFcn(app, @tabPointsKeyPress, true);
523 app.tabPoints.KeyReleaseFcn = createCallbackFcn(app, @tabPointsKeyRelease, true);
524 app.tabPoints.Layout.Row = 2;
525 app.tabPoints.Layout.Column = 1;
527 % Create gridTabLbls
528 app.gridTabLbls = uigridlayout(app.gridTable);
529 app.gridTabLbls.ColumnWidth = {150, 150, 200};
530 app.gridTabLbls.RowHeight = {'1x'};
531 app.gridTabLbls.ColumnSpacing = 0;
532 app.gridTabLbls.RowSpacing = 0;
533 app.gridTabLbls.Padding = [0 0 0 0];
534 app.gridTabLbls.Layout.Row = 1;
535 app.gridTabLbls.Layout.Column = 1;
536
537 % Create lblTabTimeInfo
538 app.lblTabTimeInfo = uilabel(app.gridTabLbls);
539 app.lblTabTimeInfo.HorizontalAlignment = 'center';
540 app.lblTabTimeInfo.VerticalAlignment = 'bottom';
541 app.lblTabTimeInfo.FontWeight = 'bold';
542 app.lblTabTimeInfo.Layout.Row = 1;
543 app.lblTabTimeInfo.Layout.Column = 1;
544 app.lblTabTimeInfo.Text = 'Time Info [mm:ss.SSS]';
545
546 % Create lblTabPosition
547 app.lblTabPosition = uilabel(app.gridTabLbls);
548 app.lblTabPosition.HorizontalAlignment = 'center';
549 app.lblTabPosition.VerticalAlignment = 'bottom';
550 app.lblTabPosition.FontWeight = 'bold';
551 app.lblTabPosition.Layout.Row = 1;
552 app.lblTabPosition.Layout.Column = 2;
553 app.lblTabPosition.Text = 'Position [m]';
554
555 % Create lblTabOrientation
556 app.lblTabOrientation = uilabel(app.gridTabLbls);
557 app.lblTabOrientation.HorizontalAlignment = 'center';
558 app.lblTabOrientation.VerticalAlignment = 'bottom';
559 app.lblTabOrientation.FontWeight = 'bold';
560 app.lblTabOrientation.Layout.Row = 1;
561 app.lblTabOrientation.Layout.Column = 3;
562 app.lblTabOrientation.Text = 'Orientation';
563
564 % Create lblOrientationHelper
565 app.lblOrientationHelper = uilabel(app.gridTable);
566 app.lblOrientationHelper.HorizontalAlignment = 'center';
567 app.lblOrientationHelper.Layout.Row = 3;
568 app.lblOrientationHelper.Layout.Column = 1;
569 app.lblOrientationHelper.Text = 'select an orientation value and press ''q'' to open the Orientation Helper App.';
570
571 % Create lblTrajDefinition
572 app.lblTrajDefinition = uilabel(app.gridMain);
573 app.lblTrajDefinition.VerticalAlignment = 'bottom';
574 app.lblTrajDefinition.FontSize = 24;
575 app.lblTrajDefinition.FontWeight = 'bold';
576 app.lblTrajDefinition.Layout.Row = 1;
577 app.lblTrajDefinition.Layout.Column = 1;
578 app.lblTrajDefinition.Text = 'Trajectory Definition';
579
580 % Create lblTrajGen
581 app.lblTrajGen = uilabel(app.gridMain);
582 app.lblTrajGen.VerticalAlignment = 'bottom';
583 app.lblTrajGen.FontSize = 24;
584 app.lblTrajGen.FontWeight = 'bold';
585 app.lblTrajGen.Layout.Row = 1;
586 app.lblTrajGen.Layout.Column = 2;
587 app.lblTrajGen.Text = 'Trajectory Generation';
588
589 % Create gridTrajMenu
590 app.gridTrajMenu = uigridlayout(app.gridMain);
591 app.gridTrajMenu.ColumnWidth = {'1x'};
592 app.gridTrajMenu.RowHeight = {30, 'fit', 30, 'fit', 30, 'fit', 30, 'fit'};
593 app.gridTrajMenu.Padding = [0 0 0 0];
594 app.gridTrajMenu.Layout.Row = 2;
595 app.gridTrajMenu.Layout.Column = 2;
596
597 % Create ImportandExportLabel
598 app.ImportandExportLabel = uilabel(app.gridTrajMenu);
599 app.ImportandExportLabel.VerticalAlignment = 'bottom';
600 app.ImportandExportLabel.FontSize = 14;
601 app.ImportandExportLabel.FontWeight = 'bold';
602 app.ImportandExportLabel.Layout.Row = 1;
603 app.ImportandExportLabel.Layout.Column = 1;
604 app.ImportandExportLabel.Text = 'Import and Export';
605
606 % Create gridImportExportMenu
607 app.gridImportExportMenu = uigridlayout(app.gridTrajMenu);
608 app.gridImportExportMenu.ColumnWidth = {'fit', 'fit', 'fit'};
609 app.gridImportExportMenu.RowHeight = {'fit'};
610 app.gridImportExportMenu.Padding = [0 0 0 0];
611 app.gridImportExportMenu.Layout.Row = 2;
612 app.gridImportExportMenu.Layout.Column = 1;
613
614 % Create ImportButton
615 app.ImportButton = uibutton(app.gridImportExportMenu, 'push');
616 app.ImportButton.Tooltip = {'Import a Trajectory object saved as a .mat file or similar.'};
617 app.ImportButton.Layout.Row = 1;
618 app.ImportButton.Layout.Column = 1;
619 app.ImportButton.Text = 'Import';
620
621 % Create ExportButton
622 app.ExportButton = uibutton(app.gridImportExportMenu, 'push');
623 app.ExportButton.Tooltip = {'Export the Trajectory object saved as a .mat file or similar.'};
624 app.ExportButton.Layout.Row = 1;
625 app.ExportButton.Layout.Column = 2;
626 app.ExportButton.Text = 'Export';
627
628 % Create NewButton
629 app.NewButton = uibutton(app.gridImportExportMenu, 'push');
630 app.NewButton.Tooltip = {'Empty the Workspace'};
631 app.NewButton.Layout.Row = 1;
632 app.NewButton.Layout.Column = 3;
633 app.NewButton.Text = 'New';
634
635 % Create WaypointTableSettingsLabel
636 app.WaypointTableSettingsLabel = uilabel(app.gridTrajMenu);
637 app.WaypointTableSettingsLabel.VerticalAlignment = 'bottom';
638 app.WaypointTableSettingsLabel.FontSize = 14;
639 app.WaypointTableSettingsLabel.FontWeight = 'bold';
640 app.WaypointTableSettingsLabel.Layout.Row = 3;
641 app.WaypointTableSettingsLabel.Layout.Column = 1;
642 app.WaypointTableSettingsLabel.Text = 'Waypoint Table Settings';
643
644 % Create gridWaypointTableMenu
645 app.gridWaypointTableMenu = uigridlayout(app.gridTrajMenu);
646 app.gridWaypointTableMenu.ColumnWidth = {'fit', 'fit'};
647 app.gridWaypointTableMenu.RowHeight = {'fit','fit'};
648 app.gridWaypointTableMenu.Padding = [0 0 0 0];
649 app.gridWaypointTableMenu.Layout.Row = 4;
650 app.gridWaypointTableMenu.Layout.Column = 1;
651
652 % Create CheckandSortButton
653 app.CheckandSortButton = uibutton(app.gridWaypointTableMenu, 'push');
654 app.CheckandSortButton.Tooltip = {'Sorts the Waypoints Table, sorts it, removes double start times and reduces the duration if there''s time overlapping'};
655 app.CheckandSortButton.Layout.Row = 1;
656 app.CheckandSortButton.Layout.Column = 1;
657 app.CheckandSortButton.Text = 'Check and Sort';
658
659 % Create AutomaticallyCheckandSortCheckBox
660 app.AutomaticallyCheckandSortCheckBox = uicheckbox(app.gridWaypointTableMenu);
661 app.AutomaticallyCheckandSortCheckBox.Text = 'Automatically Check and Sort';
662 app.AutomaticallyCheckandSortCheckBox.Layout.Row = 1;
663 app.AutomaticallyCheckandSortCheckBox.Layout.Column = 2;
664 app.AutomaticallyCheckandSortCheckBox.Value = true;
665
666 % Create btnPlotWaypoints
667 app.btnPlotWaypoints = uibutton(app.gridWaypointTableMenu, 'push');
668 app.btnPlotWaypoints.Tooltip = {'Plots the Waypoints in a 3D Plot'};
669 app.btnPlotWaypoints.Layout.Row = 2;
670 app.btnPlotWaypoints.Layout.Column = 1;
671 app.btnPlotWaypoints.Text = 'Plot Waypoints';
672
673 % Create InterpolationSettingsLabel
674 app.InterpolationSettingsLabel = uilabel(app.gridTrajMenu);
675 app.InterpolationSettingsLabel.VerticalAlignment = 'bottom';
676 app.InterpolationSettingsLabel.FontSize = 14;
677 app.InterpolationSettingsLabel.FontWeight = 'bold';
678 app.InterpolationSettingsLabel.Layout.Row = 5;
679 app.InterpolationSettingsLabel.Layout.Column = 1;
680 app.InterpolationSettingsLabel.Text = 'Interpolation Settings';
681
682 % Create gridInterpolationMenu
683 app.gridInterpolationMenu = uigridlayout(app.gridTrajMenu);
684 app.gridInterpolationMenu.ColumnWidth = {'fit', 'fit'};
685 app.gridInterpolationMenu.RowHeight = {'fit', 'fit','fit'};
686 app.gridInterpolationMenu.Padding = [0 0 0 0];
687 app.gridInterpolationMenu.Layout.Row = 6;
688 app.gridInterpolationMenu.Layout.Column = 1;
689
690 % Create SetSamplingFrequencyInputLabel
691 app.SetSamplingFrequencyInputLabel = uilabel(app.gridInterpolationMenu);
692 app.SetSamplingFrequencyInputLabel.HorizontalAlignment = 'right';
693 app.SetSamplingFrequencyInputLabel.Layout.Row = 1;
694 app.SetSamplingFrequencyInputLabel.Layout.Column = 1;
695 app.SetSamplingFrequencyInputLabel.Text = 'fs [Hz]';
696
697 % Create SetSamplingFrequencyInput
698 app.SetSamplingFrequencyInput = uieditfield(app.gridInterpolationMenu, 'numeric');
699 app.SetSamplingFrequencyInput.Limits = [0 Inf];
700 app.SetSamplingFrequencyInput.Value = 200;
701 app.SetSamplingFrequencyInput.Layout.Row = 1;
702 app.SetSamplingFrequencyInput.Layout.Column = 2;
703
704 % Create PositionDropDownLabel
705 app.PositionDropDownLabel = uilabel(app.gridInterpolationMenu);
706 app.PositionDropDownLabel.HorizontalAlignment = 'right';
707 app.PositionDropDownLabel.Layout.Row = 2;
708 app.PositionDropDownLabel.Layout.Column = 1;
709 app.PositionDropDownLabel.Text = 'Position';
710
711 % Create PositionDropDown
712 app.PositionDropDown = uidropdown(app.gridInterpolationMenu);
713 app.PositionDropDown.Items = {'none'};
714 app.PositionDropDown.ValueChangedFcn = createCallbackFcn(app, @InterpolationDropDownValueChanged, false);
715 app.PositionDropDown.Layout.Row = 2;
716 app.PositionDropDown.Layout.Column = 2;
717 app.PositionDropDown.Value = 'none';
718
719 % Create OrientationDropDownLabel
720 app.OrientationDropDownLabel = uilabel(app.gridInterpolationMenu);
721 app.OrientationDropDownLabel.HorizontalAlignment = 'right';
722 app.OrientationDropDownLabel.Layout.Row = 3;
723 app.OrientationDropDownLabel.Layout.Column = 1;
724 app.OrientationDropDownLabel.Text = 'Orientation';
725
726 % Create OrientationDropDown
727 app.OrientationDropDown = uidropdown(app.gridInterpolationMenu);
728 app.OrientationDropDown.Items = {'none'};
729 app.OrientationDropDown.ValueChangedFcn = createCallbackFcn(app, @InterpolationDropDownValueChanged, false);
730 app.OrientationDropDown.Layout.Row = 3;
731 app.OrientationDropDown.Layout.Column = 2;
732 app.OrientationDropDown.Value = 'none';
733
734 % Create TrajectoryGenerationLabel
735 app.TrajectoryGenerationLabel = uilabel(app.gridTrajMenu);
736 app.TrajectoryGenerationLabel.VerticalAlignment = 'bottom';
737 app.TrajectoryGenerationLabel.FontSize = 14;
738 app.TrajectoryGenerationLabel.FontWeight = 'bold';
739 app.TrajectoryGenerationLabel.Layout.Row = 7;
740 app.TrajectoryGenerationLabel.Layout.Column = 1;
741 app.TrajectoryGenerationLabel.Text = 'Trajectory Generation';
742
743 % Create GridLayout
744 app.GridLayout = uigridlayout(app.gridTrajMenu);
745 app.GridLayout.ColumnWidth = {'fit', 'fit'};
746 app.GridLayout.RowHeight = {'fit'};
747 app.GridLayout.Padding = [0 0 0 0];
748 app.GridLayout.Layout.Row = 8;
749 app.GridLayout.Layout.Column = 1;
750
751 % Create GenerateButton
752 app.GenerateButton = uibutton(app.GridLayout, 'push');
753 app.GenerateButton.Layout.Row = 1;
754 app.GenerateButton.Layout.Column = 1;
755 app.GenerateButton.Text = 'Generate';
756
757 % Create PlayButton
758 app.PlayButton = uibutton(app.GridLayout, 'push');
759 app.PlayButton.Layout.Row = 1;
760 app.PlayButton.Layout.Column = 2;
761 app.PlayButton.Text = 'Play';
762
763 % Create Image
764 app.Image = uiimage(app.gridMain);
765 app.Image.Layout.Row = 4;
766 app.Image.Layout.Column = 1;
767 app.Image.HorizontalAlignment = 'left';
768 app.Image.ImageSource = 'logo_isc.png';
769
770 % Create mossFeb2024Label
771 app.mossFeb2024Label = uilabel(app.gridMain);
772 app.mossFeb2024Label.HorizontalAlignment = 'right';
773 app.mossFeb2024Label.VerticalAlignment = 'bottom';
774 app.mossFeb2024Label.FontColor = [0.502 0.502 0.502];
775 app.mossFeb2024Label.Layout.Row = 4;
776 app.mossFeb2024Label.Layout.Column = 2;
777 app.mossFeb2024Label.Text = 'moss, Feb 2024';
778
779 % Show the figure after all components are created
780 app.TrajectoryAppUIFigure.Visible = 'on';
781 end
782 end
783
784 % App creation and deletion
785 methods (Access = public)
786
787 % Construct app
788 function app = trajectoryGenerationApp(varargin)
789
790 % Create UIFigure and components
791 createComponents(app)
792
793 % Register the app with App Designer
794 registerApp(app, app.TrajectoryAppUIFigure)
795
796 % Execute the startup function
797 runStartupFcn(app, @(app)startupFcn(app, varargin{:}))
798
799 if nargout == 0
800 clear app
801 end
802 end
803
804 % Code that executes before app deletion
805 function delete(app)
806
807 % Delete UIFigure when app is deleted
808 delete(app.TrajectoryAppUIFigure)
809 end
810 end
811end
Trajectory Class for generating and manipulating trajectories from waypoints.
Definition Trajectory.m:37
function copy(in obj)
get a copy of the Trajectory object
function cleanTab(in obj)
clean the waypoints table
function getSamplingFrequency(in obj)
get the sampling frequency
function reduce(in obj)
return the waypoints table in a reduced format
app that helps finding an orientation and the corresponding quaternion
handle class from MATLAB.
app that helps to generate a trajectory.
function trajectoryGenerationApp(in varargin)
function SamplingFrequencyChanged(in app)
function tabPointsAddRow(in app)
function tabPointsEditCell(in app, in row, in col)
function uiTableToTraj(in app)
function tabPointsCheckandSort(in app)
function GenerateButtonPushed(in app)
function ImportButtonPushed(in app)
function tabPointsDoubleClicked(in app, in event)
function startupFcn(in app, in traj)
function tabPointsUpdate(in app)
function tabPointsKeyPress(in app, in event)
function tabPointsKeyRelease(in app, in event)
function PlayButtonPushed(in app)
function trajToUiTable(in app)
function InterpolationDropDownValueChanged(in app)
function tabPointsCellEdit(in app, in event)
function createComponents(in app)
function btnPlotWaypointsPushed(in app)
function ExportButtonPushed(in app)
function NewButtonPushed(in app)
app that can be used to visualize a Trajectory object