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
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045 #include "Robots/LoBot/control/LoLGMDExtricateEMD.H"
00046 #include "Robots/LoBot/control/LoMetrics.H"
00047 #include "Robots/LoBot/control/LoTurnArbiter.H"
00048 #include "Robots/LoBot/control/LoSpinArbiter.H"
00049 #include "Robots/LoBot/control/LoSpeedArbiter.H"
00050
00051 #include "Robots/LoBot/LoApp.H"
00052 #include "Robots/LoBot/slam/LoMap.H"
00053 #include "Robots/LoBot/config/LoConfigHelpers.H"
00054 #include "Robots/LoBot/thread/LoUpdateLock.H"
00055
00056 #include "Robots/LoBot/misc/LoExcept.H"
00057 #include "Robots/LoBot/misc/LoRegistry.H"
00058 #include "Robots/LoBot/misc/singleton.hh"
00059
00060 #include "Robots/LoBot/util/LoGL.H"
00061 #include "Robots/LoBot/util/LoMath.H"
00062
00063
00064 #ifdef INVT_HAVE_LIBGL
00065 #include <GL/gl.h>
00066 #endif
00067
00068
00069 #include <iomanip>
00070 #include <sstream>
00071 #include <algorithm>
00072 #include <memory>
00073
00074
00075
00076 namespace lobot {
00077
00078
00079
00080 namespace {
00081
00082
00083 template<typename T>
00084 inline T conf(const std::string& key, const T& default_value)
00085 {
00086 return get_conf<T>(LOBE_LGMD_EXTRICATE_EMD, key, default_value) ;
00087 }
00088
00089
00090
00091 class Params : public singleton<Params> {
00092
00093
00094
00095 float m_threshold ;
00096
00097
00098
00099
00100
00101 float m_extricate_speed ;
00102
00103
00104
00105
00106
00107
00108
00109
00110
00111 int m_extricate_pwm ;
00112
00113
00114
00115
00116
00117
00118
00119 bool m_spin_style_steering ;
00120
00121
00122
00123
00124
00125
00126
00127 int m_update_delay ;
00128
00129
00130
00131 Drawable::Geometry m_geometry ;
00132
00133
00134 Params() ;
00135
00136
00137 friend class singleton<Params> ;
00138
00139 public:
00140
00141
00142 static float threshold() {return instance().m_threshold ;}
00143 static float extricate_speed() {return instance().m_extricate_speed ;}
00144 static int extricate_pwm() {return instance().m_extricate_pwm ;}
00145 static bool spin_style_steering(){return instance().m_spin_style_steering;}
00146 static int update_delay() {return instance().m_update_delay ;}
00147 static Drawable::Geometry geometry() {return instance().m_geometry ;}
00148
00149 } ;
00150
00151
00152 Params::Params()
00153 : m_threshold(conf("threshold", 1000.0f)),
00154 m_extricate_speed(clamp(conf("extricate_speed", 0.15f), 0.1f, 0.75f)),
00155 m_extricate_pwm(clamp(conf("extricate_pwm", 25), 10, 50)),
00156 m_spin_style_steering(conf("spin_style_steering", false)),
00157 m_update_delay(clamp(conf("update_delay", 150), 1, 1000)),
00158 m_geometry(conf<std::string>("geometry", "0 0 10 10"))
00159 {}
00160
00161 }
00162
00163
00164
00165 LGMDExtricateEMD::LGMDExtricateEMD()
00166 : base(Params::update_delay(), LOBE_LGMD_EXTRICATE_EMD, Params::geometry())
00167 {
00168 start(LOBE_LGMD_EXTRICATE_EMD) ;
00169 }
00170
00171 void LGMDExtricateEMD::pre_run()
00172 {
00173 if (! App::robot())
00174 throw behavior_error(MOTOR_SYSTEM_MISSING) ;
00175
00176 UpdateLock::begin_read() ;
00177 const App::LocustModels& L = App::locusts() ;
00178 const int N = L.size() - 1 ;
00179 if (N < 1) {
00180 UpdateLock::end_read() ;
00181 throw behavior_error(NOT_ENOUGH_LOCUSTS) ;
00182 }
00183
00184 m_emds.reserve(N) ;
00185 for (int i = 0; i < N; ++i) {
00186 float direction = (L[i]->direction() + L[i + 1]->direction())/2.0f ;
00187 m_emds.push_back(new LMD(L[i], L[i + 1], direction)) ;
00188 }
00189 UpdateLock::end_read() ;
00190 }
00191
00192 LGMDExtricateEMD::Command::Command()
00193 : drive(0), turn(0)
00194 {}
00195
00196
00197
00198
00199
00200
00201
00202 void LGMDExtricateEMD::action()
00203 {
00204
00205
00206 UpdateLock::begin_read() ;
00207 const int N = m_emds.size() ;
00208 Vector emd ;
00209 for (int i = 0; i < N; ++i)
00210 emd += m_emds[i]->update() ;
00211 UpdateLock::end_read() ;
00212
00213
00214 Command C ;
00215 if (magnitude(emd) >= Params::threshold())
00216 {
00217 const int T = random(TurnArbiter::turn_step(), TurnArbiter::turn_max());
00218 int s = 0 ;
00219 switch (octant(direction(emd)))
00220 {
00221 case 1:
00222 C.drive = -1 ; C.turn = T ; s = -T ;
00223 break ;
00224 case 2:
00225 case 3:
00226 case 4:
00227 C.drive = 1 ; C.turn = -T ; s = -T ;
00228 break ;
00229 case 5:
00230 case 6:
00231 case 7:
00232 C.drive = 1 ; C.turn = T ; s = T ;
00233 break ;
00234 case 8:
00235 C.drive = -1 ; C.turn = -T ; s = T ;
00236 break ;
00237 default:
00238 throw misc_error(LOGIC_ERROR) ;
00239 }
00240
00241 if (Params::spin_style_steering())
00242 SpinArbiter::instance().vote(base::name, new SpinArbiter::Vote(s)) ;
00243 else
00244 {
00245 SpeedArbiter::instance().vote(base::name,
00246 new SpeedArbiter::Vote(C.drive * Params::extricate_speed(),
00247 C.drive * Params::extricate_pwm())) ;
00248 TurnArbiter::instance().vote(base::name,
00249 new TurnArbiter::Vote(turn_vote_centered_at(C.turn))) ;
00250 }
00251
00252 Metrics::Log log ;
00253 log << std::setw(Metrics::opw()) << std::left << base::name ;
00254 Map* M = App::map() ;
00255 if (M)
00256 log << M->current_pose() ;
00257 }
00258
00259
00260 viz_lock() ;
00261 m_emd_vector = emd ;
00262 m_cmd = C ;
00263 viz_unlock() ;
00264 }
00265
00266
00267
00268 #ifdef INVT_HAVE_LIBGL
00269
00270
00271
00272 static std::string mag(char label, const Vector& v)
00273 {
00274 using namespace std ;
00275
00276 std::ostringstream v_str ;
00277 v_str << label << ": " << fixed << setprecision(1) << magnitude(v) ;
00278 return v_str.str() ;
00279 }
00280
00281
00282 void LGMDExtricateEMD::render_me()
00283 {
00284
00285
00286 viz_lock() ;
00287 Command C = m_cmd ;
00288 Vector E = m_emd_vector ;
00289 viz_unlock() ;
00290
00291
00292
00293
00294 unit_view_volume() ;
00295 glColor3f(1, 1, 1) ;
00296 glBegin(GL_LINES) ;
00297 glVertex2i(0, -1) ;
00298 glVertex2i(0, 1) ;
00299 glVertex2i(-1, 0) ;
00300 glVertex2i( 1, 0) ;
00301 glEnd() ;
00302
00303 glPushAttrib(GL_LINE_BIT) ;
00304 glEnable(GL_LINE_STIPPLE) ;
00305 glLineStipple(1, 0x0F0F) ;
00306 glBegin(GL_LINES) ;
00307 glVertex2i(-1, +1) ;
00308 glVertex2i(+1, -1) ;
00309
00310 glVertex2i(+1, +1) ;
00311 glVertex2i(-1, -1) ;
00312 glEnd() ;
00313 glPopAttrib() ;
00314
00315
00316 if (C.drive == 0 && C.turn == 0)
00317 ;
00318 else
00319 {
00320 glColor3f(1, 0, 0) ;
00321 draw_vector(normalized(E)) ;
00322
00323 glColor3f(0, 1, 0) ;
00324 draw_vector(Vector(0.75f * C.drive * cos(C.turn), 0.75f * sin(C.turn))) ;
00325 }
00326
00327
00328
00329 restore_view_volume() ;
00330 text_view_volume() ;
00331 glColor3f(0, 1, 1) ;
00332 draw_label(3, 12, "LGMD Ext. EMD") ;
00333
00334 glColor3f(0.15f, 0.75f, 0.85f) ;
00335 draw_label(3, m_geometry.height - 4, mag('E', E).c_str()) ;
00336 restore_view_volume() ;
00337 }
00338
00339 #endif
00340
00341
00342
00343 LGMDExtricateEMD::~LGMDExtricateEMD()
00344 {
00345 purge_container(m_emds) ;
00346 }
00347
00348
00349
00350 }
00351
00352
00353
00354
00355