00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00034
00035
00036
00037
00038 #include "kobuki_dock_drive/dock_drive.hpp"
00039
00040
00041
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
00051
00052
00053 namespace kobuki {
00054
00055
00056
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
00099 pose_priv = pose;
00100
00101 ecl::linear_algebra::Vector3d pose_update_rates;
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
00124
00125
00126
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
00142
00143 std::ostringstream debug_stream;
00144
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
00152
00153
00154
00155
00156
00157
00158
00159 std::string far_signal = "[F: ";
00160 std::string near_signal = "[N: ";
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
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
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
00198
00199
00200 debug_str = "";
00201 do {
00202 if ( state==DONE ) setState(IDLE);
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; }
00214 else { setStateVel(BUMPED_DOCK, -0.01, 0.0); break; }
00215 } else if (state == BUMPED) {
00216 setState(IDLE);
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 ) {
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 ) {
00279
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 ) {
00286
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) {
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) {
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
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
00325 debug_output = debug_stream.str();
00326
00327
00328
00329 velocityCommands(vx, wz);
00330
00331 return;
00332 }
00333
00334 void DockDrive::velocityCommands(const double &vx_, const double &wz_) {
00335
00336
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 }