53 #ifndef ILQGAMES_DYNAMICS_SINGLE_PLAYER_FLAT_CAR_6D_H 54 #define ILQGAMES_DYNAMICS_SINGLE_PLAYER_FLAT_CAR_6D_H 56 #include <ilqgames/dynamics/single_player_flat_system.h> 57 #include <ilqgames/utils/types.h> 59 #include <glog/logging.h> 68 inter_axle_distance_(inter_axle_distance) {}
71 VectorXf Evaluate(
const VectorXf& x,
const VectorXf& u)
const;
74 void LinearizedSystem(Eigen::Ref<MatrixXf> A, Eigen::Ref<MatrixXf> B)
const;
77 MatrixXf InverseDecouplingMatrix(
const VectorXf& x)
const;
78 VectorXf AffineTerm(
const VectorXf& x)
const;
79 VectorXf ToLinearSystemState(
const VectorXf& x)
const;
80 VectorXf FromLinearSystemState(
const VectorXf& xi)
const;
81 void Partial(
const VectorXf& xi, std::vector<VectorXf>* grads,
82 std::vector<MatrixXf>* hesses)
const;
83 bool IsLinearSystemStateSingular(
const VectorXf& xi)
const;
86 float DistanceBetween(
const VectorXf& x0,
const VectorXf& x1)
const;
89 std::vector<Dimension> PositionDimensions()
const {
return {kPxIdx, kPyIdx}; }
92 static const Dimension kNumXDims;
93 static const Dimension kPxIdx;
94 static const Dimension kPyIdx;
95 static const Dimension kThetaIdx;
96 static const Dimension kPhiIdx;
97 static const Dimension kVIdx;
98 static const Dimension kAIdx;
99 static const Dimension kVxIdx;
100 static const Dimension kVyIdx;
101 static const Dimension kAxIdx;
102 static const Dimension kAyIdx;
105 static const Dimension kNumUDims;
106 static const Dimension kOmegaIdx;
107 static const Dimension kJerkIdx;
111 const float inter_axle_distance_;
116 inline VectorXf SinglePlayerFlatCar6D::Evaluate(
const VectorXf& x,
117 const VectorXf& u)
const {
118 VectorXf xdot(xdim_);
119 xdot(kPxIdx) = x(kVIdx) * std::cos(x(kThetaIdx));
120 xdot(kPyIdx) = x(kVIdx) * std::sin(x(kThetaIdx));
121 xdot(kThetaIdx) = (x(kVIdx) / inter_axle_distance_) * std::tan(x(kPhiIdx));
122 xdot(kPhiIdx) = u(kOmegaIdx);
123 xdot(kVIdx) = x(kAIdx);
124 xdot(kAIdx) = u(kJerkIdx);
129 inline void SinglePlayerFlatCar6D::LinearizedSystem(
130 Eigen::Ref<MatrixXf> A, Eigen::Ref<MatrixXf> B)
const {
131 A(kPxIdx, kVxIdx) += time::kTimeStep;
132 A(kPyIdx, kVyIdx) += time::kTimeStep;
133 A(kVxIdx, kAxIdx) += time::kTimeStep;
134 A(kVyIdx, kAyIdx) += time::kTimeStep;
136 B(kAxIdx, 0) = time::kTimeStep;
137 B(kAyIdx, 1) = time::kTimeStep;
140 inline MatrixXf SinglePlayerFlatCar6D::InverseDecouplingMatrix(
141 const VectorXf& x)
const {
142 MatrixXf M_inv(kNumUDims, kNumUDims);
144 const float sin_t = std::sin(x(kThetaIdx));
145 const float cos_t = std::cos(x(kThetaIdx));
147 const float kSmallOffset = sgn(x(kVIdx) + 0.0000001) * 0.00011;
148 const float cos_phi_v = std::cos(x(kPhiIdx)) / (x(kVIdx) + kSmallOffset);
149 const float scaling = inter_axle_distance_ * cos_phi_v * cos_phi_v;
151 CHECK_GT(std::abs(x(kVIdx) + kSmallOffset), 1e-4);
153 M_inv(0, 0) = -scaling * sin_t;
154 M_inv(0, 1) = scaling * cos_t;
161 inline VectorXf SinglePlayerFlatCar6D::AffineTerm(
const VectorXf& x)
const {
162 VectorXf m = VectorXf::Zero(kNumUDims);
164 const float sin_t = std::sin(x(kThetaIdx));
165 const float cos_t = std::cos(x(kThetaIdx));
166 const float tan_phi = std::tan(x(kPhiIdx));
167 const float v_over_l = x(kVIdx) / inter_axle_distance_;
169 m(0) = -v_over_l * tan_phi *
170 (3.0 * x(kAIdx) * sin_t + v_over_l * x(kVIdx) * tan_phi * cos_t);
171 m(1) = v_over_l * tan_phi *
172 (3.0 * x(kAIdx) * cos_t - v_over_l * x(kVIdx) * tan_phi * sin_t);
177 inline VectorXf SinglePlayerFlatCar6D::ToLinearSystemState(
178 const VectorXf& x)
const {
179 VectorXf xi(kNumXDims);
181 const float sin_t = std::sin(x(kThetaIdx));
182 const float cos_t = std::cos(x(kThetaIdx));
183 const float tan_phi = std::tan(x(kPhiIdx));
184 const float vv_over_l = x(kVIdx) * x(kVIdx) / inter_axle_distance_;
186 xi(kPxIdx) = x(kPxIdx);
187 xi(kPyIdx) = x(kPyIdx);
188 xi(kVxIdx) = x(kVIdx) * cos_t;
189 xi(kVyIdx) = x(kVIdx) * sin_t;
190 xi(kAxIdx) = x(kAIdx) * cos_t - vv_over_l * sin_t * tan_phi;
191 xi(kAyIdx) = x(kAIdx) * sin_t + vv_over_l * cos_t * tan_phi;
196 inline VectorXf SinglePlayerFlatCar6D::FromLinearSystemState(
197 const VectorXf& xi)
const {
198 VectorXf x(kNumXDims);
200 x(kPxIdx) = xi(kPxIdx);
201 x(kPyIdx) = xi(kPyIdx);
202 x(kThetaIdx) = std::atan2(xi(kVyIdx), xi(kVxIdx));
203 x(kVIdx) = std::hypot(xi(kVyIdx), xi(kVxIdx));
205 const float cos_t = xi(kVxIdx) / x(kVIdx);
206 const float sin_t = xi(kVyIdx) / x(kVIdx);
208 x(kAIdx) = cos_t * xi(kAxIdx) + sin_t * xi(kAyIdx);
209 x(kPhiIdx) = std::atan((x(kAIdx) * cos_t - xi(kAxIdx)) *
210 inter_axle_distance_ / (x(kVIdx) * x(kVIdx) * sin_t));
215 inline bool SinglePlayerFlatCar6D::IsLinearSystemStateSingular(
216 const VectorXf& xi)
const {
217 constexpr
float kTolerance = 1e-2;
218 return (std::isnan(xi(kVxIdx)) || std::isnan(xi(kVyIdx))) ||
219 (std::abs(xi(kVxIdx)) < kTolerance &&
220 std::abs(xi(kVyIdx)) < kTolerance);
223 inline float SinglePlayerFlatCar6D::DistanceBetween(
const VectorXf& x0,
224 const VectorXf& x1)
const {
226 const float dx = x0(kPxIdx) - x1(kPxIdx);
227 const float dy = x0(kPyIdx) - x1(kPyIdx);
228 return dx * dx + dy * dy;