dock_drive.cpp
Go to the documentation of this file.
00001 /*
00002  * copyright (c) 2013, 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;}
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(RobotDockingState::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   , signal_window(20)
00069   , ROBOT_STATE_STR(13)
00070 {
00071   // Debug messages
00072   ROBOT_STATE_STR[0] = "IDLE";
00073   ROBOT_STATE_STR[1] = "DONE";
00074   ROBOT_STATE_STR[2] = "DOCKED_IN";
00075   ROBOT_STATE_STR[3] = "BUMPED_DOCK";
00076   ROBOT_STATE_STR[4] = "BUMPED";
00077   ROBOT_STATE_STR[5] = "SCAN";
00078   ROBOT_STATE_STR[6] = "FIND_STREAM";
00079   ROBOT_STATE_STR[7] = "GET_STREAM";
00080   ROBOT_STATE_STR[8] = "ALIGNED";
00081   ROBOT_STATE_STR[9] = "ALIGNED_FAR";
00082   ROBOT_STATE_STR[10] = "ALIGNED_NEAR";
00083   ROBOT_STATE_STR[11] = "UNKNOWN";
00084   ROBOT_STATE_STR[12] = "LOST";
00085 }
00086 
00087 DockDrive::~DockDrive(){;}
00088 
00089 void DockDrive::setVel(double v, double w)
00090 {
00091   vx = sign(v) * std::max(std::abs(v), min_abs_v);
00092   wz = sign(w) * std::max(std::abs(w), min_abs_w);
00093 }
00094 
00095 void DockDrive::modeShift(const std::string& mode)
00096 {
00097   if (mode == "enable")  { is_enabled = true;  can_run = true; state = RobotDockingState::IDLE;}
00098   if (mode == "disable") { is_enabled = false; can_run = false; }
00099   if (mode == "run")  can_run = true;
00100   if (mode == "stop") can_run = false;
00101 }
00102 
00103 
00114 void DockDrive::update(const std::vector<unsigned char> &signal
00115                 , const unsigned char &bumper
00116                 , const unsigned char &charger
00117                 , const ecl::LegacyPose2D<double>& pose) {
00118 
00119   ecl::LegacyPose2D<double> pose_update;
00120   std::vector<unsigned char> signal_filt(signal.size(), 0);
00121   std::string debug_str;
00122 
00123   // process bumper and charger event first
00124   // docking algorithm terminates here
00125   if(bumper || charger) {
00126     processBumpChargeEvent(bumper, charger);
00127   }
00128   else {
00129     computePoseUpdate(pose_update, pose);
00130     filterIRSensor(signal_filt, signal);
00131     updateVelocity(signal_filt, pose_update, debug_str);
00132   }
00133 
00134   velocityCommands(vx, wz);
00135 
00136   // for easy debugging
00137   generateDebugMessage(signal_filt, bumper, charger, pose_update, debug_str);
00138 
00139   return;
00140 }
00141 
00148 void DockDrive::computePoseUpdate(ecl::LegacyPose2D<double>& pose_update, const ecl::LegacyPose2D<double>& pose)
00149 {
00150   double dx = pose.x() - pose_priv.x();
00151   double dy = pose.y() - pose_priv.y();
00152   pose_update.x( std::sqrt( dx*dx + dy*dy ) );
00153   pose_update.heading( pose.heading() - pose_priv.heading() );
00154   //std::cout << pose_diff << "=" << pose << "-" << pose_priv << " | " << pose_update << std::endl;
00155   pose_priv = pose;
00156 
00157 }
00158 
00159 
00167 void DockDrive::filterIRSensor(std::vector<unsigned char>& signal_filt,const std::vector<unsigned char> &signal)
00168 {
00169   //dock_ir signals filtering
00170   past_signals.push_back(signal);
00171   while (past_signals.size() > signal_window) {
00172     past_signals.erase( past_signals.begin(), past_signals.begin() + past_signals.size() - signal_window);
00173   }
00174 
00175   for ( unsigned int i = 0; i < past_signals.size(); i++) {
00176     if (signal_filt.size() != past_signals[i].size())
00177       continue;
00178     for (unsigned int j = 0; j < signal_filt.size(); j++)
00179       signal_filt[j] |= past_signals[i][j];
00180   }
00181 }
00182 
00183 
00184 void DockDrive::velocityCommands(const double &vx_, const double &wz_) {
00185   // vx: in m/s
00186   // wz: in rad/s
00187   vx = vx_;
00188   wz = wz_;
00189 }
00190 
00191 /****************************************************
00192  * @brief process bumper and charge event. If robot is charging, terminates auto dokcing process. If it bumps something, Set the next state as bumped and go backward
00193  *
00194  * @bumper - indicates whether bumper has pressed
00195  * @charger - indicates whether robot is charging
00196  *
00197  ****************************************************/
00198 void DockDrive::processBumpChargeEvent(const unsigned char& bumper, const unsigned char& charger) {
00199   RobotDockingState::State new_state;
00200   if(charger && bumper) {
00201     new_state = RobotDockingState::BUMPED_DOCK;
00202     setStateVel(new_state, -0.01, 0.0);
00203   }
00204   else if(charger) {
00205     if(dock_stabilizer++ == 0) {
00206       new_state = RobotDockingState::DOCKED_IN;
00207       setStateVel(new_state, 0.0, 0.0);
00208     }
00209     else if(dock_stabilizer > 20) {
00210       dock_stabilizer = 0;
00211       is_enabled = false;
00212       can_run = false;
00213       new_state = RobotDockingState::DONE;
00214       setStateVel(new_state, 0.0, 0.0);
00215     }
00216     else {
00217       new_state = RobotDockingState::DOCKED_IN;
00218       setStateVel(new_state, 0.0, 0.0);
00219     }
00220   }
00221   else if(bumper) {
00222     new_state = RobotDockingState::BUMPED;
00223     setStateVel(new_state, -0.05, 0.0);
00224     bump_remainder = 0;
00225   }
00226   state_str = ROBOT_STATE_STR[new_state];
00227 }
00228 
00229 /*************************
00230  * @breif processing. algorithms; transforma to velocity command
00231  *
00232  * @param dock_ir signal
00233  * @param bumper sensor
00234  * @param charger sensor
00235  * @param pose_update
00236  *
00237  *************************/
00238 void DockDrive::updateVelocity(const std::vector<unsigned char>& signal_filt, const ecl::LegacyPose2D<double>& pose_update, std::string& debug_str)
00239 {
00240   std::ostringstream oss;
00241   RobotDockingState::State current_state, new_state;
00242   double new_vx = 0.0;
00243   double new_wz = 0.0;
00244 
00245   // determine the current state based on ir and the previous state
00246   // common transition. idle -> scan -> find_stream -> get_stream -> scan -> aligned_far -> aligned_near -> docked_in -> done
00247 
00248   current_state = new_state = state;
00249   switch((unsigned int)current_state) {
00250     case RobotDockingState::IDLE:
00251       idle(new_state, new_vx, new_wz);
00252       break;
00253     case RobotDockingState::SCAN:
00254       scan(new_state, new_vx, new_wz, signal_filt, pose_update, debug_str);
00255       break;
00256     case RobotDockingState::FIND_STREAM:
00257       find_stream(new_state, new_vx, new_wz, signal_filt);
00258       break;
00259     case RobotDockingState::GET_STREAM:
00260       get_stream(new_state, new_vx, new_wz, signal_filt);
00261       break;
00262     case RobotDockingState::ALIGNED:
00263     case RobotDockingState::ALIGNED_FAR:
00264     case RobotDockingState::ALIGNED_NEAR:
00265       aligned(new_state, new_vx, new_wz, signal_filt, debug_str);
00266       break;
00267     case RobotDockingState::BUMPED:
00268       bumped(new_state, new_vx, new_wz, bump_remainder);
00269       break;
00270     default:
00271       oss << "Wrong state : " << current_state;
00272       debug_str = oss.str();
00273       break;
00274   }
00275 
00276   setStateVel(new_state, new_vx, new_wz);
00277   state_str = ROBOT_STATE_STR[new_state];
00278 }
00279 
00280 /*************************
00281  * @breif Check if any ir sees the given state signal from dock station
00282  *
00283  * @param filtered signal
00284  * @param dock ir state
00285  *
00286  * @ret true or false
00287  *************************/
00288 bool DockDrive::validateSignal(const std::vector<unsigned char>& signal_filt, const unsigned int state)
00289 {
00290   unsigned int i;
00291   for(i = 0; i < signal_filt.size(); i++)
00292   {
00293     if(signal_filt[i] & state)
00294       return true;
00295   }
00296   return false;
00297 }
00298 
00299 } // kobuki namespace


kobuki_dock_drive
Author(s): Younghun Ju
autogenerated on Thu Jun 6 2019 20:24:33