Master Thesis Code
by Simon Moser
Loading...
Searching...
No Matches
getOrientationApp.m
Go to the documentation of this file.
1% =========================================================================== %
2%> @brief app that helps finding an orientation and the corresponding quaternion
3%>
4%> This app is mainly an orientation visualizer and editor. It can be used to
5%> find the correct orientation of a body and the corresponding quaternion. It
6%> is designed to work with the app @ref trajectoryGenerationApp.m, but can be
7%> used as a standalone app as well.
8%>
9%> The app can be called with no arguments:
10%> @code
12%> @endcode
13%>
14%> or with a quaternion as argument:
15%> @code
16%> getOrientationApp([1,0,0,0]);
17%> @endcode
18%>
19%> or with a quaternion and a calling app as argument:
20%> @code
21%> getOrientationApp(caller,[1,0,0,0]);
22%> @endcode
23%> in the last case, the app will save the new quaternion in the public property
24%> appReturnValue of the calling app.
25%>
26%> @copyright see the file @ref LICENSE in the root directory of the repository
27%>
28%> \par Example Usage
29%>
30%> \image html getOrientationApp.gif
31% =========================================================================== %
32
33classdef getOrientationApp < matlab.apps.AppBase
34
35 % Properties that correspond to app components
36 properties (Access = public)
37 OrientationAppUIFigure matlab.ui.Figure
38 gridMain matlab.ui.container.GridLayout
39 gridSliders matlab.ui.container.GridLayout
40 mossFeb2024Label matlab.ui.control.Label
41 Image matlab.ui.control.Image
42 QuaternionEditField matlab.ui.control.EditField
43 QuaternionEditFieldLabel matlab.ui.control.Label
44 SaveOrientationButton matlab.ui.control.Button
45 DefineOrientationLabel matlab.ui.control.Label
46 slidRoll matlab.ui.control.Slider
47 RollLabel matlab.ui.control.Label
48 slidPitch matlab.ui.control.Slider
49 PitchLabel matlab.ui.control.Label
50 slidYaw matlab.ui.control.Slider
51 YawLabel matlab.ui.control.Label
52 poseVisu matlab.ui.control.UIAxes
53 end
55
56 properties (Access = private)
57 callingApp
58 quat % orientation
59 quatSave % backup from beginning
60 end
61
62 methods (Access = private)
63
64 end
65
67 % Callbacks that handle component events
68 methods (Access = private)
69
70 % Code that executes after component creation
71 function startupFcn(app, varargin)
72
73 switch nargin
74 case 1
75 caller = missing;
76 quat = [1,0,0,0];
77 case 2
78 caller = missing;
79 quat = varargin{1};
80 case 3
81 caller = varargin{1};
82 quat = varargin{2};
83 otherwise
84 e = errordlg("Invalid number of arguments");
85 uiwait(e);
86 app.OrientationAppUIFigureCloseRequest;
87 end
88
89 app.callingApp = caller;
90
91 try
92 app.quat = quaternion(quat);
93 catch
94 app.quat = quaternion([1,0,0,0]);
95 end
96
97 % save the argument for backup
98 app.quatSave = app.quat;
99
100 % set the sliders correctly
101 ang = app.quat.eulerd("ZYX","frame");
102 app.slidYaw.Value = mod(ang(1) + 360,360);
103 app.slidPitch.Value = mod(ang(2) + 360,360);
104 app.slidRoll.Value = mod(ang(3) + 360,360);
105
106 % set the quaternion correctly
107 app.QuaternionEditField.Value = sprintf("%.2f,%.2f,%.2f,%.2f",app.quat.compact);
108
109 % make the poseplot
110 poseplot(app.poseVisu,app.quat,"NED","MeshFileName","jumpSimplified.stl");
111 app.poseVisu.XGrid = true;
112 app.poseVisu.YGrid = true;
113 app.poseVisu.ZGrid = true;
114 app.poseVisu.Children(1).PatchFaceAlpha = 0.7;
115 app.poseVisu.Children(1).Orientation;
116 app.poseVisu.Children(1).PatchFaceColor = [0,0.57,0.82];
117 app.poseVisu.PlotBoxAspectRatioMode = "manual";
118 app.poseVisu.PlotBoxAspectRatio = [1,1,1];
119 end
120
121 % Value changed function: slidPitch, slidRoll, slidYaw
122 function sliderValChange(app, event)
123 yaw = round(app.slidYaw.Value);
124 pitch = round(app.slidPitch.Value);
125 roll = round(app.slidRoll.Value);
126
127 app.quat = quaternion([yaw,pitch,roll],"eulerd","ZYX","frame");
128 app.poseVisu.Children(1).Orientation = app.quat;
129
130 app.QuaternionEditField.Value = sprintf("%.2f,%.2f,%.2f,%.2f",app.quat.compact);
131 end
132
133 % Button pushed function: SaveOrientationButton
134 function SaveOrientationButtonPushed(app, event)
135 app.quatSave = app.quat;
136 app.OrientationAppUIFigureCloseRequest;
137 end
138
139 % Close request function: OrientationAppUIFigure
140 function OrientationAppUIFigureCloseRequest(app, event)
141
142 if ~ismissing(app.callingApp)
143 try
144 app.callingApp.appReturnValue = app.quatSave.compact;
145 catch
146 e = errordlg("No Parent App Defined");
147 uiwait(e);
148 end
149 end
150
151 delete(app)
152
153 end
154
155 % Value changed function: QuaternionEditField
156 function QuaternionEditFieldValueChanged(app, event)
157 value = str2double(strsplit(app.QuaternionEditField.Value,','));
159 try
160 app.quat = quaternion(value);
161 ang = app.quat.eulerd("ZYX","frame");
162 app.slidYaw.Value = mod(ang(1)+360,360);
163 app.slidPitch.Value = mod(ang(2)+360,360);
164 app.slidRoll.Value = mod(ang(3),360);
165 app.sliderValChange;
166 catch
167 e = errordlg("Invalid Quaternion Input");
168 app.sliderValChange;
169 uiwait(e);
170 end
171
172
173 end
174
175 % Key release function: OrientationAppUIFigure
176 function OrientationAppUIFigureKeyRelease(app, event)
177 key = event.Key;
178
179 switch key
180 case 'return'
181 app.SaveOrientationButtonPushed;
182 case 'escape'
183 app.OrientationAppUIFigureCloseRequest;
184 end
185 end
186 end
187
188 % Component initialization
189 methods (Access = private)
190
191 % Create UIFigure and components
192 function createComponents(app)
193
194 % Create OrientationAppUIFigure and hide until all components are created
195 app.OrientationAppUIFigure = uifigure('Visible', 'off');
196 app.OrientationAppUIFigure.Position = [100 100 892 480];
197 app.OrientationAppUIFigure.Name = 'Orientation App';
198 app.OrientationAppUIFigure.Icon = 'logo_zhaw.png';
199 app.OrientationAppUIFigure.CloseRequestFcn = createCallbackFcn(app, @OrientationAppUIFigureCloseRequest, true);
200 app.OrientationAppUIFigure.KeyReleaseFcn = createCallbackFcn(app, @OrientationAppUIFigureKeyRelease, true);
201 app.OrientationAppUIFigure.WindowStyle = 'modal';
202
203 % Create gridMain
204 app.gridMain = uigridlayout(app.OrientationAppUIFigure);
205 app.gridMain.ColumnWidth = {'2x', '3x'};
206 app.gridMain.RowHeight = {'1x'};
207
208 % Create poseVisu
209 app.poseVisu = uiaxes(app.gridMain);
210 xlabel(app.poseVisu, 'X')
211 ylabel(app.poseVisu, 'Y')
212 zlabel(app.poseVisu, 'Z')
213 app.poseVisu.Layout.Row = 1;
214 app.poseVisu.Layout.Column = 2;
215
216 % Create gridSliders
217 app.gridSliders = uigridlayout(app.gridMain);
218 app.gridSliders.ColumnWidth = {150, '1x'};
219 app.gridSliders.RowHeight = {'1x', 'fit', 'fit', 'fit', 'fit', 'fit', 'fit', '1x', 75};
220 app.gridSliders.Layout.Row = 1;
221 app.gridSliders.Layout.Column = 1;
222
223 % Create YawLabel
224 app.YawLabel = uilabel(app.gridSliders);
225 app.YawLabel.HorizontalAlignment = 'right';
226 app.YawLabel.Layout.Row = 3;
227 app.YawLabel.Layout.Column = 1;
228 app.YawLabel.Text = 'Yaw';
229
230 % Create slidYaw
231 app.slidYaw = uislider(app.gridSliders);
232 app.slidYaw.Limits = [0 360];
233 app.slidYaw.ValueChangedFcn = createCallbackFcn(app, @sliderValChange, true);
234 app.slidYaw.Layout.Row = 3;
235 app.slidYaw.Layout.Column = 2;
236
237 % Create PitchLabel
238 app.PitchLabel = uilabel(app.gridSliders);
239 app.PitchLabel.HorizontalAlignment = 'right';
240 app.PitchLabel.Layout.Row = 4;
241 app.PitchLabel.Layout.Column = 1;
242 app.PitchLabel.Text = {'Pitch'; ''};
243
244 % Create slidPitch
245 app.slidPitch = uislider(app.gridSliders);
246 app.slidPitch.Limits = [0 360];
247 app.slidPitch.ValueChangedFcn = createCallbackFcn(app, @sliderValChange, true);
248 app.slidPitch.Layout.Row = 4;
249 app.slidPitch.Layout.Column = 2;
250
251 % Create RollLabel
252 app.RollLabel = uilabel(app.gridSliders);
253 app.RollLabel.HorizontalAlignment = 'right';
254 app.RollLabel.Layout.Row = 5;
255 app.RollLabel.Layout.Column = 1;
256 app.RollLabel.Text = 'Roll';
257
258 % Create slidRoll
259 app.slidRoll = uislider(app.gridSliders);
260 app.slidRoll.Limits = [0 360];
261 app.slidRoll.ValueChangedFcn = createCallbackFcn(app, @sliderValChange, true);
262 app.slidRoll.Layout.Row = 5;
263 app.slidRoll.Layout.Column = 2;
264
265 % Create DefineOrientationLabel
266 app.DefineOrientationLabel = uilabel(app.gridSliders);
267 app.DefineOrientationLabel.HorizontalAlignment = 'center';
268 app.DefineOrientationLabel.FontSize = 18;
269 app.DefineOrientationLabel.FontWeight = 'bold';
270 app.DefineOrientationLabel.Layout.Row = 2;
271 app.DefineOrientationLabel.Layout.Column = 2;
272 app.DefineOrientationLabel.Text = 'Define Orientation';
273
274 % Create SaveOrientationButton
275 app.SaveOrientationButton = uibutton(app.gridSliders, 'push');
276 app.SaveOrientationButton.ButtonPushedFcn = createCallbackFcn(app, @SaveOrientationButtonPushed, true);
277 app.SaveOrientationButton.Layout.Row = 7;
278 app.SaveOrientationButton.Layout.Column = 2;
279 app.SaveOrientationButton.Text = 'Save Orientation';
280
281 % Create QuaternionEditFieldLabel
282 app.QuaternionEditFieldLabel = uilabel(app.gridSliders);
283 app.QuaternionEditFieldLabel.HorizontalAlignment = 'right';
284 app.QuaternionEditFieldLabel.Layout.Row = 6;
285 app.QuaternionEditFieldLabel.Layout.Column = 1;
286 app.QuaternionEditFieldLabel.Text = 'Quaternion';
287
288 % Create QuaternionEditField
289 app.QuaternionEditField = uieditfield(app.gridSliders, 'text');
290 app.QuaternionEditField.ValueChangedFcn = createCallbackFcn(app, @QuaternionEditFieldValueChanged, true);
291 app.QuaternionEditField.HorizontalAlignment = 'center';
292 app.QuaternionEditField.Layout.Row = 6;
293 app.QuaternionEditField.Layout.Column = 2;
294 app.QuaternionEditField.Value = '0,1,0,0';
295
296 % Create Image
297 app.Image = uiimage(app.gridSliders);
298 app.Image.Layout.Row = 9;
299 app.Image.Layout.Column = 1;
300 app.Image.VerticalAlignment = 'bottom';
301 app.Image.ImageSource = 'logo_isc.png';
302
303 % Create mossFeb2024Label
304 app.mossFeb2024Label = uilabel(app.gridSliders);
305 app.mossFeb2024Label.HorizontalAlignment = 'center';
306 app.mossFeb2024Label.VerticalAlignment = 'bottom';
307 app.mossFeb2024Label.FontColor = [0.502 0.502 0.502];
308 app.mossFeb2024Label.Layout.Row = 9;
309 app.mossFeb2024Label.Layout.Column = 2;
310 app.mossFeb2024Label.Text = 'moss, Feb 2024';
311
312 % Show the figure after all components are created
313 app.OrientationAppUIFigure.Visible = 'on';
314 end
315 end
316
317 % App creation and deletion
318 methods (Access = public)
319
320 % Construct app
321 function app = getOrientationApp(varargin)
322
323 % Create UIFigure and components
324 createComponents(app)
325
326 % Register the app with App Designer
327 registerApp(app, app.OrientationAppUIFigure)
328
329 % Execute the startup function
330 runStartupFcn(app, @(app)startupFcn(app, varargin{:}))
331
332 if nargout == 0
333 clear app
334 end
335 end
336
337 % Code that executes before app deletion
338 function delete(app)
339
340 % Delete UIFigure when app is deleted
341 delete(app.OrientationAppUIFigure)
342 end
343 end
344end
app that helps finding an orientation and the corresponding quaternion
function OrientationAppUIFigureCloseRequest(in app, in event)
Property OrientationAppUIFigure
function SaveOrientationButtonPushed(in app, in event)
function QuaternionEditFieldValueChanged(in app, in event)
Property DefineOrientationLabel
function sliderValChange(in app, in event)
function OrientationAppUIFigureKeyRelease(in app, in event)
function getOrientationApp(in varargin)
function startupFcn(in app, in varargin)
function createComponents(in app)
Property QuaternionEditFieldLabel
handle class from MATLAB.
app that helps to generate a trajectory.