LCOV - code coverage report
Current view: top level - src/microsim/devices - MSDevice_BTreceiver.cpp (source / functions) Coverage Total Hit
Test: lcov.info Lines: 90.8 % 240 218
Test Date: 2026-03-26 16:31:35 Functions: 100.0 % 18 18

            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              : /****************************************************************************/
        

Generated by: LCOV version 2.0-1