Eclipse SUMO - Simulation of Urban MObility
PolygonDynamics.cpp
Go to the documentation of this file.
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 /****************************************************************************/
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"
28 
29 
30 //#define DEBUG_DYNAMIC_SHAPES
31 
33  SUMOPolygon* p,
34  SUMOTrafficObject* trackedObject,
35  const std::vector<double>& timeSpan,
36  const std::vector<double>& alphaSpan,
37  bool looped,
38  bool rotate) :
39  myPolygon(p),
40  myCurrentTime(0),
41  myLastUpdateTime(creationTime),
42  animated(!timeSpan.empty()),
43  looped(looped),
44  tracking(trackedObject != nullptr),
45  rotate(rotate),
46  myTrackedObject(trackedObject),
47  myTrackedObjectID(""),
48  myTrackedObjectsInitialPositon(nullptr),
49  myTrackedObjectsInitialAngle(-1),
50  myOriginalShape(nullptr),
51  myTimeSpan(nullptr),
52  myAlphaSpan(nullptr),
53  myVis(nullptr) {
54  // Check for consistency
55  if (animated) {
56  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  myPrevTime = myTimeSpan->begin();
68  myNextTime = ++myTimeSpan->begin();
69  }
70 #ifdef DEBUG_DYNAMIC_SHAPES
71  else {
72  assert(myAlphaSpan == nullptr);
73  }
74 #endif
75 
76  myOriginalShape = std::unique_ptr<PositionVector>(new PositionVector(p->getShape()));
77 
78  if (tracking) {
79  // Try initializing the tracked position (depends on whether object is already on the road)
82  }
83 
84  if (!alphaSpan.empty()) {
85  myAlphaSpan = std::unique_ptr<std::vector<double> >(new std::vector<double>(alphaSpan));
86  assert(myAlphaSpan->size() >= 2);
87  assert(myAlphaSpan->size() == myTimeSpan->size());
88  myPrevAlpha = myAlphaSpan->begin();
89  myNextAlpha = ++myAlphaSpan->begin();
90  }
91 }
92 
94 {}
95 
96 
99 #ifdef DEBUG_DYNAMIC_SHAPES
100  std::cout << t << " PolygonDynamics::update() for polygon '" << myPolygon->getID() << "'" << std::endl;
101 #endif
102  const double simtime = STEPS2TIME(t);
103  const double dt = simtime - myLastUpdateTime;
104  myLastUpdateTime = simtime;
105 
106  SUMOTime ret = DELTA_T;
107 
108  if (tracking) {
109  if (myTrackedObjectsInitialPositon == nullptr) {
110  // Tracked object hasn't entered the network, until now.
111  // Continuously try to obtain its initial position
113  }
114  if (myTrackedObjectsInitialPositon != nullptr) {
115  // Initial position was initialized, relative tracking is possible
116  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  if (rotate) {
125  const double relRotation = myTrackedObject->getAngle() - myTrackedObjectsInitialAngle;
126  newShape.rotate2D(relRotation);
127 #ifdef DEBUG_DYNAMIC_SHAPES
128  std::cout << " Relative rotation wrt original rotation: " << relRotation << std::endl;
129 #endif
130  }
131  newShape.add(objPos);
132  myPolygon->setShape(newShape);
133  }
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  if (animated) {
150  // Continue animation
151  myCurrentTime += dt;
152  while (myCurrentTime >= *myNextTime) {
153  // step forward along time lines to appropriate anchor points
154  ++myPrevTime;
155  ++myNextTime;
156  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  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  if (looped) {
179  const bool resetAnimation = myCurrentTime >= *myNextTime;
180 #ifdef DEBUG_DYNAMIC_SHAPES
181  if (resetAnimation) {
182  std::cout << " (resetting animation!)";
183  }
184 #endif
185  if (resetAnimation) {
186  // Reset animation time line to start, if appropriate
187  while (myCurrentTime >= *myNextTime) {
189  }
191  myPrevTime = myTimeSpan->begin();
192  myNextTime = ++myTimeSpan->begin();
193  if (myAlphaSpan != nullptr) {
194  myPrevAlpha = myAlphaSpan->begin();
195  myNextAlpha = ++myAlphaSpan->begin();
196  }
197  }
198  }
199  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  if (*myNextTime - *myPrevTime != 0) {
210  theta = (myCurrentTime - *myPrevTime) / (*myNextTime - *myPrevTime);
211  }
212  }
213  if (myAlphaSpan != nullptr) {
214  // Interpolate values of properties
215  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  return ret;
226 }
227 
228 void
230  const Position& objPos = myTrackedObject->getPosition();
231  if (objPos != Position::INVALID) {
232  // Initialize Position of tracked object
233  myTrackedObjectsInitialPositon = std::unique_ptr<Position>(new Position(objPos));
235  // Store original polygon shape relative to the tracked object's original position
237 #ifdef DEBUG_DYNAMIC_SHAPES
238  std::cout << " Tracking object '" << myTrackedObject->getID() << "' at initial positon: " << *myTrackedObjectsInitialPositon << std::endl;
239 #endif
240  }
241 }
242 
243 void
245  int a = (int) alpha;
246  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 }
long long int SUMOTime
Definition: GUI.h:35
SUMOTime DELTA_T
Definition: SUMOTime.cpp:38
#define STEPS2TIME(x)
Definition: SUMOTime.h:55
T MAX2(T a, T b)
Definition: StdDefs.h:82
const std::string & getID() const
Returns the id.
Definition: Named.h:74
std::vector< double >::const_iterator myNextAlpha
PolygonDynamics(double creationTime, SUMOPolygon *p, SUMOTrafficObject *trackedObject, const std::vector< double > &timeSpan, const std::vector< double > &alphaSpan, bool looped, bool rotate)
Constructor that takes a SUMOPolygon and adds timelines for the properties to be modified dynamically...
std::unique_ptr< Position > myTrackedObjectsInitialPositon
Initial position of the tracked object.
bool looped
Whether animation should be looped.
virtual ~PolygonDynamics()
void initTrackedPosition()
Initialize the object's position.
bool tracking
Whether this polygon tracks an object.
std::string myTrackedObjectID
double myTrackedObjectsInitialAngle
Initial angle of the tracked object.
std::unique_ptr< std::vector< double > > myTimeSpan
Time points corresponding to the anchor values of the dynamic properties.
std::vector< double >::const_iterator myNextTime
void setAlpha(double alpha)
Sets the alpha value for the shape's color.
bool animated
Whether this polygon is animated, i.e., whether timelines should be used to control properties.
double myCurrentTime
Current time.
SUMOTime update(SUMOTime t)
Updates the polygon according to its timeSpan and follows the tracked object.
SUMOTrafficObject * myTrackedObject
An object tracked by the shape, deletion by caller.
std::vector< double >::const_iterator myPrevTime
Pointer to the next time points in timeSpan.
SUMOPolygon * myPolygon
The polygon this dynamics acts upon.
bool rotate
Whether this polygon should be rotated with the tracked object.
std::unique_ptr< PositionVector > myOriginalShape
the original shape of the polygon (in case of tracking another object, this is converted to relative ...
std::unique_ptr< std::vector< double > > myAlphaSpan
Alpha values corresponding to.
double myLastUpdateTime
The last time the animation has been updated.
std::vector< double >::const_iterator myPrevAlpha
Pointer to the next alpha points in alphaSpan.
A point in 2D or 3D with translation and scaling methods.
Definition: Position.h:37
static const Position INVALID
used to indicate that a position is valid
Definition: Position.h:322
A list of positions.
void rotate2D(double angle)
void add(double xoff, double yoff, double zoff)
const PositionVector & getShape() const
Returns the shape of the polygon.
Definition: SUMOPolygon.cpp:51
virtual void setShape(const PositionVector &shape)
Sets the shape of the polygon.
Definition: SUMOPolygon.cpp:87
Representation of a vehicle, person, or container.
virtual double getAngle() const =0
Returns the object's angle in degrees.
virtual Position getPosition(const double offset=0) const =0
Return current position (x/y, cartesian)
void setShapeAlpha(unsigned char alpha)
Sets a new alpha value.
Definition: Shape.h:143