// created: 2011/05/01 // filename: CircleFollower.cpp // // author: Guillaume Sanahuja // Copyright Heudiasyc UMR UTC/CNRS 7253 // // version: $Id: $ // // purpose: demo cercle avec optitrack // // /*********************************************************************/ #include "CircleFollower.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include using namespace std; using namespace flair::core; using namespace flair::gui; using namespace flair::sensor; using namespace flair::filter; using namespace flair::meta; CircleFollower::CircleFollower(TargetController *controller): UavStateMachine(controller), behaviourMode(BehaviourMode_t::Default), vrpnLost(false) { Uav* uav=GetUav(); VrpnClient* vrpnclient=new VrpnClient("vrpn", uav->GetDefaultVrpnAddress(),80); uavVrpn = new MetaVrpnObject(uav->ObjectName()); getFrameworkManager()->AddDeviceToLog(uavVrpn); uav->GetAhrs()->YawPlot()->AddCurve(uavVrpn->State()->Element(2),DataPlot::Green); startCircle=new PushButton(GetButtonsLayout()->NewRow(),"start_circle"); stopCircle=new PushButton(GetButtonsLayout()->LastRowLastCol(),"stop_circle"); if(vrpnclient->UseXbee()==true) { targetVrpn=new MetaVrpnObject("target",1); } else { targetVrpn=new MetaVrpnObject("target"); } vrpnclient->Start(); getFrameworkManager()->AddDeviceToLog(targetVrpn); circle=new TrajectoryGenerator2DCircle(vrpnclient->GetLayout()->NewRow(),"circle"); uavVrpn->xPlot()->AddCurve(circle->Matrix()->Element(0,0),DataPlot::Blue); uavVrpn->yPlot()->AddCurve(circle->Matrix()->Element(0,1),DataPlot::Blue); uavVrpn->VxPlot()->AddCurve(circle->Matrix()->Element(1,0),DataPlot::Blue); uavVrpn->VyPlot()->AddCurve(circle->Matrix()->Element(1,1),DataPlot::Blue); uavVrpn->XyPlot()->AddCurve(circle->Matrix()->Element(0,1),circle->Matrix()->Element(0,0),DataPlot::Blue,"circle"); uX=new Pid(setupLawTab->At(1,0),"u_x"); uX->UseDefaultPlot(graphLawTab->NewRow()); uY=new Pid(setupLawTab->At(1,1),"u_y"); uY->UseDefaultPlot(graphLawTab->LastRowLastCol()); customReferenceOrientation= new AhrsData(this,"reference"); uav->GetAhrs()->AddPlot(customReferenceOrientation,DataPlot::Yellow); AddDataToControlLawLog(customReferenceOrientation); customOrientation=new AhrsData(this,"orientation"); getFrameworkManager()->AddDeviceToLog(uav->GetVerticalCamera()); } CircleFollower::~CircleFollower() { } const AhrsData *CircleFollower::GetOrientation(void) const { //get yaw from vrpn Quaternion vrpnQuaternion; uavVrpn->GetQuaternion(vrpnQuaternion); //get roll, pitch and w from imu Quaternion ahrsQuaternion; Vector3Df ahrsAngularSpeed; GetDefaultOrientation()->GetQuaternionAndAngularRates(ahrsQuaternion, ahrsAngularSpeed); Euler ahrsEuler=ahrsQuaternion.ToEuler(); ahrsEuler.yaw=vrpnQuaternion.ToEuler().yaw; Quaternion mixQuaternion=ahrsEuler.ToQuaternion(); customOrientation->SetQuaternionAndAngularRates(mixQuaternion,ahrsAngularSpeed); return customOrientation; } void CircleFollower::AltitudeValues(float &z,float &dz) const{ Vector3Df uav_pos,uav_vel; uavVrpn->GetPosition(uav_pos); uavVrpn->GetSpeed(uav_vel); //z and dz must be in uav's frame z=-uav_pos.z; dz=-uav_vel.z; } AhrsData *CircleFollower::GetReferenceOrientation(void) { Vector2Df pos_err, vel_err; // in Uav coordinate system float yaw_ref; Euler refAngles; PositionValues(pos_err, vel_err, yaw_ref); refAngles.yaw=yaw_ref; uX->SetValues(pos_err.x, vel_err.x); uX->Update(GetTime()); refAngles.pitch=uX->Output(); uY->SetValues(pos_err.y, vel_err.y); uY->Update(GetTime()); refAngles.roll=-uY->Output(); customReferenceOrientation->SetQuaternionAndAngularRates(refAngles.ToQuaternion(),Vector3Df(0,0,0)); return customReferenceOrientation; } void CircleFollower::PositionValues(Vector2Df &pos_error,Vector2Df &vel_error,float &yaw_ref) { Vector3Df uav_pos,uav_vel; // in VRPN coordinate system Vector2Df uav_2Dpos,uav_2Dvel; // in VRPN coordinate system uavVrpn->GetPosition(uav_pos); uavVrpn->GetSpeed(uav_vel); uav_pos.To2Dxy(uav_2Dpos); uav_vel.To2Dxy(uav_2Dvel); if (behaviourMode==BehaviourMode_t::PositionHold) { pos_error=uav_2Dpos-posHold; vel_error=uav_2Dvel; yaw_ref=yawHold; } else { //Circle Vector3Df target_pos; Vector2Df circle_pos,circle_vel; Vector2Df target_2Dpos; targetVrpn->GetPosition(target_pos); target_pos.To2Dxy(target_2Dpos); circle->SetCenter(target_2Dpos); //circle reference circle->Update(GetTime()); circle->GetPosition(circle_pos); circle->GetSpeed(circle_vel); //error in optitrack frame pos_error=uav_2Dpos-circle_pos; vel_error=uav_2Dvel-circle_vel; yaw_ref=atan2(target_pos.y-uav_pos.y,target_pos.x-uav_pos.x); } //error in uav frame Quaternion currentQuaternion=GetCurrentQuaternion(); Euler currentAngles;//in vrpn frame currentQuaternion.ToEuler(currentAngles); pos_error.Rotate(-currentAngles.yaw); vel_error.Rotate(-currentAngles.yaw); } void CircleFollower::SignalEvent(Event_t event) { UavStateMachine::SignalEvent(event); switch(event) { case Event_t::TakingOff: behaviourMode=BehaviourMode_t::Default; vrpnLost=false; break; case Event_t::EnteringControlLoop: if ((behaviourMode==BehaviourMode_t::Circle) && (!circle->IsRunning())) { VrpnPositionHold(); } break; case Event_t::EnteringFailSafeMode: behaviourMode=BehaviourMode_t::Default; break; } } void CircleFollower::ExtraSecurityCheck(void) { if ((!vrpnLost) && ((behaviourMode==BehaviourMode_t::Circle) || (behaviourMode==BehaviourMode_t::PositionHold))) { if (!targetVrpn->IsTracked(500)) { Thread::Err("VRPN, target lost\n"); vrpnLost=true; EnterFailSafeMode(); Land(); } if (!uavVrpn->IsTracked(500)) { Thread::Err("VRPN, uav lost\n"); vrpnLost=true; EnterFailSafeMode(); Land(); } } } void CircleFollower::ExtraCheckPushButton(void) { if(startCircle->Clicked() && (behaviourMode!=BehaviourMode_t::Circle)) { StartCircle(); } if(stopCircle->Clicked() && (behaviourMode==BehaviourMode_t::Circle)) { StopCircle(); } } void CircleFollower::ExtraCheckJoystick(void) { //R1 and Circle if(GetJoystick()->IsButtonPressed(9) && GetJoystick()->IsButtonPressed(4) && (behaviourMode!=BehaviourMode_t::Circle)) { StartCircle(); } //R1 and Cross if(GetJoystick()->IsButtonPressed(9) && GetJoystick()->IsButtonPressed(5) && (behaviourMode==BehaviourMode_t::Circle)) { StopCircle(); } } void CircleFollower::StartCircle(void) { if (SetOrientationMode(OrientationMode_t::Custom)) { Thread::Info("CircleFollower: start circle\n"); } else { Thread::Warn("CircleFollower: could not start circle\n"); return; } Vector3Df uav_pos,target_pos; Vector2Df uav_2Dpos,target_2Dpos; targetVrpn->GetPosition(target_pos); target_pos.To2Dxy(target_2Dpos); circle->SetCenter(target_2Dpos); uavVrpn->GetPosition(uav_pos); uav_pos.To2Dxy(uav_2Dpos); circle->StartTraj(uav_2Dpos); uX->Reset(); uY->Reset(); behaviourMode=BehaviourMode_t::Circle; } void CircleFollower::StopCircle(void) { circle->FinishTraj(); //GetJoystick()->Rumble(0x70); Thread::Info("CircleFollower: finishing circle\n"); } void CircleFollower::VrpnPositionHold(void) { Quaternion vrpnQuaternion; uavVrpn->GetQuaternion(vrpnQuaternion); yawHold=vrpnQuaternion.ToEuler().yaw; Vector3Df vrpnPosition; uavVrpn->GetPosition(vrpnPosition); vrpnPosition.To2Dxy(posHold); uX->Reset(); uY->Reset(); behaviourMode=BehaviourMode_t::PositionHold; SetOrientationMode(OrientationMode_t::Custom); Thread::Info("CircleFollower: holding position\n"); }