TrajoptLib
Library for generating time-optimal trajectories for FRC robots.
Loading...
Searching...
No Matches
generate_linear_initial_guess.hpp
1// Copyright (c) TrajoptLib contributors
2
3#pragma once
4
5#include <cmath>
6#include <concepts>
7#include <cstddef>
8#include <vector>
9
10#include "trajopt/geometry/pose2.hpp"
11#include "trajopt/util/trajopt_util.hpp"
12
13namespace trajopt {
14
16
17// TODO: Replace with std::vector.append_range() from C++23
18template <typename T>
19inline void append_range(std::vector<T>& base,
20 const std::vector<T>& new_items) {
21 base.insert(base.end(), new_items.begin(), new_items.end());
22}
23
24template <typename Solution>
25inline Solution generate_linear_initial_guess(
26 const std::vector<std::vector<Pose2d>>& initial_guess_points,
27 const std::vector<size_t> control_interval_counts) {
28 size_t wpt_cnt = control_interval_counts.size() + 1;
29 size_t samp_tot = get_index(control_interval_counts, wpt_cnt - 1, 0) + 1;
30
31 Solution initial_guess;
32
33 initial_guess.x.reserve(samp_tot);
34 initial_guess.y.reserve(samp_tot);
35 if constexpr (std::same_as<Solution, DifferentialSolution>) {
36 initial_guess.heading.reserve(samp_tot);
37 } else {
38 initial_guess.thetacos.reserve(samp_tot);
39 initial_guess.thetasin.reserve(samp_tot);
40 }
41
42 initial_guess.dt.reserve(samp_tot);
43
44 initial_guess.x.push_back(initial_guess_points.front().front().x());
45 initial_guess.y.push_back(initial_guess_points.front().front().y());
46 if constexpr (std::same_as<Solution, DifferentialSolution>) {
47 initial_guess.heading.push_back(
48 initial_guess_points.front().front().rotation().radians());
49 } else {
50 initial_guess.thetacos.push_back(
51 initial_guess_points.front().front().rotation().cos());
52 initial_guess.thetasin.push_back(
53 initial_guess_points.front().front().rotation().sin());
54 }
55
56 for (size_t i = 0; i < samp_tot; ++i) {
57 initial_guess.dt.push_back((wpt_cnt * 5.0) / samp_tot);
58 }
59
60 for (size_t wpt_index = 1; wpt_index < wpt_cnt; ++wpt_index) {
61 size_t N_sgmt = control_interval_counts.at(wpt_index - 1);
62 size_t guess_point_count = initial_guess_points.at(wpt_index).size();
63 size_t N_guess_sgmt = N_sgmt / guess_point_count;
64 append_range(
65 initial_guess.x,
66 linspace(initial_guess_points.at(wpt_index - 1).back().x(),
67 initial_guess_points.at(wpt_index).front().x(), N_guess_sgmt));
68 append_range(
69 initial_guess.y,
70 linspace(initial_guess_points.at(wpt_index - 1).back().y(),
71 initial_guess_points.at(wpt_index).front().y(), N_guess_sgmt));
72 auto wpt_thetas = angle_linspace(
73 initial_guess_points.at(wpt_index - 1).back().rotation().radians(),
74 initial_guess_points.at(wpt_index).front().rotation().radians(),
75 N_guess_sgmt);
76 for (auto theta : wpt_thetas) {
77 if constexpr (std::same_as<Solution, DifferentialSolution>) {
78 initial_guess.heading.push_back(theta);
79 } else {
80 initial_guess.thetacos.push_back(std::cos(theta));
81 initial_guess.thetasin.push_back(std::sin(theta));
82 }
83 }
84 for (size_t guess_point_index = 1;
85 guess_point_index < guess_point_count - 1;
86 ++guess_point_index) { // if three or more guess points
87 append_range(
88 initial_guess.x,
89 linspace(
90 initial_guess_points.at(wpt_index).at(guess_point_index - 1).x(),
91 initial_guess_points.at(wpt_index).at(guess_point_index).x(),
92 N_guess_sgmt));
93 append_range(
94 initial_guess.y,
95 linspace(
96 initial_guess_points.at(wpt_index).at(guess_point_index - 1).y(),
97 initial_guess_points.at(wpt_index).at(guess_point_index).y(),
98 N_guess_sgmt));
99 auto guess_thetas = angle_linspace(initial_guess_points.at(wpt_index)
100 .at(guess_point_index - 1)
101 .rotation()
102 .radians(),
103 initial_guess_points.at(wpt_index)
104 .at(guess_point_index)
105 .rotation()
106 .radians(),
107 N_guess_sgmt);
108 for (auto theta : guess_thetas) {
109 if constexpr (std::same_as<Solution, DifferentialSolution>) {
110 initial_guess.heading.push_back(theta);
111 } else {
112 initial_guess.thetacos.push_back(std::cos(theta));
113 initial_guess.thetasin.push_back(std::sin(theta));
114 }
115 }
116 }
117 if (guess_point_count > 1) { // if two or more guess points
118 size_t N_last_guess_sgmt =
119 N_sgmt - (guess_point_count - 1) * N_guess_sgmt;
120 append_range(
121 initial_guess.x,
122 linspace(
123 initial_guess_points.at(wpt_index).at(guess_point_count - 2).x(),
124 initial_guess_points.at(wpt_index).back().x(),
125 N_last_guess_sgmt));
126 append_range(
127 initial_guess.y,
128 linspace(
129 initial_guess_points.at(wpt_index).at(guess_point_count - 2).y(),
130 initial_guess_points.at(wpt_index).back().y(),
131 N_last_guess_sgmt));
132 auto last_thetas = angle_linspace(
133 initial_guess_points.at(wpt_index)
134 .at(guess_point_count - 2)
135 .rotation()
136 .radians(),
137 initial_guess_points.at(wpt_index).back().rotation().radians(),
138 N_last_guess_sgmt);
139 for (auto theta : last_thetas) {
140 if constexpr (std::same_as<Solution, DifferentialSolution>) {
141 initial_guess.heading.push_back(theta);
142 } else {
143 initial_guess.thetacos.push_back(std::cos(theta));
144 initial_guess.thetasin.push_back(std::sin(theta));
145 }
146 }
147 }
148 }
149
150 return initial_guess;
151}
152
153} // namespace trajopt
The holonomic trajectory optimization solution.
Definition differential_trajectory_generator.hpp:47
std::vector< double > x
X positions.
Definition differential_trajectory_generator.hpp:52