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

Last change on this file since 428 was 422, checked in by Sanahuja Guillaume, 4 years ago

test pour recaler l'us en fonction de l'orientation

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