SUMO - Simulation of Urban MObility
MSPModel_Remote.cpp
Go to the documentation of this file.
1 /****************************************************************************/
7 // The pedestrian following model for remote controlled pedestrian movement
8 /****************************************************************************/
9 // SUMO, Simulation of Urban MObility; see http://sumo.dlr.de/
10 // Copyright (C) 2014-2017 DLR (http://www.dlr.de/) and contributors
11 /****************************************************************************/
12 //
13 // This file is part of SUMO.
14 // SUMO is free software: you can redistribute it and/or modify
15 // it under the terms of the GNU General Public License as published by
16 // the Free Software Foundation, either version 3 of the License, or
17 // (at your option) any later version.
18 //
19 /****************************************************************************/
20 
21 #include "MSPModel_Remote.h"
22 #include <grpc++/grpc++.h>
23 #include "microsim/MSEdge.h"
24 #include "microsim/MSLane.h"
25 #include "microsim/MSEdgeControl.h"
27 #include "hybridsim.grpc.pb.h"
28 #include "utils/geom/Position.h"
30 
31 using grpc::Channel;
32 using grpc::ClientContext;
33 using grpc::Status;
34 
36  : myNet(net) {
37  const std::string address = oc.getString("pedestrian.remote.address");
38  myHybridsimStub = hybridsim::HybridSimulation::NewStub(grpc::CreateChannel(
39  address, grpc::InsecureChannelCredentials()));
40 
41  initialize();
42 
43  Event* e = new Event(this);
45 }
47 
49 
50  PState* state = new PState(person, stage);
51 
52  hybridsim::Agent req;
53  int id = myLastId++;
54  remoteIdPStateMapping[id] = state;
55  req.set_id(id);
56 
57  MSLane* departureLane = getFirstPedestrianLane(*(stage->getRoute().begin()));
58  double departureOffsetAlongLane = stage->getDepartPos();
59 
60  //TODO fix this on casim side [GL]
61  double offset = departureOffsetAlongLane == 0 ? 0.4 : -0.4;
62  departureOffsetAlongLane += offset;
63 
64  Position departurePos = departureLane->getShape().positionAtOffset(departureOffsetAlongLane);
65  hybridsim::Coordinate* departureCoordinate = req.mutable_enterlocation();
66  departureCoordinate->set_x(departurePos.x());
67  departureCoordinate->set_y(departurePos.y());
68 
69  MSLane* arrivalLane = getFirstPedestrianLane(*(stage->getRoute().end() - 1));
70  double arrivalOffsetAlongLange = stage->getArrivalPos();
71  Position arrivalPos = arrivalLane->getShape().positionAtOffset(arrivalOffsetAlongLange);
72  hybridsim::Coordinate* arrivalCoordinate = req.mutable_leavelocation();
73  arrivalCoordinate->set_x(arrivalPos.x());
74  arrivalCoordinate->set_y(arrivalPos.y());
75 
76 
77  const MSEdge* prv = 0;
78  for (ConstMSEdgeVector::const_iterator it = stage->getRoute().begin(); it != stage->getRoute().end(); it++) {
79  const MSEdge* edge = *it;
80  int dir = FORWARD;//default
81  if (prv == 0) {
82  if (stage->getRoute().size() > 1) {
83  const MSEdge* nxt = *(it + 1);
84  dir = (edge->getFromJunction() == nxt->getFromJunction()
85  || edge->getFromJunction() == nxt->getToJunction()) ? BACKWARD : FORWARD;
86  } else {
87  dir = stage->getDepartPos() == 0 ? FORWARD : BACKWARD;
88  }
89  } else {
90  dir = (edge->getFromJunction() == prv->getToJunction()
91  || edge->getFromJunction() == prv->getFromJunction()) ? FORWARD : BACKWARD;
92  }
93  if (edgesTransitionsMapping.find(edge) == edgesTransitionsMapping.end()) {
94  ProcessError("Cannot map edge : " + edge->getID() + " to remote simulation");
95  };
96  std::tuple<int, int> transitions = edgesTransitionsMapping[edge];
97 
98  int frId = dir == FORWARD ? std::get<0>(transitions) : std::get<1>(transitions);
99  int toId = dir == FORWARD ? std::get<1>(transitions) : std::get<0>(transitions);
100  hybridsim::Destination* destFr = req.add_dests();
101  destFr->set_id(frId);
102  hybridsim::Destination* destTo = req.add_dests();
103  destTo->set_id(toId);
104  prv = edge;
105  }
106 
107  hybridsim::Boolean rpl;
108  ClientContext context;
109  Status st = myHybridsimStub->transferAgent(&context, req, &rpl);
110  if (!st.ok()) {
111  ProcessError("Person: " + person->getID() + " could not be transferred to remote simulation");
112  }
113  if (!rpl.val()) {
114  //TODO not yet implemented
115  ProcessError("Remote simulation declined to accept person: " + person->getID() + ".");
116  }
117 
118  return state;
119 }
120 
122 
123  hybridsim::Empty req;
124  hybridsim::Empty rpl;
125  ClientContext context1;
126  Status st = myHybridsimStub->shutdown(&context1, req, &rpl);
127  if (!st.ok()) {
128  ProcessError("Could not shutdown remote server");
129  }
130 
131 
132 }
133 
135 
136  hybridsim::LeftClosedRightOpenTimeInterval interval;
137  interval.set_fromtimeincluding(time / DELTA_T);
138  interval.set_totimeexcluding((time + DELTA_T) / DELTA_T);
139 
140 
141  //1. simulate time interval
142  hybridsim::Empty rpl;
143  ClientContext context1;
144  Status st = myHybridsimStub->simulatedTimeInerval(&context1, interval, &rpl);
145  if (!st.ok()) {
146  ProcessError("Could not simulated time interval from: " + toString(time) + " to: " + toString(time + DELTA_T));
147  }
148 
149  //2. receive trajectories
150  hybridsim::Empty req2;
151  hybridsim::Trajectories trajectories;
152  ClientContext context2;
153  Status st2 = myHybridsimStub->receiveTrajectories(&context2, req2, &trajectories);
154  if (!st2.ok()) {
155  ProcessError("Could not receive trajectories from remote simulation");
156  }
157  for (hybridsim::Trajectory trajectory : trajectories.trajectories()) {
158  if (remoteIdPStateMapping.find(trajectory.id()) != remoteIdPStateMapping.end()) {
159  PState* pState = remoteIdPStateMapping[trajectory.id()];
160  pState->setPosition(trajectory.x(), trajectory.y());
161  pState->setPhi(trajectory.phi());
162  if (transitionsEdgesMapping.find(trajectory.currentdest().id()) != transitionsEdgesMapping.end()) {
163  const MSEdge* nextTargetEdge = transitionsEdgesMapping[trajectory.currentdest().id()];
164  const MSEdge* nextStageEdge = pState->getStage()->getNextRouteEdge();
165 // const MSEdge* currentStageEdge = pState->getStage()->getEdge();
166  if (nextTargetEdge == nextStageEdge) {
167  const bool arrived = pState->getStage()->moveToNextEdge(pState->getPerson(), time);
168  std::cout << "next edge" << std::endl;
169  }
170  }
171 // pState.
172  } else {
173  ProcessError("Pedestrian with id: " + toString(trajectory.id()) + " is not known.");
174  }
175  }
176 
177  //3. retrieve agents that are ready to come back home to SUMO
178  hybridsim::Empty req3;
179  hybridsim::Agents agents;
180  ClientContext context3;
181  Status st3 = myHybridsimStub->queryRetrievableAgents(&context3, req3, &agents);
182  if (!st3.ok()) {
183  ProcessError("Could not query retrievable agents");
184  }
185  //TODO check whether agents can be retrieved
186  for (hybridsim::Agent agent : agents.agents()) {
187  if (remoteIdPStateMapping.find(agent.id()) != remoteIdPStateMapping.end()) {
188  PState* pState = remoteIdPStateMapping[agent.id()];
189  while (!pState->getStage()->moveToNextEdge(pState->getPerson(), time)) {
190  remoteIdPStateMapping.erase(agent.id());
191  delete pState;
192  }
193  }
194  }
195 
196  //4. confirm transferred agents
197  hybridsim::Empty rpl2;
198  ClientContext context4;
199  Status st4 = myHybridsimStub->confirmRetrievedAgents(&context4, agents, &rpl2);
200  if (!st4.ok()) {
201  ProcessError("Could not confirm retrieved agents");
202  }
203 
204  return DELTA_T;
205 }
207  for (MSLane* lane : edge->getLanes()) {
208  if (lane->getPermissions() == SVC_PEDESTRIAN) {
209  return lane;
210  }
211  }
212  ProcessError("Edge: " + edge->getID() + " does not allow pedestrians.");
213 }
214 
216 
217 }
218 
221 }
222 
224  hybridsim::Scenario req;
225 
226  //1. for all edges
227  for (MSEdge* e : myNet->getEdgeControl().getEdges()) {
228  if (e->isInternal()) {
229  continue;
230  }
231  if (e->isWalkingArea()) {
232  handleWalkingArea(e, req);
233  continue;
234  }
235  for (MSLane* l : e->getLanes()) {
236  if (l->getPermissions() == SVC_PEDESTRIAN) {
237  handlePedestrianLane(l, req);
238  }
239  }
240  }
241 
242  //add boundary
243  hybridsim::Edge* edge = req.add_edges();
244  edge->mutable_c0()->set_x(myBoundary.xmin());
245  edge->mutable_c0()->set_y(myBoundary.ymin());
246  edge->mutable_c1()->set_x(myBoundary.xmax());
247  edge->mutable_c1()->set_y(myBoundary.ymin());
248  edge->set_type(hybridsim::Edge_Type_OBSTACLE);
249 
250  edge = req.add_edges();
251  edge->mutable_c0()->set_x(myBoundary.xmax());
252  edge->mutable_c0()->set_y(myBoundary.ymin());
253  edge->mutable_c1()->set_x(myBoundary.xmax());
254  edge->mutable_c1()->set_y(myBoundary.ymax());
255  edge->set_type(hybridsim::Edge_Type_OBSTACLE);
256 
257  edge = req.add_edges();
258  edge->mutable_c0()->set_x(myBoundary.xmax());
259  edge->mutable_c0()->set_y(myBoundary.ymax());
260  edge->mutable_c1()->set_x(myBoundary.xmin());
261  edge->mutable_c1()->set_y(myBoundary.ymax());
262  edge->set_type(hybridsim::Edge_Type_OBSTACLE);
263 
264  edge = req.add_edges();
265  edge->mutable_c0()->set_x(myBoundary.xmin());
266  edge->mutable_c0()->set_y(myBoundary.ymax());
267  edge->mutable_c1()->set_x(myBoundary.xmin());
268  edge->mutable_c1()->set_y(myBoundary.ymin());
269  edge->set_type(hybridsim::Edge_Type_OBSTACLE);
270 
271 
272  hybridsim::Empty rpl;
273  ClientContext context;
274  Status st = myHybridsimStub->initScenario(&context, req, &rpl);
275  if (!st.ok()) {
276  ProcessError("Remote side could not initialize scenario!");
277  }
278 
279 }
280 void MSPModel_Remote::handleWalkingArea(MSEdge* msEdge, hybridsim::Scenario& scenario) {
281  MSLane* l = *(msEdge->getLanes().begin());
282 
283  const PositionVector shape = l->getShape();
284  if (shape.size() < 2) {//should never happen
285  return;
286  }
287 
288  handleShape(shape, scenario);
289 
290 
291  //close walking area
292  Position frst = *shape.begin();
293  Position scnd = *(shape.end() - 1);
294  hybridsim::Edge* edge = scenario.add_edges();
295  edge->mutable_c0()->set_x(frst.x());
296  edge->mutable_c0()->set_y(frst.y());
297  edge->mutable_c1()->set_x(scnd.x());
298  edge->mutable_c1()->set_y(scnd.y());
299  edge->set_type(hybridsim::Edge_Type_OBSTACLE);
300 
301 
302 }
303 void MSPModel_Remote::handlePedestrianLane(MSLane* l, hybridsim::Scenario& scenario) {
304  double width = l->getWidth();
305  PositionVector centerLine = PositionVector(l->getShape());
306  if (centerLine.size() < 2) {//should never happen
307  return;
308  }
309 
310 
311  int fromId = myLastTransitionId++;
312  int toId = myLastTransitionId++;
313  edgesTransitionsMapping[&(l->getEdge())] = std::make_tuple(fromId, toId);
314  transitionsEdgesMapping[fromId] = &(l->getEdge());
315  transitionsEdgesMapping[toId] = &(l->getEdge());
316 
317  hybridsim::Edge_Type edgeType;
318  if (l->getEdge().isCrossing()) {
319  edgeType = hybridsim::Edge_Type_TRANSITION_HOLDOVER;
320  } else if (l->getEdge().isWalkingArea()) {
321  edgeType = hybridsim::Edge_Type_TRANSITION_INTERNAL;
322  } else {
323  edgeType = hybridsim::Edge_Type_TRANSITION;
324  }
325 
326  //start and end
327  Position frst = *centerLine.begin();
328  Position scnd = *(centerLine.begin() + 1);
329  makeStartOrEndTransition(frst, scnd, width, scenario, edgeType, fromId);
330  Position thrd = *(centerLine.end() - 1);
331  Position frth = *(centerLine.end() - 2);
332  makeStartOrEndTransition(thrd, frth, width, scenario, edgeType, toId);
333 
334  centerLine.move2side(-width / 2.);
335  handleShape(centerLine, scenario);
336  centerLine.move2side(width);
337  handleShape(centerLine, scenario);
338 
339 }
340 void
341 MSPModel_Remote::makeStartOrEndTransition(Position frst, Position scnd, double width, hybridsim::Scenario& scenario,
342  hybridsim::Edge_Type type, int id) {
343 
344  double dx = scnd.x() - frst.x();
345  double dy = scnd.y() - frst.y();
346  double length = sqrt(dx * dx + dy * dy);
347  dx /= length;
348  dy /= length;
349  double x0 = frst.x() - dy * width / 2.;
350  double y0 = frst.y() + dx * width / 2.;
351  double x1 = frst.x() + dy * width / 2.;
352  double y1 = frst.y() - dx * width / 2.;
353  hybridsim::Edge* edge = scenario.add_edges();
354  edge->mutable_c0()->set_x(x0);
355  edge->mutable_c0()->set_y(y0);
356  edge->mutable_c1()->set_x(x1);
357  edge->mutable_c1()->set_y(y1);
358  edge->set_type(type);
359  edge->set_id(id);
360 
361 }
362 void MSPModel_Remote::handleShape(const PositionVector& shape, hybridsim::Scenario& scenario) {
363  PositionVector::const_iterator it = shape.begin();
364  Position frst = *it;
365 
366  myBoundary.add(frst.x(), frst.y());
367  it++;
368  for (; it != shape.end(); it++) {
369  hybridsim::Edge* edge = scenario.add_edges();
370  edge->mutable_c0()->set_x(frst.x());
371  edge->mutable_c0()->set_y(frst.y());
372  edge->mutable_c1()->set_x((*it).x());
373  edge->mutable_c1()->set_y((*it).y());
374  edge->set_type(hybridsim::Edge_Type_OBSTACLE);
375  frst = *it;
376  myBoundary.add(frst.x(), frst.y());
377  }
378 }
379 
380 
381 
382 // ===========================================================================
383 // MSPModel_Remote::PState method definitions
384 // ===========================================================================
386  : myPerson(person), myPhi(0), myPosition(0, 0), myStage(stage) {
387 
388 
389 }
391 
392 }
394  return 0;
395 }
397  return myPosition;
398 }
400  return myPhi;
401 }
403  return 0;
404 }
406  return 0;
407 }
409  return nullptr;
410 }
411 void MSPModel_Remote::PState::setPosition(double x, double y) {
412  myPosition.set(x, y);
413 }
415  myPhi = phi;
416 }
418  return myStage;
419 }
421  return myPerson;
422 }
423 
424 
425 
double xmax() const
Returns maximum x-coordinate.
Definition: Boundary.cpp:132
PState(MSPerson *person, MSPerson::MSPersonStage_Walking *stage)
double getDepartPos() const
Definition: MSPerson.h:152
virtual void cleanupHelper()
Definition: MSPModel.h:106
MSEdge & getEdge() const
Returns the lane&#39;s edge.
Definition: MSLane.h:582
double getWidth() const
Returns the lane&#39;s width.
Definition: MSLane.h:500
const MSEdge * getNextRouteEdge() const
Definition: MSPerson.h:167
double getSpeed(const MSPerson::MSPersonStage_Walking &stage) const override
return the current speed of the person
is a pedestrian
double getArrivalPos() const
Definition: MSPerson.h:160
const std::vector< MSLane * > & getLanes() const
Returns this edge&#39;s lanes.
Definition: MSEdge.h:168
double ymax() const
Returns maximum y-coordinate.
Definition: Boundary.cpp:144
MSLane * getFirstPedestrianLane(const MSEdge *const &edge)
double x() const
Returns the x-position.
Definition: Position.h:63
void makeStartOrEndTransition(Position position, Position scnd, double width, hybridsim::Scenario &scenario, hybridsim::Edge_Type type, int i)
bool isWalkingArea() const
return whether this edge is walking area
Definition: MSEdge.h:249
static const int FORWARD
Definition: MSPModel.h:106
MSPModel_Remote(const OptionsCont &oc, MSNet *net)
double getEdgePos(const MSPerson::MSPersonStage_Walking &stage, SUMOTime now) const override
return the offset from the start of the current edge measured in its natural direction ...
MSPerson::MSPersonStage_Walking * getStage()
SUMOTime DELTA_T
Definition: SUMOTime.cpp:40
const std::string & getID() const
returns the id of the transportable
std::map< int, const MSEdge * > transitionsEdgesMapping
void handlePedestrianLane(MSLane *pLane, hybridsim::Scenario &scenario)
void set(double x, double y)
set positions x and y
Definition: Position.h:93
SUMOTime getCurrentTimeStep() const
Returns the current simulation step.
Definition: MSNet.h:252
SUMOTime execute(SUMOTime time)
The simulated network and simulation perfomer.
Definition: MSNet.h:89
std::string getString(const std::string &name) const
Returns the string-value of the named option (only for Option_String)
const std::string & getID() const
Returns the id.
Definition: Named.h:66
A road/street connecting two junctions.
Definition: MSEdge.h:81
double getAngle(const MSPerson::MSPersonStage_Walking &stage, SUMOTime now) const override
return the direction in which the person faces in degrees
bool moveToNextEdge(MSPerson *person, SUMOTime currentTime, MSEdge *nextInternal=0)
move forward and return whether the person arrived
Definition: MSPerson.cpp:244
std::string toString(const T &t, std::streamsize accuracy=gPrecision)
Definition: ToString.h:56
std::map< int, PState * > remoteIdPStateMapping
A point in 2D or 3D with translation and scaling methods.
Definition: Position.h:46
const ConstMSEdgeVector & getRoute() const
Definition: MSPerson.h:170
A list of positions.
StageType getCurrentStageType() const
the current stage type of the transportable
MSEventControl * getBeginOfTimestepEvents()
Returns the event control for events executed at the begin of a time step.
Definition: MSNet.h:398
double y() const
Returns the y-position.
Definition: Position.h:68
virtual void addEvent(Command *operation, SUMOTime execTimeStep=-1)
Adds an Event.
void remove(PedestrianState *state) override
remove the specified person from the pedestrian simulation
void handleShape(const PositionVector &shape, hybridsim::Scenario &scenario)
void setPosition(double x, double y)
void move2side(double amount)
move position vector to side using certain ammount
PedestrianState * add(MSPerson *person, MSPerson::MSPersonStage_Walking *stage, SUMOTime now) override
register the given person as a pedestrian
abstract base class for managing callbacks to retrieve various state information from the model ...
Definition: MSPModel.h:129
const MSEdge * getNextEdge(const MSPerson::MSPersonStage_Walking &stage) const override
return the list of internal edges if the pedestrian is on an intersection
Container for pedestrian state and individual position update function.
SUMOTime getWaitingTime(const MSPerson::MSPersonStage_Walking &stage, SUMOTime now) const override
return the time the person spent standing
Position positionAtOffset(double pos, double lateralOffset=0) const
Returns the position at the given length.
double xmin() const
Returns minimum x-coordinate.
Definition: Boundary.cpp:126
A storage for options typed value containers)
Definition: OptionsCont.h:99
double ymin() const
Returns minimum y-coordinate.
Definition: Boundary.cpp:138
std::unique_ptr< hybridsim::HybridSimulation::Stub > myHybridsimStub
std::map< const MSEdge *, std::tuple< int, int > > edgesTransitionsMapping
static const int BACKWARD
Definition: MSPModel.h:110
const PositionVector & getShape() const
Returns this lane&#39;s shape.
Definition: MSLane.h:426
MSPerson::MSPersonStage_Walking * myStage
bool isCrossing() const
return whether this edge is a pedestrian crossing
Definition: MSEdge.h:235
const MSJunction * getFromJunction() const
Definition: MSEdge.h:349
MSEdgeControl & getEdgeControl()
Returns the edge control.
Definition: MSNet.h:348
long long int SUMOTime
Definition: TraCIDefs.h:52
void add(double x, double y, double z=0)
Makes the boundary include the given coordinate.
Definition: Boundary.cpp:86
Representation of a lane in the micro simulation.
Definition: MSLane.h:79
void cleanupHelper() override
void handleWalkingArea(MSEdge *msEdge, hybridsim::Scenario &scenario)
const MSJunction * getToJunction() const
Definition: MSEdge.h:353
const MSEdgeVector & getEdges() const
Returns loaded edges.
Position getPosition(const MSPerson::MSPersonStage_Walking &stage, SUMOTime now) const override
return the network coordinate of the person