Branch data Line data Source code
1 : : // ----------------- BEGIN LICENSE BLOCK ---------------------------------
2 : : //
3 : : // Copyright (C) 2018-2021 Intel Corporation
4 : : //
5 : : // SPDX-License-Identifier: MIT
6 : : //
7 : : // ----------------- END LICENSE BLOCK -----------------------------------
8 : :
9 : : #include "ad/map/config/MapConfigFileHandler.hpp"
10 : :
11 : : #include <boost/algorithm/string/predicate.hpp>
12 : : #include <boost/filesystem/operations.hpp>
13 : : #include <boost/filesystem/path.hpp>
14 : : #include <boost/program_options/parsers.hpp>
15 : : #include <boost/program_options/variables_map.hpp>
16 : : #include <fstream>
17 : : #include "ad/map/access/Logging.hpp"
18 : : #include "ad/map/point/GeoOperation.hpp"
19 : :
20 : 44 : inline std::istream &operator>>(std::istream &input, ::ad::physics::Distance &distance)
21 : : {
22 : : double dummy;
23 [ + - + - : 44 : if (input >> dummy)
+ + ]
24 : : {
25 : 43 : distance = ::ad::physics::Distance(dummy);
26 : : }
27 : 44 : return input;
28 : : }
29 : :
30 : 669 : inline std::istream &operator>>(std::istream &input, ::ad::map::point::Latitude &latitude)
31 : : {
32 : : double dummy;
33 [ + - + - : 669 : if (input >> dummy)
+ + ]
34 : : {
35 : 667 : latitude = ::ad::map::point::Latitude(dummy);
36 : : }
37 : 669 : return input;
38 : : }
39 : :
40 : 667 : inline std::istream &operator>>(std::istream &input, ::ad::map::point::Longitude &longitude)
41 : : {
42 : : double dummy;
43 [ + - + - : 667 : if (input >> dummy)
+ + ]
44 : : {
45 : 664 : longitude = ::ad::map::point::Longitude(dummy);
46 : : }
47 : 667 : return input;
48 : : }
49 : :
50 : 664 : inline std::istream &operator>>(std::istream &input, ::ad::map::point::Altitude &altitude)
51 : : {
52 : : double dummy;
53 [ + - + - : 664 : if (input >> dummy)
+ + ]
54 : : {
55 : 662 : altitude = ::ad::map::point::Altitude(dummy);
56 : : }
57 : 664 : return input;
58 : : }
59 : :
60 : : namespace ad {
61 : : namespace map {
62 : : namespace config {
63 : :
64 : 214 : bool MapConfigFileHandler::readConfig(std::string const &configFileName)
65 : : {
66 : 214 : reset();
67 [ + + ]: 214 : if (!parseConfigFile(configFileName))
68 : : {
69 : 18 : reset();
70 : 18 : return false;
71 : : }
72 : 196 : return true;
73 : : }
74 : :
75 : 900742 : bool MapConfigFileHandler::isInitialized() const
76 : : {
77 : 900742 : return !mConfigFileName.empty();
78 : : }
79 : :
80 : 74 : std::vector<PointOfInterest> const &MapConfigFileHandler::pointsOfInterest() const
81 : : {
82 : 74 : return mPointsOfInterest;
83 : : }
84 : :
85 : 2 : bool MapConfigFileHandler::isInitializedWithFilename(std::string const &configFileName) const
86 : : {
87 [ + - + - : 4 : auto path = boost::filesystem::canonical(boost::filesystem::path(configFileName));
+ - ]
88 : 2 : auto const isEqual = (path.string() == mConfigFileName);
89 : :
90 [ + + ]: 2 : if (!isEqual)
91 : : {
92 [ + - + - ]: 2 : access::getLogger()->warn("AdMapAccess already initialized with a different config. Present {}, Requested {}",
93 : 1 : mConfigFileName,
94 : 1 : path.string());
95 : : }
96 : :
97 : 4 : return isEqual;
98 : : }
99 : :
100 : 210 : void MapConfigFileHandler::updateFilenameAndPath(std::string const &configFileName)
101 : : {
102 [ + - + - : 420 : auto path = boost::filesystem::canonical(boost::filesystem::path(configFileName));
+ - ]
103 [ + - ]: 210 : mConfigFileName = path.string();
104 [ + - + - ]: 210 : mBaseDir = path.parent_path().string();
105 : 210 : }
106 : :
107 : 214 : bool MapConfigFileHandler::parseConfigFile(std::string const &configFileName)
108 : : {
109 : : namespace po = boost::program_options;
110 [ + - ]: 428 : po::variables_map vm;
111 [ + - ]: 428 : po::options_description options;
112 : : // clang-format off
113 [ + - + - : 214 : options.add_options()("ADMap.map", po::value<std::string>(), "AD map")
+ - ]
114 [ + - + - ]: 214 : ("ADMap.openDriveOverlapMargin", po::value<std::string>(), "OpenDrive Map reader margin for overlap calculation")
115 [ + - + - ]: 214 : ("ADMap.openDriveDefaultIntersectionType", po::value<std::string>(), "OpenDrive Map default intersection type")
116 [ + - + - ]: 214 : ("ADMap.openDriveDefaultTrafficLightType", po::value<std::string>(), "OpenDrive Map default traffic light type (only relevant for IntersectionType::TrafficLight)")
117 [ + - + - ]: 214 : ("POI.poi", po::value<std::vector<std::string>>(), "Points of interest")
118 [ + - + - ]: 214 : ("ENUReference.default", po::value<std::string>(), "Default ENU reference point");
119 : : // clang-format on
120 : :
121 : : try
122 : : {
123 [ + - ]: 217 : std::ifstream settingsFile(configFileName);
124 [ + - + + ]: 214 : if (!settingsFile.is_open())
125 : : {
126 [ + - + - ]: 8 : access::getLogger()->error("Cannot open config file for reading: {}", configFileName);
127 : 4 : return false;
128 : : }
129 [ + - + - ]: 420 : access::getLogger()->trace("Reading config file {}", configFileName);
130 [ + - + - ]: 210 : po::store(po::parse_config_file(settingsFile, options), vm);
131 [ + - ]: 210 : po::notify(vm);
132 : :
133 : : // we need the correct mBaseDir before we can construct any filename for the maps
134 [ + - ]: 210 : updateFilenameAndPath(configFileName);
135 : :
136 [ + - + - : 210 : if (vm.count("ADMap.map"))
+ - ]
137 : : {
138 [ + - ]: 213 : MapEntry mapEntry;
139 [ + - + - : 423 : auto const mapFilename = vm["ADMap.map"].as<std::string>();
+ - + - ]
140 [ + - ]: 213 : boost::filesystem::path path(mBaseDir);
141 [ + - + - ]: 210 : path /= boost::filesystem::path(mapFilename);
142 [ + - + + ]: 212 : path = boost::filesystem::canonical(path);
143 [ + - + + ]: 208 : if (!boost::starts_with(path.string(), mBaseDir))
144 : : {
145 [ + - + - ]: 2 : access::getLogger()->error("Given map file {} seems not to be located below current configuration directory {} "
146 : : "concatenating results in: {}",
147 : : mapFilename,
148 : 1 : mBaseDir,
149 : 1 : path.string());
150 : 1 : return false;
151 : : }
152 [ + - ]: 207 : mapEntry.filename = path.string();
153 : :
154 : 207 : physics::Distance openDriveOverlapMargin{0.};
155 [ + - + - : 207 : if (vm.count("ADMap.openDriveOverlapMargin"))
+ + ]
156 : : {
157 [ + - + - : 88 : auto const overlapMarginString = vm["ADMap.openDriveOverlapMargin"].as<std::string>();
+ - + - ]
158 [ + - ]: 44 : std::istringstream input{overlapMarginString};
159 [ + - + - : 44 : if (!(input >> openDriveOverlapMargin))
+ + ]
160 : : {
161 [ + - + - ]: 1 : access::getLogger()->warn("Error extracting openDriveOverlapMargin");
162 : 1 : return false;
163 : : }
164 : : }
165 : 206 : mapEntry.openDriveOverlapMargin = openDriveOverlapMargin;
166 : :
167 : 206 : intersection::IntersectionType openDriveDefaultIntersectionType = intersection::IntersectionType::Unknown;
168 [ + - + - : 206 : if (vm.count("ADMap.openDriveDefaultIntersectionType"))
+ + ]
169 : : {
170 : : auto const openDriveDefaultIntersectionTypeString
171 [ + - + - : 65 : = vm["ADMap.openDriveDefaultIntersectionType"].as<std::string>();
+ - + - ]
172 : : openDriveDefaultIntersectionType
173 [ + + ]: 32 : = fromString<intersection::IntersectionType>(openDriveDefaultIntersectionTypeString);
174 : : }
175 : 205 : mapEntry.openDriveDefaultIntersectionType = openDriveDefaultIntersectionType;
176 : :
177 [ + + ]: 205 : if (mapEntry.openDriveDefaultIntersectionType == intersection::IntersectionType::TrafficLight)
178 : : {
179 : 19 : landmark::TrafficLightType openDriveDefaultTrafficLightType
180 : : = landmark::TrafficLightType::SOLID_RED_YELLOW_GREEN;
181 [ + - + - : 19 : if (vm.count("ADMap.openDriveDefaultTrafficLightType"))
+ + ]
182 : : {
183 : : auto const openDriveDefaultTrafficLightTypeString
184 [ + - + - : 36 : = vm["ADMap.openDriveDefaultTrafficLightType"].as<std::string>();
+ - + - ]
185 : : openDriveDefaultTrafficLightType
186 [ + - ]: 18 : = fromString<landmark::TrafficLightType>(openDriveDefaultTrafficLightTypeString);
187 : : }
188 : 19 : mapEntry.openDriveDefaultTrafficLightType = openDriveDefaultTrafficLightType;
189 : : }
190 : :
191 [ + - ]: 205 : mAdMapEntry = mapEntry;
192 : : }
193 : :
194 [ + - + - : 205 : if (vm.count("POI.poi"))
+ + ]
195 : : {
196 [ + - + - : 119 : auto const &entries = vm["POI.poi"].as<std::vector<std::string>>();
+ - ]
197 [ + + ]: 631 : for (auto const &entry : entries)
198 : : {
199 [ + - + + ]: 517 : if (!parsePointOfIntereset(entry))
200 : : {
201 [ + - + - ]: 10 : access::getLogger()->warn("Invalid POI poi entry in config file: {}, Entry: {}", configFileName, entry);
202 : 5 : return false;
203 : : }
204 : : }
205 : : }
206 : :
207 [ + - + - : 200 : if (vm.count("ENUReference.default"))
+ + ]
208 : : {
209 [ + - + - : 153 : auto const &entry = vm["ENUReference.default"].as<std::string>();
+ - ]
210 [ + - + + ]: 153 : if (!parseENUReference(entry))
211 : : {
212 [ + - + - ]: 8 : access::getLogger()->warn(
213 : : "Invalid default ENU reference entry in config file: {}, Entry: {}", configFileName, entry);
214 : 4 : return false;
215 : : }
216 : : }
217 : : }
218 : 3 : catch (std::exception const &e)
219 : : {
220 [ + - + - ]: 6 : access::getLogger()->error("Error while parsing {}, Reason: {}", configFileName, e.what());
221 : 3 : return false;
222 : : }
223 : 196 : return true;
224 : : }
225 : :
226 : 517 : bool MapConfigFileHandler::parsePointOfIntereset(std::string const &entry)
227 : : {
228 [ + - ]: 1034 : std::istringstream input{entry};
229 [ + - ]: 1034 : PointOfInterest poi;
230 [ + - + - : 517 : if (!(input >> poi.name))
+ + ]
231 : : {
232 [ + - + - ]: 1 : access::getLogger()->warn("Error extracting name of poi!");
233 : 1 : return false;
234 : : }
235 [ + - + - : 516 : if (!(input >> poi.geoPoint.latitude))
+ + ]
236 : : {
237 [ + - + - ]: 1 : access::getLogger()->warn("Error extracting lat");
238 : 1 : return false;
239 : : }
240 [ + - + - : 515 : if (!(input >> poi.geoPoint.longitude))
+ + ]
241 : : {
242 [ + - + - ]: 1 : access::getLogger()->warn("Error extracting lon");
243 : 1 : return false;
244 : : }
245 [ + - + - : 514 : if (!(input >> poi.geoPoint.altitude))
+ + ]
246 : : {
247 [ + - + - ]: 1 : access::getLogger()->warn("Error extracting altitude");
248 : 1 : return false;
249 : : }
250 [ + + + - ]: 1855 : for (auto existingEntry : mPointsOfInterest)
251 : : {
252 [ + + ]: 1343 : if (existingEntry.name == poi.name)
253 : : {
254 [ + - + - ]: 2 : access::getLogger()->warn("POI defined twice: {}", existingEntry.name);
255 : 1 : return false;
256 : : }
257 : : }
258 [ + - ]: 512 : mPointsOfInterest.push_back(poi);
259 : :
260 : 512 : return true;
261 : : }
262 : :
263 : 153 : bool MapConfigFileHandler::parseENUReference(std::string const &entry)
264 : : {
265 [ + - ]: 306 : std::istringstream input{entry};
266 [ + - ]: 153 : point::GeoPoint enuReference;
267 [ + - + - : 153 : if (!(input >> enuReference.latitude))
+ + ]
268 : : {
269 [ + - + - ]: 1 : access::getLogger()->warn("Error extracting lat");
270 : 1 : return false;
271 : : }
272 [ + - + - : 152 : if (!(input >> enuReference.longitude))
+ + ]
273 : : {
274 [ + - + - ]: 2 : access::getLogger()->warn("Error extracting lon");
275 : 2 : return false;
276 : : }
277 [ + - + - : 150 : if (!(input >> enuReference.altitude))
+ + ]
278 : : {
279 [ + - + - ]: 1 : access::getLogger()->warn("Error extracting altitude");
280 : 1 : return false;
281 : : }
282 : 149 : mDefaultEnuReference = enuReference;
283 : 149 : return true;
284 : : }
285 : :
286 : 9 : std::string const &MapConfigFileHandler::configFileName() const
287 : : {
288 : 9 : return mConfigFileName;
289 : : }
290 : :
291 : 317 : MapEntry const &MapConfigFileHandler::adMapEntry() const
292 : : {
293 : 317 : return mAdMapEntry;
294 : : }
295 : :
296 : 680 : void MapConfigFileHandler::reset()
297 : : {
298 : 680 : mConfigFileName = "";
299 : 680 : mAdMapEntry = MapEntry();
300 : 680 : mPointsOfInterest.clear();
301 : 680 : mDefaultEnuReference = point::GeoPoint();
302 : 680 : mBaseDir.clear();
303 : 680 : }
304 : :
305 : 144 : point::GeoPoint MapConfigFileHandler::defaultEnuReference() const
306 : : {
307 : 144 : return mDefaultEnuReference;
308 : : }
309 : :
310 : 189 : bool MapConfigFileHandler::defaultEnuReferenceAvailable() const
311 : : {
312 : 189 : return point::isValid(mDefaultEnuReference, false);
313 : : }
314 : :
315 : : } // namespace config
316 : : } // namespace map
317 : : } // namespace ad
|