77#include < algorithm>
88#include < chrono>
99#include < ranges>
10- #include < utility>
1110#include < vector>
1211
1312#include < sleipnir/optimization/OptimizationProblem.hpp>
@@ -84,7 +83,7 @@ SwerveTrajectoryGenerator::SwerveTrajectoryGenerator(
8483 _Fy.reserve (moduleCnt);
8584 }
8685
87- dts.reserve (sgmtCnt );
86+ dts.reserve (sampTot );
8887
8988 for (size_t index = 0 ; index < sampTot; ++index) {
9089 x.emplace_back (problem.DecisionVariable ());
@@ -102,9 +101,7 @@ SwerveTrajectoryGenerator::SwerveTrajectoryGenerator(
102101 Fx.at (index).emplace_back (problem.DecisionVariable ());
103102 Fy.at (index).emplace_back (problem.DecisionVariable ());
104103 }
105- }
106104
107- for (size_t sgmtIndex = 0 ; sgmtIndex < sgmtCnt; ++sgmtIndex) {
108105 dts.emplace_back (problem.DecisionVariable ());
109106 }
110107
@@ -118,7 +115,6 @@ SwerveTrajectoryGenerator::SwerveTrajectoryGenerator(
118115 }
119116
120117 // Minimize total time
121- sleipnir::Variable T_tot = 0 ;
122118 const double maxForce =
123119 path.drivetrain .wheelMaxTorque * 4 / path.drivetrain .wheelRadius ;
124120 const auto maxAccel = maxForce / path.drivetrain .mass ;
@@ -131,21 +127,16 @@ SwerveTrajectoryGenerator::SwerveTrajectoryGenerator(
131127 const auto maxAngVel = maxDrivetrainVelocity / maxWheelPositionRadius;
132128 const auto maxAngAccel = maxAccel / maxWheelPositionRadius;
133129 for (size_t sgmtIndex = 0 ; sgmtIndex < Ns.size (); ++sgmtIndex) {
134- auto & dt = dts.at (sgmtIndex);
135130 auto N_sgmt = Ns.at (sgmtIndex);
136- auto T_sgmt = dt * static_cast < int >(N_sgmt );
137- T_tot += T_sgmt ;
131+ const auto sgmt_start = GetIndex (Ns, sgmtIndex );
132+ const auto sgmt_end = GetIndex (Ns, sgmtIndex + 1 ) ;
138133
139- problem.SubjectTo (dt >= 0 );
140- problem.SubjectTo (dt * path.drivetrain .wheelRadius *
141- path.drivetrain .wheelMaxAngularVelocity <=
142- minWidth);
143134 if (N_sgmt == 0 ) {
144- dt.SetValue (0 );
135+ for (size_t index = sgmt_start; index < sgmt_end + 1 ; ++index) {
136+ dts.at (index).SetValue (0.0 );
137+ }
145138 } else {
146139 // Use initialGuess and Ns to find the dx, dy, dθ between wpts
147- const auto sgmt_start = GetIndex (Ns, sgmtIndex);
148- const auto sgmt_end = GetIndex (Ns, sgmtIndex + 1 );
149140 const auto dx =
150141 initialGuess.x .at (sgmt_end) - initialGuess.x .at (sgmt_start);
151142 const auto dy =
@@ -167,15 +158,20 @@ SwerveTrajectoryGenerator::SwerveTrajectoryGenerator(
167158 CalculateTrapezoidalTime (dist, maxLinearVel, maxAccel);
168159 const double sgmtTime = angularTime + linearTime;
169160
170- dt.SetValue (sgmtTime / N_sgmt);
161+ for (size_t index = sgmt_start; index < sgmt_end + 1 ; ++index) {
162+ auto & dt = dts.at (index);
163+ problem.SubjectTo (dt >= 0 );
164+ problem.SubjectTo (dt <= 3 );
165+ dt.SetValue (sgmtTime / N_sgmt);
166+ }
171167 }
172168 }
173- problem.Minimize (std::move (T_tot));
169+ problem.Minimize (
170+ std::accumulate (dts.begin (), dts.end (), sleipnir::Variable{0.0 }));
174171
175172 // Apply kinematics constraints
176173 for (size_t wptIndex = 0 ; wptIndex < wptCnt - 1 ; ++wptIndex) {
177174 size_t N_sgmt = Ns.at (wptIndex);
178- auto dt = dts.at (wptIndex);
179175
180176 for (size_t sampleIndex = 0 ; sampleIndex < N_sgmt; ++sampleIndex) {
181177 size_t index = GetIndex (Ns, wptIndex, sampleIndex);
@@ -198,14 +194,20 @@ SwerveTrajectoryGenerator::SwerveTrajectoryGenerator(
198194 auto α_k = α.at (index);
199195 auto α_k_1 = α.at (index + 1 );
200196
197+ auto dt_k = dts.at (index);
198+ if (sampleIndex < N_sgmt - 1 ) {
199+ auto dt_k_1 = dts.at (index + 1 );
200+ problem.SubjectTo (dt_k_1 == dt_k);
201+ }
202+
201203 // xₖ₊₁ = xₖ + vₖt + 1/2aₖt²
202204 // θₖ₊₁ = θₖ + ωₖt
203205 // vₖ₊₁ = vₖ + aₖt
204206 // ωₖ₊₁ = ωₖ + αₖt
205- problem.SubjectTo (x_k_1 == x_k + v_k * dt + a_k * 0.5 * dt * dt );
206- problem.SubjectTo ((θ_k_1 - θ_k) == Rotation2v{ω_k * dt });
207- problem.SubjectTo (v_k_1 == v_k + a_k * dt );
208- problem.SubjectTo (ω_k_1 == ω_k + α_k * dt );
207+ problem.SubjectTo (x_k_1 == x_k + v_k * dt_k + a_k * 0.5 * dt_k * dt_k );
208+ problem.SubjectTo ((θ_k_1 - θ_k) == Rotation2v{ω_k * dt_k });
209+ problem.SubjectTo (v_k_1 == v_k + a_k * dt_k );
210+ problem.SubjectTo (ω_k_1 == ω_k + α_k * dt_k );
209211 }
210212 }
211213
@@ -379,17 +381,6 @@ void SwerveTrajectoryGenerator::ApplyInitialGuess(
379381}
380382
381383SwerveSolution SwerveTrajectoryGenerator::ConstructSwerveSolution () {
382- std::vector<double > dtPerSample;
383- for (size_t sgmtIndex = 0 ; sgmtIndex < Ns.size (); ++sgmtIndex) {
384- auto N = Ns.at (sgmtIndex);
385- auto dt = dts.at (sgmtIndex);
386-
387- double dt_value = dt.Value ();
388- for (size_t i = 0 ; i < N; ++i) {
389- dtPerSample.push_back (dt_value);
390- }
391- }
392-
393384 auto getValue = [](auto & var) { return var.Value (); };
394385
395386 // TODO: Use std::ranges::to() from C++23
@@ -408,7 +399,7 @@ SwerveSolution SwerveTrajectoryGenerator::ConstructSwerveSolution() {
408399 return std::vector<std::vector<double >>{std::begin (view), std::end (view)};
409400 };
410401
411- return SwerveSolution{dtPerSample, vectorValue (x), vectorValue (y),
402+ return SwerveSolution{vectorValue (dts), vectorValue (x), vectorValue (y),
412403 vectorValue (cosθ), vectorValue (sinθ), vectorValue (vx),
413404 vectorValue (vy), vectorValue (ω), vectorValue (ax),
414405 vectorValue (ay), vectorValue (α), matrixValue (Fx),
0 commit comments