// %flair:license{ // This file is part of the Flair framework distributed under the // CECILL-C License, Version 1.0. // %flair:license} // created: 2013/04/03 // filename: VrpnObject.cpp // // author: César Richard, Guillaume Sanahuja // Copyright Heudiasyc UMR UTC/CNRS 7253 // // version: $Id: $ // // purpose: objet vrpn // // /*********************************************************************/ #include "VrpnObject_impl.h" #include "VrpnObject.h" #include "VrpnClient.h" #include "VrpnClient_impl.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include using std::string; using namespace flair::core; using namespace flair::gui; using namespace flair::sensor; VrpnObject_impl::VrpnObject_impl(VrpnObject* self,const VrpnClient *parent,string name, int id,const TabWidget* tab) { this->parent=parent; this->self=self; if(id==-1 && parent->UseXbee()) { self->Err("erreur aucun identifiant specifie pour la connexion Xbee\n"); } if(id!=-1 && !parent->UseXbee()) { self->Warn("identifiant pour la connexion Xbee ignore car pas en mode Xbee\n"); } if(parent->UseXbee()) { parent->pimpl_->AddTrackable(this,id); tracker=NULL; } else { parent->pimpl_->AddTrackable(self); tracker = new vrpn_Tracker_Remote(name.c_str(), parent->pimpl_->connection); tracker->register_change_handler(this,handle_pos); tracker->shutup=true; } //state cvmatrix_descriptor* desc=new cvmatrix_descriptor(6,1); desc->SetElementName(0,0,"roll"); desc->SetElementName(1,0,"pitch"); desc->SetElementName(2,0,"yaw"); desc->SetElementName(3,0,"x"); desc->SetElementName(4,0,"y"); desc->SetElementName(5,0,"z"); output=new cvmatrix(self,desc,floatType); desc=new cvmatrix_descriptor(3,1); desc->SetElementName(0,0,"roll"); desc->SetElementName(1,0,"pitch"); desc->SetElementName(2,0,"yaw"); state=new cvmatrix(self,desc,floatType); //ui plot_tab=new Tab(tab,"Mesures "+ name); x_plot=new DataPlot1D(plot_tab->NewRow(),"x",-10,10); x_plot->AddCurve(output->Element(3)); y_plot=new DataPlot1D(plot_tab->LastRowLastCol(),"y",-10,10); y_plot->AddCurve(output->Element(4)); z_plot=new DataPlot1D(plot_tab->LastRowLastCol(),"z",-2,0); z_plot->AddCurve(output->Element(5)); } VrpnObject_impl::~VrpnObject_impl(void) { if(tracker!=NULL)//normal { parent->pimpl_->RemoveTrackable(self); tracker->unregister_change_handler(this,handle_pos); delete tracker; } else//xbee { parent->pimpl_->RemoveTrackable(this); } delete plot_tab; } void VrpnObject_impl::mainloop(void) { tracker->mainloop(); } bool VrpnObject_impl::IsTracked(unsigned int timeout_ms) { output->GetMutex(); Time a=GetTime(); Time dt=a-output->DataTime(); output->ReleaseMutex(); if(dt>(Time)(timeout_ms*1000000)) { //self->Printf("%lld %lld %lld %lld\n",a,output->DataTime(),dt,(Time)(timeout_ms*1000000)); return false; } else { return true; } } void VrpnObject_impl::GetEuler(Euler &euler) { output->GetMutex(); euler.roll=output->ValueNoMutex(0,0); euler.pitch=output->ValueNoMutex(1,0); euler.yaw=output->ValueNoMutex(2,0); output->ReleaseMutex(); } void VrpnObject_impl::GetQuaternion(Quaternion &quaternion) { output->GetMutex(); quaternion.q0=this->quaternion.q0; quaternion.q1=this->quaternion.q1; quaternion.q2=this->quaternion.q2; quaternion.q3=this->quaternion.q3; output->ReleaseMutex(); } void VrpnObject_impl::GetPosition(Vector3D &point) { output->GetMutex(); point.x=output->ValueNoMutex(3,0); point.y=output->ValueNoMutex(4,0); point.z=output->ValueNoMutex(5,0); output->ReleaseMutex(); } void VRPN_CALLBACK VrpnObject_impl::handle_pos(void *userdata, const vrpn_TRACKERCB t) { bool is_nan=false; VrpnObject_impl* caller= reinterpret_cast(userdata); Time time=GetTime(); //check if something is nan for(int i=0;i<3;i++) { if(isnan(t.pos[i])==true) is_nan=true; } for(int i=0;i<4;i++) { if(isnan(t.quat[i])==true) is_nan=true; } if(is_nan==true) { caller->self->Warn("data is nan, skipping it (time %lld)\n",time); return; } //on prend une fois pour toute le mutex et on fait des accès directs caller->output->GetMutex(); //warning: t.quat is defined as (qx,qy,qz,qw), which is different from flair::core::Quaternion caller->quaternion.q0=t.quat[3]; caller->quaternion.q1=t.quat[0]; caller->quaternion.q2=t.quat[1]; caller->quaternion.q3=t.quat[2]; Vector3D pos((float)t.pos[0],(float)t.pos[1],(float)t.pos[2]); //on effectue les rotation caller->parent->pimpl_->ComputeRotations(pos); caller->parent->pimpl_->ComputeRotations(caller->quaternion); Euler euler; caller->quaternion.ToEuler(euler); caller->output->SetValueNoMutex( 0, 0,euler.roll); caller->output->SetValueNoMutex( 1, 0,euler.pitch); caller->output->SetValueNoMutex( 2, 0,euler.yaw); caller->output->SetValueNoMutex( 3, 0,pos.x); caller->output->SetValueNoMutex( 4, 0,pos.y); caller->output->SetValueNoMutex( 5, 0,pos.z); caller->output->SetDataTime(time); caller->output->ReleaseMutex(); caller->state->GetMutex(); caller->state->SetValueNoMutex( 0, 0,Euler::ToDegree(euler.roll)); caller->state->SetValueNoMutex( 1, 0,Euler::ToDegree(euler.pitch)); caller->state->SetValueNoMutex(2, 0,Euler::ToDegree(euler.yaw)); caller->state->ReleaseMutex(); caller->self->ProcessUpdate(caller->output); }