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/io/LoDangerZone.H"
00046
00047 #include "Robots/LoBot/config/LoConfigHelpers.H"
00048
00049 #include "Robots/LoBot/misc/LoExcept.H"
00050 #include "Robots/LoBot/util/LoString.H"
00051 #include "Robots/LoBot/util/LoMath.H"
00052
00053
00054 #include "Util/log.H"
00055
00056
00057 #include <sstream>
00058 #include <algorithm>
00059
00060
00061
00062 namespace lobot {
00063
00064
00065
00066
00067 template<typename T>
00068 static inline T conf(const std::string& key, const T& default_value)
00069 {
00070 return get_conf<T>("danger_zone", key, default_value) ;
00071 }
00072
00073
00074
00075
00076 static inline int sanify_dzone(int z, const range<int>& D)
00077 {
00078 return (z <= 0) ? -1 : clamp(z, D) ;
00079 }
00080
00081
00082 static bool dzone_cmp(const DangerZone::Block& a, const DangerZone::Block& b)
00083 {
00084 return a.danger_zone() < b.danger_zone() ;
00085 }
00086
00087
00088
00089 const LaserRangeFinder* DangerZone::m_lrf ;
00090
00091
00092
00093 DangerZone::DangerZone()
00094 : m_max(0), m_lrf_data(0)
00095 {
00096
00097 if (! m_lrf)
00098 throw misc_error(DANGER_ZONE_LRF_NOT_SETUP) ;
00099
00100 const range<int> A = m_lrf->get_angular_range() ;
00101 const range<int> D = m_lrf->get_distance_range() ;
00102
00103
00104 std::vector<int> B(string_to_vector<int>(
00105 conf<std::string>("angular_blocks", to_string(A)))) ;
00106 int N = B.size() ;
00107 if (N < 2) {
00108 B.clear() ;
00109 B.push_back(A.min()) ;
00110 B.push_back(A.max()) ;
00111 N = 2 ;
00112 }
00113
00114
00115 std::vector<int> Z(string_to_vector<int>(
00116 conf<std::string>("danger_zones", dup_string(" 350", N - 1)))) ;
00117
00118
00119 std::vector<int> T(string_to_vector<int>(
00120 conf<std::string>("thresholds", dup_string(" 10", N - 1)))) ;
00121
00122
00123 m_blocks.reserve(N - 1) ;
00124 for (int i = 0, j = 1; j < N - 1; ++i, ++j)
00125 if (A.in(B[i]) && A.in(B[j]))
00126 m_blocks.push_back(Block(B[i], B[j] - 1,
00127 sanify_dzone(Z[i], D), T[i])) ;
00128
00129 int penultimate_start = clamp(B[N - 2], A.min(), A.max() - 1) ;
00130 m_blocks.push_back(Block(penultimate_start,
00131 clamp(B[N - 1], penultimate_start + 1, A.max()),
00132 sanify_dzone(Z[N - 2], D),
00133 T[N - 2])) ;
00134
00135
00136 Blocks::const_iterator max =
00137 std::max_element(m_blocks.begin(), m_blocks.end(), dzone_cmp) ;
00138 m_max = max->danger_zone() ;
00139 }
00140
00141
00142 DangerZone::Block::Block(const range<int>& x, int z, int t)
00143 : m_extents(x),
00144 m_danger_zone(z),
00145 m_threshold(clamp(t, 0, m_extents.size()))
00146 {
00147 m_danger_zone_readings.reserve(m_extents.size()) ;
00148 }
00149
00150 DangerZone::Block::Block(int start, int end, int z, int t)
00151 : m_extents(start, end),
00152 m_danger_zone(z),
00153 m_threshold(clamp(t, 0, m_extents.size()))
00154 {
00155 m_danger_zone_readings.reserve(m_extents.size()) ;
00156 }
00157
00158
00159
00160 DangerZone::Block::update::update(const LRFData& d)
00161 : lrf(d)
00162 {}
00163
00164 void DangerZone::Block::update::operator()(const DangerZone::Block& B) const
00165 {
00166 Block& block = const_cast<Block&>(B) ;
00167
00168 block.clear() ;
00169 for (int angle = block.start(); angle <= block.end(); ++angle)
00170 {
00171 int distance = lrf[angle] ;
00172 if (distance < 0)
00173 continue ;
00174 if (distance <= block.danger_zone())
00175 block.add(Reading(angle, distance)) ;
00176 }
00177
00178 }
00179
00180 void DangerZone::update()
00181 {
00182 DangerZone& Z = instance() ;
00183
00184 delete Z.m_lrf_data ;
00185 Z.m_lrf_data = new LRFData(m_lrf) ;
00186 std::for_each(Z.m_blocks.begin(), Z.m_blocks.end(),
00187 Block::update(*Z.m_lrf_data));
00188 }
00189
00190
00191
00192 bool DangerZone::penetrated()
00193 {
00194 const DangerZone& Z = instance() ;
00195 const int N = Z.m_blocks.size() ;
00196 for (int i = 0; i < N; ++i)
00197 if (Z.m_blocks[i].penetrated())
00198 return true ;
00199 return false ;
00200 }
00201
00202
00203
00204 DangerZone::~DangerZone()
00205 {
00206 delete m_lrf_data ;
00207 }
00208
00209
00210
00211 void DangerZone::Block::dump(const std::string& caller) const
00212 {
00213 std::ostringstream str ;
00214
00215 str << "from " << caller << '\n' ;
00216
00217 str << "\n\tExtents: [" << m_extents.min() << ' '
00218 << m_extents.max() << "]" ;
00219 str << "\tDanger Zone: " << m_danger_zone ;
00220 str << "\tThreshold: " << m_threshold ;
00221
00222 str << "\n\tDanger zone readings: " ;
00223 const Readings& R = m_danger_zone_readings ;
00224 for (Readings::const_iterator it = R.begin(); it != R.end(); ++it)
00225 str << '(' << it->angle() << ' ' << it->distance() << ") " ;
00226 str << '\n' ;
00227
00228 LERROR("%s", str.str().c_str()) ;
00229 }
00230
00231
00232
00233 }
00234
00235
00236
00237
00238