Skip to content

Commit 691e200

Browse files
committed
allow dynamic update of jupedsim shapes #17642
1 parent 9d65e5f commit 691e200

File tree

5 files changed

+90
-27
lines changed

5 files changed

+90
-27
lines changed

src/microsim/MSNet.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -177,7 +177,7 @@ class MSNet : public Parameterised {
177177
MSNet(MSVehicleControl* vc, MSEventControl* beginOfTimestepEvents,
178178
MSEventControl* endOfTimestepEvents,
179179
MSEventControl* insertionEvents,
180-
ShapeContainer* shapeCont = 0);
180+
ShapeContainer* shapeCont = nullptr);
181181

182182

183183
/// @brief Destructor

src/microsim/transportables/MSPModel_JuPedSim.cpp

Lines changed: 40 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -564,13 +564,13 @@ MSPModel_JuPedSim::execute(SUMOTime time) {
564564
}
565565

566566
// Remove pedestrians that are in a predefined area, at a predefined rate.
567-
for (AreaData& area : myAreas) {
568-
const std::vector<JPS_Point>& areaBoundary = area.areaBoundary;
567+
for (const auto& area : myAreas) {
568+
const std::vector<JPS_Point>& areaBoundary = area->areaBoundary;
569569
JPS_AgentIdIterator agentsInArea = JPS_Simulation_AgentsInPolygon(myJPSSimulation, areaBoundary.data(), areaBoundary.size());
570-
if (area.areaType == "vanishing_area") {
571-
const SUMOTime period = area.params.count("period") > 0 ? string2time(area.params.at("period")) : 1000;
570+
if (area->areaType == "vanishing_area") {
571+
const SUMOTime period = area->params.count("period") > 0 ? string2time(area->params.at("period")) : 1000;
572572
const int nbrPeriodsCoveringTimestep = (int)ceil(TS / STEPS2TIME(period));
573-
if (time - area.lastRemovalTime >= nbrPeriodsCoveringTimestep * period) {
573+
if (time - area->lastRemovalTime >= nbrPeriodsCoveringTimestep * period) {
574574
for (int k = 0; k < nbrPeriodsCoveringTimestep; k++) {
575575
const JPS_AgentId agentID = JPS_AgentIdIterator_Next(agentsInArea);
576576
if (agentID != 0) {
@@ -584,21 +584,21 @@ MSPModel_JuPedSim::execute(SUMOTime time) {
584584
// Code below only works if the removal happens at the last stage.
585585
const bool finalStage = person->getNumRemainingStages() == 1;
586586
if (finalStage) {
587-
WRITE_MESSAGEF(TL("Person '%' in vanishing area '%' was removed from the simulation."), person->getID(), area.id);
587+
WRITE_MESSAGEF(TL("Person '%' in vanishing area '%' was removed from the simulation."), person->getID(), area->id);
588588
while (!state->getStage()->moveToNextEdge(person, time, 1, nullptr));
589589
registerArrived(agentID);
590590
myPedestrianStates.erase(iterator);
591-
area.lastRemovalTime = time;
591+
area->lastRemovalTime = time;
592592
}
593593
}
594594
}
595595
}
596596
}
597597
} else { // areaType == "influencer"
598598
for (JPS_AgentId agentID = JPS_AgentIdIterator_Next(agentsInArea); agentID != 0; agentID = JPS_AgentIdIterator_Next(agentsInArea)) {
599-
if (area.params.count("speed") > 0) {
599+
if (area->params.count("speed") > 0) {
600600
const JPS_Agent agent = JPS_Simulation_GetAgent(myJPSSimulation, agentID, nullptr);
601-
const double newMaxSpeed = StringUtils::toDouble(area.params.at("speed"));
601+
const double newMaxSpeed = StringUtils::toDouble(area->params.at("speed"));
602602
switch (myJPSModel) {
603603
case JPS_Model::CollisionFreeSpeed: {
604604
JPS_CollisionFreeSpeedModelState modelState = JPS_Agent_GetCollisionFreeSpeedModelState(agent, nullptr);
@@ -1257,19 +1257,7 @@ MSPModel_JuPedSim::initialize(const OptionsCont& oc) {
12571257
}
12581258
// Polygons that define vanishing areas aren't part of the regular JuPedSim geometry.
12591259
for (const auto& polygonWithID : myNetwork->getShapeContainer().getPolygons()) {
1260-
const SUMOPolygon* const poly = polygonWithID.second;
1261-
if (poly->getShapeType() == "jupedsim.vanishing_area" || poly->getShapeType() == "jupedsim.influencer") {
1262-
std::vector<JPS_Point> areaBoundary;
1263-
for (const Position& p : poly->getShape()) {
1264-
areaBoundary.push_back({p.x(), p.y()});
1265-
}
1266-
// Make sure the shape is not repeating the first point.
1267-
if (areaBoundary.back().x == areaBoundary.front().x && areaBoundary.back().y == areaBoundary.front().y) {
1268-
areaBoundary.pop_back();
1269-
}
1270-
const std::string type = StringTokenizer(poly->getShapeType(), ".").getVector()[1];
1271-
myAreas.push_back({poly->getID(), type, areaBoundary, poly->getParametersMap(), 0});
1272-
}
1260+
polygonChanged(polygonWithID.second, true, false);
12731261
}
12741262
if (OutputDevice::createDeviceByOption("pedestrian.jupedsim.py")) {
12751263
myPythonScript = &OutputDevice::getDeviceByOption("pedestrian.jupedsim.py");
@@ -1284,6 +1272,36 @@ MSPModel_JuPedSim::initialize(const OptionsCont& oc) {
12841272
crossing.second.first = addWaitingSet(crossing.first, true);
12851273
crossing.second.second = addWaitingSet(crossing.first, false);
12861274
}
1275+
myNetwork->getShapeContainer().addShapeListener(this);
1276+
}
1277+
1278+
1279+
void
1280+
MSPModel_JuPedSim::polygonChanged(const SUMOPolygon* const poly, const bool added, const bool removed) {
1281+
if (poly->getShapeType() == "jupedsim.vanishing_area" || poly->getShapeType() == "jupedsim.influencer") {
1282+
SUMOTime lastRemovalTime = 0;
1283+
if (!added) {
1284+
for (auto areaIt = myAreas.begin(); areaIt != myAreas.end(); ++areaIt) {
1285+
if (poly->getID() == (*areaIt)->id) {
1286+
lastRemovalTime = (*areaIt)->lastRemovalTime;
1287+
myAreas.erase(areaIt);
1288+
break;
1289+
}
1290+
}
1291+
}
1292+
if (!removed) {
1293+
std::vector<JPS_Point> areaBoundary;
1294+
for (const Position& p : poly->getShape()) {
1295+
areaBoundary.push_back({p.x(), p.y()});
1296+
}
1297+
// Make sure the shape is not repeating the first point.
1298+
if (areaBoundary.back().x == areaBoundary.front().x && areaBoundary.back().y == areaBoundary.front().y) {
1299+
areaBoundary.pop_back();
1300+
}
1301+
const std::string type = StringTokenizer(poly->getShapeType(), ".").getVector()[1];
1302+
myAreas.emplace_back(std::unique_ptr<AreaData>(new AreaData{poly->getID(), type, areaBoundary, poly->getParametersMap(), lastRemovalTime}));
1303+
}
1304+
}
12871305
}
12881306

12891307

src/microsim/transportables/MSPModel_JuPedSim.h

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,8 @@
2727
#include <map>
2828
#include <geos_c.h>
2929
#include <jupedsim/jupedsim.h>
30-
#include "microsim/MSNet.h"
30+
#include <utils/shapes/ShapeContainer.h>
31+
#include <microsim/MSNet.h>
3132
#include "MSPModel_Interacting.h"
3233

3334

@@ -45,7 +46,7 @@ class OutputDevice;
4546
* @brief A pedestrian following model that acts as a proxy for pedestrian models
4647
* provided by the JuPedSim third-party simulation framework.
4748
*/
48-
class MSPModel_JuPedSim : public MSPModel_Interacting {
49+
class MSPModel_JuPedSim : public MSPModel_Interacting, public ShapeListener {
4950
public:
5051
MSPModel_JuPedSim(const OptionsCont& oc, MSNet* net);
5152
~MSPModel_JuPedSim();
@@ -80,6 +81,9 @@ class MSPModel_JuPedSim : public MSPModel_Interacting {
8081
};
8182

8283
typedef std::tuple<JPS_StageId, Position, double> WaypointDesc;
84+
85+
void polygonChanged(const SUMOPolygon* const poly, const bool added, const bool removed) override;
86+
8387
private:
8488
/**
8589
* @class PState
@@ -189,14 +193,14 @@ class MSPModel_JuPedSim : public MSPModel_Interacting {
189193
const std::string id;
190194
const std::string areaType;
191195
const std::vector<JPS_Point> areaBoundary;
192-
const Parameterised::Map params;
196+
const Parameterised::Map& params;
193197

194198
/// @brief The last time a pedestrian was removed in a vanishing area.
195199
SUMOTime lastRemovalTime;
196200
};
197201

198202
/// @brief Array of special areas.
199-
std::vector<AreaData> myAreas;
203+
std::vector<std::unique_ptr<AreaData> > myAreas;
200204

201205
/// @brief Array of stopped trains, used to detect whether to add carriages and ramps to the geometry.
202206
std::vector<SUMOTrafficObject::NumericalID> myAllStoppedTrainIDs;

src/utils/shapes/ShapeContainer.cpp

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -156,12 +156,24 @@ ShapeContainer::removePolygon(const std::string& id, bool /* useLock */) {
156156
std::cout << "ShapeContainer: Removing Polygon '" << id << "'" << std::endl;
157157
#endif
158158
removePolygonDynamics(id);
159+
SUMOPolygon* p = myPolygons.get(id);
160+
if (p != nullptr) {
161+
for (ShapeListener* listener : myListeners) {
162+
listener->polygonChanged(p, false, true);
163+
}
164+
}
159165
return myPolygons.remove(id);
160166
}
161167

162168

163169
bool
164170
ShapeContainer::removePOI(const std::string& id) {
171+
PointOfInterest* p = myPOIs.get(id);
172+
if (p != nullptr) {
173+
for (ShapeListener* listener : myListeners) {
174+
listener->poiChanged(p, false, true);
175+
}
176+
}
165177
return myPOIs.remove(id);
166178
}
167179

@@ -171,6 +183,9 @@ ShapeContainer::movePOI(const std::string& id, const Position& pos) {
171183
PointOfInterest* p = myPOIs.get(id);
172184
if (p != nullptr) {
173185
static_cast<Position*>(p)->set(pos);
186+
for (ShapeListener* listener : myListeners) {
187+
listener->poiChanged(p, false, false);
188+
}
174189
}
175190
}
176191

@@ -180,6 +195,9 @@ ShapeContainer::reshapePolygon(const std::string& id, const PositionVector& shap
180195
SUMOPolygon* p = myPolygons.get(id);
181196
if (p != nullptr) {
182197
p->setShape(shape);
198+
for (ShapeListener* listener : myListeners) {
199+
listener->polygonChanged(p, false, false);
200+
}
183201
}
184202
}
185203

@@ -190,6 +208,9 @@ ShapeContainer::add(SUMOPolygon* poly, bool /* ignorePruning */) {
190208
delete poly;
191209
return false;
192210
}
211+
for (ShapeListener* listener : myListeners) {
212+
listener->polygonChanged(poly, true, false);
213+
}
193214
return true;
194215
}
195216

@@ -200,6 +221,9 @@ ShapeContainer::add(PointOfInterest* poi, bool /* ignorePruning */) {
200221
delete poi;
201222
return false;
202223
}
224+
for (ShapeListener* listener : myListeners) {
225+
listener->poiChanged(poi, true, false);
226+
}
203227
return true;
204228
}
205229

src/utils/shapes/ShapeContainer.h

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@
3434
// class declarations
3535
// ===========================================================================
3636
class PolygonDynamics;
37+
class ShapeListener;
3738
class SUMOTrafficObject;
3839
template <class T, class S>
3940
class ParametrisedWrappingCommand;
@@ -175,6 +176,10 @@ class ShapeContainer {
175176
/** @brief Remove all dynamics before quick-loading state */
176177
void clearState();
177178

179+
void addShapeListener(ShapeListener* listener) {
180+
myListeners.push_back(listener);
181+
}
182+
178183
protected:
179184
/// @brief add polygon
180185
virtual bool add(SUMOPolygon* poly, bool ignorePruning = false);
@@ -221,5 +226,17 @@ class ShapeContainer {
221226
private:
222227
/// @brief Command pointers for scheduled polygon update. Maps PolyID->Command
223228
std::map<const std::string, ParametrisedWrappingCommand<ShapeContainer, PolygonDynamics*>*> myPolygonUpdateCommands;
229+
std::vector<ShapeListener*> myListeners;
230+
231+
};
224232

233+
234+
/**
235+
* @class ShapeListener
236+
* @brief Interface for objects which want to be notified about shape updates
237+
*/
238+
class ShapeListener {
239+
public:
240+
virtual void polygonChanged(const SUMOPolygon* const poly, const bool added, const bool removed) {}
241+
virtual void poiChanged(const PointOfInterest* const poi, const bool added, const bool removed) {}
225242
};

0 commit comments

Comments
 (0)