00001
00017 #include "Odometry.h"
00018
00019
00020
00021 static const char* odometry_spec[] =
00022 {
00023 "implementation_id", "Odometry",
00024 "type_name", "Odometry",
00025 "description", "detect position by Odometry",
00026 "version", "4.0.0",
00027 "vendor", "AIST INVENT",
00028 "category", "Localization",
00029 "activity_type", "PERIODIC",
00030 "kind", "DataFlowComponent",
00031 "max_instance", "10",
00032 "language", "C++",
00033 "lang_type", "compile",
00034 "exec_cxt.periodic.rate", "1000.0",
00035
00036 "conf.default.leftWheelID", "0",
00037 "conf.default.rightWheelID", "1",
00038 "conf.default.radiusOfLeftWheel", "0.1",
00039 "conf.default.radiusOfRightWheel", "0.1",
00040 "conf.default.lengthOfAxle", "0.441",
00041 "conf.default.radiusOfBodyArea", "0.45",
00042 ""
00043 };
00044
00045
00050 Odometry::Odometry(RTC::Manager* manager)
00051
00052 : RTC::DataFlowComponentBase(manager),
00053 m_CurrentWheelAngleIn("CurrentWheelAngle", m_CurrentWheelAngle),
00054 m_LocalizedPositionIn("LocalizedPosition", m_LocalizedPosition),
00055 m_OdometryPositionOut("OdometryPosition", m_OdometryPosition)
00056
00057
00058 {
00059 }
00060
00064 Odometry::~Odometry()
00065 {
00066 }
00067
00068
00072 RTC::ReturnCode_t Odometry::onInitialize()
00073 {
00074
00075
00076
00077 registerInPort("CurrentWheelAngle", m_CurrentWheelAngleIn);
00078 registerInPort("LocalizedPosition", m_LocalizedPositionIn);
00079
00080
00081 registerOutPort("OdometryPosition", m_OdometryPositionOut);
00082
00083
00084
00085
00086
00087
00088
00089
00090
00091
00092
00093 bindParameter("leftWheelID", m_leftWheelID, "0");
00094 bindParameter("rightWheelID", m_rightWheelID, "1");
00095 bindParameter("radiusOfLeftWheel", m_radiusOfLeftWheel, "0.1");
00096 bindParameter("radiusOfRightWheel", m_radiusOfRightWheel, "0.1");
00097 bindParameter("lengthOfAxle", m_lengthOfAxle, "0.441");
00098 bindParameter("radiusOfBodyArea", m_radiusOfBodyArea, "0.45");
00099
00100
00101
00102
00103 std::cout << "OnInitialize()" << std::endl;
00104
00105
00106
00107 RotationAngleBorder = 3.1415927/180.0;
00108 RhoBorder = 10000.0;
00109
00110
00111 #if CALLBACK
00112
00113
00114
00115 #endif
00116
00117
00118 return RTC::RTC_OK;
00119 }
00120
00121
00122
00123
00124
00125
00126
00127
00128
00129
00130
00131
00132
00133
00134
00135
00136
00137
00138
00139
00140
00141
00148 RTC::ReturnCode_t Odometry::onActivated(RTC::UniqueId ec_id)
00149 {
00150
00151 std::cout << "on Activated" << std::endl;
00152
00153
00154
00155 Body.wheelRadiusLeft = Body.wheelRadiusRight = Body.bodyRadius = Body.length = 0.0;
00156 Body.leftID = Body.rightID = -1;
00157
00158
00159 Current.BodyVel = Current.RightVel = Current.LeftVel = Current.BodyAccel = Current.Rho = Current.BodyOmega = 0.0;
00160 Current.x = 0.0;
00161 Current.y = 0.0;
00162 Current.xOld = 0.0;
00163 Current.yOld = 0.0;
00164 Current.theta = 0.0;
00165 Current.thetaOld = 0.0;
00166 Current.BodyVelOld = Current.BodyOmegaOld = Current.RhoOld = 0.0;
00167 Current.Time = Current.TimeOld = 0.0;
00168
00169 Current.sec = Current.nsec = Current.secOld = Current.nsecOld = 0;
00170
00171
00172 InitialPositionFlag = InitialAngleFlag = false;
00173
00174 #if DEBUG
00175
00176 ofs.open("odometry.dat");
00177 #endif
00178
00179
00180 Body.leftID = m_leftWheelID;
00181 Body.rightID = m_rightWheelID;
00182 Body.wheelRadiusLeft = m_radiusOfLeftWheel;
00183 Body.wheelRadiusRight = m_radiusOfRightWheel;
00184 Body.bodyRadius = 0.5 * m_lengthOfAxle;
00185 Body.length = m_radiusOfBodyArea;
00186
00187 #if DEBUG
00188 std::cout << "Body.leftID: " << Body.leftID << " Body.rightID: " << Body.rightID << std::endl;
00189 std::cout << "Body.wheelRadius[L]: " << Body.wheelRadiusLeft << "Body.wheelRadius[R]: " << Body.wheelRadiusRight << " Body.bodyRadius: " << Body.bodyRadius << std::endl;
00190 #endif
00191
00192
00193 m_CurrentWheelAngleIn.update();
00194 m_LocalizedPositionIn.update();
00195
00196
00197 for(int i=0; i < Dof; i++){
00198
00199 Current.Ang[i] = Current.AngVel[i] = 0.0;
00200 Current.AngOld[i] = Current.AngVelOld[i] = 0.0;
00201 }
00202 #if DEBUG2
00203 counter = 0;
00204 ofs2.open("runtime.dat");
00205 ofs3.open("runtime2.dat");
00206
00207 timerclear(&TotalTime);
00208
00209 if(gettimeofday(&TotalTime, NULL)){
00210 std::cout << "failed to gettimeofday" << std::endl;
00211 }
00212 #endif
00213
00214
00215
00216 return RTC::RTC_OK;
00217 }
00218
00223 RTC::ReturnCode_t Odometry::onDeactivated(RTC::UniqueId ec_id)
00224 {
00225
00226 std::cout << "on Deactivated" << std::endl;
00227
00228
00229
00230 #if DEBUG
00231 ofs.close();
00232 #endif
00233 #if DEBUG2
00234 ofs2.close();
00235 ofs3.close();
00236 #endif
00237
00238
00239
00240 return RTC::RTC_OK;
00241 }
00242
00250 RTC::ReturnCode_t Odometry::onExecute(RTC::UniqueId ec_id)
00251 {
00252
00253
00254
00255 #if DEBUG2
00256
00257 if(gettimeofday(&SetTime, NULL)){
00258 std::cout << "failed to gettimeofday" << std::endl;
00259 }
00260 timerclear(&GetTime);
00261 timersub(&SetTime, &TotalTime, &GetTime);
00262
00263 unsigned long sec_debug_start = GetTime.tv_sec;
00264 unsigned long nsec_debug_start = GetTime.tv_usec*1000;
00265 double starttime = sec_debug_start + 1.0e-9*nsec_debug_start;
00266
00267
00268 #endif
00269
00270
00271
00272
00273
00274
00275
00276
00277
00278
00279
00280
00281
00282
00283 while (!m_LocalizedPositionIn.isEmpty())
00284 getLocalizedPosition();
00285
00286
00287
00288 if (true) {
00289
00290 if (m_CurrentWheelAngleIn.isNew()) {
00291
00292 if (getWheelAngleData()) {
00293
00294 calcOdometry();
00295
00296 setCurrentToOld();
00297
00298 usleep(10000);
00299 outputData();
00300 }
00301 }
00302 else {
00303 #if DEBUG
00304 std::cout << " --------[SKIP] can't get wheel angle data from [MotorControlRTC]---" << std::endl;
00305 #endif
00306 }
00307 }
00308
00309 #if DEBUG2
00310 if(gettimeofday(&SetTime, NULL)){
00311 std::cout << "failed to gettimeofday" << std::endl;
00312 }
00313 timerclear(&GetTime);
00314 timersub(&SetTime, &TotalTime, &GetTime);
00315
00316 unsigned long sec_debug_end = GetTime.tv_sec;
00317 unsigned long nsec_debug_end = GetTime.tv_usec*1000;
00318 double endtime = sec_debug_end + 1.0e-9*nsec_debug_end;
00319
00320 double deltaTime = 1.0e3*( endtime - starttime);
00321
00322 std::cout << "----[RuntTime(" << counter << ")] StartTime [sec] = " << starttime << " EndTime [sec] = " << endtime << " [ " << deltaTime << " msec]" << std::endl;
00323
00324
00325
00326
00327
00328 std::cout << std::endl;
00329 ofs2 << counter++ << " , CurTime= " << Current.Time << " , dTime[ms]= " << deltaTime << std::endl;
00330 #endif
00331
00332
00333
00334 return RTC::RTC_OK;
00335 }
00336
00337
00338
00339
00340
00341
00342 inline void Odometry::getLocalizedPosition()
00343 {
00344
00345
00346 m_LocalizedPositionIn.read();
00347
00348
00349 if (!InitialPositionFlag) {
00350
00351
00352
00353
00354
00355
00356 Current.xOld = m_LocalizedPosition.data.position.x;
00357 Current.yOld = m_LocalizedPosition.data.position.y;
00358 Current.thetaOld = m_LocalizedPosition.data.heading;
00359 Current.secOld = 0;
00360 Current.nsecOld = 0;
00361 Current.TimeOld = Current.secOld + 1.0e-9*Current.nsecOld;
00362 InitialPositionFlag = true;
00363 std::cout << " [INITIALIZED] X = " << Current.xOld << " , Y = " << Current.yOld << " , THETA =" << Current.thetaOld << std::endl;
00364 } else if ( 1) {
00365
00366
00367
00368
00369
00370
00371 Current.xOld = m_LocalizedPosition.data.position.x;
00372 Current.yOld = m_LocalizedPosition.data.position.y;
00373 Current.thetaOld = m_LocalizedPosition.data.heading;
00374 } else {
00375 #if DEBUG
00376 std::cout << " -----[NoCorresponding (LocalizedTime)--(previousTime)] LocalizedSEC = " << m_LocalizedPosition.tm.sec << " , LocalizedNSEC = " << m_LocalizedPosition.tm.nsec << " , SecOld =" << Current.secOld << " , NSecOld =" << Current.nsecOld << std::endl;
00377 #endif
00378 }
00379
00380 return ;
00381 }
00382
00383
00384
00385
00386
00387 inline bool Odometry::getWheelAngleData()
00388 {
00389
00390
00391 m_CurrentWheelAngleIn.read();
00392
00393
00394 Current.Ang[Body.leftID] = m_CurrentWheelAngle.data[Body.leftID];
00395 Current.Ang[Body.rightID] = m_CurrentWheelAngle.data[Body.rightID];
00396
00397
00398 Current.sec = m_CurrentWheelAngle.tm.sec;
00399 Current.nsec = m_CurrentWheelAngle.tm.nsec;
00400
00401
00402 Current.Time = Current.sec + 1.0e-9*Current.nsec;
00403
00404
00405 if (!InitialAngleFlag) {
00406 Current.AngOld[Body.leftID] = Current.Ang[Body.leftID];
00407 Current.AngOld[Body.rightID] = Current.Ang[Body.rightID];
00408 timeStep = 1.0e5;
00409 InitialAngleFlag = true;
00410 std::cout << " [INITIALIZED] Angle[L] = " << Current.AngOld[Body.leftID] << " , Angle[R] = " << Current.AngOld[Body.rightID] << std::endl;
00411 } else {
00412
00413 timeStep = Current.Time - Current.TimeOld;
00414 }
00415
00416 #if DEBUG
00417 std::cout << std::endl;
00418 std::cout << "--[TIME(sec)]: " << Current.Time << "--------------------------------------" << std::endl;
00419 std::cout << " TimeStep[sec] = " << timeStep << std::endl;
00420 std::cout << " [Current] currWheelAng[L] = " << m_CurrentWheelAngle.data[Body.leftID] << " / currWheelAng[R] = " << m_CurrentWheelAngle.data[Body.rightID] << " TIME1= " << m_CurrentWheelAngle.tm.sec << " TIME2=" << m_CurrentWheelAngle.tm.nsec << std::endl;
00421 #endif
00422
00423 if (timeStep <= 0.0) {
00424 std::cout << "== [ERROR(timeStep)] [Old or Same] timestamp's data were send, so couldn't calculate Odometry position values. " << std::endl;
00425 return false;
00426 }
00427
00428
00429 Current.AngVel[Body.leftID] = (Current.Ang[Body.leftID] - Current.AngOld[Body.leftID]) / timeStep;
00430 Current.AngVel[Body.rightID] = (Current.Ang[Body.rightID] - Current.AngOld[Body.rightID]) / timeStep;
00431
00432
00433 return true;
00434 }
00435
00436
00437
00438
00439
00440 inline void Odometry::calcOdometry() {
00441
00442 double dl,dfai,faiDummy;
00443
00444 Current.LeftVel = Body.wheelRadiusLeft * Current.AngVel[Body.leftID];
00445 Current.RightVel = Body.wheelRadiusRight * Current.AngVel[Body.rightID];
00446
00447 #if DEBUG
00448 std::cout << "----calc CurrentPosition by Odometry-----------" << std::endl;
00449 std::cout << " [odometry] AngularVel[L] = " << Current.AngVel[Body.leftID] << " / AngularVel[R] = " << Current.AngVel[Body.rightID] << std::endl;
00450 std::cout << " [odometry] BodyleftVel = " << Current.LeftVel << " / BodyRightVel = " << Current.RightVel << std::endl;
00451 #endif
00452
00453
00454 Current.BodyVel = 0.5 * (Current.RightVel + Current.LeftVel) * 9.0/5.5;
00455 Current.BodyAccel = (Current.BodyVel - Current.BodyVelOld) / timeStep;
00456 Current.BodyOmega = 0.5 * (Current.RightVel - Current.LeftVel) * 9.0/5.5 / Body.bodyRadius;
00457
00458
00459
00460 dfai = Current.BodyOmega * timeStep * 6.28/(6.28 - 0.2);
00461
00462
00463 Current.theta = Current.thetaOld + dfai;
00464
00465
00466 while (Current.theta <= -1.0*M_PI || Current.theta >= 1.0*M_PI) {
00467 if( Current.theta <= -1.0*M_PI) Current.theta += 2.0*M_PI;
00468 else if ( Current.theta >= 1.0*M_PI) Current.theta -= 2.0*M_PI;
00469 }
00470
00471 #if DEBUG
00472 std::cout << " [odometry] BodyVel = " << Current.BodyVel << " / PreBodyVel = " << Current.BodyVelOld << " / BodyAccel = " << Current.BodyAccel << " / dfai[deg] = " << dfai*180/M_PI << " / CurrPostureAng[deg] = " << Current.theta*180/M_PI << " / Current.BodyOmega[deg/s] = " <<Current.BodyOmega*180/M_PI << " / Current.BodyOmegaOLD[deg/s] = " <<Current.BodyOmegaOld*180/M_PI << std::endl;
00473 #endif
00474
00475
00476 if(dfai != 0.0) {
00477 Current.Rho = Body.bodyRadius * (Current.RightVel + Current.LeftVel) / (Current.RightVel - Current.LeftVel);
00478
00479
00480 #if DEBUG
00481
00482 std::cout << " [odometry] Current.RhoOld = " << Current.RhoOld << " Current.rho = " << Current.Rho << std::endl;
00483 #endif
00484
00485
00486 if (fabs(Current.Rho) > RhoBorder && Current.Rho >= 0.0 ) {
00487 Current.Rho = RhoBorder;
00488 dl = 0.5 * (Current.BodyVel + Current.BodyVelOld) * timeStep;
00489 } else if (fabs(Current.Rho) > RhoBorder && Current.Rho < 0.0 ) {
00490 Current.Rho = -1.0*RhoBorder;
00491 dl = 0.5 * (Current.BodyVel + Current.BodyVelOld) * timeStep;
00492 } else if(fabs(dfai) < RotationAngleBorder) {
00493 dl = Current.Rho * dfai;
00494
00495 } else {
00496 dl = 2.0 * Current.Rho * sin(0.5 * dfai);
00497
00498 }
00499
00500 } else {
00501 Current.Rho = 0.0;
00502 dl = 0.5 * (Current.BodyVel + Current.BodyVelOld) * timeStep;
00503 }
00504
00505
00506
00507 faiDummy = Current.thetaOld + 0.5*dfai;
00508
00509
00510 Current.x = Current.xOld + dl * cos(faiDummy);
00511 Current.y = Current.yOld + dl * sin(faiDummy);
00512
00513
00514 std::cout << "[odometry] Current.x = " << Current.x << " Current.y = " << Current.y << " Current.theta = " << Current.theta << " deltaL = " << dl << std::endl;
00515
00516
00517 return ;
00518 }
00519
00520
00521
00522
00523
00524 inline void Odometry::setCurrentToOld()
00525 {
00526
00527
00528 Current.xOld = Current.x;
00529 Current.yOld = Current.y;
00530 Current.thetaOld = Current.theta;
00531
00532 Current.BodyVelOld = Current.BodyVel;
00533 Current.BodyOmegaOld = Current.BodyOmega;
00534 Current.RhoOld = Current.Rho;
00535
00536 Current.AngOld[Body.leftID] = Current.Ang[Body.leftID];
00537 Current.AngVelOld[Body.leftID] = Current.AngVel[Body.leftID];
00538 Current.AngOld[Body.rightID] = Current.Ang[Body.rightID];
00539 Current.AngVelOld[Body.rightID] = Current.AngVel[Body.rightID];
00540
00541 Current.secOld = Current.sec;
00542 Current.nsecOld = Current.nsec;
00543 Current.TimeOld = Current.Time;
00544
00545 return;
00546 }
00547
00548
00549
00550
00551
00552 inline void Odometry::outputData()
00553 {
00554
00555
00556
00557
00558
00559
00560
00561
00562
00563 m_OdometryPosition.data.position.x = Current.x;
00564 m_OdometryPosition.data.position.y = Current.y;
00565 m_OdometryPosition.data.heading = Current.theta;
00566 m_OdometryPosition.tm.sec = Current.sec;
00567 m_OdometryPosition.tm.nsec = Current.nsec;
00568
00569 #if DEBUG
00570 std::cout << " [output] currWheelAng[L]: " << Current.Ang[Body.leftID] << ", currWheelAng[R]:" << Current.Ang[Body.rightID] << " TIME1= " << Current.sec << " TIME2=" << Current.nsec << std::endl;
00571 #endif
00572
00573
00574 m_OdometryPositionOut.write();
00575
00576 #if DEBUG
00577
00578 ofs << Current.x << " " << Current.y << " " << Current.theta << " " << 180.0*Current.theta/M_PI << std::endl;
00579 #endif
00580
00581 #if LOG
00582 std::cout << "[Odometry Position] Time = " << Current.Time << "[s] (X[m],Y[m],Theta[deg]/[rad]) = (" << Current.x << " , " << Current.y << " , " << 180.0*Current.theta/M_PI << "/" << Current.theta << ") " << std::endl;
00583 #endif
00584
00585 return;
00586 }
00587
00588
00589
00590
00591
00592
00593
00594
00595
00596
00597
00598
00599
00600
00601
00602
00603
00604
00605
00606
00607
00608
00609
00610
00611
00612
00613
00614
00615
00616
00617
00618
00619
00620
00621
00622
00623
00624
00625
00626
00627 extern "C"
00628 {
00629
00630 void OdometryInit(RTC::Manager* manager)
00631 {
00632 coil::Properties profile(odometry_spec);
00633 manager->registerFactory(profile,
00634 RTC::Create<Odometry>,
00635 RTC::Delete<Odometry>);
00636 }
00637
00638 };
00639
00640