TrajoptLib
Library for generating time-optimal trajectories for FRC robots.
Loading...
Searching...
No Matches
generate_spline_initial_guess.hpp
1// Copyright (c) TrajoptLib contributors
2
3#pragma once
4
5#include <cmath>
6#include <cstddef>
7#include <concepts>
8#include <utility>
9#include <vector>
10
11#include "trajopt/geometry/pose2.hpp"
12#include "trajopt/geometry/rotation2.hpp"
13#include "trajopt/geometry/translation2.hpp"
14#include "trajopt/spline/cubic_hermite_pose_spline_holonomic.hpp"
15#include "trajopt/spline/cubic_hermite_spline.hpp"
16#include "trajopt/spline/spline_helper.hpp"
17#include "trajopt/util/trajopt_util.hpp"
18
19namespace trajopt {
20
22
23using PoseWithCurvature = std::pair<Pose2d, double>;
24
25template <typename Solution>
26inline std::vector<CubicHermitePoseSplineHolonomic> splines_from_waypoints(
27 const std::vector<std::vector<Pose2d>> initial_guess_points) {
28 size_t total_guess_points = 0;
29 for (const auto& points : initial_guess_points) {
30 total_guess_points += points.size();
31 }
32 std::vector<Translation2d> flat_translation_points;
33 std::vector<Rotation2d> flat_headings;
34 flat_translation_points.reserve(total_guess_points);
35 flat_headings.reserve(total_guess_points);
36
37 // populate translation and heading vectors
38 for (const auto& guess_points : initial_guess_points) {
39 for (const auto& guess_point : guess_points) {
40 flat_translation_points.emplace_back(guess_point.translation().x(),
41 guess_point.translation().y());
42 flat_headings.emplace_back(guess_point.rotation().cos(),
43 guess_point.rotation().sin());
44 }
45 }
46
47 std::vector<CubicHermiteSpline> splines_temp;
48 splines_temp.reserve(total_guess_points);
49
50 if constexpr (std::same_as<Solution, DifferentialSolution>) {
51 for (size_t i = 1; i < flat_translation_points.size(); ++i) {
52 const auto spline_control_vectors =
54 Pose2d{flat_translation_points.at(i - 1),
55 flat_headings.at(i - 1)},
56 {}, Pose2d{flat_translation_points.at(i), flat_headings.at(i)});
58 spline_control_vectors.front(), {}, spline_control_vectors.back());
59 for (const auto& _s : s) {
60 splines_temp.push_back(_s);
61 }
62 }
63 } else {
64 // calculate angles and pose for start and end of path spline
65 const auto start_spline_angle =
66 (flat_translation_points.at(1) - flat_translation_points.at(0)).angle();
67 const auto end_spline_angle =
68 (flat_translation_points.back() -
69 flat_translation_points.at(flat_translation_points.size() - 2))
70 .angle();
71 const Pose2d start{flat_translation_points.front(), start_spline_angle};
72 const Pose2d end{flat_translation_points.back(), end_spline_angle};
73
74 // use all interior points to create the path spline
75 std::vector<Translation2d> interior_points{
76 flat_translation_points.begin() + 1, flat_translation_points.end() - 1};
77
78 const auto spline_control_vectors =
80 start, interior_points, end);
82 spline_control_vectors.front(), interior_points,
83 spline_control_vectors.back());
84 for (const auto& _s : s) {
85 splines_temp.push_back(_s);
86 }
87 }
88
89 std::vector<CubicHermitePoseSplineHolonomic> splines;
90 splines.reserve(splines_temp.size());
91 for (size_t i = 1; i <= splines_temp.size(); ++i) {
92 splines.emplace_back(splines_temp.at(i - 1).get_initial_control_vector().x,
93 splines_temp.at(i - 1).get_final_control_vector().x,
94 splines_temp.at(i - 1).get_initial_control_vector().y,
95 splines_temp.at(i - 1).get_final_control_vector().y,
96 flat_headings.at(i - 1), flat_headings.at(i));
97 }
98 return splines;
99}
100
101template <typename Solution>
102inline Solution generate_spline_initial_guess(
103 const std::vector<std::vector<Pose2d>>& initial_guess_points,
104 const std::vector<size_t> control_interval_counts) {
105 std::vector<CubicHermitePoseSplineHolonomic> splines =
106 splines_from_waypoints<Solution>(initial_guess_points);
107 std::vector<std::vector<PoseWithCurvature>> sgmt_points;
108 for (size_t i = 0; i < initial_guess_points.size(); ++i) {
109 for ([[maybe_unused]]
110 size_t j = 0;
111 j < initial_guess_points.at(i).size(); ++j) {
112 sgmt_points.push_back(std::vector<PoseWithCurvature>());
113 }
114 }
115
116 size_t traj_idx = 0;
117 if constexpr (std::same_as<Solution, DifferentialSolution>) {
118 sgmt_points.at(0).push_back(
119 splines.at(traj_idx).get_point(0, true).value());
120 } else {
121 sgmt_points.at(0).push_back(
122 splines.at(traj_idx).get_point(0, false).value());
123 }
124 for (size_t sgmt_idx = 1; sgmt_idx < initial_guess_points.size();
125 ++sgmt_idx) {
126 auto guess_points_size = initial_guess_points.at(sgmt_idx).size();
127 auto samples_for_sgmt = control_interval_counts.at(sgmt_idx - 1);
128 size_t samples = samples_for_sgmt / guess_points_size;
129 for (size_t guessIdx = 0; guessIdx < guess_points_size; ++guessIdx) {
130 if (guessIdx == (guess_points_size - 1)) {
131 samples += (samples_for_sgmt % guess_points_size);
132 }
133 for (size_t sample_idx = 1; sample_idx < samples + 1; ++sample_idx) {
134 auto t = static_cast<double>(sample_idx) / samples;
135
136 if constexpr (std::same_as<Solution, DifferentialSolution>) {
137 const auto state = splines.at(traj_idx).get_point(t, true).value();
138 sgmt_points.at(traj_idx + 1).push_back(state);
139 } else {
140 const auto state = splines.at(traj_idx).get_point(t, false).value();
141 sgmt_points.at(traj_idx + 1).push_back(state);
142 }
143 }
144 ++traj_idx;
145 }
146 }
147
148 size_t wpt_cnt = control_interval_counts.size() + 1;
149 size_t samp_tot = get_index(control_interval_counts, wpt_cnt - 1, 0) + 1;
150
151 Solution initial_guess;
152
153 initial_guess.x.reserve(samp_tot);
154 initial_guess.y.reserve(samp_tot);
155 if constexpr (std::same_as<Solution, DifferentialSolution>) {
156 initial_guess.heading.reserve(samp_tot);
157 } else {
158 initial_guess.thetacos.reserve(samp_tot);
159 initial_guess.thetasin.reserve(samp_tot);
160 }
161
162 initial_guess.dt.reserve(samp_tot);
163 for (size_t i = 0; i < samp_tot; ++i) {
164 initial_guess.dt.push_back((wpt_cnt * 5.0) / samp_tot);
165 }
166
167 for (auto sgmt : sgmt_points) {
168 for (auto pt : sgmt) {
169 initial_guess.x.push_back(pt.first.x());
170 initial_guess.y.push_back(pt.first.y());
171 if constexpr (std::same_as<Solution, DifferentialSolution>) {
172 initial_guess.heading.push_back(pt.first.rotation().radians());
173 } else {
174 initial_guess.thetacos.push_back(pt.first.rotation().cos());
175 initial_guess.thetasin.push_back(pt.first.rotation().sin());
176 }
177 }
178 }
179 return initial_guess;
180}
181
182} // namespace trajopt
static std::vector< CubicHermiteSpline > cubic_splines_from_control_vectors(const Spline< 3 >::ControlVector &start, std::vector< Translation2d > waypoints, const Spline< 3 >::ControlVector &end)
Definition spline_helper.hpp:60
static std::array< Spline< 3 >::ControlVector, 2 > cubic_control_vectors_from_waypoints(const Pose2d &start, const std::vector< Translation2d > &interior_waypoints, const Pose2d &end)
Definition spline_helper.hpp:29
The holonomic trajectory optimization solution.
Definition differential_trajectory_generator.hpp:47