Line data Source code
1 : /****************************************************************************/
2 : // Eclipse SUMO, Simulation of Urban MObility; see https://eclipse.dev/sumo
3 : // Copyright (C) 2013-2026 German Aerospace Center (DLR) and others.
4 : // This program and the accompanying materials are made available under the
5 : // terms of the Eclipse Public License 2.0 which is available at
6 : // https://www.eclipse.org/legal/epl-2.0/
7 : // This Source Code may also be made available under the following Secondary
8 : // Licenses when the conditions for such availability set forth in the Eclipse
9 : // Public License 2.0 are satisfied: GNU General Public License, version 2
10 : // or later which is available at
11 : // https://www.gnu.org/licenses/old-licenses/gpl-2.0-standalone.html
12 : // SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later
13 : /****************************************************************************/
14 : /// @file MSDevice_BTreceiver.cpp
15 : /// @author Daniel Krajzewicz
16 : /// @author Jakob Erdmann
17 : /// @author Michael Behrisch
18 : /// @date 14.08.2013
19 : ///
20 : // A BT Receiver
21 : /****************************************************************************/
22 : #include <config.h>
23 :
24 : #include <utils/common/MsgHandler.h>
25 : #include <utils/options/OptionsCont.h>
26 : #include <utils/iodevices/OutputDevice.h>
27 : #include <utils/vehicle/SUMOVehicle.h>
28 : #include <utils/geom/Position.h>
29 : #include <utils/geom/GeomHelper.h>
30 : #include <microsim/MSNet.h>
31 : #include <microsim/MSLane.h>
32 : #include <microsim/MSEdge.h>
33 : #include <microsim/MSVehicle.h>
34 : #include <microsim/transportables/MSTransportable.h>
35 : #include <microsim/transportables/MSTransportableControl.h>
36 : #include <microsim/MSEventControl.h>
37 : #include "MSDevice_Tripinfo.h"
38 : #include "MSDevice_BTreceiver.h"
39 : #include "MSDevice_BTsender.h"
40 :
41 :
42 : // ===========================================================================
43 : // static members
44 : // ===========================================================================
45 : bool MSDevice_BTreceiver::myWasInitialised = false;
46 : bool MSDevice_BTreceiver::myHasPersons = true;
47 : double MSDevice_BTreceiver::myRange = -1.;
48 : double MSDevice_BTreceiver::myOffTime = -1.;
49 : SumoRNG MSDevice_BTreceiver::sRecognitionRNG("btreceiver");
50 : std::map<std::string, MSDevice_BTreceiver::VehicleInformation*> MSDevice_BTreceiver::sVehicles;
51 :
52 :
53 : // ===========================================================================
54 : // method definitions
55 : // ===========================================================================
56 : // ---------------------------------------------------------------------------
57 : // static initialisation methods
58 : // ---------------------------------------------------------------------------
59 :
60 : void
61 44303 : MSVehicleDevice_BTreceiver::insertOptions(OptionsCont& oc) {
62 88606 : insertDefaultAssignmentOptions("btreceiver", "Communication", oc);
63 :
64 44303 : oc.doRegister("device.btreceiver.range", new Option_Float(300));
65 88606 : oc.addDescription("device.btreceiver.range", "Communication", TL("The range of the bt receiver"));
66 :
67 44303 : oc.doRegister("device.btreceiver.all-recognitions", new Option_Bool(false));
68 88606 : oc.addDescription("device.btreceiver.all-recognitions", "Communication", TL("Whether all recognition point shall be written"));
69 :
70 44303 : oc.doRegister("device.btreceiver.offtime", new Option_Float(0.64));
71 88606 : oc.addDescription("device.btreceiver.offtime", "Communication", TL("The offtime used for calculating detection probability (in seconds)"));
72 :
73 44303 : myWasInitialised = false;
74 44303 : myHasPersons = false;
75 44303 : }
76 :
77 :
78 : void
79 5554741 : MSVehicleDevice_BTreceiver::buildVehicleDevices(SUMOVehicle& v, std::vector<MSVehicleDevice*>& into) {
80 5554741 : OptionsCont& oc = OptionsCont::getOptions();
81 11109482 : if (equippedByDefaultAssignmentOptions(oc, "btreceiver", v, false)) {
82 480 : MSVehicleDevice_BTreceiver* device = new MSVehicleDevice_BTreceiver(v, "btreceiver_" + v.getID());
83 480 : into.push_back(device);
84 480 : if (!myWasInitialised) {
85 171 : new BTreceiverUpdate();
86 171 : myWasInitialised = true;
87 171 : myRange = oc.getFloat("device.btreceiver.range");
88 171 : myOffTime = oc.getFloat("device.btreceiver.offtime");
89 342 : sRecognitionRNG.seed(oc.getInt("seed"));
90 : }
91 : }
92 5554741 : }
93 :
94 : void
95 44303 : MSTransportableDevice_BTreceiver::insertOptions(OptionsCont& oc) {
96 88606 : insertDefaultAssignmentOptions("btreceiver", "Communication", oc, true);
97 44303 : }
98 :
99 :
100 : void
101 509046 : MSTransportableDevice_BTreceiver::buildDevices(MSTransportable& t, std::vector<MSTransportableDevice*>& into) {
102 509046 : OptionsCont& oc = OptionsCont::getOptions();
103 1018092 : if (equippedByDefaultAssignmentOptions(oc, "btreceiver", t, false, true)) {
104 132 : MSTransportableDevice_BTreceiver* device = new MSTransportableDevice_BTreceiver(t, "btreceiver_" + t.getID());
105 132 : into.push_back(device);
106 132 : myHasPersons = true;
107 132 : if (!myWasInitialised) {
108 72 : new BTreceiverUpdate();
109 72 : myWasInitialised = true;
110 72 : myRange = oc.getFloat("device.btreceiver.range");
111 72 : myOffTime = oc.getFloat("device.btreceiver.offtime");
112 144 : sRecognitionRNG.seed(oc.getInt("seed"));
113 : }
114 : }
115 509046 : }
116 :
117 :
118 : // ---------------------------------------------------------------------------
119 : // MSDevice_BTreceiver::BTreceiverUpdate-methods
120 : // ---------------------------------------------------------------------------
121 243 : MSDevice_BTreceiver::BTreceiverUpdate::BTreceiverUpdate() {
122 243 : MSNet::getInstance()->getEndOfTimestepEvents()->addEvent(this);
123 243 : }
124 :
125 :
126 486 : MSDevice_BTreceiver::BTreceiverUpdate::~BTreceiverUpdate() {
127 447 : for (const auto& vehicleInfo : MSDevice_BTsender::sVehicles) {
128 204 : vehicleInfo.second->amOnNet = false;
129 204 : vehicleInfo.second->haveArrived = true;
130 : }
131 447 : for (const auto& vehicleInfo : MSDevice_BTreceiver::sVehicles) {
132 204 : vehicleInfo.second->amOnNet = false;
133 204 : vehicleInfo.second->haveArrived = true;
134 : }
135 243 : execute(MSNet::getInstance()->getCurrentTimeStep());
136 486 : }
137 :
138 :
139 : SUMOTime
140 137687 : MSDevice_BTreceiver::BTreceiverUpdate::execute(SUMOTime /*currentTime*/) {
141 : // loop over equipped persons to update their positions
142 137687 : if (myHasPersons && MSNet::getInstance()->hasPersons()) { // the check whether the net has persons is only important in the final cleanup
143 98116 : MSTransportableControl& c = MSNet::getInstance()->getPersonControl();
144 287840 : for (MSTransportableControl::constVehIt i = c.loadedBegin(); i != c.loadedEnd(); ++i) {
145 189724 : MSTransportable* t = i->second;
146 189724 : if (t->getCurrentStageType() != MSStageType::WAITING_FOR_DEPART) {
147 189556 : MSDevice_BTsender* snd = dynamic_cast<MSDevice_BTsender*>(t->getDevice(typeid(MSTransportableDevice_BTsender)));
148 189556 : MSDevice_BTreceiver* rec = dynamic_cast<MSDevice_BTreceiver*>(t->getDevice(typeid(MSTransportableDevice_BTreceiver)));
149 189556 : if (snd) {
150 129152 : snd->notifyMove(*t, t->getPositionOnLane(), t->getPositionOnLane(), t->getSpeed());
151 129152 : if (MSDevice_BTsender::sVehicles[t->getID()]->route.back() != t->getEdge()) {
152 240 : MSDevice_BTsender::sVehicles[t->getID()]->route.push_back(t->getEdge());
153 : }
154 : }
155 189556 : if (rec) {
156 129152 : rec->notifyMove(*t, t->getPositionOnLane(), t->getPositionOnLane(), t->getSpeed());
157 129152 : if (sVehicles[t->getID()]->route.back() != t->getEdge()) {
158 240 : sVehicles[t->getID()]->route.push_back(t->getEdge());
159 : }
160 : }
161 : }
162 : }
163 : }
164 :
165 : // build rtree with senders
166 : NamedRTree rt;
167 292943 : for (std::map<std::string, MSDevice_BTsender::VehicleInformation*>::const_iterator i = MSDevice_BTsender::sVehicles.begin(); i != MSDevice_BTsender::sVehicles.end(); ++i) {
168 155256 : MSDevice_BTsender::VehicleInformation* vi = (*i).second;
169 : Boundary b = vi->getBoxBoundary();
170 155256 : b.grow(POSITION_EPS);
171 155256 : const float cmin[2] = {(float) b.xmin(), (float) b.ymin()};
172 155256 : const float cmax[2] = {(float) b.xmax(), (float) b.ymax()};
173 310512 : rt.Insert(cmin, cmax, vi);
174 : }
175 :
176 : // check visibility for all receivers
177 137687 : OptionsCont& oc = OptionsCont::getOptions();
178 137687 : bool allRecognitions = oc.getBool("device.btreceiver.all-recognitions");
179 275374 : bool haveOutput = oc.isSet("bt-output");
180 359911 : for (std::map<std::string, MSDevice_BTreceiver::VehicleInformation*>::iterator i = MSDevice_BTreceiver::sVehicles.begin(); i != MSDevice_BTreceiver::sVehicles.end();) {
181 : // collect surrounding vehicles
182 222224 : MSDevice_BTreceiver::VehicleInformation* vi = (*i).second;
183 : Boundary b = vi->getBoxBoundary();
184 222224 : b.grow(vi->range);
185 222224 : const float cmin[2] = {(float) b.xmin(), (float) b.ymin()};
186 222224 : const float cmax[2] = {(float) b.xmax(), (float) b.ymax()};
187 : std::set<const Named*> surroundingVehicles;
188 : Named::StoringVisitor sv(surroundingVehicles);
189 : rt.Search(cmin, cmax, sv);
190 :
191 : // loop over surrounding vehicles, check visibility status
192 364134 : for (const Named* vehicle : surroundingVehicles) {
193 141910 : if ((*i).first == vehicle->getID()) {
194 : // seeing oneself? skip
195 82778 : continue;
196 : }
197 59132 : updateVisibility(*vi, *MSDevice_BTsender::sVehicles.find(vehicle->getID())->second);
198 : }
199 :
200 222224 : if (vi->haveArrived) {
201 : // vehicle has left the simulation; remove
202 612 : if (haveOutput) {
203 348 : writeOutput((*i).first, vi->seen, allRecognitions);
204 : }
205 612 : delete vi;
206 : MSDevice_BTreceiver::sVehicles.erase(i++);
207 : } else {
208 : // vehicle is still in the simulation; reset state
209 221612 : vi->updates.erase(vi->updates.begin(), vi->updates.end() - 1);
210 : ++i;
211 : }
212 : }
213 :
214 : // remove arrived senders / reset state
215 292943 : for (std::map<std::string, MSDevice_BTsender::VehicleInformation*>::iterator i = MSDevice_BTsender::sVehicles.begin(); i != MSDevice_BTsender::sVehicles.end();) {
216 155256 : MSDevice_BTsender::VehicleInformation* vi = (*i).second;
217 155256 : if (vi->haveArrived) {
218 348 : delete vi;
219 : MSDevice_BTsender::sVehicles.erase(i++);
220 : } else {
221 154908 : vi->updates.erase(vi->updates.begin(), vi->updates.end() - 1);
222 : ++i;
223 : }
224 : }
225 137687 : return DELTA_T;
226 : }
227 :
228 :
229 : void
230 59132 : MSDevice_BTreceiver::BTreceiverUpdate::updateVisibility(MSDevice_BTreceiver::VehicleInformation& receiver,
231 : MSDevice_BTsender::VehicleInformation& sender) {
232 : const MSDevice_BTsender::VehicleState& receiverData = receiver.updates.back();
233 : const MSDevice_BTsender::VehicleState& senderData = sender.updates.back();
234 59132 : if (!receiver.amOnNet || !sender.amOnNet) {
235 : // at least one of the vehicles has left the simulation area for any reason
236 280 : if (receiver.currentlySeen.find(sender.getID()) != receiver.currentlySeen.end()) {
237 248 : leaveRange(receiver, receiverData, sender, senderData, 0);
238 : }
239 : }
240 :
241 59132 : const Position& oldReceiverPosition = receiver.updates.front().position;
242 59132 : const Position& oldSenderPosition = sender.updates.front().position;
243 :
244 : // let the other's current position be the one obtained by applying the relative direction vector to the initial position
245 : const Position senderDelta = senderData.position - oldSenderPosition;
246 : const Position receiverDelta = receiverData.position - oldReceiverPosition;
247 : const Position translatedSender = senderData.position - receiverDelta;
248 : // find crossing points
249 : std::vector<double> intersections;
250 59132 : GeomHelper::findLineCircleIntersections(oldReceiverPosition, receiver.range, oldSenderPosition, translatedSender, intersections);
251 59132 : switch (intersections.size()) {
252 58120 : case 0:
253 : // no intersections -> other vehicle either stays within or beyond range
254 58120 : if (receiver.amOnNet && sender.amOnNet && receiverData.position.distanceTo(senderData.position) < receiver.range) {
255 55680 : if (receiver.currentlySeen.find(sender.getID()) == receiver.currentlySeen.end()) {
256 204 : enterRange(0., receiverData, sender.getID(), senderData, receiver.currentlySeen);
257 : } else {
258 55476 : addRecognitionPoint(SIMTIME, receiverData, senderData, receiver.currentlySeen[sender.getID()]);
259 : }
260 : } else {
261 2440 : if (receiver.currentlySeen.find(sender.getID()) != receiver.currentlySeen.end()) {
262 24 : leaveRange(receiver, receiverData, sender, senderData, 0.);
263 : }
264 : }
265 : break;
266 1012 : case 1: {
267 : // one intersection -> other vehicle either enters or leaves the range
268 1012 : MSDevice_BTsender::VehicleState intersection1ReceiverData(receiverData);
269 1012 : intersection1ReceiverData.position = oldReceiverPosition + receiverDelta * intersections.front();
270 1012 : MSDevice_BTsender::VehicleState intersection1SenderData(senderData);
271 1012 : intersection1SenderData.position = oldSenderPosition + senderDelta * intersections.front();
272 1012 : if (receiver.currentlySeen.find(sender.getID()) != receiver.currentlySeen.end()) {
273 444 : leaveRange(receiver, intersection1ReceiverData,
274 444 : sender, intersection1SenderData, (intersections.front() - 1.) * TS);
275 : } else {
276 568 : enterRange((intersections.front() - 1.) * TS, intersection1ReceiverData,
277 568 : sender.getID(), intersection1SenderData, receiver.currentlySeen);
278 : }
279 : }
280 1012 : break;
281 0 : case 2:
282 : // two intersections -> other vehicle enters and leaves the range
283 0 : if (receiver.currentlySeen.find(sender.getID()) == receiver.currentlySeen.end()) {
284 0 : MSDevice_BTsender::VehicleState intersectionReceiverData(receiverData);
285 0 : intersectionReceiverData.position = oldReceiverPosition + receiverDelta * intersections.front();
286 0 : MSDevice_BTsender::VehicleState intersectionSenderData(senderData);
287 0 : intersectionSenderData.position = oldSenderPosition + senderDelta * intersections.front();
288 0 : enterRange((intersections.front() - 1.) * TS, intersectionReceiverData,
289 0 : sender.getID(), intersectionSenderData, receiver.currentlySeen);
290 0 : intersectionReceiverData.position = oldReceiverPosition + receiverDelta * intersections.back();
291 0 : intersectionSenderData.position = oldSenderPosition + senderDelta * intersections.back();
292 0 : leaveRange(receiver, intersectionReceiverData,
293 0 : sender, intersectionSenderData, (intersections.back() - 1.) * TS);
294 : } else {
295 0 : WRITE_WARNINGF(TL("The vehicle '%' cannot be in the range of vehicle '%', leave, and enter it in one step."), sender.getID(), receiver.getID());
296 : }
297 : break;
298 0 : default:
299 0 : WRITE_WARNING("Nope, a circle cannot be crossed more often than twice by a line.");
300 0 : break;
301 : }
302 59132 : }
303 :
304 :
305 : void
306 772 : MSDevice_BTreceiver::BTreceiverUpdate::enterRange(double atOffset, const MSDevice_BTsender::VehicleState& receiverState,
307 : const std::string& senderID, const MSDevice_BTsender::VehicleState& senderState,
308 : std::map<std::string, SeenDevice*>& currentlySeen) {
309 772 : MeetingPoint mp(SIMTIME + atOffset, receiverState, senderState);
310 772 : SeenDevice* sd = new SeenDevice(mp);
311 772 : currentlySeen[senderID] = sd;
312 772 : addRecognitionPoint(SIMTIME, receiverState, senderState, sd);
313 772 : }
314 :
315 :
316 : void
317 716 : MSDevice_BTreceiver::BTreceiverUpdate::leaveRange(VehicleInformation& receiverInfo, const MSDevice_BTsender::VehicleState& receiverState,
318 : MSDevice_BTsender::VehicleInformation& senderInfo, const MSDevice_BTsender::VehicleState& senderState,
319 : double tOffset) {
320 : std::map<std::string, SeenDevice*>::iterator i = receiverInfo.currentlySeen.find(senderInfo.getID());
321 : // check whether the other was recognized
322 716 : addRecognitionPoint(SIMTIME + tOffset, receiverState, senderState, i->second);
323 : // build leaving point
324 716 : i->second->meetingEnd = new MeetingPoint(STEPS2TIME(MSNet::getInstance()->getCurrentTimeStep()) + tOffset, receiverState, senderState);
325 716 : ConstMSEdgeVector::const_iterator begin = receiverInfo.route.begin() + i->second->meetingBegin.observerState.routePos;
326 716 : ConstMSEdgeVector::const_iterator end = receiverInfo.route.begin() + receiverState.routePos + 1;
327 716 : i->second->receiverRoute = toString<const MSEdge>(begin, end);
328 716 : begin = senderInfo.route.begin() + i->second->meetingBegin.seenState.routePos;
329 716 : end = senderInfo.route.begin() + senderState.routePos + 1;
330 716 : i->second->senderRoute = toString<const MSEdge>(begin, end);
331 716 : receiverInfo.seen[senderInfo.getID()].push_back(i->second);
332 : receiverInfo.currentlySeen.erase(i);
333 716 : }
334 :
335 :
336 : void
337 56964 : MSDevice_BTreceiver::BTreceiverUpdate::addRecognitionPoint(const double tEnd, const MSDevice_BTsender::VehicleState& receiverState,
338 : const MSDevice_BTsender::VehicleState& senderState,
339 : SeenDevice* senderDevice) const {
340 56964 : if (senderDevice->nextView == -1.) {
341 772 : senderDevice->nextView = senderDevice->lastView + inquiryDelaySlots(int(myOffTime / 0.000625 + .5)) * 0.000625;
342 : }
343 56964 : if (tEnd > senderDevice->nextView) {
344 56458 : senderDevice->lastView = senderDevice->nextView;
345 56458 : MeetingPoint* mp = new MeetingPoint(tEnd, receiverState, senderState);
346 56458 : senderDevice->recognitionPoints.push_back(mp);
347 56458 : senderDevice->nextView = senderDevice->lastView + inquiryDelaySlots(int(myOffTime / 0.000625 + .5)) * 0.000625;
348 : }
349 56964 : }
350 :
351 :
352 : void
353 348 : MSDevice_BTreceiver::BTreceiverUpdate::writeOutput(const std::string& id, const std::map<std::string, std::vector<SeenDevice*> >& seen, bool allRecognitions) {
354 348 : OutputDevice& os = OutputDevice::getDeviceByOption("bt-output");
355 696 : os.openTag("bt").writeAttr("id", id);
356 704 : for (const auto& item : seen) {
357 1072 : for (const SeenDevice* const device : item.second) {
358 716 : os.openTag("seen").writeAttr("id", item.first);
359 : const MSDevice_BTsender::VehicleState& obsBeg = device->meetingBegin.observerState;
360 : const MSDevice_BTsender::VehicleState& seenBeg = device->meetingBegin.seenState;
361 716 : os.writeAttr("tBeg", device->meetingBegin.t)
362 716 : .writeAttr("observerPosBeg", obsBeg.position).writeAttr("observerSpeedBeg", obsBeg.speed)
363 716 : .writeAttr("observerLaneIDBeg", obsBeg.laneID).writeAttr("observerLanePosBeg", obsBeg.lanePos)
364 716 : .writeAttr("seenPosBeg", seenBeg.position).writeAttr("seenSpeedBeg", seenBeg.speed)
365 716 : .writeAttr("seenLaneIDBeg", seenBeg.laneID).writeAttr("seenLanePosBeg", seenBeg.lanePos);
366 716 : const MSDevice_BTsender::VehicleState& obsEnd = device->meetingEnd->observerState;
367 : const MSDevice_BTsender::VehicleState& seenEnd = device->meetingEnd->seenState;
368 716 : os.writeAttr("tEnd", device->meetingEnd->t)
369 716 : .writeAttr("observerPosEnd", obsEnd.position).writeAttr("observerSpeedEnd", obsEnd.speed)
370 716 : .writeAttr("observerLaneIDEnd", obsEnd.laneID).writeAttr("observerLanePosEnd", obsEnd.lanePos)
371 716 : .writeAttr("seenPosEnd", seenEnd.position).writeAttr("seenSpeedEnd", seenEnd.speed)
372 716 : .writeAttr("seenLaneIDEnd", seenEnd.laneID).writeAttr("seenLanePosEnd", seenEnd.lanePos)
373 716 : .writeAttr("observerRoute", device->receiverRoute).writeAttr("seenRoute", device->senderRoute);
374 28692 : for (const MeetingPoint* const mp : device->recognitionPoints) {
375 28364 : os.openTag("recognitionPoint").writeAttr("t", mp->t)
376 28364 : .writeAttr("observerPos", mp->observerState.position).writeAttr("observerSpeed", mp->observerState.speed)
377 28364 : .writeAttr("observerLaneID", mp->observerState.laneID).writeAttr("observerLanePos", mp->observerState.lanePos)
378 28364 : .writeAttr("seenPos", mp->seenState.position).writeAttr("seenSpeed", mp->seenState.speed)
379 28364 : .writeAttr("seenLaneID", mp->seenState.laneID).writeAttr("seenLanePos", mp->seenState.lanePos)
380 56728 : .closeTag();
381 28364 : if (!allRecognitions) {
382 : break;
383 : }
384 : }
385 1432 : os.closeTag();
386 : }
387 : }
388 348 : os.closeTag();
389 348 : }
390 :
391 :
392 : // ---------------------------------------------------------------------------
393 : // MSDevice_BTreceiver-methods
394 : // ---------------------------------------------------------------------------
395 612 : MSDevice_BTreceiver::~MSDevice_BTreceiver() {
396 612 : }
397 :
398 :
399 : bool
400 5616 : MSDevice_BTreceiver::notifyEnter(SUMOTrafficObject& veh, MSMoveReminder::Notification reason, const MSLane* /* enteredLane */) {
401 5616 : if (reason == MSMoveReminder::NOTIFICATION_DEPARTED && sVehicles.find(veh.getID()) == sVehicles.end()) {
402 612 : sVehicles[veh.getID()] = new VehicleInformation(veh.getID(), myRange);
403 612 : sVehicles[veh.getID()]->route.push_back(veh.getEdge());
404 : }
405 5616 : if (reason == MSMoveReminder::NOTIFICATION_TELEPORT && sVehicles.find(veh.getID()) != sVehicles.end()) {
406 0 : sVehicles[veh.getID()]->amOnNet = true;
407 : }
408 5616 : if (reason == MSMoveReminder::NOTIFICATION_TELEPORT || reason == MSMoveReminder::NOTIFICATION_JUNCTION) {
409 1640 : sVehicles[veh.getID()]->route.push_back(veh.getEdge());
410 : }
411 5616 : const std::string location = MSDevice_BTsender::getLocation(veh);
412 11232 : sVehicles[veh.getID()]->updates.push_back(MSDevice_BTsender::VehicleState(veh.getSpeed(), veh.getPosition(), location, veh.getPositionOnLane(), veh.getRoutePosition()));
413 5616 : return true;
414 : }
415 :
416 :
417 : bool
418 189626 : MSDevice_BTreceiver::notifyMove(SUMOTrafficObject& veh, double /* oldPos */, double newPos, double newSpeed) {
419 189626 : if (sVehicles.find(veh.getID()) == sVehicles.end()) {
420 0 : WRITE_WARNINGF(TL("btreceiver: Can not update position of vehicle '%' which is not on the road."), veh.getID());
421 0 : return true;
422 : }
423 189626 : const std::string location = MSDevice_BTsender::getLocation(veh);
424 379252 : sVehicles[veh.getID()]->updates.push_back(MSDevice_BTsender::VehicleState(newSpeed, veh.getPosition(), location, newPos, veh.getRoutePosition()));
425 : return true;
426 : }
427 :
428 :
429 : bool
430 5412 : MSDevice_BTreceiver::notifyLeave(SUMOTrafficObject& veh, double /* lastPos */, MSMoveReminder::Notification reason, const MSLane* /* enteredLane */) {
431 5412 : if (reason < MSMoveReminder::NOTIFICATION_TELEPORT) {
432 : return true;
433 : }
434 408 : if (sVehicles.find(veh.getID()) == sVehicles.end()) {
435 0 : WRITE_WARNINGF(TL("btreceiver: Can not update position of vehicle '%' which is not on the road."), veh.getID());
436 0 : return true;
437 : }
438 408 : const std::string location = MSDevice_BTsender::getLocation(veh);
439 408 : sVehicles[veh.getID()]->updates.push_back(MSDevice_BTsender::VehicleState(veh.getSpeed(), veh.getPosition(), location, veh.getPositionOnLane(), veh.getRoutePosition()));
440 408 : if (reason == MSMoveReminder::NOTIFICATION_TELEPORT) {
441 0 : sVehicles[veh.getID()]->amOnNet = false;
442 : }
443 408 : if (reason >= MSMoveReminder::NOTIFICATION_ARRIVED) {
444 408 : sVehicles[veh.getID()]->amOnNet = false;
445 408 : sVehicles[veh.getID()]->haveArrived = true;
446 : }
447 : return true;
448 : }
449 :
450 :
451 : double
452 57230 : MSDevice_BTreceiver::inquiryDelaySlots(const int backoffLimit) {
453 : const int phaseOffset = RandHelper::rand(2047, &sRecognitionRNG);
454 57230 : const bool interlaced = RandHelper::rand(&sRecognitionRNG) < 0.7;
455 57230 : const double delaySlots = RandHelper::rand(&sRecognitionRNG) * 15;
456 57230 : const int backoff = RandHelper::rand(backoffLimit, &sRecognitionRNG);
457 57230 : if (interlaced) {
458 40054 : return RandHelper::rand(&sRecognitionRNG) * 31 + backoff;
459 : }
460 17176 : if (RandHelper::rand(31, &sRecognitionRNG) < 16) {
461 : // correct train for f0
462 8755 : return delaySlots + backoff;
463 : }
464 8421 : if (RandHelper::rand(30, &sRecognitionRNG) < 16) {
465 : // correct train for f1
466 4590 : return 2048 - phaseOffset + delaySlots + backoff;
467 : }
468 3831 : if (RandHelper::rand(29, &sRecognitionRNG) < 16) {
469 : // f2 is in train A but has overlap with both trains
470 2336 : if (2 * 2048 - phaseOffset + backoff < 4096) {
471 1717 : return 2 * 2048 - phaseOffset + delaySlots + backoff;
472 : }
473 : // the following is wrong but should only happen in about 3% of the non-interlaced cases
474 619 : return 2 * 2048 - phaseOffset + delaySlots + backoff;
475 : }
476 1495 : return 2 * 2048 + delaySlots + backoff;
477 : }
478 :
479 :
480 : /****************************************************************************/
|