CARLA
Lane.cpp
Go to the documentation of this file.
1 // Copyright (c) 2020 Computer Vision Center (CVC) at the Universitat Autonoma
2 // de Barcelona (UAB).
3 //
4 // This work is licensed under the terms of the MIT license.
5 // For a copy, see <https://opensource.org/licenses/MIT>.
6 
7 #include "carla/road/Lane.h"
8 
9 #include <limits>
10 
11 #include "carla/Debug.h"
12 #include "carla/geom/Math.h"
18 #include "carla/road/LaneSection.h"
19 #include "carla/road/MapData.h"
20 #include "carla/road/Road.h"
21 
22 namespace carla {
23 namespace road {
24 
26  return _lane_section;
27  }
28 
29  Road *Lane::GetRoad() const {
30  DEBUG_ASSERT(_lane_section != nullptr);
31  return _lane_section->GetRoad();
32  }
33 
34  LaneId Lane::GetId() const {
35  return _id;
36  }
37 
39  return _type;
40  }
41 
42  bool Lane::GetLevel() const {
43  return _level;
44  }
45 
46  double Lane::GetDistance() const {
47  DEBUG_ASSERT(_lane_section != nullptr);
48  return _lane_section->GetDistance();
49  }
50 
51  double Lane::GetLength() const {
52  const auto *road = GetRoad();
53  DEBUG_ASSERT(road != nullptr);
54  const auto s = GetDistance();
55  return road->UpperBound(s) - s;
56  }
57 
58  double Lane::GetWidth(const double s) const {
59  RELEASE_ASSERT(s <= GetRoad()->GetLength());
60  const auto width_info = GetInfo<element::RoadInfoLaneWidth>(s);
61  if(width_info != nullptr){
62  return width_info->GetPolynomial().Evaluate(s);
63  }
64  return 0.0f;
65  }
66 
67  bool Lane::IsStraight() const {
68  Road *road = GetRoad();
69  RELEASE_ASSERT(road != nullptr);
70  auto *geometry = road->GetInfo<element::RoadInfoGeometry>(GetDistance());
71  DEBUG_ASSERT(geometry != nullptr);
72  auto geometry_type = geometry->GetGeometry().GetType();
73  if (geometry_type != element::GeometryType::LINE) {
74  return false;
75  }
76  if(GetDistance() < geometry->GetDistance() ||
77  GetDistance() + GetLength() >
78  geometry->GetDistance() + geometry->GetGeometry().GetLength()) {
79  return false;
80  }
81  auto lane_offsets = GetInfos<element::RoadInfoLaneOffset>();
82  for (auto *lane_offset : lane_offsets) {
83  if (std::abs(lane_offset->GetPolynomial().GetC()) > 0 ||
84  std::abs(lane_offset->GetPolynomial().GetD()) > 0) {
85  return false;
86  }
87  }
88  auto elevations = road->GetInfos<element::RoadInfoElevation>();
89  for (auto *elevation : elevations) {
90  if (std::abs(elevation->GetPolynomial().GetC()) > 0 ||
91  std::abs(elevation->GetPolynomial().GetD()) > 0) {
92  return false;
93  }
94  }
95  return true;
96  }
97 
98  /// Returns a pair containing first = width, second = tangent,
99  /// for an specific Lane given an s and a iterator over lanes
100  template <typename T>
101  static std::pair<double, double> ComputeTotalLaneWidth(
102  const T container,
103  const double s,
104  const LaneId lane_id) {
105 
106  // lane_id can't be 0
107  RELEASE_ASSERT(lane_id != 0);
108 
109  const bool negative_lane_id = lane_id < 0;
110  double dist = 0.0;
111  double tangent = 0.0;
112  for (const auto &lane : container) {
113  auto info = lane.second.template GetInfo<element::RoadInfoLaneWidth>(s);
114  RELEASE_ASSERT(info != nullptr);
115  const auto current_polynomial = info->GetPolynomial();
116  auto current_dist = current_polynomial.Evaluate(s);
117  auto current_tang = current_polynomial.Tangent(s);
118  if (lane.first != lane_id) {
119  dist += negative_lane_id ? current_dist : -current_dist;
120  tangent += negative_lane_id ? current_tang : -current_tang;
121  } else {
122  current_dist *= 0.5;
123  dist += negative_lane_id ? current_dist : -current_dist;
124  tangent += (negative_lane_id ? current_tang : -current_tang) * 0.5;
125  break;
126  }
127  }
128  return std::make_pair(dist, tangent);
129  }
130 
131  geom::Transform Lane::ComputeTransform(const double s) const {
132  const Road *road = GetRoad();
133  DEBUG_ASSERT(road != nullptr);
134 
135  // must s be smaller (or eq) than road length and bigger (or eq) than 0?
136  RELEASE_ASSERT(s <= road->GetLength());
137  RELEASE_ASSERT(s >= 0.0);
138 
139  const auto *lane_section = GetLaneSection();
140  DEBUG_ASSERT(lane_section != nullptr);
141  const std::map<LaneId, Lane> &lanes = lane_section->GetLanes();
142 
143  // check that lane_id exists on the current s
144  RELEASE_ASSERT(!lanes.empty());
145  RELEASE_ASSERT(GetId() >= lanes.begin()->first);
146  RELEASE_ASSERT(GetId() <= lanes.rbegin()->first);
147 
148  // These will accumulate the lateral offset (t) and lane heading of all
149  // the lanes in between the current lane and lane 0, where the main road
150  // geometry is described
151  float lane_t_offset = 0.0f;
152  float lane_tangent = 0.0f;
153 
154  if (GetId() < 0) {
155  // right lane
156  const auto side_lanes = MakeListView(
157  std::make_reverse_iterator(lanes.lower_bound(0)), lanes.rend());
158  const auto computed_width =
159  ComputeTotalLaneWidth(side_lanes, s, GetId());
160  lane_t_offset = static_cast<float>(computed_width.first);
161  lane_tangent = static_cast<float>(computed_width.second);
162  } else if (GetId() > 0) {
163  // left lane
164  const auto side_lanes = MakeListView(lanes.lower_bound(1), lanes.end());
165  const auto computed_width =
166  ComputeTotalLaneWidth(side_lanes, s, GetId());
167  lane_t_offset = static_cast<float>(computed_width.first);
168  lane_tangent = static_cast<float>(computed_width.second);
169  }
170 
171  // Compute the tangent of the road's (lane 0) "laneOffset" on the current s
172  const auto lane_offset_info = road->GetInfo<element::RoadInfoLaneOffset>(s);
173  const auto lane_offset_tangent =
174  static_cast<float>(lane_offset_info->GetPolynomial().Tangent(s));
175 
176  // Update the road tangent with the "laneOffset" information at current s
177  lane_tangent -= lane_offset_tangent;
178 
179  // Get a directed point on the center of the current lane given an s
181 
182  // Transform from the center of the road to the center of the lane
183  dp.ApplyLateralOffset(lane_t_offset);
184 
185  // Update the lane tangent with the road "laneOffset" at current s
186  dp.tangent -= lane_tangent;
187 
188  // Unreal's Y axis hack
189  dp.location.y *= -1;
190  dp.tangent *= -1;
191 
192  geom::Rotation rot(
193  geom::Math::ToDegrees(static_cast<float>(dp.pitch)),
194  geom::Math::ToDegrees(static_cast<float>(dp.tangent)),
195  0.0f);
196 
197  // Fix the direction of the possitive lanes
198  if (GetId() > 0) {
199  rot.yaw += 180.0f;
200  rot.pitch = 360.0f - rot.pitch;
201  }
202 
203  return geom::Transform(dp.location, rot);
204  }
205 
206  std::pair<geom::Vector3D, geom::Vector3D> Lane::GetCornerPositions(
207  const double s, const float extra_width) const {
208  const Road *road = GetRoad();
209  DEBUG_ASSERT(road != nullptr);
210 
211  const auto *lane_section = GetLaneSection();
212  DEBUG_ASSERT(lane_section != nullptr);
213  const std::map<LaneId, Lane> &lanes = lane_section->GetLanes();
214 
215  // check that lane_id exists on the current s
216  RELEASE_ASSERT(!lanes.empty());
217  RELEASE_ASSERT(GetId() >= lanes.begin()->first);
218  RELEASE_ASSERT(GetId() <= lanes.rbegin()->first);
219 
220  float lane_t_offset = 0.0f;
221 
222  if (GetId() < 0) {
223  // right lane
224  const auto side_lanes = MakeListView(
225  std::make_reverse_iterator(lanes.lower_bound(0)), lanes.rend());
226  const auto computed_width =
227  ComputeTotalLaneWidth(side_lanes, s, GetId());
228  lane_t_offset = static_cast<float>(computed_width.first);
229  } else if (GetId() > 0) {
230  // left lane
231  const auto side_lanes = MakeListView(lanes.lower_bound(1), lanes.end());
232  const auto computed_width =
233  ComputeTotalLaneWidth(side_lanes, s, GetId());
234  lane_t_offset = static_cast<float>(computed_width.first);
235  }
236 
237  float lane_width = static_cast<float>(GetWidth(s)) / 2.0f;
238  if (extra_width != 0.f && road->IsJunction() && GetType() == Lane::LaneType::Driving) {
239  lane_width += extra_width;
240  }
241 
242  // Get two points on the center of the road on given s
243  element::DirectedPoint dp_r, dp_l;
244  dp_r = dp_l = road->GetDirectedPointIn(s);
245 
246  // Transform from the center of the road to each of lane corners
247  dp_r.ApplyLateralOffset(lane_t_offset + lane_width);
248  dp_l.ApplyLateralOffset(lane_t_offset - lane_width);
249 
250  // Unreal's Y axis hack
251  dp_r.location.y *= -1;
252  dp_l.location.y *= -1;
253 
254  // Apply an offset to the Sidewalks
255  if (GetType() == LaneType::Sidewalk) {
256  // RoadRunner doesn't export it right now and as a workarround where 15.24 cm
257  // is the exact height that match with most of the RoadRunner sidewalks
258  dp_r.location.z += 0.1524f;
259  dp_l.location.z += 0.1524f;
260  /// @TODO: use the OpenDRIVE 5.3.7.2.1.1.9 Lane Height Record
261  }
262 
263  return std::make_pair(dp_r.location, dp_l.location);
264  }
265 
266 } // road
267 } // carla
Road * GetRoad() const
Definition: LaneSection.cpp:23
LaneType GetType() const
Definition: Lane.cpp:38
std::vector< const T * > GetInfos() const
Definition: Road.h:118
double GetDistance() const
Definition: LaneSection.cpp:13
LaneType _type
Definition: Lane.h:132
The lane offset record defines a lateral shift of the lane reference line(which is usually identical ...
Road * GetRoad() const
Definition: Lane.cpp:29
bool IsJunction() const
Definition: Road.cpp:42
double GetDistance() const
Definition: Lane.cpp:46
double GetLength() const
Definition: Lane.cpp:51
This file contains definitions of common data structures used in traffic manager. ...
Definition: Carla.cpp:133
double GetWidth(const double s) const
Returns the total lane width given a s.
Definition: Lane.cpp:58
const T * GetInfo(const double s) const
Definition: Road.h:113
#define DEBUG_ASSERT(predicate)
Definition: Debug.h:66
LaneSection * _lane_section
Definition: Lane.h:126
#define RELEASE_ASSERT(pred)
Definition: Debug.h:84
LaneType
Can be used as flags.
Definition: Lane.h:29
int32_t LaneId
Definition: RoadTypes.h:19
LaneId _id
Definition: Lane.h:128
bool IsStraight() const
Checks whether the geometry is straight or not.
Definition: Lane.cpp:67
static std::pair< double, double > ComputeTotalLaneWidth(const T container, const double s, const LaneId lane_id)
Returns a pair containing first = width, second = tangent, for an specific Lane given an s and a iter...
Definition: Lane.cpp:101
geom::Transform ComputeTransform(const double s) const
Definition: Lane.cpp:131
static constexpr T ToDegrees(T rad)
Definition: Math.h:37
static auto MakeListView(Iterator begin, Iterator end)
bool GetLevel() const
Definition: Lane.cpp:42
void ApplyLateralOffset(float lateral_offset)
Definition: Geometry.cpp:28
std::pair< geom::Vector3D, geom::Vector3D > GetCornerPositions(const double s, const float extra_width=0.f) const
Computes the location of the edges given a s.
Definition: Lane.cpp:206
geom::Transform Transform
Definition: rpc/Transform.h:16
element::DirectedPoint GetDirectedPointIn(const double s) const
Returns a directed point on the center of the road (lane 0), with the corresponding laneOffset and el...
Definition: Road.cpp:180
LaneId GetId() const
Definition: Lane.cpp:34
const LaneSection * GetLaneSection() const
Definition: Lane.cpp:25