dock_drive.cpp
Go to the documentation of this file.
00001 /*
00002  * Copyright (c) 2012, Yujin Robot.
00003  * All rights reserved.
00004  *
00005  * Redistribution and use in source and binary forms, with or without
00006  * modification, are permitted provided that the following conditions are met:
00007  *
00008  *     * Redistributions of source code must retain the above copyright
00009  *       notice, this list of conditions and the following disclaimer.
00010  *     * Redistributions in binary form must reproduce the above copyright
00011  *       notice, this list of conditions and the following disclaimer in the
00012  *       documentation and/or other materials provided with the distribution.
00013  *     * Neither the name of Yujin Robot nor the names of its
00014  *       contributors may be used to endorse or promote products derived from
00015  *       this software without specific prior written permission.
00016  *
00017  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
00018  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
00019  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
00020  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
00021  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
00022  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
00023  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
00024  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
00025  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
00026  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
00027  * POSSIBILITY OF SUCH DAMAGE.
00028  */
00034 /*****************************************************************************
00035 ** Includes
00036 *****************************************************************************/
00037 
00038 #include "kobuki_dock_drive/dock_drive.hpp"
00039 
00040 /*****************************************************************************
00041 ** Defines
00042 *****************************************************************************/
00043 
00044 #define sign(x) (x>0?+1:x<0?-1:0)
00045 #define stringfy(x) #x
00046 #define setState(x) {state=x;state_str=stringfy(x);}
00047 #define setStateVel(x,v,w) {setState(x);setVel(v,w);}
00048 
00049 /*****************************************************************************
00050 ** Namespaces
00051 *****************************************************************************/
00052 
00053 namespace kobuki {
00054 
00055 /*****************************************************************************
00056 ** Implementation
00057 *****************************************************************************/
00058 DockDrive::DockDrive() :
00059   is_enabled(false), can_run(false) 
00060   , state(IDLE), state_str("IDLE")
00061   , vx(0.0), wz(0.0)
00062   , bump_remainder(0)
00063   , dock_stabilizer(0)
00064   , dock_detector(0)
00065   , rotated(0.0)
00066   , min_abs_v(0.01)
00067   , min_abs_w(0.1)
00068 {
00069 }
00070 
00071 DockDrive::~DockDrive(){;}
00072 
00073 void DockDrive::setVel(double v, double w)
00074 {
00075   vx = sign(v) * std::max(std::abs(v), min_abs_v);
00076   wz = sign(w) * std::max(std::abs(w), min_abs_w);
00077 }
00078 
00079 void DockDrive::modeShift(const std::string& mode)
00080 {
00081   if (mode == "enable")  { is_enabled = true;  can_run = true; }
00082   if (mode == "disable") { is_enabled = false; can_run = false; }
00083   if (mode == "run")  can_run = true;
00084   if (mode == "stop") can_run = false;
00085 }
00086 
00087 void DockDrive::update(const std::vector<unsigned char> &signal
00088                 , const unsigned char &bumper
00089                 , const unsigned char &charger
00090                 , const ecl::Pose2D<double> &pose) {
00091   static ecl::Pose2D<double> pose_priv;
00092   ecl::Pose2D<double> pose_update;
00093 
00094   double dx = pose.x() - pose_priv.x();
00095   double dy = pose.y() - pose_priv.y();
00096   pose_update.x( std::sqrt( dx*dx + dy*dy ) );
00097   pose_update.heading( pose.heading() - pose_priv.heading() );
00098   //std::cout << pose_diff << "=" << pose << "-" << pose_priv << " | " << pose_update << std::endl;
00099   pose_priv = pose;
00100 
00101   ecl::linear_algebra::Vector3d pose_update_rates; //dummy
00102   update( signal, bumper, charger, pose_update, pose_update_rates );
00103 }
00104 
00105 
00117 void DockDrive::update(const std::vector<unsigned char> &signal
00118                 , const unsigned char &bumper
00119                 , const unsigned char &charger
00120                 , const ecl::Pose2D<double> &pose_update
00121                 , const ecl::linear_algebra::Vector3d &pose_update_rates) {
00122   /*************************
00123    * pre processing
00124    *************************/
00125 
00126   //dock_ir signals filtering
00127   past_signals.push_back(signal);
00128   unsigned int window = 20;
00129   while (past_signals.size() > window)
00130     past_signals.erase( past_signals.begin(), past_signals.begin() + past_signals.size() - window );
00131 
00132   std::vector<unsigned char> signal_filt(signal.size(), 0);
00133   for ( unsigned int i=0; i<past_signals.size(); i++) {
00134     if (signal_filt.size() != past_signals[i].size()) continue;
00135     for (unsigned int j=0; j<signal_filt.size(); j++)
00136       signal_filt[j] |= past_signals[i][j];
00137   }
00138 
00139 
00140   /*************************
00141    * debug prints
00142    *************************/
00143   std::ostringstream debug_stream;
00144   // pose_update and pose_update_rates for debugging
00145   debug_stream << std::fixed << std::setprecision(4)
00146     << "[x: "    << std::setw(7) << pose_update.x()
00147     << ", y: "  << std::setw(7) << pose_update.y()
00148     << ", th: " << std::setw(7) << pose_update.heading()
00149     << "]";
00150 
00151   //dock_ir signal
00152   /*
00153   debug_stream 
00154     << "[l: "  << binary(signal_filt[2])
00155     << ", c: " << binary(signal_filt[1])
00156     << ", r: " << binary(signal_filt[0])
00157     << "]";
00158   */
00159   std::string far_signal  = "[F: "; //far field
00160   std::string near_signal = "[N: "; //near field
00161   for (unsigned int i=0; i<3; i++) {
00162     if (signal_filt[2-i]&FAR_LEFT   ) far_signal  += "L"; else far_signal  += "-";
00163     if (signal_filt[2-i]&FAR_CENTER ) far_signal  += "C"; else far_signal  += "-";
00164     if (signal_filt[2-i]&FAR_RIGHT  ) far_signal  += "R"; else far_signal  += "-";
00165     if (signal_filt[2-i]&NEAR_LEFT  ) near_signal += "L"; else near_signal += "-";
00166     if (signal_filt[2-i]&NEAR_CENTER) near_signal += "C"; else near_signal += "-";
00167     if (signal_filt[2-i]&NEAR_RIGHT ) near_signal += "R"; else near_signal += "-";
00168     far_signal  += " ";
00169     near_signal += " ";
00170   }
00171   far_signal  += "]";
00172   near_signal += "]";
00173   debug_stream << far_signal << near_signal;
00174 
00175   //bumper
00176   {
00177   std::string out = "[B: ";
00178   if (bumper&4) out += "L"; else out += "-";
00179   if (bumper&2) out += "C"; else out += "-";
00180   if (bumper&1) out += "R"; else out += "-";
00181   out += "]";
00182   debug_stream << out;
00183   }
00184 
00185   //charger
00186   {
00187   std::ostringstream oss;
00188   oss << "[C:" << std::setw(2) << (unsigned int)charger;
00189   oss << "(";
00190   if (charger) oss << "ON"; else oss << "  ";
00191   oss << ")]";
00192   debug_stream << oss.str();
00193   }
00194 
00195 
00196   /*************************
00197    * processing. algorithms; transforma to velocity command
00198    *************************/
00199   //std::string debug_str = "";
00200   debug_str = "";
00201   do {  // a kind of hack
00202     if ( state==DONE ) setState(IDLE); // when this function is called after final state 'DONE'.
00203     if ( state==DOCKED_IN ) {
00204       if ( dock_stabilizer++ > 20 ) {
00205         is_enabled = false;
00206         can_run = false;
00207         setStateVel(DONE, 0.0, 0.0); break;
00208       }
00209       setStateVel(DOCKED_IN, 0.0, 0.0); break;
00210     }
00211     if ( bump_remainder > 0 ) {
00212       bump_remainder--;
00213       if ( charger ) { setStateVel(DOCKED_IN, 0.0, 0.0); break; } // when bumper signal is received early than charger(dock) signal.
00214       else {           setStateVel(BUMPED_DOCK, -0.01, 0.0); break; }
00215     } else if (state == BUMPED) {
00216       setState(IDLE); //should I remember and recall previous state?
00217       debug_str="how dare!!";
00218     }
00219     if ( bumper || charger ) {
00220       if( bumper && charger ) {
00221         bump_remainder = 0;
00222         setStateVel(BUMPED_DOCK, -0.01, 0.0); break;
00223       }
00224       if ( bumper ) {
00225         bump_remainder = 50;
00226         setStateVel(BUMPED, -0.05, 0.0); break;
00227       }
00228       if ( charger ) { // already docked in
00229         dock_stabilizer = 0;
00230         setStateVel(DOCKED_IN, 0.0, 0.0); break;
00231       }
00232     } else {
00233       if ( state==IDLE ) {
00234         dock_detector = 0;
00235         rotated = 0.0;
00236         setStateVel(SCAN, 0.00, 0.66); break;
00237       }
00238       if ( state==SCAN ) {
00239         rotated += pose_update.heading()/(2.0*M_PI);
00240         std::ostringstream oss;
00241         oss << "rotated: " << std::fixed << std::setprecision(2) << std::setw(4) << rotated;
00242         debug_str = oss.str();
00243         if( std::abs(rotated) > 1.6 ) {
00244           setStateVel(FIND_STREAM, 0.0, 0.0); break;
00245         }
00246         if (  signal_filt[1]&(FAR_LEFT  + NEAR_LEFT )) dock_detector--;
00247         if (  signal_filt[1]&(FAR_RIGHT + NEAR_RIGHT)) dock_detector++;
00248         if ( (signal_filt[1]&FAR_CENTER) || (signal_filt[1]&NEAR_CENTER) ) {
00249           setStateVel(ALIGNED, 0.05, 0.00); break;
00250         } else if ( signal_filt[1] ) {
00251           setStateVel(SCAN, 0.00, 0.10); break;
00252         } else {
00253           setStateVel(SCAN, 0.00, 0.66); break;
00254         }
00255 
00256       } else if (state==ALIGNED || state==ALIGNED_FAR || state==ALIGNED_NEAR) {
00257         if ( signal_filt[1] ) {
00258           if ( signal_filt[1]&NEAR )
00259           {
00260             if ( ((signal_filt[1]&NEAR) == NEAR_CENTER) || ((signal_filt[1]&NEAR) == NEAR) ) { setStateVel(ALIGNED_NEAR, 0.05,  0.0); debug_str = "AlignedNearCenter"; break; }
00261             if (   signal_filt[1]&NEAR_LEFT  ) {                                               setStateVel(ALIGNED_NEAR, 0.05,  0.1); debug_str = "AlignedNearLeft"  ; break; }
00262             if (   signal_filt[1]&NEAR_RIGHT ) {                                               setStateVel(ALIGNED_NEAR, 0.05, -0.1); debug_str = "AlignedNearRight" ; break; }
00263           }
00264           if ( signal_filt[1]&FAR )
00265           {
00266             if ( ((signal_filt[1]&FAR) == FAR_CENTER) || ((signal_filt[1]&FAR) == FAR) ) { setStateVel(ALIGNED_FAR, 0.1,  0.0); debug_str = "AlignedFarCenter"; break; }
00267             if (   signal_filt[1]&FAR_LEFT  ) {                                            setStateVel(ALIGNED_FAR, 0.1,  0.3); debug_str = "AlignedFarLeft"  ; break; }
00268             if (   signal_filt[1]&FAR_RIGHT ) {                                            setStateVel(ALIGNED_FAR, 0.1, -0.3); debug_str = "AlignedFarRight" ; break; }
00269           }
00270           dock_detector = 0;
00271           rotated = 0.0;
00272           setStateVel(SCAN, 0.00, 0.66); break;
00273         } else {
00274           debug_str = "lost signals";
00275           setStateVel(LOST, 0.00, 0.00); break;
00276         }
00277       } else if (state==FIND_STREAM) {
00278         if (dock_detector > 0 ) { // robot is placed in right side of docking station
00279           //turn  right , negative direction til get right signal from left sensor
00280           if (signal_filt[2]&(FAR_RIGHT+NEAR_RIGHT)) {
00281             setStateVel(GET_STREAM, 0.05, 0.0); break;
00282           } else {
00283             setStateVel(FIND_STREAM, 0.0, -0.33); break;
00284           }
00285         } else if (dock_detector < 0 ) { // robot is placed in left side of docking station
00286           //turn left, positive direction till get left signal from right sensor
00287           if (signal_filt[0]&(FAR_LEFT+NEAR_LEFT)) {
00288             setStateVel(GET_STREAM, 0.05, 0.0); break;
00289           } else {
00290             setStateVel(FIND_STREAM, 0.0, 0.33); break;
00291           }
00292         }
00293       } else if (state==GET_STREAM) {
00294         if (dock_detector > 0) { //robot is placed in right side of docking station
00295           if (signal_filt[2]&(FAR_LEFT+NEAR_LEFT)) {
00296             dock_detector = 0;
00297             rotated = 0.0;
00298             setStateVel(SCAN, 0.0, 0.10); break;
00299           } else {
00300             setStateVel(GET_STREAM, 0.05, 0.0); break;
00301           }
00302         } else if (dock_detector < 0) { // robot is placed in left side of docking station
00303           if (signal_filt[0]&(FAR_RIGHT+NEAR_RIGHT)) {
00304             dock_detector = 0;
00305             rotated = 0.0;
00306             setStateVel(SCAN, 0.0, 0.10); break;
00307           } else {
00308             setStateVel(GET_STREAM, 0.05, 0.0); break;
00309           }
00310         }
00311       } else {
00312         dock_detector = 0;
00313         rotated = 0.0;
00314         setStateVel(SCAN, 0.00, 0.66); break;
00315       }
00316     }
00317     setStateVel(UNKNOWN, 0.00, 0.00); break;
00318   } while(0);
00319 
00320   //debug_stream << std::fixed << std::setprecision(4)
00321   debug_stream << "[vx: " << std::setw(7) << vx << ", wz: " << std::setw(7) << wz << "]";
00322   debug_stream << "[S: " << state_str << "]";
00323   debug_stream << "[" << debug_str << "]";
00324   //debug_stream << std::endl;
00325   debug_output = debug_stream.str();
00326 
00327   //std::cout << debug_output << std::endl;;
00328 
00329   velocityCommands(vx, wz);
00330 //  this->vx = vx; this->wz = wz;
00331   return;
00332 }
00333 
00334 void DockDrive::velocityCommands(const double &vx_, const double &wz_) {
00335   // vx: in m/s
00336   // wz: in rad/s
00337   vx = vx_;
00338   wz = wz_;
00339 }
00340 
00341 std::string DockDrive::binary(unsigned char number) const {
00342   std::string ret;
00343   for( unsigned int i=0;i<6; i++){
00344     if (number&1) ret = "1" + ret;
00345     else          ret = "0" + ret;
00346     number = number >> 1;
00347   }
00348   return ret;
00349 }
00350 
00351 } // namespace kobuki


kobuki_dock_drive
Author(s): Younghun Ju
autogenerated on Thu Aug 27 2015 13:43:56