fixes #241

initialize pedestrians from file.
See changelog for options and restrictions
parent 5926052e
......@@ -73,7 +73,7 @@ bool PedDistributionParser::LoadPedDistribution(vector<std::shared_ptr<StartDist
double premovement_sigma = xmltof(e->Attribute("pre_movement_sigma"), 0);
//double risk_tolerance_mean = xmltof(e->Attribute("risk_tolerance_mean"), 0);
//double risk_tolerance_sigma = xmltof(e->Attribute("risk_tolerance_sigma"), 0);
string positions_dir = xmltoa(e->Attribute("positions_dir"), "");
double x_min = xmltof(e->Attribute("x_min"), -FLT_MAX);
double x_max = xmltof(e->Attribute("x_max"), FLT_MAX);
double y_min = xmltof(e->Attribute("y_min"), -FLT_MAX);
......@@ -102,7 +102,12 @@ bool PedDistributionParser::LoadPedDistribution(vector<std::shared_ptr<StartDist
dis->SetHeight(height);
dis->SetPatience(patience);
dis->InitPremovementTime(premovement_mean, premovement_sigma);
dis->SetPositionsDir(positions_dir);
if (dis->GetPositionsDir().length())
{
Log->Write("INFO:\tPositions_dir = <%s>\n", dis->GetPositionsDir().c_str());
}
if (e->Attribute("risk_tolerance_mean") && e->Attribute("risk_tolerance_sigma")) {
std::string distribution_type = "normal";
double risk_tolerance_mean = xmltof(e->Attribute("risk_tolerance_mean"), NAN);
......
......@@ -100,7 +100,7 @@ Building::Building(const Configuration* configuration, PedDistributor& pedDistri
if (!pedDistributor.Distribute(this)) {
Log->Write("ERROR:\t could not distribute the pedestrians");
Log->Write("ERROR:\tcould not distribute the pedestrians\n");
exit(EXIT_FAILURE);
}
......
......@@ -6,7 +6,7 @@
<!-- seed used for initialising random generator -->
<seed>12542</seed>
<max_sim_time >10</max_sim_time>
<max_sim_time >40</max_sim_time>
<!-- geometry file -->
<geometry>1.2_bottleneck.xml</geometry>
<!-- traectories file and format -->
......@@ -14,7 +14,7 @@
<file location="trajectories.xml" />
</trajectories>
<!-- where to store the logs -->
<logfile>log</logfile>
<!-- <logfile>log</logfile> -->
<num_threads>10</num_threads>
<!-- traffic information: e.g closed doors or smoked rooms -->
<traffic_constraints>
......@@ -47,12 +47,12 @@
<!--persons information and distribution -->
<agents operational_model_id="3">
<agents_distribution>
<group group_id="1" agent_parameter_id="1" room_id="0" subroom_id="2" number="0" goal_id="0" router_id="1" />
<group group_id="1" agent_parameter_id="1" room_id="0" subroom_id="2" number="1" goal_id="0" router_id="1" positions_dir="/Users/chraibi/test_directories"/>
</agents_distribution>
<!-- frequency in persons/minute -->
<agents_sources>
<source id="1" frequency="10" agents_max="50" group_id="1" caption="source 1" />
<source_ id="1" frequency="10" agents_max="50" group_id="1" caption="source 1" />
</agents_sources>
<!-- <agents_sources/> -->
</agents>
......
......@@ -38,9 +38,20 @@
#include "PedDistributionLoader.h"
#include "../hybrid/PedDistributionFromProtobufLoader.h"
#include <boost/filesystem.hpp>
#include <boost/lambda/bind.hpp>
#include <boost/foreach.hpp>
#include <boost/algorithm/string.hpp> //split
#include <boost/range/combine.hpp>
#include<fstream>
#include <string>
#include <vector>
using namespace std;
using namespace std;
namespace fs = boost::filesystem;
using namespace boost::lambda;
/************************************************************
PedDistributor
************************************************************/
......@@ -108,11 +119,63 @@ bool PedDistributor::Distribute(Building *building) const {
// the positions were already computed
if (allFreePosRoom.count(subroomID) > 0)
continue;
auto possibleSubroomPositions = PedDistributor::PossiblePositions(*sr);
shuffle(possibleSubroomPositions.begin(), possibleSubroomPositions.end(), dist->GetGenerator());
allFreePosRoom[subroomID] = possibleSubroomPositions;
}
// check if we should read positions from some file
bool fromDirectory = false;
if(dist->GetPositionsDir().length()){
string directory = dist->GetPositionsDir();
fs::path the_path(directory);
if(fs::exists(directory) && fs::is_directory(directory)){
fs::directory_iterator it(the_path), eod;
BOOST_FOREACH(fs::path const &p, std::make_pair(it, eod))
{
if(fs::is_regular_file(p))
{
std::string basename = fs::basename(p);
std::string extention = fs::extension(p);
// check filename. regx "bla_N.ext"
// number is after "_" and before "."
std::size_t first = basename.find_last_of("_");
if(first != std::string::npos){
std::string tmp;
tmp.assign(basename.begin() + first + 1, basename.end());
int n = stoi(tmp);
if(n == dist->GetAgentsNumber()){
auto tmpPositions = GetPositionsFromFile(p.string(), n);
//check if positions are
//empty. May happen if file
//is misformed.
if(tmpPositions.empty()){
Log->Write("ERROR: \tproblems with file <%s%s>.", basename.c_str(), extention.c_str());
return false; //maybe just ignore?
}
else
allFreePosRoom[subroomID] = tmpPositions;
fromDirectory = true;
Log->Write("INFO: \tDistributing %d pedestrians using file <%s%s>", n, basename.c_str(), extention.c_str());
break; //leave BOOST_FOREEACH
}
}
else{
Log->Write("ERROR: \twrong file name <%s>.\n \tshould be something like <blabla_number.ext>", basename.c_str());
return false; //maybe just ignore?
}
}//regular file
} // for files
}// check if directory
}//if we have a directoy
//------------------------------------- pack in function ------------
else{
auto possibleSubroomPositions = PedDistributor::PossiblePositions(*sr);
shuffle(possibleSubroomPositions.begin(), possibleSubroomPositions.end(), dist->GetGenerator());
allFreePosRoom[subroomID] = possibleSubroomPositions;
}
} // for sub_dis
//collect the available positions for that room
for (const auto &dist: _start_dis) {
......@@ -366,6 +429,80 @@ vector<Point>PedDistributor::PositionsOnFixY(double min_x, double max_x, double
return positions;
}
// format: id fr x y
const vector<Point> PedDistributor::GetPositionsFromFile(std::string filename, int n) const{
std::ifstream infile(filename);
// read all data from file in xpos, ypos, ids and frames
// @todo: need to read z too
std::vector<double> xpos;
std::vector<double> ypos;
std::vector<int> ids;
std::vector<int> frames;
// here we push_back only the first (x,y) of every id.
// std::vector<double> first_xpos;
// std::vector<double> first_ypos;
std::vector<Point> positions;
std::vector<int> first_ids;
if (infile.good()){
std::string sLine;
std::vector<std::string> strs;
float x, y;
int id, fr;
while(getline(infile, sLine))
{
if ( sLine[0] != '#' && !(sLine.empty()) )
{
boost::split(strs, sLine, boost::is_any_of("\t "));
id = atoi(strs[0].c_str());
fr = atoi(strs[1].c_str());
x = atof(strs[2].c_str());
y = atof(strs[3].c_str());
// @todo: check for z component. Some data don't have. Some do.
xpos.push_back(x);
ypos.push_back(y);
ids.push_back(id);
frames.push_back(fr);
}
}
}
infile.close();
// now extract the first coordinates
for (auto tup : boost::combine(ids, frames, xpos, ypos)) {
float x, y;
int id, fr;
boost::tie(id, fr, x, y) = tup;
auto it = std::find(first_ids.begin(), first_ids.end(), id);
if (it == first_ids.end()) { // <id> is not yet in first_ids
Point pos(x, y);
positions.push_back(pos);
first_ids.push_back(id);
}
else
continue;
}
if(first_ids.size() != (unsigned)n){
Log->Write("ERROR: \tGetPositionsFromFile: number of peds <%d> does not match number of peds from file <%d>",
n, first_ids.size());
positions.clear();
}
// control
//debuging
// for (auto tup : boost::combine(first_ids, positions)) {
// Point pos;
// int id;
// boost::tie(id, pos) = tup;
// printf("id = %d, x = %f, y = %f \n", id, pos._x, pos._y);
// }
return positions;
}
vector<Point> PedDistributor::PossiblePositions(const SubRoom &r) {
double uni = 0.7; // wenn ein Raum in x oder y -Richtung schmaler ist als 0.7 wird in der Mitte verteilt
double bufx = 0.12;
......
......@@ -93,6 +93,14 @@ public:
const std::vector<std::shared_ptr<AgentsSource> > &GetAgentsSources() const;
/**
* Get positions from filename
* Only for frame's position for every id is given
* WARNING: It is assumed that positions should be in the corresponding room/subroom.
* checks with n if the file delivers the right number of peds
*/
const vector<Point> GetPositionsFromFile(std::string filename, int n) const;
};
#endif /* _PEDDISTRIBUTOR_H */
......
......@@ -62,6 +62,7 @@ StartDistribution::StartDistribution(int seed)
_yMin=-FLT_MAX;
_yMax=FLT_MAX;
_groupParameters=NULL;
_positions_dir = "";
static bool _seeded = false; // seed only once, not every time
if(!_seeded) {
_generator = std::default_random_engine(seed); // mt19937 g(static_cast<uint32_t>(_configuration->GetSeed()));
......@@ -390,3 +391,11 @@ double StartDistribution::GetRiskTolerance()
}
}
void StartDistribution::SetPositionsDir(const std::string& dir)
{
_positions_dir = dir;
}
const std::string& StartDistribution::GetPositionsDir() const
{
return _positions_dir;
}
......@@ -53,6 +53,7 @@ private:
//demographic parameters
//TODO: should also follow a distribution, see _premovement
std::string _gender;
std::string _positions_dir; // directory containing >=1 file(s) used to setup starting positions
int _age;
int _height;
double _patience;
......@@ -122,7 +123,9 @@ public:
double GetPremovementTime() const;
void InitRiskTolerance(std::string distribution_type, double para1, double para2);
double GetRiskTolerance();
void SetPositionsDir(const std::string& dir);
const std::string& GetPositionsDir() const;
Pedestrian* GenerateAgent(Building* building, int* pid, std::vector<Point>& positions);
};
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment