CARLA
Loading...
Searching...
No Matches
test_ackermann_conversion.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
7#include "test.h"
8
10
11#include <cmath>
12#include <limits>
13#include <variant>
14
15TEST(AckermannConversion, identity_field_mapping) {
16 const auto control = carla::ros2::FromAckermannDrive(0.1f, 0.5f, 12.0f, 1.0f, 0.25f);
17
18 EXPECT_FLOAT_EQ(control.steer, 0.1f);
19 EXPECT_FLOAT_EQ(control.steer_speed, 0.5f);
20 EXPECT_FLOAT_EQ(control.speed, 12.0f);
21 EXPECT_FLOAT_EQ(control.acceleration, 1.0f);
22 EXPECT_FLOAT_EQ(control.jerk, 0.25f);
23}
24
25TEST(AckermannConversion, zero_inputs) {
26 const auto control = carla::ros2::FromAckermannDrive(0.0f, 0.0f, 0.0f, 0.0f, 0.0f);
27 EXPECT_FLOAT_EQ(control.steer, 0.0f);
28 EXPECT_FLOAT_EQ(control.steer_speed, 0.0f);
29 EXPECT_FLOAT_EQ(control.speed, 0.0f);
30 EXPECT_FLOAT_EQ(control.acceleration, 0.0f);
31 EXPECT_FLOAT_EQ(control.jerk, 0.0f);
32}
33
34TEST(AckermannConversion, negative_speed_passthrough) {
35 // ROS ackermann_msgs allows negative speed (reverse). Verify CARLA passes the
36 // sign through without clamping or remapping to a reverse flag.
37 const auto control = carla::ros2::FromAckermannDrive(0.0f, 0.0f, -3.0f, -0.5f, 0.0f);
38 EXPECT_FLOAT_EQ(control.speed, -3.0f);
39 EXPECT_FLOAT_EQ(control.acceleration, -0.5f);
40}
41
42TEST(AckermannConversion, large_steering_angle_passthrough) {
43 // The conversion seam does not enforce vehicle-physical limits; clipping is the
44 // simulator's job. Confirm large angles survive the field-mapping step.
45 const auto control = carla::ros2::FromAckermannDrive(3.14159f, 100.0f, 0.0f, 0.0f, 0.0f);
46 EXPECT_FLOAT_EQ(control.steer, 3.14159f);
47 EXPECT_FLOAT_EQ(control.steer_speed, 100.0f);
48}
49
50TEST(AckermannConversion, nan_propagation) {
51 // NaN inputs propagate to the output struct unchanged so downstream code can
52 // detect and reject them at the simulator boundary.
53 const float nan_val = std::numeric_limits<float>::quiet_NaN();
54 const auto control = carla::ros2::FromAckermannDrive(nan_val, 0.0f, 0.0f, 0.0f, 0.0f);
55 EXPECT_TRUE(std::isnan(control.steer));
56 EXPECT_FALSE(std::isnan(control.steer_speed));
57}
58
59namespace {
60
61// Exhaustive over ROS2CallbackData: std::visit requires a handler per
62// alternative, so growing the variant (VehicleAccelerationControl, Autoware
63// port) extends this visitor too.
64struct CountingVisitor {
65 int visited_vehicle{0};
66 int visited_ackermann{0};
67 int visited_acceleration{0};
68 void operator()(const carla::ros2::VehicleControl &) { ++visited_vehicle; }
69 void operator()(const carla::ros2::AckermannControl &) { ++visited_ackermann; }
70 void operator()(const carla::ros2::VehicleAccelerationControl &) { ++visited_acceleration; }
71};
72
73} // namespace
74
75TEST(ROS2CallbackData, visit_routes_ackermann_to_correct_overload) {
76 CountingVisitor visitor;
77
79 carla::ros2::FromAckermannDrive(0.0f, 0.0f, 0.0f, 0.0f, 0.0f);
80 std::visit(visitor, data);
81
82 EXPECT_EQ(visitor.visited_ackermann, 1);
83 EXPECT_EQ(visitor.visited_vehicle, 0);
84 EXPECT_EQ(visitor.visited_acceleration, 0);
85}
86
87TEST(ROS2CallbackData, visit_routes_vehicle_to_correct_overload) {
88 CountingVisitor visitor;
89
91 payload.throttle = 1.0f;
92 carla::ros2::ROS2CallbackData data = payload;
93 std::visit(visitor, data);
94
95 EXPECT_EQ(visitor.visited_vehicle, 1);
96 EXPECT_EQ(visitor.visited_ackermann, 0);
97 EXPECT_EQ(visitor.visited_acceleration, 0);
98}
99
100TEST(ROS2CallbackData, visit_routes_acceleration_to_correct_overload) {
101 CountingVisitor visitor;
102
104 payload.acceleration = 1.5f;
105 carla::ros2::ROS2CallbackData data = payload;
106 std::visit(visitor, data);
107
108 EXPECT_EQ(visitor.visited_acceleration, 1);
109 EXPECT_EQ(visitor.visited_vehicle, 0);
110 EXPECT_EQ(visitor.visited_ackermann, 0);
111}
AckermannControl FromAckermannDrive(float steering_angle, float steering_angle_velocity, float speed, float acceleration, float jerk)
std::variant< VehicleControl, AckermannControl, VehicleAccelerationControl > ROS2CallbackData
Control decoded from Autoware's /control/command/control_cmd: longitudinal acceleration [m/s^2] + ste...
TEST(AckermannConversion, identity_field_mapping)