CARLA
Loading...
Searching...
No Matches
AutowareSteeringCompensation.h
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
7#pragma once
8
9#include <array>
10#include <cmath>
11#include <cstddef>
12#include <tuple>
13
14namespace carla {
15namespace ros2 {
16/**
17 * Ported verbatim from tier4/autoware-support (commit 63e831e85 lineage).
18 *
19 * @note This solution is not ideal and it should be temporary. Ideally a root
20 * cause should be found and some other solution should be implemented based on
21 * the findings. This solution is purely based on experiments. For better
22 * accuracy more data points can be added to the lookup table.
23 */
24namespace autoware_steering_compensation {
25namespace detail {
26
27constexpr std::tuple<float, float> MakeDataPoint(const float desired, const float actual) {
28 return std::make_tuple(desired, actual);
29}
30
31/**
32 * @note Steering compensation lookup table.
33 * Tuples of (desired_steering_angle, actual_steering_angle).
34 * Desired steering angle is the normalized steer input applied to the vehicle;
35 * actual steering angle is the steady-state tire angle in radians derived from
36 * the measured yaw rate via the bicycle model (delta = atan(L * w / v)).
37 * Measured on the UE5.8 Chaos Lincoln MKZ (2026-08-20 sweep at ~3 m/s); the
38 * response is near-linear, unlike the strongly degressive UE5.5 vehicle the
39 * original tier4 table was calibrated against.
40 * Only positive values stored; absolute value used for lookup.
41 */
42constexpr std::array DATA{
43 MakeDataPoint(0.025, 0.0246614),
44 MakeDataPoint(0.05, 0.0495395),
45 MakeDataPoint(0.1, 0.0949895),
46 MakeDataPoint(0.15, 0.142492 ),
47 MakeDataPoint(0.2, 0.188953 ),
48 MakeDataPoint(0.25, 0.239746 ),
49 MakeDataPoint(0.3, 0.287899 ),
50 MakeDataPoint(0.35, 0.333537 ),
51 MakeDataPoint(0.4, 0.381975 ),
52 MakeDataPoint(0.45, 0.416428 ),
53 MakeDataPoint(0.5, 0.466122 ),
54 MakeDataPoint(0.55, 0.516003 ),
55 MakeDataPoint(0.6, 0.559125 ),
56 MakeDataPoint(0.65, 0.592443 ),
57 MakeDataPoint(0.7, 0.628645 )
58};
59
60// Linear interpolation function
61inline float Lerp(const float a, const float b, const float t) {
62 return a + t * (b - a);
63}
64
65// Get steering compensation ratio from lookup table with LERP
66template<std::size_t key_idx, std::size_t value_idx>
67float InterpolateSteeringData(const float angle) {
68 const auto AdjustSign = [angle](const float value) -> float {
69 return angle < 0.0f ? -value : value;
70 };
71
72 // Use absolute value for symmetric steering
73 const float key_angle = std::abs(angle);
74
75 // Handle edge cases
76 if (const auto front_key = std::get<key_idx>(DATA.front()); key_angle <= front_key) {
77 // Interpolate between 0 and first data point
78 const float t = key_angle / front_key;
79 return AdjustSign(Lerp(0.0f, std::get<value_idx>(DATA.front()), t));
80 }
81 if (key_angle >= std::get<key_idx>(DATA.back())) {
82 return AdjustSign(std::get<value_idx>(DATA.back()));
83 }
84
85 // Find the two points to interpolate between
86 for (size_t i = 0; i < DATA.size() - 1; ++i) {
87 const auto current_key_angle = std::get<key_idx >(DATA[i]);
88 const auto current_value_angle = std::get<value_idx>(DATA[i]);
89 const auto next_key_angle = std::get<key_idx >(DATA[i + 1]);
90 const auto next_value_angle = std::get<value_idx>(DATA[i + 1]);
91
92 if (current_key_angle <= key_angle && key_angle <= next_key_angle) {
93 // Calculate interpolation factor
94 const float t = (key_angle - current_key_angle) / (next_key_angle - current_key_angle);
95 // Interpolate between the two ratio values
96 return AdjustSign(Lerp(current_value_angle, next_value_angle, t));
97 }
98 }
99
100 // Default fallback (should not reach here)
101 return angle;
102}
103} // namespace detail
104
105/// Desired vehicle-input angle -> observed (actual) tire angle. Used when
106/// publishing the SteeringReport so Autoware sees the angle the wheels really
107/// reached.
108inline float GetSteeringOutput(const float input_angle) {
109 return detail::InterpolateSteeringData<0, 1>(input_angle);
110}
111
112/// Target (actual) tire angle -> vehicle input that produces it. Used when
113/// applying Autoware's steering command to the vehicle.
114inline float GetSteeringInput(const float output_angle) {
115 return detail::InterpolateSteeringData<1, 0>(output_angle);
116}
117} // namespace autoware_steering_compensation
118} // namespace ros2
119} // namespace carla
constexpr std::tuple< float, float > MakeDataPoint(const float desired, const float actual)
float Lerp(const float a, const float b, const float t)
float GetSteeringOutput(const float input_angle)
Desired vehicle-input angle -> observed (actual) tire angle.
float GetSteeringInput(const float output_angle)
Target (actual) tire angle -> vehicle input that produces it.
This file contains definitions of common data structures used in traffic manager.