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/LoTurnArbiter.H"
00046
00047 #include "Robots/LoBot/config/LoConfigHelpers.H"
00048 #include "Robots/LoBot/thread/LoUpdateLock.H"
00049
00050 #include "Robots/LoBot/misc/LoExcept.H"
00051 #include "Robots/LoBot/util/LoGL.H"
00052 #include "Robots/LoBot/util/LoDebug.H"
00053 #include "Robots/LoBot/util/LoSTL.H"
00054
00055
00056 #ifdef INVT_HAVE_LIBGL
00057 #include <GL/gl.h>
00058 #endif
00059
00060
00061 #include <algorithm>
00062 #include <functional>
00063 #include <iterator>
00064 #include <utility>
00065
00066
00067
00068 namespace lobot {
00069
00070
00071
00072
00073 template<typename T>
00074 static inline T conf(const std::string& key, const T& default_value)
00075 {
00076 return get_conf<T>("turn_arbiter", key, default_value) ;
00077 }
00078
00079
00080
00081 TurnArbiter::TurnArbiter()
00082 : Arbiter(clamp(conf("update_delay", 500), 1, 1000),
00083 "turn_arbiter", conf<std::string>("geometry", "480 420 140 140"))
00084 {
00085 start("turn_arbiter") ;
00086 }
00087
00088 float TurnArbiter::get_configured_priority(const std::string& behaviour) const
00089 {
00090 return abs(get_conf(behaviour, "turn_priority", 0.0f)) ;
00091 }
00092
00093
00094
00095
00096 static TurnArbiter::Vote operator*(TurnArbiter::Vote V, float weight)
00097 {
00098 std::transform(V.begin(), V.end(), V.begin(),
00099 std::bind2nd(std::multiplies<float>(), weight)) ;
00100 return V ;
00101 }
00102
00103
00104
00105
00106
00107
00108 void TurnArbiter::motor_cmd(const Arbiter::Votes& votes, Robot* robot)
00109 {
00110 Vote result ;
00111
00112
00113 Arbiter::Votes::const_iterator it = votes.begin() ;
00114 for (; it != votes.end(); ++it)
00115 result +=
00116 (*dynamic_cast<Vote*>((*it)->vote)) * priority((*it)->behavior_name) ;
00117
00118
00119
00120 typedef Vote::VoteMap::value_type DVP ;
00121 std::vector<DVP> V(result.m_votes.begin(), result.m_votes.end()) ;
00122
00123 const int N = V.size() ;
00124 const int W = clamp(Params::smoothing_width(), 1, N) ;
00125 const float S = 2 * Params::sigma() * Params::sigma() ;
00126 const float s = 1/(2.506628f * Params::sigma()) ;
00127
00128 for (int i = 0; i < N; ++i)
00129 {
00130 float v = 0 ;
00131 for (int j = i - W; j <= i + W; ++j) {
00132 if (j < 0 || j >= N)
00133 continue ;
00134 float d = V[j].first - V[i].first ;
00135 v += V[j].second * exp(-(d*d)/S) * s ;
00136 }
00137 result[V[i].first] = v ;
00138 }
00139
00140
00141 result.normalize() ;
00142
00143
00144 viz_lock() ;
00145 m_vote = result ;
00146
00147 viz_unlock() ;
00148
00149
00150 Vote::iterator max = std::max_element(result.begin(), result.end()) ;
00151
00152
00153 UpdateLock::begin_write() ;
00154 robot->turn(max.direction()) ;
00155 UpdateLock::end_write() ;
00156 }
00157
00158
00159
00160
00161 TurnArbiter::Vote::Vote()
00162 {
00163 const int M = turn_max() ;
00164 const int S = turn_step() ;
00165 m_votes[0] = 0 ;
00166 for (int direction = +S; direction <= +M; direction += S)
00167 m_votes[direction] = 0 ;
00168 for (int direction = -S; direction >= -M; direction -= S)
00169 m_votes[direction] = 0 ;
00170 }
00171
00172
00173 std::vector<int> TurnArbiter::Vote::get_directions() const
00174 {
00175 std::vector<int> V ;
00176 V.reserve(m_votes.size()) ;
00177 std::transform(m_votes.begin(), m_votes.end(), std::back_inserter(V),
00178 get_first<VoteMap::value_type>) ;
00179 return V ;
00180 }
00181
00182 class abs_diff {
00183 int direction ;
00184 public:
00185 abs_diff(int d) : direction(d) {}
00186 bool operator()(const std::pair<int, float>& a,
00187 const std::pair<int, float>& b) const {
00188 return abs(a.first - direction) < abs(b.first - direction) ;
00189 }
00190 } ;
00191
00192
00193
00194 TurnArbiter::Vote::VoteMap::mapped_type&
00195 TurnArbiter::Vote::
00196 operator[](int direction)
00197 {
00198 VoteMap::iterator it = m_votes.find(direction) ;
00199 if (it == m_votes.end())
00200
00201 it = std::min_element(m_votes.begin(), m_votes.end(),
00202 abs_diff(direction)) ;
00203 return it->second ;
00204 }
00205
00206
00207 TurnArbiter::Vote::~Vote(){}
00208
00209
00210 TurnArbiter::Vote::iterator::iterator(const TurnArbiter::Vote& V)
00211 : m_vote(const_cast<TurnArbiter::Vote&>(V)),
00212 m_iterator(m_vote.m_votes.begin())
00213 {}
00214
00215
00216 TurnArbiter::Vote::iterator::iterator(const TurnArbiter::Vote& V, bool)
00217 : m_vote(const_cast<TurnArbiter::Vote&>(V)),
00218 m_iterator(m_vote.m_votes.end())
00219 {}
00220
00221
00222 TurnArbiter::Vote::iterator::iterator(const TurnArbiter::Vote::iterator& it)
00223 : m_vote(it.m_vote),
00224 m_iterator(it.m_iterator)
00225 {}
00226
00227
00228 TurnArbiter::Vote::iterator&
00229 TurnArbiter::Vote::iterator::operator=(const TurnArbiter::Vote::iterator& it)
00230 {
00231 if (& it != this) {
00232 m_vote = it.m_vote ;
00233 m_iterator = it.m_iterator ;
00234 }
00235 return *this ;
00236 }
00237
00238
00239 TurnArbiter::Vote::iterator::~iterator(){}
00240
00241
00242 TurnArbiter::Vote& TurnArbiter::Vote::operator+=(const TurnArbiter::Vote& V)
00243 {
00244 std::transform(V.begin(), V.end(), begin(), begin(), std::plus<float>()) ;
00245 return *this ;
00246 }
00247
00248
00249
00250
00251
00252
00253
00254
00255
00256
00257
00258
00259
00260
00261
00262
00263
00264
00265
00266
00267
00268
00269
00270 class scale_vote {
00271 float min, max ;
00272 public:
00273 scale_vote(float m, float M) : min(m), max(M) {}
00274 float operator()(const float& v) const {
00275 return 2 * (v - min)/(max - min) - 1 ;
00276 }
00277 } ;
00278
00279
00280
00281 void TurnArbiter::Vote::normalize()
00282 {
00283 float min = *std::min_element(begin(), end()) ;
00284 float max = *std::max_element(begin(), end()) ;
00285 normalize(min, max) ;
00286 }
00287
00288
00289
00290 void TurnArbiter::Vote::normalize(float min, float max)
00291 {
00292 std::transform(begin(), end(), begin(), scale_vote(min, max)) ;
00293 }
00294
00295
00296 void TurnArbiter::Vote::dump(const std::string& caller) const
00297 {
00298 lobot::dump(m_votes, caller, "m_votes") ;
00299 }
00300
00301
00302
00303
00304
00305
00306
00307
00308
00309
00310
00311
00312
00313
00314
00315
00316
00317
00318
00319
00320
00321
00322
00323
00324
00325
00326
00327
00328
00329
00330
00331
00332
00333
00334
00335
00336
00337
00338
00339
00340
00341
00342
00343
00344
00345
00346
00347
00348
00349
00350
00351
00352
00353
00354
00355
00356
00357
00358
00359
00360
00361
00362
00363
00364 TurnArbiter::Vote turn_vote_centered_at(float C)
00365 {
00366 const int T = TurnArbiter::turn_max() ;
00367
00368 TurnArbiter::Vote V ;
00369 TurnArbiter::Vote::iterator it = V.begin() ;
00370 for (; it != V.end(); ++it)
00371 *it = clamp(1 - abs(it.direction() - C)/T, -1.0f, +1.0f) ;
00372 return V ;
00373 }
00374
00375
00376
00377 #ifdef INVT_HAVE_LIBGL
00378
00379 void TurnArbiter::render_me()
00380 {
00381
00382
00383 viz_lock() ;
00384 Vote V = m_vote ;
00385 viz_unlock() ;
00386
00387
00388 unit_view_volume() ;
00389 glBegin(GL_LINES) ;
00390 for (Vote::iterator it = V.begin(); it; ++it)
00391 {
00392 float vote = it.value() ;
00393 float direction = it.direction() ;
00394 if (vote < 0)
00395 {
00396 glColor3f(1, 0, 0) ;
00397 glVertex2i(0, 0) ;
00398 glVertex2f(-vote * cos(direction), -vote * sin(direction)) ;
00399 }
00400 else if (vote > 0)
00401 {
00402 glColor3f(0, 1, 0) ;
00403 glVertex2i(0, 0) ;
00404 glVertex2f(vote * cos(direction), vote * sin(direction)) ;
00405 }
00406 }
00407
00408 Vote::iterator max = std::max_element(V.begin(), V.end()) ;
00409 if (max.value() > 0)
00410 {
00411 glColor3f(1, 1, 1) ;
00412 glLineWidth(2) ;
00413 glVertex2i(0, 0) ;
00414 glVertex2f(cos(max.direction()), sin(max.direction())) ;
00415 }
00416 glEnd() ;
00417
00418
00419
00420 restore_view_volume() ;
00421 text_view_volume() ;
00422 glColor3f(0, 1, 1) ;
00423 draw_label(3, 12, "Turn Arbiter") ;
00424
00425 restore_view_volume() ;
00426 }
00427
00428 #endif
00429
00430
00431
00432 TurnArbiter::~TurnArbiter(){}
00433
00434
00435
00436
00437 TurnArbiter::Params::Params()
00438 : m_turn_max (clamp(conf("turn_max", 20), 5, 60)),
00439 m_turn_step(clamp(conf("turn_step", 1), 1, m_turn_max/2)),
00440 m_smoothing_width(conf("smoothing_window_width", 7)),
00441 m_sigma(clamp(conf("smoothing_sigma", 1.0f), 0.5f, m_turn_max/2.0f))
00442 {}
00443
00444
00445 TurnArbiter::Params::~Params(){}
00446
00447
00448
00449 }
00450
00451
00452
00453
00454