CARLA
Loading...
Searching...
No Matches
carla/road/element/Geometry.cpp
Go to the documentation of this file.
1// Copyright (c) 2026 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
8
9#include "carla/Debug.h"
10#include "carla/Exception.h"
11#include "carla/geom/Location.h"
12#include "carla/geom/Math.h"
13#include "carla/geom/Vector2D.h"
14
16
17#include <algorithm>
18#include <cmath>
19#include <stdexcept>
20
21namespace carla {
22namespace road {
23namespace element {
24
25 void DirectedPoint::ApplyLateralOffset(float lateral_offset) {
26 /// @todo Z axis??
27 auto normal_x = std::sin(static_cast<float>(tangent));
28 auto normal_y = -std::cos(static_cast<float>(tangent));
29 location.x += lateral_offset * normal_x;
30 location.y += lateral_offset * normal_y;
31 }
32
34 DEBUG_ASSERT(_length > 0.0);
35 dist = geom::Math::Clamp(dist, 0.0, _length);
37 p.location.x += static_cast<float>(dist * std::cos(p.tangent));
38 p.location.y += static_cast<float>(dist * std::sin(p.tangent));
39 return p;
40 }
41
43 dist = geom::Math::Clamp(dist, 0.0, _length);
44 DEBUG_ASSERT(_length > 0.0);
45 DEBUG_ASSERT(std::fabs(_curvature) > 1e-15);
46 const double radius = 1.0 / _curvature;
47 constexpr double pi_half = geom::Math::Pi<double>() / 2.0;
49 p.location.x += static_cast<float>(radius * std::cos(p.tangent + pi_half));
50 p.location.y += static_cast<float>(radius * std::sin(p.tangent + pi_half));
51 p.tangent += dist * _curvature;
52 p.location.x -= static_cast<float>(radius * std::cos(p.tangent + pi_half));
53 p.location.y -= static_cast<float>(radius * std::sin(p.tangent + pi_half));
54 return p;
55 }
56
57 // helper function for rotating points
58 geom::Vector2D RotatebyAngle(double angle, double x, double y) {
59 const double cos_a = std::cos(angle);
60 const double sin_a = std::sin(angle);
61 return geom::Vector2D(
62 static_cast<float>(x * cos_a - y * sin_a),
63 static_cast<float>(y * cos_a + x * sin_a));
64 }
65
67 dist = geom::Math::Clamp(dist, 0.0, _length);
68 DEBUG_ASSERT(_length > 0.0);
70
71 const double curve_end = (_curve_end);
72 const double curve_start = (_curve_start);
73 const double curve_dot = (curve_end - curve_start) / (_length);
74 const double s_o = curve_start / curve_dot;
75 double s = s_o + dist;
76
77 double x;
78 double y;
79 double t;
80 odrSpiral(s, curve_dot, &x, &y, &t);
81
82 double x_o;
83 double y_o;
84 double t_o;
85 odrSpiral(s_o, curve_dot, &x_o, &y_o, &t_o);
86
87 x = x - x_o;
88 y = y - y_o;
89 t = t - t_o;
90
92 p.location.x += pos.x;
93 p.location.y += pos.y;
94 p.tangent = _heading + t;
95
96 return p;
97 }
98
99 /// @todo
100 std::pair<float, float> GeometrySpiral::DistanceTo(const geom::Location &location) const {
101 // Not analytic, discretize and find nearest point
102 // throw_exception(std::runtime_error("not implemented"));
103 return {location.x - _start_position.x, location.y - _start_position.y};
104 }
105
107 auto result = _rtree.GetNearestNeighbours(
108 Rtree::BPoint(static_cast<float>(dist))).front();
109
110 auto &val1 = result.second.first;
111 auto &val2 = result.second.second;
112
113 double rate = (val2.s - dist) / (val2.s - val1.s);
114 double u = rate * val1.u + (1.0 - rate) * val2.u;
115 double v = rate * val1.v + (1.0 - rate) * val2.v;
116 double tangent = atan((rate * val1.t + (1.0 - rate) * val2.t)); // ?
117
120 p.location.x += pos.x;
121 p.location.y += pos.y;
122 return p;
123 }
124
125 std::pair<float, float> GeometryPoly3::DistanceTo(const geom::Location & /*p*/) const {
126 // No analytical expression (Newton-Raphson?/point search)
127 // throw_exception(std::runtime_error("not implemented"));
129 }
130
132 // Roughly the interval size in m
133 constexpr double interval_size = 0.3;
134 const double delta_u = interval_size; // interval between values of u
135 double current_s = 0;
136 double current_u = 0;
137 double last_u = 0;
138 double last_v = _poly.Evaluate(current_u);
139 double last_s = 0;
140 RtreeValue last_val{last_u, last_v, last_s, _poly.Tangent(current_u)};
141 while (current_s < _length + delta_u) {
142 current_u += delta_u;
143 double current_v = _poly.Evaluate(current_u);
144 double du = current_u - last_u;
145 double dv = current_v - last_v;
146 double ds = sqrt(du * du + dv * dv);
147 current_s += ds;
148 double current_t = _poly.Tangent(current_u);
149 RtreeValue current_val{current_u, current_v, current_s, current_t};
150
151 Rtree::BPoint p1(static_cast<float>(last_s));
152 Rtree::BPoint p2(static_cast<float>(current_s));
153 _rtree.InsertElement(Rtree::BSegment(p1, p2), last_val, current_val);
154
155 last_u = current_u;
156 last_v = current_v;
157 last_s = current_s;
158 last_val = current_val;
159
160 }
161 }
162
164 auto result = _rtree.GetNearestNeighbours(
165 Rtree::BPoint(static_cast<float>(dist))).front();
166
167 auto &val1 = result.second.first;
168 auto &val2 = result.second.second;
169 double rate = (val2.s - dist) / (val2.s - val1.s);
170 double u = rate * val1.u + (1.0 - rate) * val2.u;
171 double v = rate * val1.v + (1.0 - rate) * val2.v;
172 double t_u = (rate * val1.t_u + (1.0 - rate) * val2.t_u);
173 double t_v = (rate * val1.t_v + (1.0 - rate) * val2.t_v);
174 double tangent = atan2(t_v, t_u); // ?
175
178 p.location.x += pos.x;
179 p.location.y += pos.y;
180 return p;
181 }
182 std::pair<float, float> GeometryParamPoly3::DistanceTo(const geom::Location &) const {
183 // No analytical expression (Newton-Raphson?/point search)
184 // throw_exception(std::runtime_error("not implemented"));
186 }
187
189 // Roughly the interval size in m
190 constexpr double interval_size = 0.5;
191 size_t number_intervals =
192 std::max(static_cast<size_t>(_length / interval_size), size_t(5));
193 double delta_p = 1.0 / static_cast<double>(number_intervals);
194 if (_arcLength) {
195 delta_p *= _length;
196 }
197 double param_p = 0;
198 double current_s = 0;
199 double last_u = _polyU.Evaluate(param_p);
200 double last_v = _polyV.Evaluate(param_p);
201 double last_s = 0;
202 RtreeValue last_val{
203 last_u,
204 last_v,
205 last_s,
206 _polyU.Tangent(param_p),
207 _polyV.Tangent(param_p) };
208 for(size_t i = 0; i < number_intervals; ++i) {
209 param_p += delta_p;
210 double current_u = _polyU.Evaluate(param_p);
211 double current_v = _polyV.Evaluate(param_p);
212 double du = current_u - last_u;
213 double dv = current_v - last_v;
214 double ds = sqrt(du * du + dv * dv);
215 current_s += ds;
216 double current_t_u = _polyU.Tangent(param_p);
217 double current_t_v = _polyV.Tangent(param_p);
218 RtreeValue current_val{
219 current_u,
220 current_v,
221 current_s,
222 current_t_u,
223 current_t_v };
224
225 Rtree::BPoint p1(static_cast<float>(last_s));
226 Rtree::BPoint p2(static_cast<float>(current_s));
227 _rtree.InsertElement(Rtree::BSegment(p1, p2), last_val, current_val);
228
229 last_u = current_u;
230 last_v = current_v;
231 last_s = current_s;
232 last_val = current_val;
233
234 if(current_s > _length){
235 break;
236 }
237 }
238 }
239} // namespace element
240} // namespace road
241} // namespace carla
float y
float x
#define DEBUG_ASSERT(predicate)
Definition Debug.h:66
std::map< std::string, unsigned int > road
value_type Evaluate(const value_type &x) const
Evaluates f(x) = a + bx + cx^2 + dx^3.
value_type Tangent(const value_type &x) const
Evaluates the tangent using df/dx = b + 2cx + 3dx^2.
static constexpr T Clamp(T a, T min=T(0), T max=T(1))
Definition Math.h:49
boost::geometry::model::point< float, Dimension, boost::geometry::cs::cartesian > BPoint
Definition Rtree.h:89
boost::geometry::model::segment< BPoint > BSegment
Definition Rtree.h:90
void InsertElement(const BSegment &segment, const T &element_start, const T &element_end)
Definition Rtree.h:93
std::vector< TreeElement > GetNearestNeighbours(const Geometry &geometry, size_t number_neighbours=1) const
Definition Rtree.h:124
DirectedPoint PosFromDist(double dist) const override
DirectedPoint PosFromDist(double dist) const override
DirectedPoint PosFromDist(double dist) const override
std::pair< float, float > DistanceTo(const geom::Location &) const override
std::pair< float, float > DistanceTo(const geom::Location &) const override
DirectedPoint PosFromDist(double dist) const override
std::pair< float, float > DistanceTo(const geom::Location &) const override
DirectedPoint PosFromDist(double dist) const override
geom::Vector2D RotatebyAngle(double angle, double x, double y)
This file contains definitions of common data structures used in traffic manager.
void odrSpiral(double s, double cDot, double *x, double *y, double *t)
compute the actual "standard" spiral, starting with curvature 0