30 static std::string ToLowerCase(S&& s) {
33 c = static_cast<char>(
std::tolower(static_cast<unsigned char>(c)));
37 static std::unordered_map<std::string, std::string> ParseProjectionParameters(
const std::string &s){
41 std::unordered_map<std::string, std::string> geo_parameters_map;
43 static const std::regex re(R
"(\+([A-Za-z0-9_]+)(?:=("[^"]*"|'[^']*'|[^ \t\r\n+]+))?)");
44 for (std::sregex_iterator it(s.begin(), s.end(), re), end; it != end; ++it) {
45 std::string key = (*it)[1].str();
46 std::string val = (*it)[2].str();
47 geo_parameters_map[key] = val;
50 return geo_parameters_map;
53 static std::unordered_map<std::string, double> ParseOffsetParameters(
const pugi::xml_node &geo_offset){
55 std::unordered_map<std::string, double> geo_offset_result;
57 for (
auto attr = geo_offset.
first_attribute(); attr; attr = attr.next_attribute()){
58 std::string key = attr.name();
59 double value = attr.as_double();
60 geo_offset_result[key] = value;
62 return geo_offset_result;
66 template <
typename M,
typename S>
67 static bool TryGetParameter(std::string& out, M& parameters, S&& name)
69 auto i = parameters.find(std::forward<S>(name));
70 if (i == parameters.cend())
76 template <
typename M,
typename S,
typename O>
78 std::enable_if_t<std::is_floating_point<O>::value,
bool>
79 TryGetParameter(O& out, M& parameters, S&& name)
81 auto i = parameters.find(std::forward<S>(name));
82 if (i == parameters.cend())
84 out =
static_cast<O
>(std::stod(i->second));
88 template <
typename M,
typename S,
typename O>
90 std::enable_if_t<std::is_integral<O>::value && std::is_unsigned<O>::value,
bool>
91 TryGetParameter(O& out, M& parameters, S&& name)
93 auto i = parameters.find(std::forward<S>(name));
94 if (i == parameters.cend())
96 out =
static_cast<O
>(std::stoull(i->second));
100 template <
typename M,
typename S,
typename O>
102 std::enable_if_t<std::is_integral<O>::value && std::is_signed<O>::value,
bool>
103 TryGetParameter(O& out, M& parameters, S&& name)
105 auto i = parameters.find(std::forward<S>(name));
106 if (i == parameters.cend())
108 out =
static_cast<O
>(std::stoll(i->second));
112 template <
typename S,
typename O>
113 static bool TryGetParameter(O& out,std::unordered_map<std::string, double>& parameters,S&& name)
115 auto i = parameters.find(std::forward<S>(name));
116 if (i == parameters.cend()){
119 out =
static_cast<O
>(i->second);
124 static geom::Ellipsoid CreateEllipsoid(std::unordered_map<std::string, std::string> parameters){
126 geom::Ellipsoid ellps;
128 bool initialized=
false;
131 if (TryGetParameter(value, parameters,
"ellps") || TryGetParameter(value, parameters,
"datum")) {
132 value = ToLowerCase(value);
135 ellps.a = it->second.first;
136 ellps.f_inv = it->second.second;
141 initialized |= TryGetParameter(ellps.a, parameters,
"a");
143 if (TryGetParameter(
x, parameters,
"b")) {
147 if (TryGetParameter(
x, parameters,
"f")) {
151 initialized |= TryGetParameter(ellps.f_inv, parameters,
"rf");
155 ellps.a = val->second.first;
156 ellps.f_inv = val->second.second;
162 static boost::optional<geom::OffsetTransform> CreateOffsetTransform(std::unordered_map<std::string, double>& offset_parameters){
164 if(offset_parameters.empty()){
173 TryGetParameter(
x, offset_parameters,
"x");
174 TryGetParameter(
y, offset_parameters,
"y");
175 TryGetParameter(
z, offset_parameters,
"z");
176 TryGetParameter(hdg, offset_parameters,
"hdg");
178 return geom::OffsetTransform{
x,
y,
z, hdg};
181 static geom::GeoProjection CreateTransverseMercatorProjection(
182 std::unordered_map<std::string, std::string> parameters,
183 std::string proj_string,
184 geom::Ellipsoid ellipsoid){
186 geom::TransverseMercatorParams p;
187 TryGetParameter(p.lat_0, parameters,
"lat_0");
188 TryGetParameter(p.lon_0, parameters,
"lon_0");
189 TryGetParameter(p.k, parameters,
"k");
190 TryGetParameter(p.x_0, parameters,
"x_0");
191 TryGetParameter(p.y_0, parameters,
"y_0");
194 projection.SetPROJString(proj_string);
198 static geom::GeoProjection CreateUniversalTransverseMercatorProjection(
199 std::unordered_map<std::string, std::string> parameters,
200 std::string proj_string,
201 geom::Ellipsoid ellipsoid, boost::optional<carla::geom::OffsetTransform> offset){
203 geom::UniversalTransverseMercatorParams p;
204 if (!TryGetParameter(p.zone, parameters,
"zone")) {
205 log_warning(
"Missing 'zone' parameter for UTM projection. Using default value " + std::to_string(p.zone));
207 p.north = (parameters.count(
"south") > 0) ?
false : true;
211 projection.SetPROJString(proj_string);
215 static geom::GeoProjection CreateWebMercatorProjection(
216 std::string proj_string,
217 geom::Ellipsoid ellipsoid){
220 geom::WebMercatorParams p;
223 projection.SetPROJString(proj_string);
227 static geom::GeoProjection CreateLambertConformalConicProjection(
228 std::unordered_map<std::string, std::string> parameters,
229 std::string proj_string,
230 geom::Ellipsoid ellipsoid){
232 geom::LambertConformalConicParams p;
233 TryGetParameter(p.lon_0, parameters,
"lon_0");
234 TryGetParameter(p.lat_0, parameters,
"lat_0");
235 if (!TryGetParameter(p.lat_1, parameters,
"lat_1"))
236 log_warning(
"Missing 'lat_1' parameter for LCC projection. Using default value " + std::to_string(p.lat_1));
237 if (!TryGetParameter(p.lat_2, parameters,
"lat_2"))
238 log_warning(
"Missing 'lat_2' parameter for LCC projection. Using default value " + std::to_string(p.lat_2));
239 TryGetParameter(p.x_0, parameters,
"x_0");
240 TryGetParameter(p.y_0, parameters,
"y_0");
243 projection.SetPROJString(proj_string);
248 static geom::GeoProjection CreateDefaultProjection(geom::Ellipsoid ellipsoid){
249 geom::TransverseMercatorParams p;
256 static geom::GeoLocation CreateTransverseMercatorGeoReference(std::unordered_map<std::string, std::string> parameters){
257 geom::GeoLocation result{0.0, 0.0, 0.0};
258 TryGetParameter(result.latitude, parameters,
"lat_0");
259 TryGetParameter(result.longitude, parameters,
"lon_0");
263 static geom::GeoLocation CreateUniversalTransverseMercatorGeoReference(std::unordered_map<std::string, std::string> parameters){
264 geom::GeoLocation result{0.0, 0.0, 0.0};
266 if (TryGetParameter(zone, parameters,
"zone"))
267 result.longitude = 6.0 * zone - 183.0;
271 static geom::GeoLocation CreateWebMercatorGeoReference(){
272 geom::GeoLocation result{0.0, 0.0, 0.0};
276 static geom::GeoLocation CreateLambertConic2SPGeoReference(std::unordered_map<std::string, std::string> parameters){
277 geom::GeoLocation result{0.0, 0.0, 0.0};
278 TryGetParameter(result.latitude, parameters,
"lat_0");
279 TryGetParameter(result.longitude, parameters,
"lon_0");
283 static geom::GeoLocation CreateDefaultGeoReference(){
284 geom::GeoLocation result{0.0, 0.0, 0.0};
288 static auto ParseGeoProjectionAndReference(
const std::string& proj_string,
const pugi::xml_node &geo_offset){
289 auto parameters = ParseProjectionParameters(proj_string);
290 auto offset_parameters = ParseOffsetParameters(geo_offset);
291 auto ellipsoid = CreateEllipsoid(parameters);
292 auto offset_transform = CreateOffsetTransform(offset_parameters);
296 if (!TryGetParameter(proj, parameters,
"proj")) {
297 log_warning(
"cannot find the type of projection, using default transverse mercator");
298 return std::make_pair(
299 CreateDefaultProjection(ellipsoid),
300 CreateDefaultGeoReference());
304 if (proj ==
"tmerc") {
305 return std::make_pair(
306 CreateTransverseMercatorProjection(parameters, proj_string, ellipsoid),
307 CreateTransverseMercatorGeoReference(parameters));
308 }
else if (proj ==
"utm") {
309 return std::make_pair(
310 CreateUniversalTransverseMercatorProjection(parameters, proj_string, ellipsoid, offset_transform),
311 CreateUniversalTransverseMercatorGeoReference(parameters));
312 }
else if (proj ==
"merc") {
313 return std::make_pair(
314 CreateWebMercatorProjection(proj_string, ellipsoid),
315 CreateWebMercatorGeoReference());
316 }
else if (proj ==
"lcc") {
317 return std::make_pair(
318 CreateLambertConformalConicProjection(parameters, proj_string, ellipsoid),
319 CreateLambertConic2SPGeoReference(parameters));
321 log_debug(
"projection '" + proj +
"' is not supported, using default transverse mercator.");
322 return std::make_pair(
323 CreateDefaultProjection(ellipsoid),
324 CreateDefaultGeoReference());
332 auto georeference_string =
338 auto georeference_offset_node =
344 auto reference_and_projection = ParseGeoProjectionAndReference(
345 georeference_string, georeference_offset_node);
static void Parse(const pugi::xml_document &xml, carla::road::MapBuilder &map_builder)
void SetGeoProjection(const geom::GeoProjection &geo_projection)
void SetGeoReference(const geom::GeoLocation &geo_reference)
xml_node child(const char_t *name) const
const char_t * child_value() const
xml_attribute first_attribute() const
static const std::unordered_map< std::string, std::pair< double, double > > custom_ellipsoids
This file contains definitions of common data structures used in traffic manager.
static void log_warning(Args &&... args)
static void log_debug(Args &&... args)
static GeoProjection Make(T &&args)