cost_learner.cpp
Go to the documentation of this file.
00001 #include <boost/algorithm/string/join.hpp>
00002 #include <boost/filesystem.hpp>
00003 #include <boost/foreach.hpp>
00004 #include <boost/lexical_cast.hpp>
00005 #include <fstream>
00006 #include <ros/ros.h>
00007 #include <stdexcept>
00008 #include <yaml-cpp/yaml.h>
00009 
00010 #include <bwi_planning/cost_learner.h>
00011 
00012 #ifdef HAVE_NEW_YAMLCPP
00013 namespace YAML {
00014   // The >> operator disappeared in yaml-cpp 0.5, so this function is
00015   // added to provide support for code written under the yaml-cpp 0.3 API.
00016   template<typename T>
00017   void operator >> (const YAML::Node& node, T& i)
00018   {
00019     i = node.as<T>();
00020   }
00021 }
00022 #endif
00023 
00024 namespace bwi_planning {
00025 
00026   CostLearner::CostLearner () {
00027 
00028     ros::NodeHandle nh, private_nh("~");
00029 
00030     std::vector<std::string> unavailable_parameters;
00031     std::string door_file;
00032     if (!(private_nh.getParam("door_file", door_file))) {
00033       unavailable_parameters.push_back("door_file");
00034     }
00035     if (!(private_nh.getParam("values_file", values_file_))) {
00036       unavailable_parameters.push_back("values_file");
00037     }
00038     if (!(private_nh.getParam("lua_file", lua_file_))) {
00039       unavailable_parameters.push_back("lua_file");
00040     }
00041     private_nh.param("alpha", alpha_, 0.5);
00042     private_nh.param("use_exponential_weighting", 
00043         use_exponential_weighting_, true);
00044 
00045     if (unavailable_parameters.size() != 0) {
00046       std::string message = "Following neccessary params not available: " +
00047         boost::algorithm::join(unavailable_parameters, ", ");
00048       ROS_INFO_STREAM(message);
00049       throw std::runtime_error(message);
00050     }
00051 
00052     readDoorFile(door_file, doors_);
00053     prepareInputData();
00054   }
00055 
00056   void CostLearner::prepareInputData() {
00057     // Compute Iteration number
00058     iteration_ = 1;
00059     while (boost::filesystem::exists(values_file_ + 
00060           boost::lexical_cast<std::string>(iteration_))) {
00061       ++iteration_;
00062     }
00063 
00064     ROS_INFO_STREAM("Starting at iteration #" << iteration_);
00065 
00066     if (iteration_ == 1) {
00067       // Input data has no meaning. Initialize optimistically
00068       for (int idx = 0; idx < doors_.size(); ++idx) {
00069         for (int j = 0; j < doors_.size(); ++j) {
00070           if (j == idx) {
00071             continue;
00072           }
00073           if (doors_[j].approach_names[0] == doors_[idx].approach_names[0]) {
00074             std::string loc = doors_[j].approach_names[0];
00075             distance_estimates_[loc][idx][j] = 1.0f;
00076             distance_samples_[loc][idx][j] = 0;
00077           }
00078           if (doors_[j].approach_names[0] == doors_[idx].approach_names[1]) {
00079             std::string loc = doors_[j].approach_names[0];
00080             distance_estimates_[loc][idx][j] = 1.0f;
00081             distance_samples_[loc][idx][j] = 0;
00082           }
00083           if (doors_[j].approach_names[1] == doors_[idx].approach_names[0]) {
00084             std::string loc = doors_[j].approach_names[1];
00085             distance_estimates_[loc][idx][j] = 1.0f;
00086             distance_samples_[loc][idx][j] = 0;
00087           }
00088           if (doors_[j].approach_names[1] == doors_[idx].approach_names[1]) {
00089             std::string loc = doors_[j].approach_names[1];
00090             distance_estimates_[loc][idx][j] = 1.0f;
00091             distance_samples_[loc][idx][j] = 0;
00092           }
00093         }
00094       }
00095       // Write the lua file as it won't be available so that it can be used
00096       // in this turn
00097       writeValuesFile(0);
00098     } else {
00099       readValuesFile(iteration_ - 1);
00100     }
00101     writeLuaFile();
00102   }
00103 
00104   void CostLearner::writeLuaFile(std::string lua_file) {
00105     if (lua_file.empty()) {
00106       lua_file = lua_file_;
00107     }
00108     std::ofstream fout(lua_file.c_str());
00109     fout << "#begin_lua" << std::endl << std::endl;
00110     fout << "loc_table={}" << std::endl;
00111     int count = 0;
00112     BOOST_FOREACH(SIIFPair const& kv, distance_estimates_) {
00113       fout << "loc_table[\"" << kv.first << "\"] = " << count << std::endl;
00114       count++;
00115     }
00116     fout << "door_table={}" << std::endl;
00117     for (unsigned int i = 0; i < doors_.size(); ++i) {
00118       fout << "door_table[\"" << doors_[i].name << "\"] = " << i << std::endl;
00119     }
00120     fout << "function dis(a,b,c)" << std::endl;
00121     fout << "\td1 = door_table[tostring(a)]" << std::endl;
00122     fout << "\td2 = door_table[tostring(b)]" << std::endl;
00123     fout << "\tif d1==d2 then return 1 end" << std::endl;
00124     fout << "\tloc = loc_table[tostring(c)]" << std::endl;
00125     count = 0;
00126     BOOST_FOREACH(SIIFPair const& kv, distance_estimates_) {
00127       fout << "\tif loc==" << count << " then" << std::endl;
00128       BOOST_FOREACH(IIFPair const& kv2, kv.second) {
00129         fout << "\t\tif d1==" << kv2.first << " then" << std::endl;
00130         BOOST_FOREACH(IFPair const& kv3, kv2.second) {
00131           fout << "\t\t\tif d2==" << kv3.first << " then return " << 
00132             lrint(kv3.second) << " end" << std::endl;
00133         }
00134         fout << "\t\tend" << std::endl;
00135       }
00136       fout << "\tend" << std::endl;
00137       count++;
00138     }
00139     fout << "\treturn 1" << std::endl;
00140     fout << "end" << std::endl << std::endl;
00141     fout << "#end_lua." << std::endl;
00142     fout.close();
00143   }
00144 
00145   void CostLearner::writeValuesFile(int episode) {
00146     if (episode == -1) {
00147       episode = iteration_;
00148     }
00149     std::string out_file_name = values_file_ + 
00150       boost::lexical_cast<std::string>(episode);
00151     std::ofstream fout(out_file_name.c_str());
00152     BOOST_FOREACH(SIIIPair const& kv, distance_samples_) {
00153       fout << " - name: " << kv.first << std::endl;
00154       fout << "   costs: " << std::endl;
00155       BOOST_FOREACH(IIIPair const& kv2, kv.second) {
00156         BOOST_FOREACH(IIPair const& kv3, kv2.second) {
00157           fout << "     - from: " << kv2.first << std::endl;
00158           fout << "       to: " << kv3.first << std::endl;
00159           fout << "       cost: " <<
00160             distance_estimates_[kv.first][kv2.first][kv3.first] << std::endl;
00161           fout << "       samples: " << kv3.second << std::endl;
00162         }
00163       }
00164     }
00165     fout.close();
00166     std::string lua_file_name = values_file_ + "_distances" +
00167       boost::lexical_cast<std::string>(episode) + ".lua";
00168     writeLuaFile(lua_file_name);
00169   }
00170 
00171   void CostLearner::readValuesFile(int episode) {
00172     if (episode == -1) {
00173       episode = iteration_;
00174     }
00175     std::string in_file_name = values_file_ + 
00176       boost::lexical_cast<std::string>(episode);
00177     std::ifstream fin(in_file_name.c_str());
00178 
00179     YAML::Node doc;
00180 #ifdef HAVE_NEW_YAMLCPP
00181     doc = YAML::Load(fin);
00182 #else
00183     YAML::Parser parser(fin);
00184     parser.GetNextDocument(doc);
00185 #endif
00186 
00187     for (size_t i = 0; i < doc.size(); ++i) {
00188       std::string loc;
00189       doc[i]["name"] >> loc;
00190       const YAML::Node &costs = doc[i]["costs"];
00191       for (size_t j = 0; j < costs.size(); ++j) {
00192         int from, to;
00193         costs[j]["from"] >> from;
00194         costs[j]["to"] >> to;
00195         costs[j]["cost"] >> distance_estimates_[loc][from][to];
00196         costs[j]["samples"] >> distance_samples_[loc][from][to];
00197       }
00198     }
00199   }
00200 
00201   bool CostLearner::addSample(const std::string& loc, int door_from, 
00202       int door_to, float cost) {
00203 
00204     if (door_from >= (int) doors_.size() || door_from < 0 ||
00205         door_to >= (int) doors_.size() || door_to < 0) {
00206       return false;
00207     }
00208 
00209     ROS_INFO_STREAM(std::string("Adding sample ") << 
00210         doors_[door_from].name << "->" <<
00211         doors_[door_to].name << ": " << cost);
00212     int samples = distance_samples_[loc][door_from][door_to];
00213     float old_cost = distance_estimates_[loc][door_from][door_to];
00214     float final_cost = 0;
00215     if (use_exponential_weighting_) {
00216       final_cost = (1.0f - alpha_) * old_cost + alpha_ * cost; 
00217     } else {
00218       if (samples != 0) {
00219         final_cost = (old_cost * samples + cost) / (samples + 1);
00220       } else {
00221         // First sample
00222         final_cost = cost;
00223       }
00224     }
00225     distance_estimates_[loc][door_from][door_to] = final_cost;
00226     distance_estimates_[loc][door_to][door_from] = final_cost;
00227     distance_samples_[loc][door_from][door_to] = samples + 1;
00228     distance_samples_[loc][door_to][door_from] = samples + 1;
00229   }
00230 
00231   bool CostLearner::addSample(const std::string& loc, 
00232       const std::string& door_from, const std::string& door_to, 
00233       float cost) {
00234 
00235     size_t door_from_idx = bwi_planning_common::resolveDoor(door_from, doors_);
00236     size_t door_to_idx = bwi_planning_common::resolveDoor(door_to, doors_);
00237 
00238     if (door_from_idx == bwi_planning_common::NO_DOOR_IDX || 
00239         door_to_idx == bwi_planning_common::NO_DOOR_IDX) {
00240       return false;
00241     }
00242 
00243     return addSample(loc, door_from_idx, door_to_idx, cost);
00244   }
00245 
00246   void CostLearner::finalizeEpisode() {
00247     writeLuaFile();
00248     writeValuesFile();
00249     ++iteration_;
00250     ROS_INFO_STREAM("Bumping cost learner to iteration #" << iteration_);
00251   }
00252 
00253 } /* bwi_planning */


bwi_planning
Author(s): Piyush Khandelwal , Fangkai Yang
autogenerated on Wed Aug 26 2015 10:54:52