source: flair-src/trunk/lib/FlairMeta/src/UavStateMachine.cpp@ 448

Last change on this file since 448 was 432, checked in by Sanahuja Guillaume, 3 years ago

add AltitudeSensor class
failsafe altitude sensor in changeable

File size: 26.7 KB
RevLine 
[10]1// %flair:license{
[15]2// This file is part of the Flair framework distributed under the
3// CECILL-C License, Version 1.0.
[10]4// %flair:license}
[7]5// created: 2014/04/29
6// filename: UavStateMachine.cpp
7//
8// author: Gildas Bayard, Guillaume Sanahuja
9// Copyright Heudiasyc UMR UTC/CNRS 7253
10//
11// version: $Id: $
12//
13// purpose: meta class for UAV
14//
15//
16/*********************************************************************/
17
18#include "UavStateMachine.h"
19#include "Uav.h"
20#include <DataPlot1D.h>
21#include <GridLayout.h>
22#include <Tab.h>
23#include <TabWidget.h>
24#include <PushButton.h>
25#include <SpinBox.h>
26#include <DoubleSpinBox.h>
27#include <X4X8Multiplex.h>
28#include <Bldc.h>
29#include <Ahrs.h>
30#include <MetaUsRangeFinder.h>
31#include <ControlLaw.h>
32#include <Pid.h>
33#include <PidThrust.h>
34#include <NestedSat.h>
35#include <MetaDualShock3.h>
36#include <AhrsData.h>
37#include <BatteryMonitor.h>
38#include <FrameworkManager.h>
39#include <Vector3D.h>
40#include <Vector2D.h>
[214]41#include <Matrix.h>
[7]42#include <stdio.h>
43#include <TrajectoryGenerator1D.h>
[42]44#include <math.h>
[7]45
46using namespace std;
47using namespace flair::core;
48using namespace flair::gui;
49using namespace flair::sensor;
50using namespace flair::actuator;
51using namespace flair::filter;
52using namespace flair::meta;
53
[122]54UavStateMachine::UavStateMachine(TargetController *controller):
[432]55 Thread(getFrameworkManager(),"UavStateMachine",50),
56 uav(GetUav()),controller(controller),failSafeMode(true),flagConnectionLost(false),flagBatteryLow(false),flagCriticalSensorLost(false),flagZTrajectoryFinished(false),safeToFly(true){
57 altitudeState=AltitudeState_t::Stopped;
58 uav->UseDefaultPlot();
[7]59
[15]60 Tab *uavTab = new Tab(getFrameworkManager()->GetTabWidget(), "uav", 0);
61 buttonslayout = new GridLayout(uavTab->NewRow(), "buttons");
62 button_kill = new PushButton(buttonslayout->NewRow(), "kill");
63 button_start_log = new PushButton(buttonslayout->NewRow(), "start_log");
64 button_stop_log = new PushButton(buttonslayout->LastRowLastCol(), "stop_log");
65 button_take_off = new PushButton(buttonslayout->NewRow(), "take_off");
66 button_land = new PushButton(buttonslayout->LastRowLastCol(), "land");
[7]67
[15]68 Tab *lawTab = new Tab(getFrameworkManager()->GetTabWidget(), "control laws");
69 TabWidget *tabWidget = new TabWidget(lawTab->NewRow(), "laws");
70 setupLawTab = new Tab(tabWidget, "Setup");
71 graphLawTab = new Tab(tabWidget, "Graphes");
[7]72
[15]73 uRoll = new NestedSat(setupLawTab->At(0, 0), "u_roll");
74 uRoll->ConvertSatFromDegToRad();
75 uRoll->UseDefaultPlot(graphLawTab->NewRow());
[7]76
[15]77 uPitch = new NestedSat(setupLawTab->At(0, 1), "u_pitch");
78 uPitch->ConvertSatFromDegToRad();
79 uPitch->UseDefaultPlot(graphLawTab->LastRowLastCol());
[7]80
[15]81 uYaw = new Pid(setupLawTab->At(0, 2), "u_yaw");
82 uYaw->UseDefaultPlot(graphLawTab->LastRowLastCol());
[7]83
[15]84 uZ = new PidThrust(setupLawTab->At(1, 2), "u_z");
85 uZ->UseDefaultPlot(graphLawTab->LastRowLastCol());
[7]86
[15]87 getFrameworkManager()->AddDeviceToLog(uZ);
88 uZ->AddDeviceToLog(uRoll);
89 uZ->AddDeviceToLog(uPitch);
90 uZ->AddDeviceToLog(uYaw);
[7]91
[216]92 joy=new MetaDualShock3("uav high level controller",controller);
93 uav->GetAhrs()->AddPlot(joy->GetReferenceOrientation(),DataPlot::Blue);
[7]94
[15]95 altitudeMode = AltitudeMode_t::Manual;
96 orientationMode = OrientationMode_t::Manual;
97 thrustMode = ThrustMode_t::Default;
98 torqueMode = TorqueMode_t::Default;
[7]99
[15]100 GroupBox *reglagesGroupbox =
101 new GroupBox(uavTab->NewRow(), "takeoff/landing");
102 desiredTakeoffAltitude =
103 new DoubleSpinBox(reglagesGroupbox->NewRow(), "desired takeoff altitude",
104 " m", 0, 5, 0.1, 2, 1);
105 desiredLandingAltitude =
106 new DoubleSpinBox(reglagesGroupbox->LastRowLastCol(),
107 "desired landing altitude", " m", 0, 1, 0.1, 1);
108 altitudeTrajectory =
109 new TrajectoryGenerator1D(uavTab->NewRow(), "alt cons", "m");
110 uav->GetMetaUsRangeFinder()->GetZPlot()->AddCurve(
[214]111 altitudeTrajectory->GetMatrix()->Element(0), DataPlot::Green);
[15]112 uav->GetMetaUsRangeFinder()->GetVzPlot()->AddCurve(
[214]113 altitudeTrajectory->GetMatrix()->Element(1), DataPlot::Green);
[432]114
115 failSafeAltitudeSensor=uav->GetMetaUsRangeFinder();
[7]116}
117
[15]118UavStateMachine::~UavStateMachine() {}
[7]119
[15]120void UavStateMachine::AddDeviceToControlLawLog(const IODevice *device) {
121 uZ->AddDeviceToLog(device);
[7]122}
123
[15]124void UavStateMachine::AddDataToControlLawLog(const core::io_data *data) {
125 uZ->AddDataToLog(data);
[7]126}
127
[313]128const TargetController *UavStateMachine::GetTargetController(void) const {
[432]129 return controller;
[38]130}
[7]131
[313]132MetaDualShock3 *UavStateMachine::GetJoystick(void) const {
[432]133 return joy;
[313]134}
135
[7]136const Quaternion &UavStateMachine::GetCurrentQuaternion(void) const {
[15]137 return currentQuaternion;
[7]138}
139
[167]140const Vector3Df &UavStateMachine::GetCurrentAngularSpeed(void) const {
[15]141 return currentAngularSpeed;
[7]142}
143
[432]144void UavStateMachine::SetFailSafeAltitudeSensor(AltitudeSensor *altitudeSensor) {
145 Warn("Replacing the FailSafeAltitudeSensor with %s\n",altitudeSensor->ObjectName().c_str());
146 failSafeAltitudeSensor=altitudeSensor;
147}
148
[15]149void UavStateMachine::AltitudeValues(float &altitude,
150 float &verticalSpeed) const {
151 FailSafeAltitudeValues(altitude, verticalSpeed);
[7]152}
153
[15]154void UavStateMachine::FailSafeAltitudeValues(float &altitude,
155 float &verticalSpeed) const {
[432]156 altitude = failSafeAltitudeSensor->z();
157 verticalSpeed = failSafeAltitudeSensor->Vz();
[422]158
[432]159 //a mettre dans le metausrangefinder?
160 //on ne sait pas si failSafeAltitudeSensor est vrpn (dans ce cas pas besoin de rotation)
161 //ou un us range finder
[422]162 //+0.04 decalage en z de l'us en simulation
163 //faire un reglage
164 /*
165 Vector3Df test(0,0,altitude+0.04);
166 Printf("altitude av %f %f %f %f\n",altitude,test.x,test.y,test.z);
167 test.Rotate(currentQuaternion);
168 Printf("altitude ap %f %f %f %f\n",altitude,test.x,test.y,test.z-0.04);
169 */
[7]170}
171
172void UavStateMachine::Run() {
[15]173 WarnUponSwitches(true);
174 uav->StartSensors();
[7]175
[15]176 if (getFrameworkManager()->ErrorOccured() == true) {
177 SafeStop();
178 }
[7]179
[15]180 while (!ToBeStopped()) {
181 SecurityCheck();
[7]182
[15]183 // get controller inputs
184 CheckJoystick();
185 CheckPushButton();
[7]186
[15]187 if (IsPeriodSet()) {
188 WaitPeriod();
189 } else {
190 WaitUpdate(uav->GetAhrs());
191 }
192 needToComputeDefaultTorques = true;
193 needToComputeDefaultThrust = true;
[7]194
[15]195 SignalEvent(Event_t::EnteringControlLoop);
[7]196
[15]197 ComputeOrientation();
198 ComputeAltitude();
[7]199
[15]200 // compute thrust and torques to apply
201 ComputeTorques();
202 ComputeThrust(); // logs are added to uz, so it must be updated at last
[7]203
[45]204 //check nan/inf problems
[271]205 bool isValuePossible=true;
206 //test it separately to warn for all problems
207 if(!IsValuePossible(currentTorques.roll,"roll torque")) isValuePossible=false;
208 if(!IsValuePossible(currentTorques.pitch,"pitch torque")) isValuePossible=false;
209 if(!IsValuePossible(currentTorques.yaw,"yaw torque")) isValuePossible=false;
210 if(!IsValuePossible(currentThrust,"thrust")) isValuePossible=false;
211 if(!isValuePossible) {
[42]212
[101]213 if(altitudeState==AltitudeState_t::Stopped) {
214 SafeStop();
215 } else {
[42]216
[101]217 if(failSafeMode) {
218 Warn("We are already in safe mode, the uav is going to crash!\n");
219 } else {
220 Thread::Warn("switching back to safe mode\n");
221 EnterFailSafeMode();
222 needToComputeDefaultTorques = true;//should not be necessary, but put it to be sure to compute default thrust/torques
223 needToComputeDefaultThrust = true;
224
225 ComputeTorques();
226 ComputeThrust();
227 }
228 }
[42]229 }
230
[15]231 // Set torques for roll, pitch and yaw angles (value between -1 and 1). Set
232 // thrust (value between 0 and 1)
233 uav->GetUavMultiplex()->SetRoll(-currentTorques.roll);
234 uav->GetUavMultiplex()->SetPitch(-currentTorques.pitch);
235 uav->GetUavMultiplex()->SetYaw(-currentTorques.yaw);
236 uav->GetUavMultiplex()->SetThrust(-currentThrust); // on raisonne en negatif
237 // sur l'altitude, a
238 // revoir avec les
239 // equations
240 uav->GetUavMultiplex()->SetRollTrim(joy->RollTrim());
241 uav->GetUavMultiplex()->SetPitchTrim(joy->PitchTrim());
242 uav->GetUavMultiplex()->SetYawTrim(0);
243 uav->GetUavMultiplex()->Update(GetTime());
244 }
[7]245
[15]246 WarnUponSwitches(false);
[7]247}
248
[45]249bool UavStateMachine::IsValuePossible(float value,std::string desc) {
[42]250 if(isnan(value)) {
251 Warn("%s is not an number\n",desc.c_str());
[101]252 return false;
[45]253 } else if(isinf(value)) {
254 Warn("%s is infinite\n",desc.c_str());
[101]255 return false;
256 } else {
[45]257 return true;
[42]258 }
259}
260
261
[7]262void UavStateMachine::ComputeOrientation(void) {
[15]263 if (failSafeMode) {
264 GetDefaultOrientation()->GetQuaternionAndAngularRates(currentQuaternion,
265 currentAngularSpeed);
266 } else {
267 GetOrientation()->GetQuaternionAndAngularRates(currentQuaternion,
268 currentAngularSpeed);
269 }
[7]270}
271
272const AhrsData *UavStateMachine::GetOrientation(void) const {
[15]273 return GetDefaultOrientation();
[7]274}
275
276const AhrsData *UavStateMachine::GetDefaultOrientation(void) const {
[15]277 return uav->GetAhrs()->GetDatas();
[7]278}
279
280void UavStateMachine::ComputeAltitude(void) {
[15]281 if (failSafeMode) {
282 FailSafeAltitudeValues(currentAltitude, currentVerticalSpeed);
283 } else {
284 AltitudeValues(currentAltitude, currentVerticalSpeed);
285 }
[7]286}
287
[15]288void UavStateMachine::ComputeReferenceAltitude(float &refAltitude,
289 float &refVerticalVelocity) {
290 if (altitudeMode == AltitudeMode_t::Manual) {
291 GetDefaultReferenceAltitude(refAltitude, refVerticalVelocity);
292 } else {
293 GetReferenceAltitude(refAltitude, refVerticalVelocity);
294 }
[7]295}
296
[15]297void UavStateMachine::GetDefaultReferenceAltitude(float &refAltitude,
298 float &refVerticalVelocity) {
299 float zc, dzc;
[7]300
[15]301 switch (altitudeState) {
302 // initiate a takeoff: increase motor speed in open loop (see ComputeThrust)
303 // until we detect a take off of 0.03m (hard coded value) above the ground.
304 case AltitudeState_t::TakingOff: {
305 if (currentAltitude > groundAltitude + 0.03) {
306 altitudeTrajectory->StartTraj(currentAltitude,
[177]307 desiredTakeoffAltitude->Value(),currentVerticalSpeed);
[15]308 altitudeState = AltitudeState_t::Stabilized;
309 SignalEvent(Event_t::Stabilized);
[7]310 }
[15]311 break;
312 }
313 // landing, only check if we reach desired landing altitude
[398]314 //no break in this case, continue with Stabilized state
[15]315 case AltitudeState_t::StartLanding: {
316 if (altitudeTrajectory->Position() == desiredLandingAltitude->Value()) {
317 // The Uav target altitude has reached its landing value (typically 0)
318 // but the real Uav altitude may not have reach this value yet because of
[42]319 // command delay. Moreover, it may never exactly reach this value if the
[38]320 // ground is not perfectly leveled (critical case: there's a
[15]321 // deep and narrow hole right in the sensor line of sight). That's why we
322 // have a 2 phases landing strategy.
323 altitudeState = AltitudeState_t::FinishLanding;
324 SignalEvent(Event_t::FinishLanding);
325 joy->SetLedOFF(1); // DualShock3::led1
326 }
327 }
328 // stabilized: check if z trajectory is finished
329 case AltitudeState_t::Stabilized: {
330 if (!altitudeTrajectory->IsRunning() && !flagZTrajectoryFinished) {
[201]331 flagZTrajectoryFinished = true;
[15]332 SignalEvent(Event_t::ZTrajectoryFinished);
333 }
334 if (flagZTrajectoryFinished && desiredTakeoffAltitude->ValueChanged()) {
335 flagZTrajectoryFinished = false;
336 altitudeTrajectory->StartTraj(currentAltitude,
337 desiredTakeoffAltitude->Value());
338 joy->SetZRef(0);
339 }
[398]340 break;
[15]341 }
342 }
[7]343
[15]344 // Récupère les consignes (du joystick dans l'implémentation par défaut). La
345 // consigne joystick est une vitesse ("delta_z", dzc). le zc est calculé par
346 // la manette
347 zc = joy->ZRef(); // a revoir, la position offset devrait se calculer dans le
348 // generator
349 dzc = joy->DzRef();
[7]350
[15]351 // z control law
352 altitudeTrajectory->SetPositionOffset(zc);
353 altitudeTrajectory->SetSpeedOffset(dzc);
[7]354
[15]355 altitudeTrajectory->Update(GetTime());
356 refAltitude = altitudeTrajectory->Position();
357 refVerticalVelocity = altitudeTrajectory->Speed();
[7]358}
359
[15]360void UavStateMachine::GetReferenceAltitude(float &refAltitude,
361 float &refVerticalVelocity) {
362 Thread::Warn("Default GetReferenceAltitude method is not overloaded => "
363 "switching back to safe mode\n");
364 EnterFailSafeMode();
[398]365 GetDefaultReferenceAltitude(refAltitude,refVerticalVelocity);
[7]366};
367
368void UavStateMachine::ComputeThrust(void) {
[398]369 if (thrustMode == ThrustMode_t::Default) {
[15]370 currentThrust = ComputeDefaultThrust();
371 } else {
372 currentThrust = ComputeCustomThrust();
373 }
[7]374}
375
376float UavStateMachine::ComputeDefaultThrust(void) {
[15]377 if (needToComputeDefaultThrust) {
378 // compute desired altitude
379 float refAltitude, refVerticalVelocity;
380 ComputeReferenceAltitude(refAltitude, refVerticalVelocity);
[7]381
[15]382 switch (altitudeState) {
383 case AltitudeState_t::TakingOff: {
384 // The progressive increase in motor speed is used to evaluate the motor
385 // speed that compensate the uav weight. This value
386 // will be used as an offset for altitude control afterwards
387 uZ->OffsetStepUp();
388 break;
[7]389 }
[15]390 case AltitudeState_t::StartLanding:
391 case AltitudeState_t::Stabilized: {
392 float p_error = currentAltitude - refAltitude;
393 float d_error = currentVerticalSpeed - refVerticalVelocity;
394 uZ->SetValues(p_error, d_error);
395 break;
396 }
397 // decrease motor speed in open loop until value offset_g , uav should have
398 // already landed or be very close to at this point
399 case AltitudeState_t::FinishLanding: {
400 if (uZ->OffsetStepDown() == false) {
401 StopMotors();
402 }
403 break;
404 }
405 }
406 uZ->Update(GetTime());
[7]407
[15]408 savedDefaultThrust = uZ->Output();
409 needToComputeDefaultThrust = false;
410 }
411
412 return savedDefaultThrust;
[7]413}
414
415float UavStateMachine::ComputeCustomThrust(void) {
[400]416 Thread::Warn("Default ComputeCustomThrust method is not overloaded => switching back "
[15]417 "to safe mode\n");
418 EnterFailSafeMode();
419 return ComputeDefaultThrust();
[7]420}
421
[15]422const AhrsData *UavStateMachine::ComputeReferenceOrientation(void) {
423 if (orientationMode == OrientationMode_t::Manual) {
424 return GetDefaultReferenceOrientation();
425 } else {
426 return GetReferenceOrientation();
427 }
[7]428}
429
[15]430const AhrsData *UavStateMachine::GetDefaultReferenceOrientation(void) const {
431 // We directly control yaw, pitch, roll angles
432 return joy->GetReferenceOrientation();
[7]433}
434
[15]435const AhrsData *UavStateMachine::GetReferenceOrientation(void) {
436 Thread::Warn("Default GetReferenceOrientation method is not overloaded => "
437 "switching back to safe mode\n");
438 EnterFailSafeMode();
439 return GetDefaultReferenceOrientation();
[7]440}
441
442void UavStateMachine::ComputeTorques(void) {
[15]443 if (torqueMode == TorqueMode_t::Default) {
444 ComputeDefaultTorques(currentTorques);
445 } else {
446 ComputeCustomTorques(currentTorques);
447 }
[7]448}
449
450void UavStateMachine::ComputeDefaultTorques(Euler &torques) {
[15]451 if (needToComputeDefaultTorques) {
452 const AhrsData *refOrientation = ComputeReferenceOrientation();
453 Quaternion refQuaternion;
[167]454 Vector3Df refAngularRates;
[15]455 refOrientation->GetQuaternionAndAngularRates(refQuaternion,
456 refAngularRates);
457 Euler refAngles = refQuaternion.ToEuler();
458 Euler currentAngles = currentQuaternion.ToEuler();
[7]459
[15]460 uYaw->SetValues(currentAngles.YawDistanceFrom(refAngles.yaw),
461 currentAngularSpeed.z - refAngularRates.z);
462 uYaw->Update(GetTime());
463 torques.yaw = uYaw->Output();
[7]464
[15]465 uPitch->SetValues(refAngles.pitch, currentAngles.pitch,
466 currentAngularSpeed.y);
467 uPitch->Update(GetTime());
468 torques.pitch = uPitch->Output();
[7]469
[15]470 uRoll->SetValues(refAngles.roll, currentAngles.roll, currentAngularSpeed.x);
471 uRoll->Update(GetTime());
472 torques.roll = uRoll->Output();
[7]473
[15]474 savedDefaultTorques = torques;
475 needToComputeDefaultTorques = false;
476 } else {
477 torques = savedDefaultTorques;
478 }
[7]479}
480
481void UavStateMachine::ComputeCustomTorques(Euler &torques) {
[15]482 Thread::Warn("Default ComputeCustomTorques method is not overloaded => "
483 "switching back to safe mode\n");
484 EnterFailSafeMode();
485 ComputeDefaultTorques(torques);
[7]486}
487
488void UavStateMachine::TakeOff(void) {
[15]489 flagZTrajectoryFinished = false;
[214]490
491 if(altitudeState!=AltitudeState_t::Stopped) {
492 Warn("cannot takeoff, altitudeState!=AltitudeState_t::Stopped\n");
493 joy->ErrorNotify();
494 } else if(!safeToFly) {
495 Warn("cannot takeoff, uav is not safe to fly\n");
496 joy->ErrorNotify();
497 } else if(!uav->isReadyToFly()) {
498 Warn("cannot takeoff, uav is not ready\n");
499 joy->ErrorNotify();
500 } else if(uav->GetBatteryMonitor()->IsBatteryLow()) {
501 Warn("cannot takeoff, battery is low\n");
502 joy->ErrorNotify();
503 } else if(flagConnectionLost) {
504 Warn("cannot takeoff, connection with flairgcs lost\n");
505 joy->ErrorNotify();
506 } else {
[157]507 //The uav always takes off in fail safe mode
[164]508 flagBatteryLow=false;
[157]509 EnterFailSafeMode();
510 joy->SetLedOFF(4);//DualShock3::led4
511 joy->SetLedOFF(1);//DualShock3::led1
512 joy->Rumble(0x70);
513 joy->SetZRef(0);
[7]514
[216]515 uZ->Reset();
516 uRoll->Reset();
517 uPitch->Reset();
518 uYaw->Reset();
[7]519
[15]520 uav->GetUavMultiplex()->LockUserInterface();
521 // Active les moteurs. Pouvoir les désactiver permet de pouvoir observer les
522 // consignes moteurs
523 // sans les faire tourner effectivement (en déplaçant à la main le drone)
524 uav->GetBldc()->SetEnabled(true);
525 altitudeState = AltitudeState_t::TakingOff;
526 SignalEvent(Event_t::TakingOff);
[317]527 ComputeAltitude();//ensure we have good altitude
528 groundAltitude = currentAltitude;
[15]529 }
[7]530}
531
532void UavStateMachine::Land(void) {
[398]533 if (thrustMode != ThrustMode_t::Default) {
534 SetThrustMode(ThrustMode_t::Default);
535 }
[15]536 if (altitudeMode != AltitudeMode_t::Manual) {
537 SetAltitudeMode(AltitudeMode_t::Manual);
538 }
539 if (altitudeState == AltitudeState_t::Stabilized) {
540 joy->SetLedOFF(4); // DualShock3::led4
541 joy->Rumble(0x70);
[7]542
[310]543 altitudeTrajectory->StopTraj();
544 joy->SetZRef(0);
545 ComputeAltitude();//ensure we have good altitude (Land() is not syncronized with Run())
546 altitudeTrajectory->StartTraj(currentAltitude,desiredLandingAltitude->Value()); //shouldn't it be groundAltitude?
547 altitudeState=AltitudeState_t::StartLanding;
548 SignalEvent(Event_t::StartLanding);
549 } else if (altitudeState==AltitudeState_t::TakingOff) {
550 EmergencyLand();
551 } else {
552 joy->ErrorNotify();
553 }
[7]554}
555
[38]556void UavStateMachine::EmergencyLand(void) {
557 //Gradually decrease motor speed
558 //Called if landing is required during take off (motors are accelerating but Uav did not actually left the ground yet), or if critical sensors have been lost (attitude is lost)
559 altitudeState=AltitudeState_t::FinishLanding;
560 safeToFly=false;
[214]561 Warn("Emergency landing!\n");
562 Warn("You will not be able to take off again\n");
[38]563}
564
[7]565void UavStateMachine::SignalEvent(Event_t event) {
[15]566 switch (event) {
567 case Event_t::StartLanding:
568 Thread::Info("Altitude: entering 'StartLanding' state\n");
569 break;
570 case Event_t::Stopped:
571 Thread::Info("Altitude: entering 'Stopped' state\n");
572 break;
573 case Event_t::TakingOff:
574 Thread::Info("Altitude: taking off\n");
575 break;
576 case Event_t::Stabilized:
577 Thread::Info("Altitude: entering 'Stabilized' state\n");
578 break;
579 case Event_t::FinishLanding:
580 Thread::Info("Altitude: entering 'FinishLanding' state\n");
581 break;
582 case Event_t::EmergencyStop:
583 Thread::Info("Emergency stop!\n");
584 break;
[310]585 case Event_t::EnteringFailSafeMode:
586 Thread::Info("Entering fail safe mode\n");
587 break;
[15]588 }
[7]589}
590
591void UavStateMachine::EmergencyStop(void) {
[38]592 if(altitudeState!=AltitudeState_t::Stopped) {
593 StopMotors();
594 EnterFailSafeMode();
595 joy->Rumble(0x70);
596 SignalEvent(Event_t::EmergencyStop);
597 }
[153]598 //safeToFly=false;
599 //Warn("Emergency stop, UAV will not take off again until program is rerunned\n");
[7]600}
601
[15]602void UavStateMachine::StopMotors(void) {
603 joy->FlashLed(1, 10, 10); // DualShock3::led1
604 uav->GetBldc()->SetEnabled(false);
605 uav->GetUavMultiplex()->UnlockUserInterface();
[201]606 altitudeState = AltitudeState_t::Stopped;
[15]607 SignalEvent(Event_t::Stopped);
608 uav->GetAhrs()->UnlockUserInterface();
[7]609
[15]610 uZ->Reset();
[216]611 uRoll->Reset();
612 uPitch->Reset();
613 uYaw->Reset();
[7]614}
615
[15]616GridLayout *UavStateMachine::GetButtonsLayout(void) const {
617 return buttonslayout;
[7]618}
619
620void UavStateMachine::SecurityCheck(void) {
[15]621 MandatorySecurityCheck();
622 ExtraSecurityCheck();
[7]623}
624
625void UavStateMachine::MandatorySecurityCheck(void) {
[15]626 if (getFrameworkManager()->ConnectionLost() && !flagConnectionLost) {
627 flagConnectionLost = true;
[186]628
[15]629 EnterFailSafeMode();
630 if (altitudeState == AltitudeState_t::Stopped) {
[186]631 Thread::Warn("Connection lost\n");
632 Thread::Warn("UAV won't take off\n");
[15]633 } else {
[186]634 Thread::Err("Connection lost\n");
[15]635 Land();
[7]636 }
[15]637 }
[38]638 if((altitudeState==AltitudeState_t::TakingOff || altitudeState==AltitudeState_t::Stabilized) && uav->GetBatteryMonitor()->IsBatteryLow() && !flagBatteryLow) {
639 flagBatteryLow=true;
640 Thread::Err("Low Battery\n");
641 EnterFailSafeMode();
642 Land();
[42]643 }/*
[38]644 Time now=GetTime();
645 if ((altitudeState==AltitudeState_t::Stopped) && (now-uav->GetAhrs()->lastUpdate>(Time)100*1000*1000)) { //100ms
646 flagCriticalSensorLost=true;
647 Thread::Err("Critical sensor lost\n");
648 EnterFailSafeMode();
[42]649 EmergencyLand();
650 }*/
[7]651}
652
653void UavStateMachine::CheckJoystick(void) {
[15]654 GenericCheckJoystick();
655 ExtraCheckJoystick();
[7]656}
657
658void UavStateMachine::GenericCheckJoystick(void) {
[15]659 static bool isEmergencyStopButtonPressed = false;
660 static bool isTakeOffButtonPressed = false;
661 static bool isSafeModeButtonPressed = false;
[7]662
[38]663 if (controller->IsButtonPressed(1)) { // select
[15]664 if (!isEmergencyStopButtonPressed) {
665 isEmergencyStopButtonPressed = true;
666 Thread::Info("Emergency stop from joystick\n");
667 EmergencyStop();
668 }
669 } else
670 isEmergencyStopButtonPressed = false;
[7]671
[38]672 if (controller->IsButtonPressed(0)) { // start
[15]673 if (!isTakeOffButtonPressed) {
674 isTakeOffButtonPressed = true;
675 switch (altitudeState) {
676 case AltitudeState_t::Stopped:
677 TakeOff();
678 break;
679 case AltitudeState_t::Stabilized:
680 Land();
681 break;
682 default:
683 joy->ErrorNotify();
684 break;
685 }
686 }
687 } else
688 isTakeOffButtonPressed = false;
[7]689
[15]690 // cross
691 // gsanahuj:conflict with Majd programs.
692 // check if l1,l2,r1 and r2 are not pressed
693 // to allow a combination in user program
[38]694 if (controller->IsButtonPressed(5) && !controller->IsButtonPressed(6) &&
695 !controller->IsButtonPressed(7) && !controller->IsButtonPressed(9) &&
696 !controller->IsButtonPressed(10)) {
[15]697 if (!isSafeModeButtonPressed) {
698 isSafeModeButtonPressed = true;
699 EnterFailSafeMode();
700 }
701 } else
702 isSafeModeButtonPressed = false;
[7]703}
704
705void UavStateMachine::CheckPushButton(void) {
[15]706 GenericCheckPushButton();
707 ExtraCheckPushButton();
[7]708}
709
710void UavStateMachine::GenericCheckPushButton(void) {
[15]711 if (button_kill->Clicked() == true)
712 SafeStop();
713 if (button_take_off->Clicked() == true)
714 TakeOff();
715 if (button_land->Clicked() == true)
716 Land();
717 if (button_start_log->Clicked() == true)
718 getFrameworkManager()->StartLog();
719 if (button_stop_log->Clicked() == true)
720 getFrameworkManager()->StopLog();
[7]721}
722
723void UavStateMachine::EnterFailSafeMode(void) {
[129]724 if(altitudeState!=AltitudeState_t::StartLanding) SetAltitudeMode(AltitudeMode_t::Manual);//
[15]725 SetOrientationMode(OrientationMode_t::Manual);
726 SetThrustMode(ThrustMode_t::Default);
727 SetTorqueMode(TorqueMode_t::Default);
[7]728
[15]729 GetDefaultOrientation()->GetQuaternionAndAngularRates(currentQuaternion,
730 currentAngularSpeed);
731 joy->SetYawRef(currentQuaternion);
732 uYaw->Reset();
733 uPitch->Reset();
734 uRoll->Reset();
[7]735
[15]736 failSafeMode = true;
737 SignalEvent(Event_t::EnteringFailSafeMode);
[7]738}
739
740bool UavStateMachine::ExitFailSafeMode(void) {
[15]741 // only exit fail safe mode if in Stabilized altitude state
742 // gsanahuj: pour la demo inaugurale on ne peut pas etre en failsafe
743 // le ruban perturbe l'us
744 /*
[7]745 if (altitudeState!=AltitudeState_t::Stabilized) {
746 return false;
747 } else*/ {
[420]748 Thread::Info("Leaving fail safe mode\n");
[15]749 failSafeMode = false;
750 return true;
751 }
[7]752}
753
754bool UavStateMachine::SetTorqueMode(TorqueMode_t const &newTorqueMode) {
[15]755 if ((newTorqueMode == TorqueMode_t::Custom) && (failSafeMode)) {
756 if (!ExitFailSafeMode())
757 return false;
758 }
759 // When transitionning from Custom to Default torque mode, we should reset the
760 // default control laws
761 if ((torqueMode == TorqueMode_t::Custom) &&
762 (newTorqueMode == TorqueMode_t::Default)) {
763 uYaw->Reset();
764 uPitch->Reset();
765 uRoll->Reset();
766 }
767 torqueMode = newTorqueMode;
768 return true;
[7]769}
770
771bool UavStateMachine::SetAltitudeMode(AltitudeMode_t const &newAltitudeMode) {
[15]772 if ((newAltitudeMode == AltitudeMode_t::Custom) && (failSafeMode)) {
773 if (!ExitFailSafeMode())
774 return false;
775 }
776 altitudeMode = newAltitudeMode;
[176]777 //avoid starting trajectory at take off (it will be started when altitudeState==AltitudeState_t::Stabilized)
778 if(altitudeState!=AltitudeState_t::Stopped) GotoAltitude(desiredTakeoffAltitude->Value());
[7]779
[15]780 return true;
[7]781}
782
783bool UavStateMachine::GotoAltitude(float desiredAltitude) {
[15]784 if (altitudeMode != AltitudeMode_t::Manual) {
785 return false;
786 }
787 altitudeTrajectory->StartTraj(uav->GetMetaUsRangeFinder()->z(),
788 desiredAltitude);
789 return true;
[7]790}
791
[15]792bool UavStateMachine::SetOrientationMode(
793 OrientationMode_t const &newOrientationMode) {
794 if ((newOrientationMode == OrientationMode_t::Custom) && (failSafeMode)) {
795 if (!ExitFailSafeMode())
796 return false;
797 }
798 // When transitionning from Custom to Manual mode we must reset to yaw
799 // reference to the current absolute yaw angle,
800 // overwise the Uav will abruptly change orientation
801 if ((orientationMode == OrientationMode_t::Custom) &&
802 (newOrientationMode == OrientationMode_t::Manual)) {
803 joy->SetYawRef(currentQuaternion);
804 }
805 orientationMode = newOrientationMode;
806 return true;
[7]807}
808
809bool UavStateMachine::SetThrustMode(ThrustMode_t const &newThrustMode) {
[15]810 if ((newThrustMode == ThrustMode_t::Custom) && (failSafeMode)) {
811 if (!ExitFailSafeMode())
812 return false;
813 }
814 thrustMode = newThrustMode;
815 return true;
[7]816}
[206]817
818NestedSat* UavStateMachine::GetURoll(void) { return uRoll;};
819NestedSat* UavStateMachine::GetUPitch(void) { return uPitch;};
820Pid* UavStateMachine::GetUYaw(void) { return uYaw;};
821PidThrust* UavStateMachine::GetUZ(void) { return uZ;};
822TrajectoryGenerator1D * UavStateMachine::GetAltitudeTrajectory(void) { return altitudeTrajectory;};
Note: See TracBrowser for help on using the repository browser.