PX4 Firmware
PX4 Autopilot Software http://px4.io
state_machine_helper_test.cpp
Go to the documentation of this file.
1 /****************************************************************************
2  *
3  * Copyright (C) 2013 PX4 Development Team. All rights reserved.
4  * Author: Simon Wilks <sjwilks@gmail.com>
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions
8  * are met:
9  *
10  * 1. Redistributions of source code must retain the above copyright
11  * notice, this list of conditions and the following disclaimer.
12  * 2. Redistributions in binary form must reproduce the above copyright
13  * notice, this list of conditions and the following disclaimer in
14  * the documentation and/or other materials provided with the
15  * distribution.
16  * 3. Neither the name PX4 nor the names of its contributors may be
17  * used to endorse or promote products derived from this software
18  * without specific prior written permission.
19  *
20  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
23  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
24  * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
25  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
26  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
27  * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
28  * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
30  * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
31  * POSSIBILITY OF SUCH DAMAGE.
32  *
33  ****************************************************************************/
34 
35 /**
36  * @file state_machine_helper_test.cpp
37  * System state machine unit test.
38  *
39  */
40 
42 
43 #include "../state_machine_helper.h"
44 #include <unit_test.h>
45 #include "../Arming/PreFlightCheck/PreFlightCheck.hpp"
46 
48 {
49 public:
50  StateMachineHelperTest() = default;
51  ~StateMachineHelperTest() override = default;
52 
53  bool run_tests() override;
54 
55 private:
58  bool isSafeTest();
59 };
60 
62 {
63  // These are the critical values from vehicle_status_s and actuator_armed_s which must be primed
64  // to simulate machine state prior to testing an arming state transition. This structure is also
65  // use to represent the expected machine state after the transition has been requested.
66  typedef struct {
67  arming_state_t arming_state; // vehicle_status_s.arming_state
68  bool armed; // actuator_armed_s.armed
69  bool ready_to_arm; // actuator_armed_s.ready_to_arm
70  } ArmingTransitionVolatileState_t;
71 
72  // This structure represents a test case for arming_state_transition. It contains the machine
73  // state prior to transition, the requested state to transition to and finally the expected
74  // machine state after transition.
75  typedef struct {
76  const char *assertMsg; // Text to show when test case fails
77  ArmingTransitionVolatileState_t current_state; // Machine state prior to transition
78  hil_state_t hil_state; // Current vehicle_status_s.hil_state
79  bool
80  condition_system_sensors_initialized; // Current vehicle_status_s.condition_system_sensors_initialized
81  bool safety_switch_available; // Current safety_s.safety_switch_available
82  bool safety_off; // Current safety_s.safety_off
83  arming_state_t requested_state; // Requested arming state to transition to
84  ArmingTransitionVolatileState_t expected_state; // Expected machine state after transition
85  transition_result_t expected_transition_result; // Expected result from arming_state_transition
86  } ArmingTransitionTest_t;
87 
88  // We use these defines so that our test cases are more readable
89 #define ATT_ARMED true
90 #define ATT_DISARMED false
91 #define ATT_READY_TO_ARM true
92 #define ATT_NOT_READY_TO_ARM false
93 #define ATT_SENSORS_INITIALIZED true
94 #define ATT_SENSORS_NOT_INITIALIZED false
95 #define ATT_SAFETY_AVAILABLE true
96 #define ATT_SAFETY_NOT_AVAILABLE true
97 #define ATT_SAFETY_OFF true
98 #define ATT_SAFETY_ON false
99 
100  // These are test cases for arming_state_transition
101  static const ArmingTransitionTest_t rgArmingTransitionTests[] = {
102  // TRANSITION_NOT_CHANGED tests
103 
104  {
105  "no transition: identical states",
106  { vehicle_status_s::ARMING_STATE_INIT, ATT_DISARMED, ATT_NOT_READY_TO_ARM }, vehicle_status_s::HIL_STATE_OFF, ATT_SENSORS_INITIALIZED, ATT_SAFETY_AVAILABLE, ATT_SAFETY_ON,
107  vehicle_status_s::ARMING_STATE_INIT,
108  { vehicle_status_s::ARMING_STATE_INIT, ATT_DISARMED, ATT_NOT_READY_TO_ARM }, TRANSITION_NOT_CHANGED
109  },
110 
111  // TRANSITION_CHANGED tests
112 
113  // Check all basic valid transitions, these don't require special state in vehicle_status_t or safety_s
114 
115  {
116  "transition: init to standby",
117  { vehicle_status_s::ARMING_STATE_INIT, ATT_DISARMED, ATT_NOT_READY_TO_ARM }, vehicle_status_s::HIL_STATE_OFF, ATT_SENSORS_INITIALIZED, ATT_SAFETY_AVAILABLE, ATT_SAFETY_ON,
118  vehicle_status_s::ARMING_STATE_STANDBY,
119  { vehicle_status_s::ARMING_STATE_STANDBY, ATT_DISARMED, ATT_READY_TO_ARM }, TRANSITION_CHANGED
120  },
121 
122  {
123  "transition: init to standby error",
124  { vehicle_status_s::ARMING_STATE_INIT, ATT_DISARMED, ATT_NOT_READY_TO_ARM }, vehicle_status_s::HIL_STATE_OFF, ATT_SENSORS_INITIALIZED, ATT_SAFETY_AVAILABLE, ATT_SAFETY_ON,
125  vehicle_status_s::ARMING_STATE_STANDBY_ERROR,
126  { vehicle_status_s::ARMING_STATE_STANDBY_ERROR, ATT_DISARMED, ATT_NOT_READY_TO_ARM }, TRANSITION_CHANGED
127  },
128 
129  {
130  "transition: init to reboot",
131  { vehicle_status_s::ARMING_STATE_INIT, ATT_DISARMED, ATT_NOT_READY_TO_ARM }, vehicle_status_s::HIL_STATE_OFF, ATT_SENSORS_INITIALIZED, ATT_SAFETY_AVAILABLE, ATT_SAFETY_ON,
132  vehicle_status_s::ARMING_STATE_SHUTDOWN,
133  { vehicle_status_s::ARMING_STATE_SHUTDOWN, ATT_DISARMED, ATT_NOT_READY_TO_ARM }, TRANSITION_CHANGED
134  },
135 
136  {
137  "transition: standby to init",
138  { vehicle_status_s::ARMING_STATE_STANDBY, ATT_DISARMED, ATT_READY_TO_ARM }, vehicle_status_s::HIL_STATE_OFF, ATT_SENSORS_INITIALIZED, ATT_SAFETY_AVAILABLE, ATT_SAFETY_ON,
139  vehicle_status_s::ARMING_STATE_INIT,
140  { vehicle_status_s::ARMING_STATE_INIT, ATT_DISARMED, ATT_NOT_READY_TO_ARM }, TRANSITION_CHANGED
141  },
142 
143  {
144  "transition: standby to standby error",
145  { vehicle_status_s::ARMING_STATE_STANDBY, ATT_DISARMED, ATT_READY_TO_ARM }, vehicle_status_s::HIL_STATE_OFF, ATT_SENSORS_INITIALIZED, ATT_SAFETY_AVAILABLE, ATT_SAFETY_ON,
146  vehicle_status_s::ARMING_STATE_STANDBY_ERROR,
147  { vehicle_status_s::ARMING_STATE_STANDBY_ERROR, ATT_DISARMED, ATT_NOT_READY_TO_ARM }, TRANSITION_CHANGED
148  },
149 
150  {
151  "transition: standby to reboot",
152  { vehicle_status_s::ARMING_STATE_STANDBY, ATT_DISARMED, ATT_READY_TO_ARM }, vehicle_status_s::HIL_STATE_OFF, ATT_SENSORS_INITIALIZED, ATT_SAFETY_AVAILABLE, ATT_SAFETY_ON,
153  vehicle_status_s::ARMING_STATE_SHUTDOWN,
154  { vehicle_status_s::ARMING_STATE_SHUTDOWN, ATT_DISARMED, ATT_NOT_READY_TO_ARM }, TRANSITION_CHANGED
155  },
156 
157  {
158  "transition: armed to standby",
159  { vehicle_status_s::ARMING_STATE_ARMED, ATT_ARMED, ATT_READY_TO_ARM }, vehicle_status_s::HIL_STATE_OFF, ATT_SENSORS_INITIALIZED, ATT_SAFETY_AVAILABLE, ATT_SAFETY_ON,
160  vehicle_status_s::ARMING_STATE_STANDBY,
161  { vehicle_status_s::ARMING_STATE_STANDBY, ATT_DISARMED, ATT_READY_TO_ARM }, TRANSITION_CHANGED
162  },
163 
164  {
165  "transition: standby error to reboot",
166  { vehicle_status_s::ARMING_STATE_STANDBY_ERROR, ATT_DISARMED, ATT_NOT_READY_TO_ARM }, vehicle_status_s::HIL_STATE_OFF, ATT_SENSORS_INITIALIZED, ATT_SAFETY_AVAILABLE, ATT_SAFETY_ON,
167  vehicle_status_s::ARMING_STATE_SHUTDOWN,
168  { vehicle_status_s::ARMING_STATE_SHUTDOWN, ATT_DISARMED, ATT_NOT_READY_TO_ARM }, TRANSITION_CHANGED
169  },
170 
171  {
172  "transition: in air restore to armed",
173  { vehicle_status_s::ARMING_STATE_IN_AIR_RESTORE, ATT_DISARMED, ATT_READY_TO_ARM }, vehicle_status_s::HIL_STATE_OFF, ATT_SENSORS_INITIALIZED, ATT_SAFETY_AVAILABLE, ATT_SAFETY_ON,
174  vehicle_status_s::ARMING_STATE_ARMED,
175  { vehicle_status_s::ARMING_STATE_ARMED, ATT_ARMED, ATT_READY_TO_ARM }, TRANSITION_CHANGED
176  },
177 
178  {
179  "transition: in air restore to reboot",
180  { vehicle_status_s::ARMING_STATE_IN_AIR_RESTORE, ATT_DISARMED, ATT_READY_TO_ARM }, vehicle_status_s::HIL_STATE_OFF, ATT_SENSORS_INITIALIZED, ATT_SAFETY_AVAILABLE, ATT_SAFETY_ON,
181  vehicle_status_s::ARMING_STATE_SHUTDOWN,
182  { vehicle_status_s::ARMING_STATE_SHUTDOWN, ATT_DISARMED, ATT_NOT_READY_TO_ARM }, TRANSITION_CHANGED
183  },
184 
185  // hil on tests, standby error to standby not normally allowed
186 
187  {
188  "transition: standby error to standby, hil on",
189  { vehicle_status_s::ARMING_STATE_STANDBY_ERROR, ATT_DISARMED, ATT_NOT_READY_TO_ARM }, vehicle_status_s::HIL_STATE_ON, ATT_SENSORS_INITIALIZED, ATT_SAFETY_AVAILABLE, ATT_SAFETY_ON,
190  vehicle_status_s::ARMING_STATE_STANDBY,
191  { vehicle_status_s::ARMING_STATE_STANDBY, ATT_DISARMED, ATT_READY_TO_ARM }, TRANSITION_CHANGED
192  },
193 
194  // Safety switch arming tests
195 
196  {
197  "transition: standby to armed, no safety switch",
198  { vehicle_status_s::ARMING_STATE_STANDBY, ATT_DISARMED, ATT_READY_TO_ARM }, vehicle_status_s::HIL_STATE_ON, ATT_SENSORS_INITIALIZED, ATT_SAFETY_NOT_AVAILABLE, ATT_SAFETY_OFF,
199  vehicle_status_s::ARMING_STATE_ARMED,
200  { vehicle_status_s::ARMING_STATE_ARMED, ATT_ARMED, ATT_READY_TO_ARM }, TRANSITION_CHANGED
201  },
202 
203  {
204  "transition: standby to armed, safety switch off",
205  { vehicle_status_s::ARMING_STATE_STANDBY, ATT_DISARMED, ATT_READY_TO_ARM }, vehicle_status_s::HIL_STATE_ON, ATT_SENSORS_INITIALIZED, ATT_SAFETY_AVAILABLE, ATT_SAFETY_OFF,
206  vehicle_status_s::ARMING_STATE_ARMED,
207  { vehicle_status_s::ARMING_STATE_ARMED, ATT_ARMED, ATT_READY_TO_ARM }, TRANSITION_CHANGED
208  },
209 
210  // TRANSITION_DENIED tests
211 
212  // Check some important basic invalid transitions, these don't require special state in vehicle_status_t or safety_s
213 
214  {
215  "no transition: init to armed",
216  { vehicle_status_s::ARMING_STATE_INIT, ATT_DISARMED, ATT_NOT_READY_TO_ARM }, vehicle_status_s::HIL_STATE_OFF, ATT_SENSORS_INITIALIZED, ATT_SAFETY_AVAILABLE, ATT_SAFETY_ON,
217  vehicle_status_s::ARMING_STATE_ARMED,
218  { vehicle_status_s::ARMING_STATE_INIT, ATT_DISARMED, ATT_NOT_READY_TO_ARM }, TRANSITION_DENIED
219  },
220 
221  {
222  "no transition: armed to init",
223  { vehicle_status_s::ARMING_STATE_ARMED, ATT_ARMED, ATT_READY_TO_ARM }, vehicle_status_s::HIL_STATE_OFF, ATT_SENSORS_INITIALIZED, ATT_SAFETY_AVAILABLE, ATT_SAFETY_ON,
224  vehicle_status_s::ARMING_STATE_INIT,
225  { vehicle_status_s::ARMING_STATE_ARMED, ATT_ARMED, ATT_READY_TO_ARM }, TRANSITION_DENIED
226  },
227 
228  {
229  "no transition: armed to reboot",
230  { vehicle_status_s::ARMING_STATE_ARMED, ATT_ARMED, ATT_READY_TO_ARM }, vehicle_status_s::HIL_STATE_OFF, ATT_SENSORS_INITIALIZED, ATT_SAFETY_AVAILABLE, ATT_SAFETY_ON,
231  vehicle_status_s::ARMING_STATE_SHUTDOWN,
232  { vehicle_status_s::ARMING_STATE_ARMED, ATT_ARMED, ATT_READY_TO_ARM }, TRANSITION_DENIED
233  },
234 
235  {
236  "no transition: standby error to armed",
237  { vehicle_status_s::ARMING_STATE_STANDBY_ERROR, ATT_DISARMED, ATT_NOT_READY_TO_ARM }, vehicle_status_s::HIL_STATE_OFF, ATT_SENSORS_INITIALIZED, ATT_SAFETY_AVAILABLE, ATT_SAFETY_ON,
238  vehicle_status_s::ARMING_STATE_ARMED,
239  { vehicle_status_s::ARMING_STATE_STANDBY_ERROR, ATT_DISARMED, ATT_NOT_READY_TO_ARM }, TRANSITION_DENIED
240  },
241 
242  {
243  "no transition: standby error to standby",
244  { vehicle_status_s::ARMING_STATE_STANDBY_ERROR, ATT_DISARMED, ATT_NOT_READY_TO_ARM }, vehicle_status_s::HIL_STATE_OFF, ATT_SENSORS_INITIALIZED, ATT_SAFETY_AVAILABLE, ATT_SAFETY_ON,
245  vehicle_status_s::ARMING_STATE_STANDBY,
246  { vehicle_status_s::ARMING_STATE_STANDBY_ERROR, ATT_DISARMED, ATT_NOT_READY_TO_ARM }, TRANSITION_DENIED
247  },
248 
249  {
250  "no transition: reboot to armed",
251  { vehicle_status_s::ARMING_STATE_SHUTDOWN, ATT_DISARMED, ATT_NOT_READY_TO_ARM }, vehicle_status_s::HIL_STATE_OFF, ATT_SENSORS_INITIALIZED, ATT_SAFETY_AVAILABLE, ATT_SAFETY_ON,
252  vehicle_status_s::ARMING_STATE_ARMED,
253  { vehicle_status_s::ARMING_STATE_SHUTDOWN, ATT_DISARMED, ATT_NOT_READY_TO_ARM }, TRANSITION_DENIED
254  },
255 
256  {
257  "no transition: in air restore to standby",
258  { vehicle_status_s::ARMING_STATE_IN_AIR_RESTORE, ATT_DISARMED, ATT_NOT_READY_TO_ARM }, vehicle_status_s::HIL_STATE_OFF, ATT_SENSORS_INITIALIZED, ATT_SAFETY_AVAILABLE, ATT_SAFETY_ON,
259  vehicle_status_s::ARMING_STATE_STANDBY,
260  { vehicle_status_s::ARMING_STATE_IN_AIR_RESTORE, ATT_DISARMED, ATT_NOT_READY_TO_ARM }, TRANSITION_DENIED
261  },
262 
263  // Sensor tests
264 
265  //{ "transition to standby error: init to standby - sensors not initialized",
266  // { vehicle_status_s::ARMING_STATE_INIT, ATT_DISARMED, ATT_NOT_READY_TO_ARM }, vehicle_status_s::HIL_STATE_OFF, ATT_SENSORS_NOT_INITIALIZED, ATT_SAFETY_AVAILABLE, ATT_SAFETY_ON,
267  // vehicle_status_s::ARMING_STATE_STANDBY,
268  // { vehicle_status_s::ARMING_STATE_STANDBY_ERROR, ATT_DISARMED, ATT_NOT_READY_TO_ARM }, TRANSITION_DENIED },
269 
270  // Safety switch arming tests
271 
272  {
273  "no transition: init to armed, safety switch on",
274  { vehicle_status_s::ARMING_STATE_STANDBY, ATT_DISARMED, ATT_READY_TO_ARM }, vehicle_status_s::HIL_STATE_OFF, ATT_SENSORS_INITIALIZED, ATT_SAFETY_AVAILABLE, ATT_SAFETY_ON,
275  vehicle_status_s::ARMING_STATE_ARMED,
276  { vehicle_status_s::ARMING_STATE_STANDBY, ATT_DISARMED, ATT_READY_TO_ARM }, TRANSITION_DENIED
277  },
278  };
279 
280  struct vehicle_status_s status = {};
281  struct vehicle_status_flags_s status_flags = {};
282  struct safety_s safety = {};
283  struct actuator_armed_s armed = {};
284 
285  size_t cArmingTransitionTests = sizeof(rgArmingTransitionTests) / sizeof(rgArmingTransitionTests[0]);
286 
287  for (size_t i = 0; i < cArmingTransitionTests; i++) {
288  const ArmingTransitionTest_t *test = &rgArmingTransitionTests[i];
289 
290  const bool check_gps = false;
291 
292  // Setup initial machine state
293  status.arming_state = test->current_state.arming_state;
294  status_flags.condition_system_sensors_initialized = test->condition_system_sensors_initialized;
295  status.hil_state = test->hil_state;
296  // The power status of the test unit is not relevant for the unit test
297  status_flags.circuit_breaker_engaged_power_check = true;
298  safety.safety_switch_available = test->safety_switch_available;
299  safety.safety_off = test->safety_off;
300  armed.armed = test->current_state.armed;
301  armed.ready_to_arm = test->current_state.ready_to_arm;
302 
303  // Attempt transition
304  transition_result_t result = arming_state_transition(&status, safety, test->requested_state, &armed,
305  true /* enable pre-arm checks */,
306  nullptr /* no mavlink_log_pub */,
307  &status_flags,
308  (check_gps ? PreFlightCheck::ARM_REQ_GPS_BIT : 0),
309  2e6 /* 2 seconds after boot, everything should be checked */
310  );
311 
312  // Validate result of transition
313  ut_compare(test->assertMsg, test->expected_transition_result, result);
314  ut_compare(test->assertMsg, status.arming_state, test->expected_state.arming_state);
315  ut_compare(test->assertMsg, armed.armed, test->expected_state.armed);
316  ut_compare(test->assertMsg, armed.ready_to_arm, test->expected_state.ready_to_arm);
317  }
318 
319  return true;
320 }
321 
323 {
324  // This structure represent a single test case for testing Main State transitions.
325  typedef struct {
326  const char *assertMsg; // Text to show when test case fails
327  uint8_t condition_bits; // Bits for various condition_* values
328  uint8_t from_state; // State prior to transition request
329  main_state_t to_state; // State to transition to
330  transition_result_t expected_transition_result; // Expected result from main_state_transition call
331  } MainTransitionTest_t;
332 
333  // Bits for condition_bits
334 #define MTT_ALL_NOT_VALID 0
335 #define MTT_ROTARY_WING 1 << 0
336 #define MTT_LOC_ALT_VALID 1 << 1
337 #define MTT_LOC_POS_VALID 1 << 2
338 #define MTT_HOME_POS_VALID 1 << 3
339 #define MTT_GLOBAL_POS_VALID 1 << 4
340 
341  static const MainTransitionTest_t rgMainTransitionTests[] = {
342 
343  // TRANSITION_NOT_CHANGED tests
344 
345  {
346  "no transition: identical states",
348  commander_state_s::MAIN_STATE_MANUAL, commander_state_s::MAIN_STATE_MANUAL, TRANSITION_NOT_CHANGED
349  },
350 
351  // TRANSITION_CHANGED tests
352 
353  {
354  "transition: MANUAL to ACRO - rotary",
356  commander_state_s::MAIN_STATE_MANUAL, commander_state_s::MAIN_STATE_ACRO, TRANSITION_CHANGED
357  },
358 
359  {
360  "transition: MANUAL to ACRO - not rotary",
362  commander_state_s::MAIN_STATE_MANUAL, commander_state_s::MAIN_STATE_ACRO, TRANSITION_CHANGED
363  },
364 
365  {
366  "transition: ACRO to MANUAL",
368  commander_state_s::MAIN_STATE_ACRO, commander_state_s::MAIN_STATE_MANUAL, TRANSITION_CHANGED
369  },
370 
371  {
372  "transition: MANUAL to AUTO_MISSION - global position valid, home position valid",
374  commander_state_s::MAIN_STATE_MANUAL, commander_state_s::MAIN_STATE_AUTO_MISSION, TRANSITION_CHANGED
375  },
376 
377  {
378  "transition: AUTO_MISSION to MANUAL - global position valid, home position valid",
380  commander_state_s::MAIN_STATE_AUTO_MISSION, commander_state_s::MAIN_STATE_MANUAL, TRANSITION_CHANGED
381  },
382 
383  {
384  "transition: MANUAL to AUTO_LOITER - global position valid",
386  commander_state_s::MAIN_STATE_MANUAL, commander_state_s::MAIN_STATE_AUTO_LOITER, TRANSITION_CHANGED
387  },
388 
389  {
390  "transition: AUTO_LOITER to MANUAL - global position valid",
392  commander_state_s::MAIN_STATE_AUTO_LOITER, commander_state_s::MAIN_STATE_MANUAL, TRANSITION_CHANGED
393  },
394 
395  {
396  "transition: MANUAL to AUTO_RTL - global position valid, home position valid",
398  commander_state_s::MAIN_STATE_MANUAL, commander_state_s::MAIN_STATE_AUTO_RTL, TRANSITION_CHANGED
399  },
400 
401  {
402  "transition: AUTO_RTL to MANUAL - global position valid, home position valid",
404  commander_state_s::MAIN_STATE_AUTO_RTL, commander_state_s::MAIN_STATE_MANUAL, TRANSITION_CHANGED
405  },
406 
407  {
408  "transition: MANUAL to ALTCTL - not rotary",
410  commander_state_s::MAIN_STATE_MANUAL, commander_state_s::MAIN_STATE_ALTCTL, TRANSITION_CHANGED
411  },
412 
413  {
414  "transition: MANUAL to ALTCTL - rotary, global position not valid, local altitude valid",
416  commander_state_s::MAIN_STATE_MANUAL, commander_state_s::MAIN_STATE_ALTCTL, TRANSITION_CHANGED
417  },
418 
419  {
420  "transition: MANUAL to ALTCTL - rotary, global position valid, local altitude not valid",
422  commander_state_s::MAIN_STATE_MANUAL, commander_state_s::MAIN_STATE_ALTCTL, TRANSITION_CHANGED
423  },
424 
425  {
426  "transition: ALTCTL to MANUAL - local altitude valid",
428  commander_state_s::MAIN_STATE_ALTCTL, commander_state_s::MAIN_STATE_MANUAL, TRANSITION_CHANGED
429  },
430 
431  {
432  "transition: MANUAL to POSCTL - local position not valid, global position valid",
434  commander_state_s::MAIN_STATE_MANUAL, commander_state_s::MAIN_STATE_POSCTL, TRANSITION_CHANGED
435  },
436 
437  {
438  "transition: MANUAL to POSCTL - local position valid, global position not valid",
440  commander_state_s::MAIN_STATE_MANUAL, commander_state_s::MAIN_STATE_POSCTL, TRANSITION_CHANGED
441  },
442 
443  {
444  "transition: POSCTL to MANUAL - local position valid, global position valid",
446  commander_state_s::MAIN_STATE_POSCTL, commander_state_s::MAIN_STATE_MANUAL, TRANSITION_CHANGED
447  },
448 
449  // TRANSITION_DENIED tests
450 
451  {
452  "no transition: MANUAL to AUTO_MISSION - global position not valid",
454  commander_state_s::MAIN_STATE_MANUAL, commander_state_s::MAIN_STATE_AUTO_MISSION, TRANSITION_DENIED
455  },
456 
457  {
458  "no transition: MANUAL to AUTO_LOITER - global position not valid",
460  commander_state_s::MAIN_STATE_MANUAL, commander_state_s::MAIN_STATE_AUTO_LOITER, TRANSITION_DENIED
461  },
462 
463  {
464  "no transition: MANUAL to AUTO_RTL - global position not valid, home position not valid",
466  commander_state_s::MAIN_STATE_MANUAL, commander_state_s::MAIN_STATE_AUTO_RTL, TRANSITION_DENIED
467  },
468 
469  {
470  "no transition: MANUAL to AUTO_RTL - global position not valid, home position valid",
472  commander_state_s::MAIN_STATE_MANUAL, commander_state_s::MAIN_STATE_AUTO_RTL, TRANSITION_DENIED
473  },
474 
475  {
476  "no transition: MANUAL to AUTO_RTL - global position valid, home position not valid",
478  commander_state_s::MAIN_STATE_MANUAL, commander_state_s::MAIN_STATE_AUTO_RTL, TRANSITION_DENIED
479  },
480 
481  {
482  "transition: MANUAL to ALTCTL - not rotary",
484  commander_state_s::MAIN_STATE_MANUAL, commander_state_s::MAIN_STATE_ALTCTL, TRANSITION_DENIED
485  },
486 
487  {
488  "no transition: MANUAL to ALTCTL - rotary, global position not valid, local altitude not valid",
490  commander_state_s::MAIN_STATE_MANUAL, commander_state_s::MAIN_STATE_ALTCTL, TRANSITION_DENIED
491  },
492 
493  {
494  "no transition: MANUAL to POSCTL - local position not valid, global position not valid",
496  commander_state_s::MAIN_STATE_MANUAL, commander_state_s::MAIN_STATE_POSCTL, TRANSITION_DENIED
497  },
498  };
499 
500  size_t cMainTransitionTests = sizeof(rgMainTransitionTests) / sizeof(rgMainTransitionTests[0]);
501 
502  for (size_t i = 0; i < cMainTransitionTests; i++) {
503  const MainTransitionTest_t *test = &rgMainTransitionTests[i];
504 
505  // Setup initial machine state
506  struct vehicle_status_s current_vehicle_status = {};
507  struct commander_state_s current_commander_state = {};
508  struct vehicle_status_flags_s current_status_flags = {};
509 
510  current_commander_state.main_state = test->from_state;
511  current_vehicle_status.vehicle_type = (test->condition_bits & MTT_ROTARY_WING) ?
512  vehicle_status_s::VEHICLE_TYPE_ROTARY_WING : vehicle_status_s::VEHICLE_TYPE_FIXED_WING;
513  current_status_flags.condition_local_altitude_valid = test->condition_bits & MTT_LOC_ALT_VALID;
514  current_status_flags.condition_local_position_valid = test->condition_bits & MTT_LOC_POS_VALID;
515  current_status_flags.condition_home_position_valid = test->condition_bits & MTT_HOME_POS_VALID;
516  current_status_flags.condition_global_position_valid = test->condition_bits & MTT_GLOBAL_POS_VALID;
517  current_status_flags.condition_auto_mission_available = true;
518 
519  // Attempt transition
520  transition_result_t result = main_state_transition(current_vehicle_status, test->to_state, current_status_flags,
521  &current_commander_state);
522 
523  // Validate result of transition
524  ut_compare(test->assertMsg, test->expected_transition_result, result);
525 
526  if (test->expected_transition_result == result) {
527  if (test->expected_transition_result == TRANSITION_CHANGED) {
528  ut_compare(test->assertMsg, test->to_state, current_commander_state.main_state);
529 
530  } else {
531  ut_compare(test->assertMsg, test->from_state, current_commander_state.main_state);
532  }
533  }
534  }
535 
536  return true;
537 }
538 
540 {
541  struct safety_s safety = {};
542  struct actuator_armed_s armed = {};
543 
544  armed.armed = false;
545  armed.lockdown = false;
546  safety.safety_switch_available = true;
547  safety.safety_off = false;
548  ut_compare("is safe: not armed", is_safe(safety, armed), true);
549 
550  armed.armed = false;
551  armed.lockdown = true;
552  safety.safety_switch_available = true;
553  safety.safety_off = true;
554  ut_compare("is safe: software lockdown", is_safe(safety, armed), true);
555 
556  armed.armed = true;
557  armed.lockdown = false;
558  safety.safety_switch_available = true;
559  safety.safety_off = true;
560  ut_compare("not safe: safety off", is_safe(safety, armed), false);
561 
562  armed.armed = true;
563  armed.lockdown = false;
564  safety.safety_switch_available = true;
565  safety.safety_off = false;
566  ut_compare("is safe: safety off", is_safe(safety, armed), true);
567 
568  armed.armed = true;
569  armed.lockdown = false;
570  safety.safety_switch_available = false;
571  safety.safety_off = false;
572  ut_compare("not safe: no safety switch", is_safe(safety, armed), false);
573 
574  return true;
575 }
576 
578 {
582 
583  return (_tests_failed == 0);
584 }
585 
#define VEHICLE_TYPE_FIXED_WING
#define ut_declare_test(test_function, test_class)
Macro to create a function which will run a unit test class and print results.
Definition: unit_test.h:82
#define ATT_SAFETY_AVAILABLE
#define MTT_LOC_ALT_VALID
#define MTT_HOME_POS_VALID
uint8_t arming_state_t
Definition: uORB.h:257
Base class to be used for unit tests.
Definition: unit_test.h:54
bool safety_switch_available
Definition: safety.h:54
#define MTT_GLOBAL_POS_VALID
#define ATT_SENSORS_INITIALIZED
~StateMachineHelperTest() override=default
int _tests_failed
The number of unit tests which failed.
Definition: unit_test.h:206
#define ATT_ARMED
#define ATT_SAFETY_OFF
static struct actuator_armed_s armed
Definition: Commander.cpp:139
void test(enum LPS25H_BUS busid)
Perform some basic functional tests on the driver; make sure we can collect data from the sensor in p...
Definition: lps25h.cpp:792
bool is_safe(const safety_s &safety, const actuator_armed_s &armed)
#define MTT_LOC_POS_VALID
StateMachineHelperTest()=default
uint8_t main_state_t
Definition: uORB.h:258
#define ATT_SAFETY_NOT_AVAILABLE
bool stateMachineHelperTest(void)
#define ATT_DISARMED
#define ATT_READY_TO_ARM
uint8_t hil_state_t
Definition: uORB.h:259
#define ut_compare(message, v1, v2)
Used to compare two integer values within a unit test.
Definition: unit_test.h:150
#define ATT_SAFETY_ON
transition_result_t main_state_transition(const vehicle_status_s &status, const main_state_t new_main_state, const vehicle_status_flags_s &status_flags, commander_state_s *internal_state)
#define ut_run_test(test)
Runs a single unit test.
Definition: unit_test.h:96
transition_result_t arming_state_transition(vehicle_status_s *status, const safety_s &safety, const arming_state_t new_arming_state, actuator_armed_s *armed, const bool fRunPreArmChecks, orb_advert_t *mavlink_log_pub, vehicle_status_flags_s *status_flags, const uint8_t arm_requirements, const hrt_abstime &time_since_boot)
#define MTT_ALL_NOT_VALID
transition_result_t
bool safety_off
Definition: safety.h:55
#define ATT_NOT_READY_TO_ARM
#define MTT_ROTARY_WING
bool run_tests() override
Override to run your unit tests.