Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
eclipse
GitHub Repository: eclipse/sumo
Path: blob/main/src/utils/shapes/PolygonDynamics.cpp
169678 views
1
/****************************************************************************/
2
// Eclipse SUMO, Simulation of Urban MObility; see https://eclipse.dev/sumo
3
// Copyright (C) 2004-2025 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
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
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)
80
initTrackedPosition();
81
myTrackedObjectID = myTrackedObject->getID();
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
93
PolygonDynamics::~PolygonDynamics()
94
{}
95
96
97
SUMOTime
98
PolygonDynamics::update(SUMOTime t) {
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
112
initTrackedPosition();
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) {
188
myCurrentTime -= *myNextTime;
189
}
190
myCurrentTime = MAX2(myCurrentTime, 0.0);
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
229
PolygonDynamics::initTrackedPosition() {
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));
234
myTrackedObjectsInitialAngle = myTrackedObject->getAngle();
235
// Store original polygon shape relative to the tracked object's original position
236
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
}
242
243
void
244
PolygonDynamics::setAlpha(double alpha) {
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
}
251
252