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