-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathbicycle_model.cpp
More file actions
102 lines (84 loc) · 3.58 KB
/
bicycle_model.cpp
File metadata and controls
102 lines (84 loc) · 3.58 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
// Copyright (c) 2025-present Polymath Robotics, Inc. All rights reserved
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#include "polymath_kinematics/bicycle_model.hpp"
#include <cmath>
#include <limits>
namespace polymath::kinematics
{
BicycleBodyVelocity BicycleModel::steeringToBodyVelocity(double velocity, double steering_angle)
{
double angular_velocity = velocity * std::tan(steering_angle) / wheelbase_m_;
return BicycleBodyVelocity{velocity, angular_velocity};
}
BicycleSteeringState BicycleModel::bodyVelocityToSteering(double linear_velocity, double angular_velocity)
{
if (std::abs(linear_velocity) < ZERO_VELOCITY_THRESHOLD) {
// Stationary: cannot determine steering angle from the bicycle model
return BicycleSteeringState{linear_velocity, 0.0, std::numeric_limits<double>::infinity(), 0.0, 0.0, 0.0, 0.0};
}
if (std::abs(angular_velocity) < ZERO_VELOCITY_THRESHOLD) {
// Straight line: no rotation, all wheels spin at the same rate
double wheel_rad_s = linear_velocity / wheel_radius_m_;
return BicycleSteeringState{
linear_velocity,
0.0,
std::numeric_limits<double>::infinity(),
wheel_rad_s,
wheel_rad_s,
wheel_rad_s,
wheel_rad_s};
}
// steering_angle = atan(omega * L / v) inverts the forward kinematic
// relation omega = v * tan(steering_angle) / L.
// atan (not atan2) is intentional: the result must stay in (-pi/2, pi/2),
double steering_angle = std::atan(angular_velocity * wheelbase_m_ / linear_velocity);
double turning_radius = turningRadius(steering_angle);
double half_track = track_width_m_ / 2.0;
// Signed lateral distance from ICR to each rear wheel along the rear axle.
double rear_left_r = turning_radius - half_track;
double rear_right_r = turning_radius + half_track;
// Signed distance from ICR to each front wheel
double front_left_r = std::copysign(std::hypot(rear_left_r, wheelbase_m_), rear_left_r);
double front_right_r = std::copysign(std::hypot(rear_right_r, wheelbase_m_), rear_right_r);
// Each wheel's ground speed = omega * distance_to_ICR (rigid body kinematics).
// Convert to wheel angular velocity by dividing by wheel radius.
double rear_left_rad_s = angular_velocity * rear_left_r / wheel_radius_m_;
double rear_right_rad_s = angular_velocity * rear_right_r / wheel_radius_m_;
double front_left_rad_s = angular_velocity * front_left_r / wheel_radius_m_;
double front_right_rad_s = angular_velocity * front_right_r / wheel_radius_m_;
return BicycleSteeringState{
linear_velocity,
steering_angle,
turning_radius,
front_right_rad_s,
front_left_rad_s,
rear_right_rad_s,
rear_left_rad_s};
}
double BicycleModel::turningRadius(double steering_angle)
{
double tan_steering = std::tan(steering_angle);
if (std::abs(tan_steering) < ZERO_VELOCITY_THRESHOLD) {
return std::numeric_limits<double>::infinity();
}
return wheelbase_m_ / tan_steering;
}
double BicycleModel::steeringAngleFromRadius(double radius)
{
if (std::isinf(radius)) {
return 0.0;
}
return std::atan(wheelbase_m_ / radius);
}
} // namespace polymath::kinematics