Skip to content

Commit c0cf591

Browse files
franzrammerstorferchristophfroehlich
authored andcommitted
Fix ackermann steering odometry (#921)
* fix Ackermann steering odometry bug issue #878 --------- Co-authored-by: Christoph Fröhlich <christophfroehlich@users.noreply.github.com> (cherry picked from commit d915497)
1 parent 2a0c387 commit c0cf591

File tree

3 files changed

+115
-2
lines changed

3 files changed

+115
-2
lines changed

steering_controllers_library/CMakeLists.txt

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,9 @@ if(BUILD_TESTING)
6767
controller_interface
6868
hardware_interface
6969
)
70+
ament_add_gmock(test_steering_odometry test/test_steering_odometry.cpp)
71+
target_link_libraries(test_steering_odometry steering_controllers_library)
72+
7073
endif()
7174

7275
install(

steering_controllers_library/src/steering_odometry.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -272,8 +272,8 @@ std::tuple<std::vector<double>, std::vector<double>> SteeringOdometry::get_comma
272272
double denominator_first_member = 2 * wheelbase_ * std::cos(alpha);
273273
double denominator_second_member = wheel_track_ * std::sin(alpha);
274274

275-
double alpha_r = std::atan2(numerator, denominator_first_member - denominator_second_member);
276-
double alpha_l = std::atan2(numerator, denominator_first_member + denominator_second_member);
275+
double alpha_r = std::atan2(numerator, denominator_first_member + denominator_second_member);
276+
double alpha_l = std::atan2(numerator, denominator_first_member - denominator_second_member);
277277
steering_commands = {alpha_r, alpha_l};
278278
}
279279
return std::make_tuple(traction_commands, steering_commands);
Lines changed: 110 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,110 @@
1+
// Copyright (c) 2023, Virtual Vehicle Research GmbH
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License");
4+
// you may not use this file except in compliance with the License.
5+
// You may obtain a copy of the License at
6+
//
7+
// http://www.apache.org/licenses/LICENSE-2.0
8+
//
9+
// Unless required by applicable law or agreed to in writing, software
10+
// distributed under the License is distributed on an "AS IS" BASIS,
11+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
// See the License for the specific language governing permissions and
13+
// limitations under the License.
14+
15+
#include "gmock/gmock.h"
16+
17+
#include "steering_controllers_library/steering_odometry.hpp"
18+
19+
TEST(TestSteeringOdometry, initialize)
20+
{
21+
EXPECT_NO_THROW(steering_odometry::SteeringOdometry());
22+
23+
steering_odometry::SteeringOdometry odom(1);
24+
odom.set_wheel_params(1., 2., 3.);
25+
odom.set_odometry_type(steering_odometry::ACKERMANN_CONFIG);
26+
EXPECT_DOUBLE_EQ(odom.get_heading(), 0.);
27+
EXPECT_DOUBLE_EQ(odom.get_x(), 0.);
28+
EXPECT_DOUBLE_EQ(odom.get_y(), 0.);
29+
}
30+
31+
TEST(TestSteeringOdometry, ackermann_fwd_kin_linear)
32+
{
33+
steering_odometry::SteeringOdometry odom(1);
34+
odom.set_wheel_params(1., 2., 1.);
35+
odom.set_odometry_type(steering_odometry::ACKERMANN_CONFIG);
36+
odom.update_open_loop(2., 0., 0.5);
37+
EXPECT_DOUBLE_EQ(odom.get_linear(), 2.);
38+
EXPECT_DOUBLE_EQ(odom.get_x(), 1.);
39+
EXPECT_DOUBLE_EQ(odom.get_y(), 0.);
40+
}
41+
42+
TEST(TestSteeringOdometry, ackermann_fwd_kin_angular_left)
43+
{
44+
steering_odometry::SteeringOdometry odom(1);
45+
odom.set_wheel_params(1., 2., 1.);
46+
odom.set_odometry_type(steering_odometry::ACKERMANN_CONFIG);
47+
odom.update_open_loop(1., 1., 1.);
48+
EXPECT_DOUBLE_EQ(odom.get_linear(), 1.);
49+
EXPECT_DOUBLE_EQ(odom.get_angular(), 1.);
50+
51+
EXPECT_GT(odom.get_x(), 0); // pos x
52+
EXPECT_GT(odom.get_y(), 0); // pos y, ie. left
53+
}
54+
55+
TEST(TestSteeringOdometry, ackermann_fwd_kin_angular_right)
56+
{
57+
steering_odometry::SteeringOdometry odom(1);
58+
odom.set_wheel_params(1., 2., 1.);
59+
odom.set_odometry_type(steering_odometry::ACKERMANN_CONFIG);
60+
odom.update_open_loop(1., -1., 1.);
61+
EXPECT_DOUBLE_EQ(odom.get_linear(), 1.);
62+
EXPECT_DOUBLE_EQ(odom.get_angular(), -1.);
63+
EXPECT_GT(odom.get_x(), 0); // pos x
64+
EXPECT_LT(odom.get_y(), 0); // neg y ie. right
65+
}
66+
67+
TEST(TestSteeringOdometry, ackermann_back_kin_linear)
68+
{
69+
steering_odometry::SteeringOdometry odom(1);
70+
odom.set_wheel_params(1., 2., 1.);
71+
odom.set_odometry_type(steering_odometry::ACKERMANN_CONFIG);
72+
odom.update_open_loop(1., 0., 1.);
73+
auto cmd = odom.get_commands(1., 0.);
74+
auto cmd0 = std::get<0>(cmd); // vel
75+
EXPECT_EQ(cmd0[0], cmd0[1]); // linear
76+
EXPECT_GT(cmd0[0], 0);
77+
auto cmd1 = std::get<1>(cmd); // steer
78+
EXPECT_EQ(cmd1[0], cmd1[1]); // no steering
79+
EXPECT_EQ(cmd1[0], 0);
80+
}
81+
82+
TEST(TestSteeringOdometry, ackermann_back_kin_left)
83+
{
84+
steering_odometry::SteeringOdometry odom(1);
85+
odom.set_wheel_params(1., 2., 1.);
86+
odom.set_odometry_type(steering_odometry::ACKERMANN_CONFIG);
87+
odom.update_from_position(0., 0.2, 1.); // assume already turn
88+
auto cmd = odom.get_commands(1., 0.1);
89+
auto cmd0 = std::get<0>(cmd); // vel
90+
EXPECT_GT(cmd0[0], cmd0[1]); // right (outer) > left (inner)
91+
EXPECT_GT(cmd0[0], 0);
92+
auto cmd1 = std::get<1>(cmd); // steer
93+
EXPECT_LT(cmd1[0], cmd1[1]); // right (outer) < left (inner)
94+
EXPECT_GT(cmd1[0], 0);
95+
}
96+
97+
TEST(TestSteeringOdometry, ackermann_back_kin_right)
98+
{
99+
steering_odometry::SteeringOdometry odom(1);
100+
odom.set_wheel_params(1., 2., 1.);
101+
odom.set_odometry_type(steering_odometry::ACKERMANN_CONFIG);
102+
odom.update_from_position(0., -0.2, 1.); // assume already turn
103+
auto cmd = odom.get_commands(1., -0.1);
104+
auto cmd0 = std::get<0>(cmd); // vel
105+
EXPECT_LT(cmd0[0], cmd0[1]); // right (inner) < left outer)
106+
EXPECT_GT(cmd0[0], 0);
107+
auto cmd1 = std::get<1>(cmd); // steer
108+
EXPECT_GT(std::abs(cmd1[0]), std::abs(cmd1[1])); // abs right (inner) > abs left (outer)
109+
EXPECT_LT(cmd1[0], 0);
110+
}

0 commit comments

Comments
 (0)