MOOS 0.2375
|
00001 00002 // 00003 // MOOS - Mission Oriented Operating Suite 00004 // 00005 // A suit of Applications and Libraries for Mobile Robotics Research 00006 // Copyright (C) 2001-2005 Massachusetts Institute of Technology and 00007 // Oxford University. 00008 // 00009 // This software was written by Paul Newman at MIT 2001-2002 and Oxford 00010 // University 2003-2005. email: pnewman@robots.ox.ac.uk. 00011 // 00012 // This file is part of a MOOS Utility Component. 00013 // 00014 // This program is free software; you can redistribute it and/or 00015 // modify it under the terms of the GNU General Public License as 00016 // published by the Free Software Foundation; either version 2 of the 00017 // License, or (at your option) any later version. 00018 // 00019 // This program is distributed in the hope that it will be useful, 00020 // but WITHOUT ANY WARRANTY; without even the implied warranty of 00021 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00022 // General Public License for more details. 00023 // 00024 // You should have received a copy of the GNU General Public License 00025 // along with this program; if not, write to the Free Software 00026 // Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 00027 // 02111-1307, USA. 00028 // 00030 00031 00032 // SixDOFAUV.cpp: implementation of the CSixDOFAUV class. 00033 // 00035 #ifdef _WIN32 00036 #pragma warning(disable : 4786) 00037 #endif 00038 00039 00040 00041 #include <math.h> 00042 #include "SixDOFAUV.h" 00043 #include "AcousticTransceiver.h" 00044 using namespace std; 00045 00046 #ifndef PI 00047 #define PI 3.141592653589793 00048 #endif 00049 00050 Matrix CrossProduct(Matrix& v1, Matrix& v2) 00051 { 00052 double a1 = v1(1,1); 00053 double a2 = v1(2,1); 00054 double a3 = v1(3,1); 00055 00056 double b1 = v2(1,1); 00057 double b2 = v2(2,1); 00058 double b3 = v2(3,1); 00059 00060 Matrix Cross(3,1); 00061 Cross<<(a2* b3 - a3*b2)<< 00062 (a3*b1 - a1*b3)<< 00063 (a1*b2 - a2*b1); 00064 00065 return Cross; 00066 } 00067 00068 00069 00070 00072 // Construction/Destruction 00074 00075 CSixDOFAUV::CSixDOFAUV() 00076 { 00077 00078 } 00079 00080 CSixDOFAUV::~CSixDOFAUV() 00081 { 00082 00083 } 00084 00085 00086 bool CSixDOFAUV::Initialise() 00087 { 00088 //if you were to say - Oi! Whats with all these 00089 //out-of-the-blue numbers? I would have to concur.... 00090 //later versions added these to a mission file.. 00091 00092 double Mass = 30.0; 00093 m_dfWeight = Mass*9.81; 00094 m_dfBuoyancy = m_dfWeight+0.001; 00095 m_dfHeading = 0; 00096 00097 //y points to front of vessel 00098 // double Ixx = 10.00; 00099 double Ixx = 5.00; 00100 double Iyy = 2.08; 00101 double Izz = 8.0; 00102 00103 m_M.ReSize(6,6); 00104 m_M = 0; 00105 m_M(1,1) = Mass; 00106 m_M(2,2) = Mass; 00107 m_M(3,3) = Mass; 00108 m_M(4,4) = Ixx; 00109 m_M(5,5) = Iyy; 00110 m_M(6,6) = Izz; 00111 m_Mi = m_M.i(); 00112 00113 00114 00115 m_Pos_e.ReSize(6,1); 00116 m_Pos_e = 0; 00117 00118 m_Vel_e.ReSize(6,1); 00119 m_Vel_e = 0; 00120 00121 m_Vel_v.ReSize(6,1); 00122 m_Vel_v = 0; 00123 00124 //entirely made up numbers.....but they are 00125 //not ridiculous 00126 m_KDrag.ReSize(6,1); 00127 m_KDrag<<100<<60<<100<<200<<10<<70.0; 00128 00129 m_Drag.ReSize(6,1); 00130 00131 m_JacVel.ReSize(6,6); 00132 m_JacVel = 0; 00133 00134 00135 m_Uf.ReSize(6,1); 00136 m_Uf = 0; 00137 00138 m_dfThrust = 0; 00139 m_dfRudder = 0; 00140 m_dfElevator =0; 00141 00142 00143 m_Hf.ReSize(6,1); 00144 m_COG.ReSize(3,1); 00145 m_COG = 0; 00146 00147 m_COB.ReSize(3,1); 00148 m_COB<<0.0<<0.0<<0.05; 00149 00150 m_dfDepth = 0; 00151 m_dfAltitude = 0; 00152 00153 /* 00154 // Set up acoustic facility 00155 CAcousticNode* pTheAcousticsBit = new CAcousticTransceiver; 00156 00157 //pass a pointer to the global params block.. 00158 pTheAcousticsBit->SetParams(m_pParams); 00159 00160 //give it a parent 00161 pTheAcousticsBit->SetParent(this); 00162 00163 //name the acoustic node 00164 pTheAcousticsBit->SetName("Tcvr1"); 00165 00166 00167 m_AcousticNodes.push_back(pTheAcousticsBit); 00168 */ 00169 00170 return true; 00171 } 00172 00173 bool CSixDOFAUV::FillVelJacobian() 00174 { 00175 double dfPhi = m_Pos_e(4,1); double cPhi = cos(dfPhi); double sPhi=sin(dfPhi); 00176 double dfTheta = m_Pos_e(5,1); double cTheta = cos(dfTheta); double sTheta = sin(dfTheta); 00177 double dfPsi = m_Pos_e(6,1); double cPsi=cos(dfPsi); double sPsi = sin(dfPsi); 00178 00179 00180 m_JacVel << cPsi*cTheta << -sPsi*cPhi+cPsi*sTheta*sPhi << sPsi*sPhi+cPsi*sTheta*cPhi <<0<<0<<0 00181 << sPsi*cTheta << cPsi*cPhi+sPsi*sTheta*sPhi << -cPsi*sPhi+sPsi*sTheta*cPhi <<0<<0<<0 00182 << -sTheta << cTheta*sPhi << cTheta*cPhi <<0<<0<<0 00183 00184 <<0<<0<<0<< 1.0 << sPhi*tan(dfTheta) << cPhi*tan(dfTheta) 00185 <<0<<0<<0<< 0 << cPhi << -sPhi 00186 <<0<<0<<0<< 0 << sPhi/cTheta << cPhi/cTheta; 00187 00188 00189 00190 00191 00192 return true; 00193 00194 } 00195 00196 bool CSixDOFAUV::Iterate(double dfTimeNow,double dfDT) 00197 { 00198 00199 DoModel(dfDT); 00200 00201 00202 return true; 00203 } 00204 00205 00206 bool CSixDOFAUV::DoModel(double dfDT) 00207 { 00208 00209 //prepare velocity jacobian 00210 FillVelJacobian(); 00211 00212 Matrix J1=m_JacVel.SubMatrix(1,3,1,3); 00213 00215 // calculate body forces.... 00217 00218 Matrix B(3,1); Matrix W(3,1); 00219 00220 //if we surface we have a discontinuity! 00221 //alternatively you could integrate over submerged volume 00222 //but this is simpler 00223 00224 int nSignDepth = m_dfDepth>=0.0?1:-1; 00225 00226 00227 B<<0.0<<0.0<<m_dfBuoyancy*nSignDepth; 00228 W<<0.0<<0.0<<-m_dfWeight*nSignDepth; 00229 00230 Matrix Fg = J1.i()*W; 00231 Matrix Fb = J1.i()*B; 00232 00233 m_Hf = (Fg+Fb) & (CrossProduct(m_COG,Fg)+CrossProduct(m_COB,Fb)); 00234 00235 00237 // Calculate thrust vector 00239 00240 // uncomment this block for stand alone testing 00241 00242 // m_dfThrust = 5.0; 00243 // m_dfElevator = 5.0*PI/180.0; 00244 // m_dfRudder = 5.0*PI/180.0; 00245 00246 00248 //note without proper added mass terms vehicle turns very 00249 //sharply hence scaling terms in the following force vector 00250 //can be extended later. 00252 00253 /* 00254 Matrix Thrust(3,1); 00255 00256 Thrust<<m_dfThrust*cos(m_dfElevator)*cos(m_dfRudder)<< 00257 m_dfThrust*cos(m_dfElevator)*sin(m_dfRudder)<< 00258 -m_dfThrust*sin(m_dfElevator); 00259 00260 Matrix Tail(3,1); Tail<<-dfLen<<0.0<<0; 00261 00262 m_Uf = Thrust & (CrossProduct(Tail,Thrust)); 00263 */ 00264 00265 00266 00267 //note Tq_y = 0 we assume no propellor reaction torque 00268 //simple thing to add though Tprop = k* vel ? 00269 00270 //half length of vehicle (assumed) 00271 double dfLen = 1.0; 00272 00273 //m_dfRudder = 0; 00274 //m_dfElevator = MOOSDeg2Rad(4); 00275 //m_dfThrust = 40; 00276 00277 m_Uf << -m_dfThrust*cos(m_dfElevator)*sin(m_dfRudder)<< 00278 3*m_dfThrust*cos(m_dfElevator)*cos(m_dfRudder)<< 00279 0.1*m_dfThrust*sin(m_dfElevator)<< 00280 -/*0.1**/dfLen*m_dfThrust*sin(m_dfElevator)<< 00281 0.0<< 00282 -0.8*m_dfThrust*dfLen*cos(m_dfElevator)*sin(m_dfRudder); 00283 00284 00285 //MOOSTrace("Elevator = %f Thrust = %f Rudder = %f\n",m_dfElevator,m_dfThrust,m_dfRudder); 00287 // calculate drag vector 00289 m_Drag << -(m_KDrag(1,1)*m_Vel_v(1,1)*fabs(m_Vel_v(1,1)))<< 00290 -(m_KDrag(2,1)*m_Vel_v(2,1)*fabs(m_Vel_v(2,1)))<< 00291 -(m_KDrag(3,1)*m_Vel_v(3,1)*fabs(m_Vel_v(3,1)))<< 00292 -(m_KDrag(4,1)*m_Vel_v(4,1)*fabs(m_Vel_v(4,1)))<< 00293 -(m_KDrag(5,1)*m_Vel_v(5,1)*fabs(m_Vel_v(5,1)))<< 00294 -(m_KDrag(6,1)*m_Vel_v(6,1)*fabs(m_Vel_v(6,1))); 00295 00296 00298 // utterly trivial integration 00299 // extend to 4th order RK when required 00301 00302 // Newton III : 00303 m_Acc_v = m_Mi * (m_Uf+m_Drag+m_Hf); 00304 00305 // integrate (1) 00306 m_Vel_v += m_Acc_v*dfDT; 00307 00308 //transform to body coordinates with jacobian 00309 m_Vel_e = m_JacVel*m_Vel_v; 00310 00311 //integrate (2) 00312 m_Pos_e += m_Vel_e*dfDT; 00313 00314 00316 // post integration house keeping 00318 00319 //Look after angles... 00320 m_Pos_e(6,1) = MOOS_ANGLE_WRAP(m_Pos_e(6,1)); 00321 00322 //figure out our heading -ve around z axis from x axis... 00323 m_dfHeading = HeadingFromYaw(m_Pos_e(6,1)); 00324 00325 //figure out speed.. 00326 m_dfSpeed = sqrt(pow(m_Vel_v(1,1),2)+pow(m_Vel_v(2,1),2)+pow(m_Vel_v(3,1),2)); 00327 00329 // Environmental properties... 00330 // some things are a function of environment and so we need 00331 // to access it to resolve some properties.... 00332 if(m_pEnvironment!=NULL) 00333 { 00334 m_dfDepth = m_pEnvironment->GetDepth(GetZ()); 00335 m_dfAltitude = m_pEnvironment->GetAltitude(GetX(),GetY(),GetZ()); 00336 } 00337 00338 return true; 00339 } 00340 00341 00342 00343 00344 double CSixDOFAUV::GetDepth() 00345 { 00346 00347 return m_dfDepth; 00348 }