18#include <gtest/gtest.h>
21#include <lanelet2_core/geometry/LineString.h>
22#include <lanelet2_traffic_rules/TrafficRulesFactory.h>
23#include <lanelet2_core/Attribute.h>
24#include <carma_perception_msgs/msg/roadway_obstacle.hpp>
25#include <carma_perception_msgs/msg/predicted_state.hpp>
26#include <carma_perception_msgs/msg/connected_vehicle_type.hpp>
27#include <boost/geometry.hpp>
28#include <boost/geometry/geometries/polygon.hpp>
29#include <tf2/LinearMath/Transform.h>
30#include <lanelet2_core/geometry/Polygon.h>
31#include <lanelet2_extension/regulatory_elements/DigitalSpeedLimit.h>
34#include <rclcpp/rclcpp.hpp>
35#include <lanelet2_extension/regulatory_elements/CarmaTrafficSignal.h>
61using namespace lanelet::units::literals;
83inline lanelet::Point3d
getPoint(
double x,
double y,
double z)
85 return lanelet::Point3d(lanelet::utils::getId(),
x,
y, z);
94 return lanelet::utils::to2D(
getPoint(
x,
y, 0.0)).basicPoint();
104inline lanelet::Lanelet
getLanelet(lanelet::LineString3d& left_ls, lanelet::LineString3d& right_ls,
105 const lanelet::Attribute& left_sub_type = lanelet::AttributeValueString::SolidSolid,
106 const lanelet::Attribute& right_sub_type = lanelet::AttributeValueString::Solid)
108 left_ls.attributes()[lanelet::AttributeName::Type] = lanelet::AttributeValueString::LineThin;
109 left_ls.attributes()[lanelet::AttributeName::Subtype] = left_sub_type;
111 right_ls.attributes()[lanelet::AttributeName::Type] = lanelet::AttributeValueString::LineThin;
112 right_ls.attributes()[lanelet::AttributeName::Subtype] = right_sub_type;
115 ll.setId(lanelet::utils::getId());
116 ll.setLeftBound(left_ls);
117 ll.setRightBound(right_ls);
119 ll.attributes()[lanelet::AttributeName::Type] = lanelet::AttributeValueString::Lanelet;
120 ll.attributes()[lanelet::AttributeName::Subtype] = lanelet::AttributeValueString::Road;
121 ll.attributes()[lanelet::AttributeName::Location] = lanelet::AttributeValueString::Urban;
122 ll.attributes()[lanelet::AttributeName::OneWay] =
"yes";
123 ll.attributes()[lanelet::AttributeName::Dynamic] =
"no";
135inline lanelet::Lanelet
getLanelet(std::vector<lanelet::Point3d> left, std::vector<lanelet::Point3d> right,
136 const lanelet::Attribute& left_sub_type = lanelet::AttributeValueString::SolidSolid,
137 const lanelet::Attribute& right_sub_type = lanelet::AttributeValueString::Solid)
139 lanelet::LineString3d left_ls(lanelet::utils::getId(), left);
141 lanelet::LineString3d right_ls(lanelet::utils::getId(), right);
143 return getLanelet(left_ls, right_ls, left_sub_type, right_sub_type);
154inline lanelet::Lanelet
getLanelet(lanelet::Id
id, lanelet::LineString3d left_ls, lanelet::LineString3d right_ls,
155 const lanelet::Attribute& left_sub_type = lanelet::AttributeValueString::SolidSolid,
156 const lanelet::Attribute& right_sub_type = lanelet::AttributeValueString::Solid)
158 auto ll =
getLanelet(left_ls, right_ls, left_sub_type, right_sub_type);
170inline lanelet::Lanelet
getLanelet(lanelet::Id
id, std::vector<lanelet::Point3d> left, std::vector<lanelet::Point3d> right,
171 const lanelet::Attribute& left_sub_type = lanelet::AttributeValueString::SolidSolid,
172 const lanelet::Attribute& right_sub_type = lanelet::AttributeValueString::Solid)
174 auto ll =
getLanelet(left, right, left_sub_type, right_sub_type);
186 std::vector<lanelet::Lanelet> all_lanelets;
187 double step_length = length / num;
189 std::vector<lanelet::Point3d> pts0;
190 std::vector<lanelet::Point3d> pts1;
191 std::vector<lanelet::Point3d> pts2;
192 std::vector<lanelet::Point3d> pts3;
194 for (
int i = 0;
i < num * 4 + 1;
i ++)
198 for (
int i = 0;
i < num * 4 + 1;
i ++)
202 for (
int i = 0;
i < num * 4 + 1;
i ++)
206 for (
int i = 0;
i < num * 4 + 1;
i ++)
211 lanelet::LineString3d ls00(lanelet::utils::getId(), std::vector<lanelet::Point3d>(pts0.begin(), pts0.begin() + num + 1));
212 lanelet::LineString3d ls01(lanelet::utils::getId(), std::vector<lanelet::Point3d>(pts0.begin() + num, pts0.begin() + 2 * num + 1));
213 lanelet::LineString3d ls02(lanelet::utils::getId(), std::vector<lanelet::Point3d>(pts0.begin() + 2 * num, pts0.begin() + 3 * num + 1)) ;
214 lanelet::LineString3d ls03(lanelet::utils::getId(), std::vector<lanelet::Point3d>(pts0.begin() + 3 * num, pts0.begin() + 4 * num + 1));
216 lanelet::LineString3d ls10(lanelet::utils::getId(), std::vector<lanelet::Point3d>(pts1.begin(), pts1.begin() + num + 1));
217 lanelet::LineString3d ls11(lanelet::utils::getId(), std::vector<lanelet::Point3d>(pts1.begin() + num, pts1.begin() + 2 * num + 1));
218 lanelet::LineString3d ls12(lanelet::utils::getId(), std::vector<lanelet::Point3d>(pts1.begin() + 2 * num, pts1.begin() + 3 * num + 1));
219 lanelet::LineString3d ls13(lanelet::utils::getId(), std::vector<lanelet::Point3d>(pts1.begin() + 3 * num, pts1.begin() + 4 * num + 1));
221 lanelet::LineString3d ls20(lanelet::utils::getId(), std::vector<lanelet::Point3d>(pts2.begin(), pts2.begin() + num + 1));
222 lanelet::LineString3d ls21(lanelet::utils::getId(), std::vector<lanelet::Point3d>(pts2.begin() + num, pts2.begin() + 2 * num + 1));
223 lanelet::LineString3d ls22(lanelet::utils::getId(), std::vector<lanelet::Point3d>(pts2.begin() + 2 * num, pts2.begin() + 3 * num + 1));
224 lanelet::LineString3d ls23(lanelet::utils::getId(), std::vector<lanelet::Point3d>(pts2.begin() + 3 * num, pts2.begin() + 4 * num + 1));
226 lanelet::LineString3d ls30(lanelet::utils::getId(), std::vector<lanelet::Point3d>(pts3.begin(), pts3.begin() + num + 1));
227 lanelet::LineString3d ls31(lanelet::utils::getId(), std::vector<lanelet::Point3d>(pts3.begin() + num, pts3.begin() + 2 * num + 1));
228 lanelet::LineString3d ls32(lanelet::utils::getId(), std::vector<lanelet::Point3d>(pts3.begin() + 2 * num, pts3.begin() + 3 * num + 1));
229 lanelet::LineString3d ls33(lanelet::utils::getId(), std::vector<lanelet::Point3d>(pts3.begin() + 3 * num, pts3.begin() + 4 * num + 1));
231 all_lanelets.push_back(
getLanelet(1200, ls00,ls10,lanelet::AttributeValueString::Solid, lanelet::AttributeValueString::Dashed));
232 all_lanelets.push_back(
getLanelet(1201, ls01,ls11,lanelet::AttributeValueString::Solid, lanelet::AttributeValueString::Dashed));
233 all_lanelets.push_back(
getLanelet(1202, ls02,ls12,lanelet::AttributeValueString::Solid, lanelet::AttributeValueString::Dashed));
234 all_lanelets.push_back(
getLanelet(1203, ls03,ls13,lanelet::AttributeValueString::Solid, lanelet::AttributeValueString::Dashed));
236 all_lanelets.push_back(
getLanelet(1210, ls10,ls20,lanelet::AttributeValueString::Dashed, lanelet::AttributeValueString::Dashed));
237 all_lanelets.push_back(
getLanelet(1211, ls11,ls21,lanelet::AttributeValueString::Dashed, lanelet::AttributeValueString::Dashed));
238 all_lanelets.push_back(
getLanelet(1212, ls12,ls22,lanelet::AttributeValueString::Dashed, lanelet::AttributeValueString::Dashed));
239 all_lanelets.push_back(
getLanelet(1213, ls13,ls23,lanelet::AttributeValueString::Dashed, lanelet::AttributeValueString::Dashed));
241 all_lanelets.push_back(
getLanelet(1220, ls20,ls30,lanelet::AttributeValueString::Dashed, lanelet::AttributeValueString::Solid));
242 all_lanelets.push_back(
getLanelet(1221, ls21,ls31,lanelet::AttributeValueString::Dashed, lanelet::AttributeValueString::Solid));
243 all_lanelets.push_back(
getLanelet(1222, ls22,ls32,lanelet::AttributeValueString::Dashed, lanelet::AttributeValueString::Solid));
244 all_lanelets.push_back(
getLanelet(1223, ls23,ls33,lanelet::AttributeValueString::Dashed, lanelet::AttributeValueString::Solid));
247 lanelet::LaneletMapPtr map = lanelet::utils::createMap(all_lanelets, {});
250 using namespace lanelet::units::literals;
266inline void addObstacle(
double x,
double y, std::shared_ptr<carma_wm::CARMAWorldModel> cmw, std::vector<std::pair<double,double>> pred_coords = {},
267 int time_step = 100,
double width = 3,
double length = 3)
269 carma_perception_msgs::msg::RoadwayObstacle rwo;
271 tf2::Quaternion tf_orientation;
272 tf_orientation.setRPY(0, 0, 1.5708);
274 rwo.object.pose.pose.position.x =
x;
275 rwo.object.pose.pose.position.y =
y;
276 rwo.object.pose.pose.position.z = 0;
278 rwo.object.pose.pose.orientation.x = tf_orientation.getX();
279 rwo.object.pose.pose.orientation.y = tf_orientation.getY();
280 rwo.object.pose.pose.orientation.z = tf_orientation.getZ();
281 rwo.object.pose.pose.orientation.w = tf_orientation.getW();
283 rwo.object.size.x = width;
284 rwo.object.size.y = length;
285 rwo.object.size.z = 1;
288 std::vector<carma_perception_msgs::msg::PredictedState> pred_states;
289 for (
auto pred : pred_coords)
291 carma_perception_msgs::msg::PredictedState ps;
292 time_stamp += (time_step * 1e6);
293 ps.header.stamp.nanosec = time_stamp;
295 ps.predicted_position.position.x = pred.first;
296 ps.predicted_position.position.y = pred.second;
297 ps.predicted_position.position.z = 0;
299 ps.predicted_position.orientation.x = tf_orientation.getX();
300 ps.predicted_position.orientation.y = tf_orientation.getY();
301 ps.predicted_position.orientation.z = tf_orientation.getZ();
302 ps.predicted_position.orientation.w = tf_orientation.getW();
303 pred_states.push_back(ps);
306 rwo.object.predictions = pred_states;
309 rwo = cmw->toRoadwayObstacle(rwo.object).get();
311 std::vector<carma_perception_msgs::msg::RoadwayObstacle> rw_objs = cmw->getRoadwayObjects();
313 rw_objs.push_back(rwo);
315 cmw->setRoadwayObjects(rw_objs);
329inline void addObstacle(
carma_wm::TrackPos tp, lanelet::Id lanelet_id, std::shared_ptr<carma_wm::CARMAWorldModel> cmw, std::vector<carma_wm::TrackPos> pred_trackpos_list = {},
int time_step = 100,
double width = 3,
double length = 3)
332 RCLCPP_DEBUG_STREAM(rclcpp::get_logger(
"carma_wm::WMTestLibForGuidance"),
"/// the following args are not used: width = " << width <<
", length = " << length <<
". Logging to avoid compiler warning.");
334 carma_perception_msgs::msg::RoadwayObstacle rwo;
336 if (!cmw->getMap() || cmw->getMap()->laneletLayer.size() == 0)
338 throw std::invalid_argument(
"Map is not set or does not contain lanelets");
340 rwo.connected_vehicle_type.type =
341 carma_perception_msgs::msg::ConnectedVehicleType::NOT_CONNECTED;
345 auto reference_llt = cmw->getMutableMap()->laneletLayer.get(lanelet_id);
346 lanelet::BasicPoint2d object_center = {(reference_llt.leftBound()[0].x() + reference_llt.rightBound()[0].x())/2 + tp.
crosstrack,
347 (reference_llt.leftBound()[0].y() + reference_llt.rightBound()[0].y())/2 + tp.
downtrack};
349 auto nearestLanelet = cmw->getMap()->laneletLayer.nearest(object_center, 1)[0];
350 if (!boost::geometry::within(object_center, nearestLanelet.polygon2d()))
352 throw std::invalid_argument(
"Given trackpos from given lanelet id does land on any lanelet in the map");
354 rwo.lanelet_id = nearestLanelet.id();
360 std::vector<carma_perception_msgs::msg::PredictedState> pred_states;
361 for (
auto pred_track_pos : pred_trackpos_list)
364 carma_perception_msgs::msg::PredictedState ps;
365 time_stamp += (time_step * 1e6);
366 ps.header.stamp.nanosec = time_stamp;
368 auto ref_llt_pred = cmw->getMutableMap()->laneletLayer.get(lanelet_id);
369 lanelet::BasicPoint2d object_center_pred = {(ref_llt_pred.leftBound()[0].x() + ref_llt_pred.rightBound()[0].x())/2 + pred_track_pos.crosstrack,
370 (ref_llt_pred.leftBound()[0].y() + ref_llt_pred.rightBound()[0].y())/2 + pred_track_pos.downtrack};
372 auto predNearestLanelet = cmw->getMap()->laneletLayer.nearest(object_center_pred, 1)[0];
373 if (!boost::geometry::within(object_center_pred, predNearestLanelet.polygon2d()))
375 RCLCPP_WARN_STREAM(rclcpp::get_logger(
"WMTestLibForGuidance"),
"Given pred trackpos from given lanelet id does land on any lanelet in the map");
378 rwo.predicted_lanelet_ids.emplace_back(predNearestLanelet.id());
380 rwo.predicted_cross_tracks.emplace_back(tp_pred.crosstrack);
381 rwo.predicted_down_tracks.emplace_back(tp_pred.downtrack);
383 pred_states.push_back(ps);
386 rwo.object.predictions = pred_states;
387 std::vector<carma_perception_msgs::msg::RoadwayObstacle> rw_objs = cmw->getRoadwayObjects();
389 rw_objs.push_back(rwo);
391 cmw->setRoadwayObjects(rw_objs);
402inline void setSpeedLimit (lanelet::Velocity speed_limit, std::shared_ptr<carma_wm::CARMAWorldModel> cmw)
404 if (!cmw->getMap() || cmw->getMap()->laneletLayer.size() == 0)
406 throw std::invalid_argument(
"setSpeedLimit: Map is not set or does not contain lanelets");
409 for (
auto llt : cmw->getMutableMap()->laneletLayer)
411 for (
auto regem : llt.regulatoryElements())
413 if (regem->attribute(lanelet::AttributeName::Subtype).value().compare(lanelet::DigitalSpeedLimit::RuleName) == 0)
415 cmw->getMutableMap()->remove(llt, regem);
418 lanelet::DigitalSpeedLimitPtr sl = std::make_shared<lanelet::DigitalSpeedLimit>(lanelet::DigitalSpeedLimit::buildData(lanelet::utils::getId(), speed_limit, {llt}, {},
419 { lanelet::Participants::Vehicle }));
420 cmw->getMutableMap()->update(llt, sl);
422 RCLCPP_INFO_STREAM(rclcpp::get_logger(
"WMTestLibForGuidance"),
"Set the new speed limit! Value: " << speed_limit.value());
433inline void setRouteByLanelets (std::vector<lanelet::ConstLanelet> lanelets, std::shared_ptr<carma_wm::CARMAWorldModel> cmw)
436 auto traffic_rules = cmw->getTrafficRules();
437 lanelet::routing::RoutingGraphUPtr map_graph = lanelet::routing::RoutingGraph::build(*cmw->getMap(), *traffic_rules.get());
440 lanelet::Optional<lanelet::routing::Route> optional_route;
441 std::vector<lanelet::ConstLanelet> middle_lanelets;
442 if (lanelets.size() > 2)
444 middle_lanelets = std::vector<lanelet::ConstLanelet>(lanelets.begin() + 1, lanelets.end() - 1);
445 optional_route = map_graph->getRouteVia(lanelets[0], middle_lanelets, lanelets[lanelets.size() - 1]);
447 else if (lanelets.size() == 2)
449 optional_route = map_graph->getRoute(lanelets[0], lanelets[1]);
453 throw lanelet::InvalidInputError(
"Fewer than 2 lanelets have been passed to setRouteByLanelets, which cannot be a valid route");
458 throw lanelet::InvalidInputError(
"There was an error in routing using the given lanelets in setRouteByLanelets");
461 lanelet::routing::Route
route = std::move(*optional_route);
463 cmw->setRoute(route_ptr);
465 RCLCPP_INFO_STREAM(rclcpp::get_logger(
"WMTestLibForGuidance"),
"New route has been set successfully!");
476inline void setRouteByIds (std::vector<lanelet::Id> lanelet_ids, std::shared_ptr<carma_wm::CARMAWorldModel> cmw)
478 std::vector<lanelet::ConstLanelet> lanelets;
479 for (
auto id : lanelet_ids)
481 lanelets.push_back(cmw->getMap()->laneletLayer.get(
id));
502inline void addTrafficLight(std::shared_ptr<carma_wm::CARMAWorldModel> cmw, lanelet::Id light_id, std::vector<lanelet::Id> entry_lanelet_ids, std::vector<lanelet::Id> exit_lanelet_ids,
503std::vector<std::pair<boost::posix_time::ptime, lanelet::CarmaTrafficSignalState>> timing_plan =
505 std::make_pair<boost::posix_time::ptime, lanelet::CarmaTrafficSignalState>(lanelet::time::timeFromSec(0), lanelet::CarmaTrafficSignalState::PROTECTED_MOVEMENT_ALLOWED),
506 std::make_pair<boost::posix_time::ptime, lanelet::CarmaTrafficSignalState>(lanelet::time::timeFromSec(4.0), lanelet::CarmaTrafficSignalState::PROTECTED_CLEARANCE),
507 std::make_pair<boost::posix_time::ptime, lanelet::CarmaTrafficSignalState>(lanelet::time::timeFromSec(24.0), lanelet::CarmaTrafficSignalState::STOP_AND_REMAIN),
508 std::make_pair<boost::posix_time::ptime, lanelet::CarmaTrafficSignalState>(lanelet::time::timeFromSec(44.0), lanelet::CarmaTrafficSignalState::PROTECTED_MOVEMENT_ALLOWED)
511 if (entry_lanelet_ids.size() != exit_lanelet_ids.size())
513 throw std::invalid_argument(
"Provided entry and exit lanelets size do not match!");
515 lanelet::Lanelets entry_lanelets;
517 for (
auto id : entry_lanelet_ids) {
518 auto iterator = cmw->getMutableMap()->laneletLayer.find(
id);
520 if (iterator == cmw->getMutableMap()->laneletLayer.end())
521 throw std::invalid_argument(
"Provided with lanelet id not in map: " +
std::to_string(
id));
523 entry_lanelets.push_back(*iterator);
526 lanelet::Lanelets exit_lanelets;
528 for (
auto id : exit_lanelet_ids) {
529 auto iterator = cmw->getMutableMap()->laneletLayer.find(
id);
531 if (iterator == cmw->getMutableMap()->laneletLayer.end())
532 throw std::invalid_argument(
"Provided with lanelet id not in map: " +
std::to_string(
id));
534 exit_lanelets.push_back(*iterator);
539 std::vector<lanelet::LineString3d> stop_lines;
540 for (
auto llt: entry_lanelets)
542 lanelet::LineString3d virtual_stop_line(lanelet::utils::getId(), { llt.leftBound().back(), llt.rightBound().back() });
543 stop_lines.push_back(virtual_stop_line);
547 std::shared_ptr<lanelet::CarmaTrafficSignal> traffic_light(
new lanelet::CarmaTrafficSignal(lanelet::CarmaTrafficSignal::buildData(light_id, stop_lines, entry_lanelets, exit_lanelets )));
550 traffic_light->setStates(timing_plan,0);
553 for (
auto llt: entry_lanelets)
555 cmw->getMutableMap()->update(llt, traffic_light);
571 std::shared_ptr<carma_wm::CARMAWorldModel> cmw = std::make_shared<carma_wm::CARMAWorldModel>();
Position in a track based coordinate system where the axis are downtrack and crosstrack....
auto to_string(const UtmZone &zone) -> std::string
TrackPos trackPos(const lanelet::ConstLanelet &lanelet, const lanelet::BasicPoint2d &point)
Returns the TrackPos, computed in 2d, of the provided point relative to the centerline of the provide...
void setSpeedLimit(lanelet::Velocity speed_limit, std::shared_ptr< carma_wm::CARMAWorldModel > cmw)
Sets all lanelets in the map the given speed limit.
void addTrafficLight(std::shared_ptr< carma_wm::CARMAWorldModel > cmw, lanelet::Id light_id, std::vector< lanelet::Id > entry_lanelet_ids, std::vector< lanelet::Id > exit_lanelet_ids, std::vector< std::pair< boost::posix_time::ptime, lanelet::CarmaTrafficSignalState > > timing_plan={ std::make_pair< boost::posix_time::ptime, lanelet::CarmaTrafficSignalState >(lanelet::time::timeFromSec(0), lanelet::CarmaTrafficSignalState::PROTECTED_MOVEMENT_ALLOWED), std::make_pair< boost::posix_time::ptime, lanelet::CarmaTrafficSignalState >(lanelet::time::timeFromSec(4.0), lanelet::CarmaTrafficSignalState::PROTECTED_CLEARANCE), std::make_pair< boost::posix_time::ptime, lanelet::CarmaTrafficSignalState >(lanelet::time::timeFromSec(24.0), lanelet::CarmaTrafficSignalState::STOP_AND_REMAIN), std::make_pair< boost::posix_time::ptime, lanelet::CarmaTrafficSignalState >(lanelet::time::timeFromSec(44.0), lanelet::CarmaTrafficSignalState::PROTECTED_MOVEMENT_ALLOWED) })
Method adds a traffic light to the provided world model instance NOTE: The stop line for the light wi...
lanelet::Lanelet getLanelet(lanelet::LineString3d &left_ls, lanelet::LineString3d &right_ls, const lanelet::Attribute &left_sub_type=lanelet::AttributeValueString::SolidSolid, const lanelet::Attribute &right_sub_type=lanelet::AttributeValueString::Solid)
helper function for quickly creating a lanelet::Lanelet using linestrings. random id is assigned
void addObstacle(double x, double y, std::shared_ptr< carma_wm::CARMAWorldModel > cmw, std::vector< std::pair< double, double > > pred_coords={}, int time_step=100, double width=3, double length=3)
adds a roadway object at the specified cartesian coords
lanelet::LaneletMapPtr buildGuidanceTestMap(double width, double length, int num=1)
helper function for creating lanelet map for getGuidanceTestMap
lanelet::BasicPoint2d getBasicPoint(double x, double y)
helper function for quickly creating a lanelet::BasicPoint. random id is assigned
std::shared_ptr< carma_wm::CARMAWorldModel > getGuidanceTestMap(MapOptions map_options)
Gets the CARMAWorldModel for the guidance test map.
void setRouteByIds(std::vector< lanelet::Id > lanelet_ids, std::shared_ptr< carma_wm::CARMAWorldModel > cmw)
Sets the route by series of lanelets id.
void setRouteByLanelets(std::vector< lanelet::ConstLanelet > lanelets, std::shared_ptr< carma_wm::CARMAWorldModel > cmw)
Sets the route by series of lanelets.
lanelet::Point3d getPoint(double x, double y, double z)
helper function for quickly creating a lanelet::Point3d. random id is assigned
std::shared_ptr< lanelet::routing::Route > LaneletRoutePtr
MapOptions(double lane_width=3.7, double lane_length=25, Obstacle obstacle=Obstacle::DEFAULT, SpeedLimit speed_limit=SpeedLimit::DEFAULT, int seg_num=1)