00001 #include <face_contour_detector/AutoParameterExplorer.h>
00002 #include <algorithm>
00003 #include <queue>
00004 #include <deque>
00005 #include <limits>
00006 #include <sstream>
00007 #include <ros/assert.h>
00008
00009 namespace face_contour_detector {
00010
00011 AutoParameterExplorer::AutoParameterExplorer(boost::function<void (const std::vector<double>&, std::map<std::string, double>&)> paramsFunction, boost::function<double (const std::map<std::string, double>&, const std::map<std::string, double>&)> costsFunction) : m_paramsFunction(paramsFunction), m_costsFunction(costsFunction) {}
00012 AutoParameterExplorer::~AutoParameterExplorer() {}
00013
00014 void AutoParameterExplorer::AddParameter(const std::string& name, double min, double max) {
00015 ROS_ASSERT(min < max);
00016
00017 m_paramNames.push_back(name);
00018 m_startEnd.push_back(std::pair<double,double>(min, max));
00019 }
00020
00021 void AutoParameterExplorer::FindBest(std::map<std::string, double> targetValue, int steps, int numResults, std::vector<std::map<std::string, double> >& results) {
00022
00023
00024
00025 ParameterPoint base;
00026 {
00027 std::vector<std::pair<double,double> >::iterator it;
00028 for (it = m_startEnd.begin(); it != m_startEnd.end(); it++) {
00029 base.AddParam(it->first);
00030 }
00031 }
00032 Area a(base);
00033 {
00034 std::vector<std::pair<double,double> >::iterator it;
00035 for (it = m_startEnd.begin(); it != m_startEnd.end(); it++) {
00036 a.AddDimension(it->second - it->first);
00037 }
00038 }
00039
00040 if (!M_IsTargetValueInside(targetValue, a)) {
00041 ROS_ERROR("The main parameter area does not contain the target values");
00042 return;
00043 }
00044
00045
00046 M_GetCosts(targetValue, a);
00047
00048
00049 std::priority_queue<Area, std::vector<Area>, Area::GreaterCosts> activeQueue;
00050 activeQueue.push(a);
00051
00052
00053 std::priority_queue<Area, std::vector<Area>, Area::GreaterCosts> inactiveQueue;
00054
00055
00056 for (int i = 0; i < steps; i++) {
00057
00058 ROS_INFO("step %i", i);
00059 Area currArea = activeQueue.top();
00060 activeQueue.pop();
00062 std::stringstream strS;
00063 strS<<currArea;
00064 ROS_INFO("%s", strS.str().c_str());
00065 std::vector<Area> subAreas;
00066 currArea.SubAreas(subAreas);
00067 std::vector<Area>::iterator subIt;
00068 bool foundGoodSubArea = false;
00069 for (subIt = subAreas.begin(); subIt != subAreas.end(); subIt++) {
00070 if (M_IsTargetValueInside(targetValue, *subIt)) {
00071 foundGoodSubArea = true;
00072 M_GetCosts(targetValue, *subIt);
00073
00074
00075
00076
00077 activeQueue.push(*subIt);
00078 }
00079 }
00080 if (!foundGoodSubArea) {
00081 inactiveQueue.push(currArea);
00082 }
00083 }
00084
00085
00086 face_contour_detector::LimitedPriorityQueueSet<ParameterPoint, ParameterPoint::LessCosts> resultPoints(numResults);
00087 while (resultPoints.Size() < numResults) {
00088 if (activeQueue.empty() && inactiveQueue.empty()) {
00089 break;
00090 }
00091 if (activeQueue.empty()) {
00092 Area top = inactiveQueue.top();
00093 M_PushAllPoints(top, targetValue, resultPoints);
00094 inactiveQueue.pop();
00095 } else if (inactiveQueue.empty()) {
00096 Area top = activeQueue.top();
00097 M_PushAllPoints(top, targetValue, resultPoints);
00098 activeQueue.pop();
00099 } else {
00100 Area activeTop = activeQueue.top();
00101 Area inactiveTop = inactiveQueue.top();
00102 if (activeTop.Costs() > inactiveTop.Costs()) {
00103 M_PushAllPoints(inactiveTop, targetValue, resultPoints);
00104 inactiveQueue.pop();
00105 } else {
00106 M_PushAllPoints(activeTop, targetValue, resultPoints);
00107 activeQueue.pop();
00108 }
00109 }
00110
00111 }
00112
00113
00114 for (int i = 0; i < numResults && !resultPoints.Empty(); i++) {
00115 ParameterPoint currP = resultPoints.PopFront();
00116
00117 std::map<std::string, double> currResult;
00118 std::vector<double> params = currP.Params();
00119 std::vector<std::string>::iterator nameIt = m_paramNames.begin();
00120 std::vector<double>::iterator valueIt = params.begin();
00121
00122 while (valueIt != params.end()) {
00123 currResult[*nameIt] = *valueIt;
00124 nameIt++;
00125 valueIt++;
00126 }
00127 results.push_back(currResult);
00128 }
00129
00130 }
00131
00132 void AutoParameterExplorer::M_GetCosts(std::map<std::string, double>& targetValue, ParameterPoint& paramPoint) {
00133
00134
00135
00136
00137
00138
00139
00140
00141
00142
00143
00144
00145
00146
00147
00148
00149
00150
00151 std::map<std::string, double> results;
00152 m_paramsFunction(paramPoint.Params(), results);
00153 paramPoint.Costs(m_costsFunction(results, targetValue));
00154 ROS_ASSERT(paramPoint.HasCosts());
00155
00156 }
00157
00158 void AutoParameterExplorer::M_GetCosts(std::map<std::string, double>& targetValue, Area& area) {
00160
00161
00162
00163
00164
00165 face_contour_detector::LimitedPriorityQueueSet<ParameterPoint, ParameterPoint::LessCosts> queue = face_contour_detector::LimitedPriorityQueueSet<ParameterPoint, ParameterPoint::LessCosts>(1);
00166
00167 M_PushAllPoints(area, targetValue, queue);
00168
00169 area.Costs(queue.Front().Costs());
00170
00171
00172
00173
00174
00175
00176
00177
00178
00179
00180 }
00181
00182 bool AutoParameterExplorer::M_IsTargetValueInside(std::map<std::string, double>& targetValue, Area& area) {
00183
00184
00185 std::map<std::string, bool> foundMin;
00186 std::map<std::string, bool> foundMax;
00187
00188 {
00189 std::map<std::string, double>::iterator it;
00190 for (it = targetValue.begin(); it != targetValue.end(); it++) {
00191 foundMin[it->first] = false;
00192 foundMax[it->first] = false;
00193 }
00194 }
00195
00196
00197 std::vector<ParameterPoint> edges;
00198 area.EdgePoints(edges);
00199 std::vector<ParameterPoint>::iterator edgeIt;
00200 for (edgeIt = edges.begin(); edgeIt != edges.end(); edgeIt++) {
00201
00202 std::map<std::string, double> result;
00203 m_paramsFunction(edgeIt->Params(), result);
00204
00205
00206 std::map<std::string, double>::iterator reIt;
00207 for (reIt = result.begin(); reIt != result.end(); reIt++) {
00208 if (reIt->second < targetValue[reIt->first]) {
00209 foundMin[reIt->first] = true;
00210 } else if (reIt->second > targetValue[reIt->first]) {
00211 foundMax[reIt->first] = true;
00212 } else if (reIt->second == targetValue[reIt->first]) {
00213 foundMax[reIt->first] = true;
00214 foundMin[reIt->first] = true;
00215 }
00216 }
00217 }
00218
00219
00220 std::map<std::string, bool>::iterator minIt;
00221 for (minIt = foundMin.begin(); minIt != foundMin.end(); minIt++) {
00222 if (!(minIt->second)) return false;
00223 }
00224
00225 std::map<std::string, bool>::iterator maxIt;
00226 for (maxIt = foundMax.begin(); maxIt != foundMax.end(); maxIt++) {
00227 if (!(maxIt->second)) return false;
00228 }
00229 return true;
00230
00231 }
00232
00233 void AutoParameterExplorer::M_PushAllPoints(Area& area, std::map<std::string, double>& targetValues, face_contour_detector::LimitedPriorityQueueSet<AutoParameterExplorer::ParameterPoint, AutoParameterExplorer::ParameterPoint::LessCosts>& results) {
00234 std::vector<ParameterPoint> points;
00235 area.EdgePoints(points);
00236 points.push_back(area.Middle());
00237 std::vector<ParameterPoint>::iterator it;
00238 for (it = points.begin(); it != points.end(); it++) {
00239 M_GetCosts(targetValues, *it);
00240 results.Push(*it);
00241 }
00242 }
00243
00244
00245
00246 AutoParameterExplorer::ParameterPoint::ParameterPoint() : m_costsSet(false) {}
00247
00248 AutoParameterExplorer::ParameterPoint::ParameterPoint(const ParameterPoint& other) : m_params(other.m_params), m_costsSet(other.m_costsSet), m_costs(other.m_costs) {}
00249
00250 void AutoParameterExplorer::ParameterPoint::AddParam(double value) {
00251 m_params.push_back(value);
00252 }
00253
00254 AutoParameterExplorer::ParameterPoint AutoParameterExplorer::ParameterPoint::Midpoint(ParameterPoint& other) {
00255 ROS_ASSERT(m_params.size() == other.m_params.size());
00256 ParameterPoint re;
00257 std::vector<double>::iterator itThis = m_params.begin();
00258 std::vector<double>::iterator itOther = other.m_params.begin();
00259 while (itThis != m_params.end()) {
00260
00261 re.AddParam( (((*itOther) - (*itThis))/2.0) +(*itThis) );
00262
00263 itThis++;
00264 itOther++;
00265 }
00266 }
00267
00268 AutoParameterExplorer::Vector AutoParameterExplorer::ParameterPoint::VectorTo(const AutoParameterExplorer::ParameterPoint& other) {
00269
00270 Vector v;
00271
00272 std::vector<double>::const_iterator thisIt = m_params.begin();
00273 std::vector<double>::const_iterator otherIt = other.m_params.begin();
00274
00275 while (thisIt != m_params.end()) {
00276
00277 v.AddParam((*otherIt) - (*thisIt));
00278
00279 thisIt++;
00280 otherIt++;
00281 }
00282 ROS_ASSERT(thisIt == m_params.end());
00283 ROS_ASSERT(otherIt == other.m_params.end());
00284
00285 return v;
00286 }
00287
00288 AutoParameterExplorer::ParameterPoint AutoParameterExplorer::ParameterPoint::operator+ (const AutoParameterExplorer::Vector& vector) {
00289
00290 ParameterPoint p;
00291
00292 std::vector<double>::const_iterator thisIt = m_params.begin();
00293 std::vector<double>::const_iterator otherIt = vector.values.begin();
00294
00295 while (thisIt != m_params.end()) {
00296
00297 p.AddParam((*otherIt) + (*thisIt));
00298
00299 thisIt++;
00300 otherIt++;
00301 }
00302 ROS_ASSERT(thisIt == m_params.end());
00303 ROS_ASSERT(otherIt == vector.values.end());
00304
00305 return p;
00306
00307 }
00308
00309
00310 AutoParameterExplorer::Vector::Vector() {}
00311
00312 AutoParameterExplorer::Vector::Vector(const Vector& other) : values(other.values) { }
00313
00314 void AutoParameterExplorer::Vector::AddParam(double value) { values.push_back(value); }
00315
00316 AutoParameterExplorer::Vector AutoParameterExplorer::Vector::operator+(const AutoParameterExplorer::Vector& other) {
00317 Vector v;
00318
00319 std::vector<double>::const_iterator thisIt = values.begin();
00320 std::vector<double>::const_iterator otherIt = other.values.begin();
00321
00322 while (thisIt != values.end()) {
00323
00324 v.AddParam((*otherIt) + (*thisIt));
00325
00326 thisIt++;
00327 otherIt++;
00328 }
00329 ROS_ASSERT(thisIt == values.end());
00330 ROS_ASSERT(otherIt == other.values.end());
00331
00332 return v;
00333 }
00334
00335 AutoParameterExplorer::Vector AutoParameterExplorer::Vector::operator*(double factor) {
00336 Vector v;
00337 std::vector<double>::const_iterator thisIt;
00338 for (thisIt = values.begin(); thisIt != values.end(); thisIt++) {
00339 v.AddParam((*thisIt) * factor);
00340 }
00341 return v;
00342 }
00343
00344
00345
00346 AutoParameterExplorer::Area::Area(const AutoParameterExplorer::ParameterPoint& base) : base(base), m_hasCosts(false) {
00347
00348 }
00349 void AutoParameterExplorer::Area::AddDimension(double value) {
00350 dimensions.push_back(value);
00351 }
00352
00353 AutoParameterExplorer::ParameterPoint AutoParameterExplorer::Area::Middle() {
00354 ROS_ASSERT(dimensions.size() > 0);
00355
00356 ParameterPoint p;
00357 std::vector<double>::iterator it;
00358 Vector sumVector;
00359
00360 for (it = dimensions.begin(); it != dimensions.end(); it++) {
00361 sumVector.AddParam((*it) * 0.5);
00362 }
00363 return base + sumVector;
00364
00365 }
00366
00367 void AutoParameterExplorer::Area::SubAreas(std::vector<AutoParameterExplorer::Area>& re) {
00368 ROS_ASSERT(dimensions.size() > 0);
00369
00370
00371 for (unsigned int i = 0; i < M_UIntPower2(dimensions.size()); i++) {
00372
00373 ParameterPoint subbase;
00374
00375 std::vector<double>::iterator dimIt;
00376 int dim = 0;
00377 for (dimIt = dimensions.begin(); dimIt != dimensions.end(); dimIt++) {
00378 ROS_ASSERT(dim < 30);
00379 if ((i) & (1<<(dim))) {
00380 subbase.Params().push_back(base.Params().at(dim) + dimensions.at(dim)/2.0);
00381 } else {
00382 subbase.Params().push_back(base.Params().at(dim));
00383 }
00384 dim++;
00385 }
00386
00387 Area subArea(subbase);
00388 for (dimIt = dimensions.begin(); dimIt != dimensions.end(); dimIt++) {
00389 subArea.AddDimension((*dimIt)/2.0);
00390 }
00391 re.push_back(subArea);
00392 }
00393
00394 }
00395
00396 void AutoParameterExplorer::Area::EdgePoints(std::vector<AutoParameterExplorer::ParameterPoint>& re) {
00397 ROS_ASSERT(dimensions.size() > 0);
00398
00399 for (unsigned int i = 0; i < M_UIntPower2(dimensions.size()); i++) {
00400
00401 ParameterPoint edge;
00402
00403 std::vector<double>::iterator dimIt;
00404 int dim = 0;
00405 for (dimIt = dimensions.begin(); dimIt != dimensions.end(); dimIt++) {
00406 ROS_ASSERT(dim < 30);
00407 if ((i) & (1<<(dim))) {
00408 edge.Params().push_back(base.Params().at(dim) + dimensions.at(dim));
00409 } else {
00410 edge.Params().push_back(base.Params().at(dim));
00411 }
00412 dim++;
00413 }
00414 re.push_back(edge);
00415 }
00416
00417 }
00418
00419 bool AutoParameterExplorer::Area::HasCosts() const {
00420 return m_hasCosts;
00421 }
00422
00423 void AutoParameterExplorer::Area::Costs(double costs) {
00424 m_hasCosts = true;
00425 m_costs = costs;
00426 }
00427
00428 double AutoParameterExplorer::Area::Costs() const {
00429 ROS_ASSERT(m_hasCosts);
00430 return m_costs;
00431 }
00432
00433 bool AutoParameterExplorer::Area::GreaterCosts::operator() (const Area& x, const Area& y) const {
00434 return x.Costs()>y.Costs();
00435 }
00436
00437 }
00438