LCOV - code coverage report
Current view: top level - src/utils/shapes - PolygonDynamics.cpp (source / functions) Hit Total Coverage
Test: lcov.info Lines: 76 76 100.0 %
Date: 2024-05-05 15:31:14 Functions: 6 6 100.0 %

          Line data    Source code
       1             : /****************************************************************************/
       2             : // Eclipse SUMO, Simulation of Urban MObility; see https://eclipse.dev/sumo
       3             : // Copyright (C) 2004-2024 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    PolygonDynamics.cpp
      15             : /// @author  Leonhard Luecken
      16             : /// @date    Apr 2019
      17             : ///
      18             : // A polygon, which holds a timeSpan for displaying dynamic properties
      19             : /****************************************************************************/
      20             : 
      21             : 
      22             : #include "PolygonDynamics.h"
      23             : 
      24             : #include <assert.h>
      25             : #include "utils/common/StdDefs.h"
      26             : #include "utils/common/SUMOTime.h"
      27             : #include "utils/vehicle/SUMOTrafficObject.h"
      28             : 
      29             : 
      30             : //#define DEBUG_DYNAMIC_SHAPES
      31             : 
      32         196 : PolygonDynamics::PolygonDynamics(double creationTime,
      33             :                                  SUMOPolygon* p,
      34             :                                  SUMOTrafficObject* trackedObject,
      35             :                                  const std::vector<double>& timeSpan,
      36             :                                  const std::vector<double>& alphaSpan,
      37             :                                  bool looped,
      38         196 :                                  bool rotate) :
      39         196 :     myPolygon(p),
      40         196 :     myCurrentTime(0),
      41         196 :     myLastUpdateTime(creationTime),
      42         196 :     animated(!timeSpan.empty()),
      43         196 :     looped(looped),
      44         196 :     tracking(trackedObject != nullptr),
      45         196 :     rotate(rotate),
      46         196 :     myTrackedObject(trackedObject),
      47         196 :     myTrackedObjectID(""),
      48             :     myTrackedObjectsInitialPositon(nullptr),
      49         196 :     myTrackedObjectsInitialAngle(-1),
      50             :     myOriginalShape(nullptr),
      51             :     myTimeSpan(nullptr),
      52             :     myAlphaSpan(nullptr),
      53         196 :     myVis(nullptr) {
      54             :     // Check for consistency
      55         196 :     if (animated) {
      56         272 :         myTimeSpan = std::unique_ptr<std::vector<double> >(new std::vector<double>(timeSpan));
      57             :         assert(myTimeSpan->size() >= 2);
      58             :         assert((*myTimeSpan)[0] == 0.0);
      59             :         assert(myAlphaSpan == nullptr || myAlphaSpan->size() >= 2);
      60             : #ifdef DEBUG_DYNAMIC_SHAPES
      61             :         if (myTimeSpan->size() >= 2) {
      62             :             for (unsigned int i = 1; i < myTimeSpan->size(); ++i) {
      63             :                 assert((*myTimeSpan)[i - 1] <= (*myTimeSpan)[i]);
      64             :             }
      65             :         }
      66             : #endif
      67         136 :         myPrevTime = myTimeSpan->begin();
      68         136 :         myNextTime = ++myTimeSpan->begin();
      69             :     }
      70             : #ifdef DEBUG_DYNAMIC_SHAPES
      71             :     else  {
      72             :         assert(myAlphaSpan == nullptr);
      73             :     }
      74             : #endif
      75             : 
      76         196 :     myOriginalShape = std::unique_ptr<PositionVector>(new PositionVector(p->getShape()));
      77             : 
      78         196 :     if (tracking) {
      79             :         // Try initializing the tracked position (depends on whether object is already on the road)
      80         140 :         initTrackedPosition();
      81         140 :         myTrackedObjectID = myTrackedObject->getID();
      82             :     }
      83             : 
      84         196 :     if (!alphaSpan.empty()) {
      85         232 :         myAlphaSpan = std::unique_ptr<std::vector<double> >(new std::vector<double>(alphaSpan));
      86             :         assert(myAlphaSpan->size() >= 2);
      87             :         assert(myAlphaSpan->size() == myTimeSpan->size());
      88         116 :         myPrevAlpha = myAlphaSpan->begin();
      89         116 :         myNextAlpha = ++myAlphaSpan->begin();
      90             :     }
      91         196 : }
      92             : 
      93         392 : PolygonDynamics::~PolygonDynamics()
      94         392 : {}
      95             : 
      96             : 
      97             : SUMOTime
      98        4386 : PolygonDynamics::update(SUMOTime t) {
      99             : #ifdef DEBUG_DYNAMIC_SHAPES
     100             :     std::cout << t << " PolygonDynamics::update() for polygon '" << myPolygon->getID() << "'" << std::endl;
     101             : #endif
     102        4386 :     const double simtime = STEPS2TIME(t);
     103        4386 :     const double dt = simtime - myLastUpdateTime;
     104        4386 :     myLastUpdateTime = simtime;
     105             : 
     106        4386 :     SUMOTime ret = DELTA_T;
     107             : 
     108        4386 :     if (tracking) {
     109        4156 :         if (myTrackedObjectsInitialPositon == nullptr) {
     110             :             // Tracked object hasn't entered the network, until now.
     111             :             // Continuously try to obtain its initial position
     112          10 :             initTrackedPosition();
     113             :         }
     114        4156 :         if (myTrackedObjectsInitialPositon != nullptr) {
     115             :             // Initial position was initialized, relative tracking is possible
     116        4156 :             const Position& objPos = myTrackedObject->getPosition();
     117             :             const bool onRoad = objPos != Position::INVALID;
     118             :             if (onRoad) {
     119             : #ifdef DEBUG_DYNAMIC_SHAPES
     120             :                 std::cout << " Tracked object '" << myTrackedObject->getID() << "' is on the road. Tracked position=" << objPos << std::endl;
     121             : #endif
     122             :                 // Update polygon's shape
     123             :                 PositionVector newShape(*myOriginalShape);
     124        4156 :                 if (rotate) {
     125        4156 :                     const double relRotation = myTrackedObject->getAngle() - myTrackedObjectsInitialAngle;
     126        4156 :                     newShape.rotate2D(relRotation);
     127             : #ifdef DEBUG_DYNAMIC_SHAPES
     128             :                     std::cout << " Relative rotation wrt original rotation: " << relRotation << std::endl;
     129             : #endif
     130             :                 }
     131        4156 :                 newShape.add(objPos);
     132        4156 :                 myPolygon->setShape(newShape);
     133        4156 :             }
     134             : #ifdef DEBUG_DYNAMIC_SHAPES
     135             :             else {
     136             :                 // tracked object is off road
     137             :                 std::cout << " Tracked object '" << myTrackedObject->getID() << "' is off road." << std::endl;
     138             :             }
     139             : #endif
     140             :         }
     141             : #ifdef DEBUG_DYNAMIC_SHAPES
     142             :         else {
     143             :             // Initial position was not initialized, yet
     144             :             std::cout << " Tracked object '" << myTrackedObject->getID() << "' hasn't entered the network since tracking was started." << std::endl;
     145             :         }
     146             : #endif
     147             :     }
     148             : 
     149        4386 :     if (animated) {
     150             :         // Continue animation
     151        1150 :         myCurrentTime += dt;
     152        2742 :         while (myCurrentTime >= *myNextTime) {
     153             :             // step forward along time lines to appropriate anchor points
     154             :             ++myPrevTime;
     155             :             ++myNextTime;
     156         568 :             if (myNextTime == myTimeSpan->end()) {
     157             :                 // Set iterators back to point to valid positions
     158             :                 --myPrevTime;
     159             :                 --myNextTime;
     160             :                 break;
     161             :             } else {
     162             :                 // Forward corresponding iterators for property time lines
     163         442 :                 if (myAlphaSpan != nullptr) {
     164             :                     ++myPrevAlpha;
     165             :                     ++myNextAlpha;
     166             :                 }
     167             :             }
     168             :         }
     169             : 
     170             :         // Linear interpolation factor between previous and next time
     171             :         double theta = 1.0;
     172             : #ifdef DEBUG_DYNAMIC_SHAPES
     173             :         std::cout << " animation: dt=" << dt
     174             :                   << ", current animation time: " << myCurrentTime
     175             :                   << ", previous anchor time: " << *myPrevTime
     176             :                   << ", next anchor time: " << *myNextTime;
     177             : #endif
     178        1150 :         if (looped) {
     179         100 :             const bool resetAnimation = myCurrentTime >= *myNextTime;
     180             : #ifdef DEBUG_DYNAMIC_SHAPES
     181             :             if (resetAnimation) {
     182             :                 std::cout << " (resetting animation!)";
     183             :             }
     184             : #endif
     185         100 :             if (resetAnimation) {
     186             :                 // Reset animation time line to start, if appropriate
     187          40 :                 while (myCurrentTime >= *myNextTime) {
     188          20 :                     myCurrentTime -= *myNextTime;
     189             :                 }
     190          20 :                 myCurrentTime = MAX2(myCurrentTime, 0.0);
     191          20 :                 myPrevTime = myTimeSpan->begin();
     192          20 :                 myNextTime = ++myTimeSpan->begin();
     193          20 :                 if (myAlphaSpan != nullptr) {
     194          20 :                     myPrevAlpha = myAlphaSpan->begin();
     195          20 :                     myNextAlpha = ++myAlphaSpan->begin();
     196             :                 }
     197             :             }
     198             :         }
     199        1150 :         if (myCurrentTime >= *myNextTime) {
     200             :             assert(!looped);
     201             :             // Reached the end of the dynamics, indicate expiration by returning zero
     202             :             // and set all properties to the final state (theta remains one)
     203             :             ret = 0;
     204             : #ifdef DEBUG_DYNAMIC_SHAPES
     205             :             std::cout << " (animation elapsed!)";
     206             : #endif
     207             :         } else {
     208             :             // Animation is still going on, schedule next update
     209        1044 :             if (*myNextTime - *myPrevTime != 0) {
     210        1044 :                 theta = (myCurrentTime - *myPrevTime) / (*myNextTime - *myPrevTime);
     211             :             }
     212             :         }
     213        1150 :         if (myAlphaSpan != nullptr) {
     214             :             // Interpolate values of properties
     215        1000 :             setAlpha(*myPrevAlpha + theta * (*myNextAlpha - *myPrevAlpha));
     216             : #ifdef DEBUG_DYNAMIC_SHAPES
     217             :             std::cout << ", previous anchor alpha: " << *myPrevAlpha
     218             :                       << ", next anchor alpha: " << *myNextAlpha;
     219             : #endif
     220             :         }
     221             : #ifdef DEBUG_DYNAMIC_SHAPES
     222             :         std::cout << ", theta=" << theta << std::endl;
     223             : #endif
     224             :     }
     225        4386 :     return ret;
     226             : }
     227             : 
     228             : void
     229         150 : PolygonDynamics::initTrackedPosition() {
     230         150 :     const Position& objPos = myTrackedObject->getPosition();
     231             :     if (objPos != Position::INVALID) {
     232             :         // Initialize Position of tracked object
     233         140 :         myTrackedObjectsInitialPositon = std::unique_ptr<Position>(new Position(objPos));
     234         140 :         myTrackedObjectsInitialAngle = myTrackedObject->getAngle();
     235             :         // Store original polygon shape relative to the tracked object's original position
     236         140 :         myOriginalShape->sub(*myTrackedObjectsInitialPositon);
     237             : #ifdef DEBUG_DYNAMIC_SHAPES
     238             :         std::cout << " Tracking object '" << myTrackedObject->getID() << "' at initial positon: " << *myTrackedObjectsInitialPositon << std::endl;
     239             : #endif
     240             :     }
     241         150 : }
     242             : 
     243             : void
     244        1000 : PolygonDynamics::setAlpha(double alpha) {
     245        1000 :     int a = (int) alpha;
     246        1000 :     myPolygon->setShapeAlpha((unsigned char) a);
     247             : #ifdef DEBUG_DYNAMIC_SHAPES
     248             :     std::cout << "\n   DynamicPolygon::setAlpha() Converted alpha=" << alpha << " into myAlpha=" << a << std::endl;
     249             : #endif
     250        1000 : }

Generated by: LCOV version 1.14