Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
eclipse
GitHub Repository: eclipse/sumo
Path: blob/main/src/utils/emissions/CharacteristicMap.h
169678 views
1
/****************************************************************************/
2
// Eclipse SUMO, Simulation of Urban MObility; see https://eclipse.dev/sumo
3
// Copyright (C) 2002-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 CharacteristicMap.h
15
/// @author Kevin Badalian ([email protected])
16
/// @date 2021-02
17
///
18
// Characteristic map for vehicle type parameters as needed by the MMPEVEM model
19
// Teaching and Research Area Mechatronics in Mobile Propulsion (MMP), RWTH Aachen
20
/****************************************************************************/
21
22
23
/******************************************************************************
24
* ============================= Example Usage ============================== *
25
******************************************************************************
26
* *
27
* Assume a function f which maps from R^2 to R^1 according to... *
28
* *
29
* | 0 | 1 | 2 | 3 | 4 -> x_1 *
30
* ----|------------------------ *
31
* -1 | 1 | 3 | 1 | -2 | *
32
* 1 | 1 | -2 | -3 | 7 | 5 *
33
* 3 | -2 | -1 | 0 | 1 | 3 *
34
* 5 | | 0 | 8 | 4 | 4 *
35
* *
36
* | *
37
* v *
38
* x_2 *
39
* *
40
* ... so that, for example, f(3, 1) = 7. Note that f is not defined at *
41
* (4, -1) and (0, 5). There are two ways to create a CharacteristicMap *
42
* object for this function. *
43
* 1) Using the standard constructor: *
44
* // Axes *
45
* std::vector<std::vector<double>> axes; *
46
* axes.push_back(std::vector<double>{0, 1, 2, 3, 4}); // Axis 1 *
47
* axes.push_back(std::vector<double>{-1, 1, 3, 5}); // Axis 2 *
48
* // Flattened row-major map entries *
49
* std::vector<double> flattenedMap{1, 3, 1, -2, std::nan(""), *
50
* 1, -2, -3, 7, 5, -2, -1, 0, 1, 3, std::nan(""), 0, 8, 4, 4}; *
51
* *
52
* CharacteristicMap map1(2, // Mapping from R^2... *
53
* 1, // ... to R^1 *
54
* axes, *
55
* flattenedMap); *
56
* *
57
* 2) Using a string-encoding of the map: *
58
* CharacteristicMap map2("2,1|0,1,2,3,4;-1,1,3,5|1,3,1,-2,nan," *
59
* "1,-2,-3,7,5,-2,-1,0,1,3,nan,0,8,4,4"); *
60
* *
61
* See below for an in-depth explanation of the format. *
62
* *
63
* *
64
* To evaluate the map at, for instance, p = (2.2, 2), one must call: *
65
* std::vector<double> res = map1.eval(std::vector<double>{2.2, 2}, // p *
66
* 1e-3); // eps *
67
* if(std::isnan(res[0])) *
68
* std::cout << "[WARNING] Couldn't evaluate the map." << std::endl; *
69
* else *
70
* std::cout << "res = " << res[0] << std::endl; *
71
* *
72
* The epsilon value is used for numerical reasons and decides how much a *
73
* point must deviate from its nearest neighbor before linear interpolation *
74
* is applied or when a point is considered outside of the map. The default *
75
* is 1e-6. *
76
* *
77
* *
78
* The string-encoding of a CharacteristicMap that maps from R^m to R^n is *
79
* formally defined as *
80
* "m,n|A_1[1],A_1[2],...,A_1[l1];A_2[1],A_2[2],...,A_2[l2];...;\ *
81
* A_m[1],A_m[2],...,A_m[lm]|\ *
82
* M_flat[1],M_flat[2],...,M_flat[l1*l2*...*lm]" *
83
* where A_i[j] denotes the j-th value of the i-th axis (which has li values *
84
* total) and M_flat[i] stands for the i-th entry in the row-major flattened *
85
* map. To be more specific, given a map M, its flattened version is *
86
* computed as follows (using pseudo code): *
87
* M_flat = "" *
88
* for i_m in {1,2,...,lm}: // Last axis *
89
* ... *
90
* for i_2 in {1,2,...,l2}: // Second axis *
91
* for i_1 in {1,2,...,l1}: // First axis (i.e. row axis) *
92
* for d in {1,2,...,n}: // Image dimensions *
93
* M_flat += M[i_1,i_2,...,i_m][d] + "," *
94
* removeTrailingComma(M_flat) *
95
* *
96
******************************************************************************/
97
#pragma once
98
99
#include <vector>
100
#include <string>
101
102
103
/**
104
* \class CharacteristicMap
105
* \brief The purpose of this class is to store a characteristic map (German:
106
* Kennfeld) of arbitrary dimensions and to provide functions in order to
107
* evaluate/interpolate points in it.
108
*/
109
class CharacteristicMap {
110
private:
111
/// Dimension of the map's domain
112
int domainDim;
113
114
/// Image dimension of the map
115
int imageDim;
116
117
/// Vector containing the values along each domain axis in ascending order
118
std::vector<std::vector<double>> axes;
119
120
/// Flattened map entries
121
std::vector<double> flattenedMap;
122
123
/// Stride for each domain dimension in the flattened map
124
std::vector<int> strides;
125
126
/**
127
* \brief Determine the stride for each map dimension in the flattened map.
128
*/
129
void determineStrides();
130
131
/**
132
* \brief Compute the index of a map entry in the flattened map.
133
*
134
* \param[in] ref_idxs Non-flattened map indices
135
* \returns Flattened map index
136
* \throws std::runtime_error
137
*/
138
int calcFlatIdx(const std::vector<int>& ref_idxs) const;
139
140
/**
141
* \brief Determine the indices of the nearest neighbor of a point in the map.
142
*
143
* A point has no such neighbor if it lies outside of the range of an axis
144
* with respect to some epsilon.
145
* \param[in] ref_p A point
146
* \param[out] ref_idxs A vector into which the indices shall be written
147
* \param[in] eps An epsilon value
148
* \returns 0 if a nearest neighbor could be found, else -1
149
* \throws std::runtime_error
150
*/
151
int findNearestNeighborIdxs(const std::vector<double>& ref_p,
152
std::vector<int>& ref_idxs, double eps = 1e-6) const;
153
154
/**
155
* \brief Access a map entry using its indices.
156
*
157
* \param[in] ref_idxs A vector containing indices
158
* \returns A vector containing the image values of the map at the specified
159
* location
160
* \throws std::runtime_error
161
*/
162
std::vector<double> at(const std::vector<int>& ref_idxs) const;
163
164
165
166
public:
167
/**
168
* \brief Constructor
169
*
170
* \param[in] domainDim The map's domain dimension
171
* \param[in] imageDim The map's image dimension
172
* \param[in] ref_axes A vector of vectors containing the entries of their
173
* respective axes in ascending order
174
* \param[in] ref_flattenedMap The row-major flattened entries of the map
175
* (i.e. the map is flattened along its first axis)
176
* \throws std::runtime_error
177
*/
178
CharacteristicMap(int domainDim, int imageDim,
179
const std::vector<std::vector<double>>& ref_axes,
180
const std::vector<double>& ref_flattenedMap);
181
182
/**
183
* \brief Constructor
184
*
185
* \param[in] ref_mapString A string representation of a characteristic map
186
* (cf. example at the top of the file)
187
* throws std::runtime_error
188
*/
189
CharacteristicMap(const std::string& ref_mapString);
190
191
/**
192
* \brief Encode the map as a string.
193
*
194
* \returns A string representation of the characteristic map (cf. example at
195
* the top of the file)
196
*/
197
std::string toString() const;
198
199
/**
200
* \brief Get the dimension of the map's domain.
201
*
202
* \returns The domain's dimension
203
*/
204
int getDomainDim() const;
205
206
/**
207
* \brief Get the image dimension of the map.
208
*
209
* \returns The image dimension of the characteristic map
210
*/
211
int getImageDim() const;
212
213
/**
214
* \brief Evaluate a point in the map using linear interpolation.
215
*
216
* Please note that the result may contain NaNs. That happens when...
217
* a) ... the point in question has no nearest neighbor (that is, it lies
218
* outside of the domain). In that case, all entries of the vector are set
219
* to NaN.
220
* b) ... an image value of the nearest neighbor is NaN. Then, the result is
221
* also NaN in that image dimension.
222
* c) ... evaluation would require interpolating with a support point which is
223
* NaN in an image dimension. The corresponding result entry is set to NaN
224
* in that case.
225
* \param[in] ref_p A point
226
* \param[in] eps An epsilon value
227
* \returns The (interpolated) image values of the map at the specified point
228
* \throws std::runtime_error
229
*/
230
std::vector<double> eval(const std::vector<double>& ref_p,
231
double eps = 1e-6) const;
232
};
233
234