52 #ifndef ILQGAMES_DYNAMICS_SINGLE_PLAYER_FLAT_UNICYCLE_4D_H 53 #define ILQGAMES_DYNAMICS_SINGLE_PLAYER_FLAT_UNICYCLE_4D_H 55 #include <ilqgames/dynamics/single_player_flat_system.h> 56 #include <ilqgames/utils/types.h> 58 #include <glog/logging.h> 68 VectorXf Evaluate(
const VectorXf& x,
const VectorXf& u)
const;
71 void LinearizedSystem(Eigen::Ref<MatrixXf> A, Eigen::Ref<MatrixXf> B)
const;
74 MatrixXf InverseDecouplingMatrix(
const VectorXf& x)
const;
75 VectorXf AffineTerm(
const VectorXf& x)
const;
76 VectorXf ToLinearSystemState(
const VectorXf& x)
const;
77 VectorXf FromLinearSystemState(
const VectorXf& xi)
const;
78 void Partial(
const VectorXf& xi, std::vector<VectorXf>* grads,
79 std::vector<MatrixXf>* hesses)
const;
80 bool IsLinearSystemStateSingular(
const VectorXf& xi)
const;
83 float DistanceBetween(
const VectorXf& x0,
const VectorXf& x1)
const;
86 std::vector<Dimension> PositionDimensions()
const {
return {kPxIdx, kPyIdx}; }
89 static const Dimension kNumXDims;
90 static const Dimension kPxIdx;
91 static const Dimension kPyIdx;
92 static const Dimension kThetaIdx;
93 static const Dimension kVIdx;
94 static const Dimension kVxIdx;
95 static const Dimension kVyIdx;
98 static const Dimension kNumUDims;
99 static const Dimension kOmegaIdx;
100 static const Dimension kAIdx;
105 inline VectorXf SinglePlayerFlatUnicycle4D::Evaluate(
const VectorXf& x,
106 const VectorXf& u)
const {
107 VectorXf xdot(xdim_);
108 xdot(kPxIdx) = x(kVIdx) * std::cos(x(kThetaIdx));
109 xdot(kPyIdx) = x(kVIdx) * std::sin(x(kThetaIdx));
110 xdot(kThetaIdx) = u(kOmegaIdx);
111 xdot(kVIdx) = u(kAIdx);
116 inline void SinglePlayerFlatUnicycle4D::LinearizedSystem(
117 Eigen::Ref<MatrixXf> A, Eigen::Ref<MatrixXf> B)
const {
118 A(kPxIdx, kVxIdx) += time::kTimeStep;
119 A(kPyIdx, kVyIdx) += time::kTimeStep;
121 B(kVxIdx, 0) = time::kTimeStep;
122 B(kVyIdx, 1) = time::kTimeStep;
125 inline MatrixXf SinglePlayerFlatUnicycle4D::InverseDecouplingMatrix(
126 const VectorXf& x)
const {
127 MatrixXf M_inv(kNumUDims, kNumUDims);
129 const float sin_t = std::sin(x(kThetaIdx));
130 const float cos_t = std::cos(x(kThetaIdx));
132 const float kSmallOffset = sgn(x(kVIdx) + 0.0000001) * 0.00011;
134 CHECK_GT(std::abs(x(kVIdx) + kSmallOffset), 1e-4);
138 M_inv(1, 0) = -sin_t / (x(kVIdx) + kSmallOffset);
139 M_inv(1, 1) = cos_t / (x(kVIdx) + kSmallOffset);
144 inline VectorXf SinglePlayerFlatUnicycle4D::AffineTerm(
145 const VectorXf& x)
const {
146 return VectorXf::Zero(kNumUDims);
149 inline VectorXf SinglePlayerFlatUnicycle4D::ToLinearSystemState(
150 const VectorXf& x)
const {
151 VectorXf xi(kNumXDims);
153 xi(kPxIdx) = x(kPxIdx);
154 xi(kPyIdx) = x(kPyIdx);
155 xi(kVxIdx) = x(kVIdx) * std::cos(x(kThetaIdx));
156 xi(kVyIdx) = x(kVIdx) * std::sin(x(kThetaIdx));
161 inline VectorXf SinglePlayerFlatUnicycle4D::FromLinearSystemState(
162 const VectorXf& xi)
const {
163 VectorXf x(kNumXDims);
165 x(kPxIdx) = xi(kPxIdx);
166 x(kPyIdx) = xi(kPyIdx);
167 x(kThetaIdx) = std::atan2(xi(kVyIdx), xi(kVxIdx));
168 x(kVIdx) = std::hypot(xi(kVyIdx), xi(kVxIdx));
173 inline bool SinglePlayerFlatUnicycle4D::IsLinearSystemStateSingular(
174 const VectorXf& xi)
const {
175 constexpr
float kTolerance = 1e-2;
176 return (std::isnan(xi(kVxIdx)) || std::isnan(xi(kVyIdx))) ||
177 (std::abs(xi(kVxIdx)) < kTolerance &&
178 std::abs(xi(kVyIdx)) < kTolerance);
181 inline void SinglePlayerFlatUnicycle4D::Partial(
182 const VectorXf& xi, std::vector<VectorXf>* grads,
183 std::vector<MatrixXf>* hesses)
const {
184 CHECK_NOTNULL(grads);
185 CHECK_NOTNULL(hesses);
187 if (grads->size() != xi.size())
188 grads->resize(xi.size(), VectorXf::Zero(kNumXDims));
190 for (
auto& grad : *grads) {
191 DCHECK_EQ(grad.size(), xi.size());
196 if (hesses->size() != xi.size())
197 hesses->resize(xi.size(), MatrixXf::Zero(kNumXDims, kNumXDims));
199 for (
auto& hess : *hesses) {
200 DCHECK_EQ(hess.rows(), xi.size());
201 DCHECK_EQ(hess.cols(), xi.size());
212 CHECK_GT(std::hypot(xi(kVxIdx), xi(kVyIdx)), 1e-2);
214 const float norm_squared = xi(kVxIdx) * xi(kVxIdx) + xi(kVyIdx) * xi(kVyIdx);
215 const float norm = std::sqrt(norm_squared);
216 const float norm_ss = norm_squared * norm_squared;
217 const float sqrt_norm_sss = std::sqrt(norm_ss * norm_squared);
219 (*grads)[kPxIdx](kPxIdx) = 1.0;
220 (*grads)[kPyIdx](kPyIdx) = 1.0;
221 (*grads)[kThetaIdx](kVxIdx) = -xi(kVyIdx) / norm_squared;
222 (*grads)[kThetaIdx](kVyIdx) = xi(kVxIdx) / norm_squared;
223 (*grads)[kVIdx](kVxIdx) = xi(kVxIdx) / norm;
224 (*grads)[kVIdx](kVyIdx) = xi(kVyIdx) / norm;
226 (*hesses)[kThetaIdx](kVxIdx, kVxIdx) =
227 2.0 * xi(kVxIdx) * xi(kVyIdx) / norm_ss;
228 (*hesses)[kThetaIdx](kVxIdx, kVyIdx) =
229 (xi(kVyIdx) * xi(kVyIdx) - xi(kVxIdx) * xi(kVxIdx)) / norm_ss;
230 (*hesses)[kThetaIdx](kVyIdx, kVxIdx) = (*hesses)[kThetaIdx](kVxIdx, kVyIdx);
231 (*hesses)[kThetaIdx](kVyIdx, kVyIdx) = -(*hesses)[kThetaIdx](kVxIdx, kVxIdx);
232 (*hesses)[kVIdx](kVxIdx, kVxIdx) = (xi(kVyIdx) * xi(kVyIdx)) / sqrt_norm_sss;
233 (*hesses)[kVIdx](kVxIdx, kVyIdx) = (-xi(kVxIdx) * xi(kVyIdx)) / sqrt_norm_sss;
234 (*hesses)[kVIdx](kVyIdx, kVxIdx) = (*hesses)[kVIdx](kVxIdx, kVyIdx);
235 (*hesses)[kVIdx](kVyIdx, kVyIdx) = (xi(kVxIdx) * xi(kVxIdx)) / sqrt_norm_sss;
238 inline float SinglePlayerFlatUnicycle4D::DistanceBetween(
239 const VectorXf& x0,
const VectorXf& x1)
const {
241 const float dx = x0(kPxIdx) - x1(kPxIdx);
242 const float dy = x0(kPyIdx) - x1(kPyIdx);
243 return dx * dx + dy * dy;