blob: 7df6998dfe14b7f09447a912cee662b8a86be110 [file] [log] [blame]
Philipp Schrader4bd29b12017-02-22 04:42:27 +00001#include "frc971/autonomous/base_autonomous_actor.h"
2
3#include <inttypes.h>
4
5#include <chrono>
6#include <cmath>
7
John Park33858a32018-09-28 23:05:48 -07008#include "aos/util/phased_loop.h"
9#include "aos/logging/logging.h"
Philipp Schrader4bd29b12017-02-22 04:42:27 +000010
Alex Perrycb7da4b2019-08-28 19:35:56 -070011#include "frc971/control_loops/control_loops_generated.h"
12#include "frc971/control_loops/drivetrain/drivetrain_goal_generated.h"
13#include "frc971/control_loops/drivetrain/drivetrain_status_generated.h"
14#include "y2019/control_loops/drivetrain/target_selector_generated.h"
Philipp Schrader4bd29b12017-02-22 04:42:27 +000015
Philipp Schrader4bd29b12017-02-22 04:42:27 +000016using ::aos::monotonic_clock;
17namespace chrono = ::std::chrono;
18namespace this_thread = ::std::this_thread;
Alex Perrycb7da4b2019-08-28 19:35:56 -070019namespace drivetrain = frc971::control_loops::drivetrain;
Philipp Schrader4bd29b12017-02-22 04:42:27 +000020
Brian Silvermanf83678c2017-03-11 14:02:26 -080021namespace frc971 {
22namespace autonomous {
Philipp Schrader4bd29b12017-02-22 04:42:27 +000023
24BaseAutonomousActor::BaseAutonomousActor(
Austin Schuh1bf8a212019-05-26 22:13:14 -070025 ::aos::EventLoop *event_loop,
Austin Schuhbcce26a2018-03-26 23:41:24 -070026 const control_loops::drivetrain::DrivetrainConfig<double> &dt_config)
Alex Perrycb7da4b2019-08-28 19:35:56 -070027 : aos::common::actions::ActorBase<Goal>(event_loop, "/autonomous"),
Philipp Schrader4bd29b12017-02-22 04:42:27 +000028 dt_config_(dt_config),
Austin Schuhc087b102019-05-12 15:33:12 -070029 initial_drivetrain_({0.0, 0.0}),
30 target_selector_hint_sender_(
Austin Schuheb99d072019-05-12 21:03:38 -070031 event_loop->MakeSender<
Austin Schuhc087b102019-05-12 15:33:12 -070032 ::y2019::control_loops::drivetrain::TargetSelectorHint>(
Alex Perrycb7da4b2019-08-28 19:35:56 -070033 "/drivetrain")),
Austin Schuhbd0a40f2019-06-30 14:56:31 -070034 drivetrain_goal_sender_(
Alex Perrycb7da4b2019-08-28 19:35:56 -070035 event_loop->MakeSender<drivetrain::Goal>("/drivetrain")),
Austin Schuhbd0a40f2019-06-30 14:56:31 -070036 drivetrain_status_fetcher_(
Alex Perrycb7da4b2019-08-28 19:35:56 -070037 event_loop->MakeFetcher<drivetrain::Status>("/drivetrain")),
Austin Schuhbd0a40f2019-06-30 14:56:31 -070038 drivetrain_goal_fetcher_(
Austin Schuh094d09b2020-11-20 23:26:52 -080039 event_loop->MakeFetcher<drivetrain::Goal>("/drivetrain")) {
40 event_loop->SetRuntimeRealtimePriority(29);
41}
Philipp Schrader4bd29b12017-02-22 04:42:27 +000042
43void BaseAutonomousActor::ResetDrivetrain() {
Austin Schuhf257f3c2019-10-27 21:00:43 -070044 AOS_LOG(INFO, "resetting the drivetrain\n");
Austin Schuh0aae9242018-03-14 19:49:44 -070045 max_drivetrain_voltage_ = 12.0;
James Kuszmaulc73bb222019-04-07 12:15:35 -070046 goal_spline_handle_ = 0;
Austin Schuhbd0a40f2019-06-30 14:56:31 -070047
Alex Perrycb7da4b2019-08-28 19:35:56 -070048 auto builder = drivetrain_goal_sender_.MakeBuilder();
49
50 drivetrain::Goal::Builder goal_builder =
51 builder.MakeBuilder<drivetrain::Goal>();
Austin Schuh872723c2019-12-25 14:38:09 -080052 goal_builder.add_controller_type(drivetrain::ControllerType::POLYDRIVE);
Alex Perrycb7da4b2019-08-28 19:35:56 -070053 goal_builder.add_highgear(true);
54 goal_builder.add_wheel(0.0);
55 goal_builder.add_throttle(0.0);
56 goal_builder.add_left_goal(initial_drivetrain_.left);
57 goal_builder.add_right_goal(initial_drivetrain_.right);
58 goal_builder.add_max_ss_voltage(max_drivetrain_voltage_);
59 builder.Send(goal_builder.Finish());
Philipp Schrader4bd29b12017-02-22 04:42:27 +000060}
61
62void BaseAutonomousActor::InitializeEncoders() {
Austin Schuhbd0a40f2019-06-30 14:56:31 -070063 // Spin until we get a message.
64 WaitUntil([this]() { return drivetrain_status_fetcher_.Fetch(); });
65
66 initial_drivetrain_.left =
Alex Perrycb7da4b2019-08-28 19:35:56 -070067 drivetrain_status_fetcher_->estimated_left_position();
Austin Schuhbd0a40f2019-06-30 14:56:31 -070068 initial_drivetrain_.right =
Alex Perrycb7da4b2019-08-28 19:35:56 -070069 drivetrain_status_fetcher_->estimated_right_position();
Philipp Schrader4bd29b12017-02-22 04:42:27 +000070}
71
72void BaseAutonomousActor::StartDrive(double distance, double angle,
Alex Perrycb7da4b2019-08-28 19:35:56 -070073 ProfileParametersT linear,
74 ProfileParametersT angular) {
Austin Schuhf257f3c2019-10-27 21:00:43 -070075 AOS_LOG(INFO, "Driving distance %f, angle %f\n", distance, angle);
Philipp Schrader4bd29b12017-02-22 04:42:27 +000076 {
77 const double dangle = angle * dt_config_.robot_radius;
78 initial_drivetrain_.left += distance - dangle;
79 initial_drivetrain_.right += distance + dangle;
80 }
81
Alex Perrycb7da4b2019-08-28 19:35:56 -070082 auto builder = drivetrain_goal_sender_.MakeBuilder();
Philipp Schrader4bd29b12017-02-22 04:42:27 +000083
Alex Perrycb7da4b2019-08-28 19:35:56 -070084 auto linear_offset = ProfileParameters::Pack(*builder.fbb(), &linear);
85 auto angular_offset = ProfileParameters::Pack(*builder.fbb(), &angular);
Philipp Schrader4bd29b12017-02-22 04:42:27 +000086
Alex Perrycb7da4b2019-08-28 19:35:56 -070087 drivetrain::Goal::Builder goal_builder =
88 builder.MakeBuilder<drivetrain::Goal>();
89
Austin Schuh872723c2019-12-25 14:38:09 -080090 goal_builder.add_controller_type(drivetrain::ControllerType::MOTION_PROFILE);
Alex Perrycb7da4b2019-08-28 19:35:56 -070091 goal_builder.add_highgear(true);
92 goal_builder.add_wheel(0.0);
93 goal_builder.add_throttle(0.0);
94 goal_builder.add_left_goal(initial_drivetrain_.left);
95 goal_builder.add_right_goal(initial_drivetrain_.right);
96 goal_builder.add_max_ss_voltage(max_drivetrain_voltage_);
97 goal_builder.add_linear(linear_offset);
98 goal_builder.add_angular(angular_offset);
99
100 builder.Send(goal_builder.Finish());
Philipp Schrader4bd29b12017-02-22 04:42:27 +0000101}
102
103void BaseAutonomousActor::WaitUntilDoneOrCanceled(
104 ::std::unique_ptr<aos::common::actions::Action> action) {
105 if (!action) {
Austin Schuhf257f3c2019-10-27 21:00:43 -0700106 AOS_LOG(ERROR, "No action, not waiting\n");
Philipp Schrader4bd29b12017-02-22 04:42:27 +0000107 return;
108 }
109
110 ::aos::time::PhasedLoop phased_loop(::std::chrono::milliseconds(5),
Austin Schuhd32b3622019-06-23 18:49:06 -0700111 event_loop()->monotonic_now(),
Philipp Schrader4bd29b12017-02-22 04:42:27 +0000112 ::std::chrono::milliseconds(5) / 2);
113 while (true) {
114 // Poll the running bit and see if we should cancel.
115 phased_loop.SleepUntilNext();
116 if (!action->Running() || ShouldCancel()) {
117 return;
118 }
119 }
120}
121
122bool BaseAutonomousActor::WaitForDriveDone() {
123 ::aos::time::PhasedLoop phased_loop(::std::chrono::milliseconds(5),
Austin Schuhd32b3622019-06-23 18:49:06 -0700124 event_loop()->monotonic_now(),
Philipp Schrader4bd29b12017-02-22 04:42:27 +0000125 ::std::chrono::milliseconds(5) / 2);
126
127 while (true) {
128 if (ShouldCancel()) {
129 return false;
130 }
131 phased_loop.SleepUntilNext();
Austin Schuhbd0a40f2019-06-30 14:56:31 -0700132 drivetrain_status_fetcher_.Fetch();
Philipp Schrader4bd29b12017-02-22 04:42:27 +0000133 if (IsDriveDone()) {
134 return true;
135 }
136 }
137}
138
139bool BaseAutonomousActor::IsDriveDone() {
Brian Silvermanf83678c2017-03-11 14:02:26 -0800140 static constexpr double kPositionTolerance = 0.02;
141 static constexpr double kVelocityTolerance = 0.10;
142 static constexpr double kProfileTolerance = 0.001;
Philipp Schrader4bd29b12017-02-22 04:42:27 +0000143
Austin Schuhbd0a40f2019-06-30 14:56:31 -0700144 if (drivetrain_status_fetcher_.get()) {
Alex Perrycb7da4b2019-08-28 19:35:56 -0700145 if (::std::abs(drivetrain_status_fetcher_->profiled_left_position_goal() -
Philipp Schrader4bd29b12017-02-22 04:42:27 +0000146 initial_drivetrain_.left) < kProfileTolerance &&
Alex Perrycb7da4b2019-08-28 19:35:56 -0700147 ::std::abs(drivetrain_status_fetcher_->profiled_right_position_goal() -
Philipp Schrader4bd29b12017-02-22 04:42:27 +0000148 initial_drivetrain_.right) < kProfileTolerance &&
Alex Perrycb7da4b2019-08-28 19:35:56 -0700149 ::std::abs(drivetrain_status_fetcher_->estimated_left_position() -
Philipp Schrader4bd29b12017-02-22 04:42:27 +0000150 initial_drivetrain_.left) < kPositionTolerance &&
Alex Perrycb7da4b2019-08-28 19:35:56 -0700151 ::std::abs(drivetrain_status_fetcher_->estimated_right_position() -
Philipp Schrader4bd29b12017-02-22 04:42:27 +0000152 initial_drivetrain_.right) < kPositionTolerance &&
Alex Perrycb7da4b2019-08-28 19:35:56 -0700153 ::std::abs(drivetrain_status_fetcher_->estimated_left_velocity()) <
Philipp Schrader4bd29b12017-02-22 04:42:27 +0000154 kVelocityTolerance &&
Alex Perrycb7da4b2019-08-28 19:35:56 -0700155 ::std::abs(drivetrain_status_fetcher_->estimated_right_velocity()) <
Philipp Schrader4bd29b12017-02-22 04:42:27 +0000156 kVelocityTolerance) {
Austin Schuhf257f3c2019-10-27 21:00:43 -0700157 AOS_LOG(INFO, "Finished drive\n");
Philipp Schrader4bd29b12017-02-22 04:42:27 +0000158 return true;
159 }
160 }
161 return false;
162}
163
164bool BaseAutonomousActor::WaitForAboveAngle(double angle) {
165 ::aos::time::PhasedLoop phased_loop(::std::chrono::milliseconds(5),
Austin Schuhd32b3622019-06-23 18:49:06 -0700166 event_loop()->monotonic_now(),
Philipp Schrader4bd29b12017-02-22 04:42:27 +0000167 ::std::chrono::milliseconds(5) / 2);
168 while (true) {
169 if (ShouldCancel()) {
170 return false;
171 }
172 phased_loop.SleepUntilNext();
Austin Schuhbd0a40f2019-06-30 14:56:31 -0700173 drivetrain_status_fetcher_.Fetch();
Philipp Schrader4bd29b12017-02-22 04:42:27 +0000174 if (IsDriveDone()) {
175 return true;
176 }
Austin Schuhbd0a40f2019-06-30 14:56:31 -0700177 if (drivetrain_status_fetcher_.get()) {
Alex Perrycb7da4b2019-08-28 19:35:56 -0700178 if (drivetrain_status_fetcher_->ground_angle() > angle) {
Philipp Schrader4bd29b12017-02-22 04:42:27 +0000179 return true;
180 }
181 }
182 }
183}
184
185bool BaseAutonomousActor::WaitForBelowAngle(double angle) {
186 ::aos::time::PhasedLoop phased_loop(::std::chrono::milliseconds(5),
Austin Schuhd32b3622019-06-23 18:49:06 -0700187 event_loop()->monotonic_now(),
Philipp Schrader4bd29b12017-02-22 04:42:27 +0000188 ::std::chrono::milliseconds(5) / 2);
189 while (true) {
190 if (ShouldCancel()) {
191 return false;
192 }
193 phased_loop.SleepUntilNext();
Austin Schuhbd0a40f2019-06-30 14:56:31 -0700194 drivetrain_status_fetcher_.Fetch();
Philipp Schrader4bd29b12017-02-22 04:42:27 +0000195 if (IsDriveDone()) {
196 return true;
197 }
Austin Schuhbd0a40f2019-06-30 14:56:31 -0700198 if (drivetrain_status_fetcher_.get()) {
Alex Perrycb7da4b2019-08-28 19:35:56 -0700199 if (drivetrain_status_fetcher_->ground_angle() < angle) {
Philipp Schrader4bd29b12017-02-22 04:42:27 +0000200 return true;
201 }
202 }
203 }
204}
205
206bool BaseAutonomousActor::WaitForMaxBy(double angle) {
207 ::aos::time::PhasedLoop phased_loop(::std::chrono::milliseconds(5),
Austin Schuhd32b3622019-06-23 18:49:06 -0700208 event_loop()->monotonic_now(),
Philipp Schrader4bd29b12017-02-22 04:42:27 +0000209 ::std::chrono::milliseconds(5) / 2);
210 double max_angle = -M_PI;
211 while (true) {
212 if (ShouldCancel()) {
213 return false;
214 }
215 phased_loop.SleepUntilNext();
Austin Schuhbd0a40f2019-06-30 14:56:31 -0700216 drivetrain_status_fetcher_.Fetch();
Philipp Schrader4bd29b12017-02-22 04:42:27 +0000217 if (IsDriveDone()) {
218 return true;
219 }
Austin Schuhbd0a40f2019-06-30 14:56:31 -0700220 if (drivetrain_status_fetcher_.get()) {
Alex Perrycb7da4b2019-08-28 19:35:56 -0700221 if (drivetrain_status_fetcher_->ground_angle() > max_angle) {
222 max_angle = drivetrain_status_fetcher_->ground_angle();
Philipp Schrader4bd29b12017-02-22 04:42:27 +0000223 }
Alex Perrycb7da4b2019-08-28 19:35:56 -0700224 if (drivetrain_status_fetcher_->ground_angle() < max_angle - angle) {
Philipp Schrader4bd29b12017-02-22 04:42:27 +0000225 return true;
226 }
227 }
228 }
229}
230
231bool BaseAutonomousActor::WaitForDriveNear(double distance, double angle) {
232 ::aos::time::PhasedLoop phased_loop(::std::chrono::milliseconds(5),
Austin Schuhd32b3622019-06-23 18:49:06 -0700233 event_loop()->monotonic_now(),
Philipp Schrader4bd29b12017-02-22 04:42:27 +0000234 ::std::chrono::milliseconds(5) / 2);
235 constexpr double kPositionTolerance = 0.02;
236 constexpr double kProfileTolerance = 0.001;
237
Austin Schuhe6af9992018-07-08 15:59:14 -0700238 bool drive_has_been_close = false;
239 bool turn_has_been_close = false;
240 bool printed_first = false;
241
Philipp Schrader4bd29b12017-02-22 04:42:27 +0000242 while (true) {
243 if (ShouldCancel()) {
244 return false;
245 }
246 phased_loop.SleepUntilNext();
Austin Schuhbd0a40f2019-06-30 14:56:31 -0700247 drivetrain_status_fetcher_.Fetch();
248 if (drivetrain_status_fetcher_.get()) {
Philipp Schrader4bd29b12017-02-22 04:42:27 +0000249 const double left_profile_error =
250 (initial_drivetrain_.left -
Alex Perrycb7da4b2019-08-28 19:35:56 -0700251 drivetrain_status_fetcher_->profiled_left_position_goal());
Philipp Schrader4bd29b12017-02-22 04:42:27 +0000252 const double right_profile_error =
253 (initial_drivetrain_.right -
Alex Perrycb7da4b2019-08-28 19:35:56 -0700254 drivetrain_status_fetcher_->profiled_right_position_goal());
Philipp Schrader4bd29b12017-02-22 04:42:27 +0000255
256 const double left_error =
257 (initial_drivetrain_.left -
Alex Perrycb7da4b2019-08-28 19:35:56 -0700258 drivetrain_status_fetcher_->estimated_left_position());
Philipp Schrader4bd29b12017-02-22 04:42:27 +0000259 const double right_error =
260 (initial_drivetrain_.right -
Alex Perrycb7da4b2019-08-28 19:35:56 -0700261 drivetrain_status_fetcher_->estimated_right_position());
Philipp Schrader4bd29b12017-02-22 04:42:27 +0000262
263 const double profile_distance_to_go =
264 (left_profile_error + right_profile_error) / 2.0;
265 const double profile_angle_to_go =
266 (right_profile_error - left_profile_error) /
267 (dt_config_.robot_radius * 2.0);
268
269 const double distance_to_go = (left_error + right_error) / 2.0;
270 const double angle_to_go =
271 (right_error - left_error) / (dt_config_.robot_radius * 2.0);
272
Austin Schuhe6af9992018-07-08 15:59:14 -0700273 const bool drive_close =
274 ::std::abs(profile_distance_to_go) < distance + kProfileTolerance &&
275 ::std::abs(distance_to_go) < distance + kPositionTolerance;
276 const bool turn_close =
Philipp Schrader4bd29b12017-02-22 04:42:27 +0000277 ::std::abs(profile_angle_to_go) < angle + kProfileTolerance &&
Austin Schuhe6af9992018-07-08 15:59:14 -0700278 ::std::abs(angle_to_go) < angle + kPositionTolerance;
279
280 drive_has_been_close |= drive_close;
281 turn_has_been_close |= turn_close;
282 if (drive_has_been_close && !turn_has_been_close && !printed_first) {
Austin Schuhf257f3c2019-10-27 21:00:43 -0700283 AOS_LOG(INFO, "Drive finished first\n");
Austin Schuhe6af9992018-07-08 15:59:14 -0700284 printed_first = true;
285 } else if (!drive_has_been_close && turn_has_been_close &&
286 !printed_first) {
Austin Schuhf257f3c2019-10-27 21:00:43 -0700287 AOS_LOG(INFO, "Turn finished first\n");
Austin Schuhe6af9992018-07-08 15:59:14 -0700288 printed_first = true;
289 }
290
291 if (drive_close && turn_close) {
Austin Schuhf257f3c2019-10-27 21:00:43 -0700292 AOS_LOG(INFO, "Closer than %f < %f distance, %f < %f angle\n",
293 distance_to_go, distance, angle_to_go, angle);
Philipp Schrader4bd29b12017-02-22 04:42:27 +0000294 return true;
295 }
296 }
297 }
298}
299
Austin Schuh0aae9242018-03-14 19:49:44 -0700300bool BaseAutonomousActor::WaitForDriveProfileNear(double tolerance) {
Philipp Schrader4bd29b12017-02-22 04:42:27 +0000301 ::aos::time::PhasedLoop phased_loop(::std::chrono::milliseconds(5),
Austin Schuhd32b3622019-06-23 18:49:06 -0700302 event_loop()->monotonic_now(),
Philipp Schrader4bd29b12017-02-22 04:42:27 +0000303 ::std::chrono::milliseconds(5) / 2);
Philipp Schrader4bd29b12017-02-22 04:42:27 +0000304 while (true) {
305 if (ShouldCancel()) {
306 return false;
307 }
308 phased_loop.SleepUntilNext();
Austin Schuhbd0a40f2019-06-30 14:56:31 -0700309 drivetrain_status_fetcher_.Fetch();
Austin Schuh0aae9242018-03-14 19:49:44 -0700310
311 const Eigen::Matrix<double, 7, 1> current_error =
312 (Eigen::Matrix<double, 7, 1>()
313 << initial_drivetrain_.left -
Alex Perrycb7da4b2019-08-28 19:35:56 -0700314 drivetrain_status_fetcher_->profiled_left_position_goal(),
Austin Schuh0aae9242018-03-14 19:49:44 -0700315 0.0, initial_drivetrain_.right -
Alex Perrycb7da4b2019-08-28 19:35:56 -0700316 drivetrain_status_fetcher_->profiled_right_position_goal(),
Austin Schuh0aae9242018-03-14 19:49:44 -0700317 0.0, 0.0, 0.0, 0.0)
318 .finished();
319 const Eigen::Matrix<double, 2, 1> linear_error =
320 dt_config_.LeftRightToLinear(current_error);
321
Austin Schuhbd0a40f2019-06-30 14:56:31 -0700322 if (drivetrain_status_fetcher_.get()) {
Austin Schuh0aae9242018-03-14 19:49:44 -0700323 if (::std::abs(linear_error(0)) < tolerance) {
Austin Schuhf257f3c2019-10-27 21:00:43 -0700324 AOS_LOG(INFO, "Finished drive\n");
Philipp Schrader4bd29b12017-02-22 04:42:27 +0000325 return true;
326 }
327 }
328 }
329}
330
Austin Schuh0aae9242018-03-14 19:49:44 -0700331bool BaseAutonomousActor::WaitForDriveProfileDone() {
332 constexpr double kProfileTolerance = 0.001;
333 return WaitForDriveProfileNear(kProfileTolerance);
334}
335
336bool BaseAutonomousActor::WaitForTurnProfileNear(double tolerance) {
Austin Schuh546a0382017-04-16 19:10:18 -0700337 ::aos::time::PhasedLoop phased_loop(::std::chrono::milliseconds(5),
Austin Schuhd32b3622019-06-23 18:49:06 -0700338 event_loop()->monotonic_now(),
Austin Schuh546a0382017-04-16 19:10:18 -0700339 ::std::chrono::milliseconds(5) / 2);
Austin Schuh546a0382017-04-16 19:10:18 -0700340 while (true) {
341 if (ShouldCancel()) {
342 return false;
343 }
344 phased_loop.SleepUntilNext();
Austin Schuhbd0a40f2019-06-30 14:56:31 -0700345 drivetrain_status_fetcher_.Fetch();
Austin Schuh0aae9242018-03-14 19:49:44 -0700346
347 const Eigen::Matrix<double, 7, 1> current_error =
348 (Eigen::Matrix<double, 7, 1>()
349 << initial_drivetrain_.left -
Alex Perrycb7da4b2019-08-28 19:35:56 -0700350 drivetrain_status_fetcher_->profiled_left_position_goal(),
Austin Schuh0aae9242018-03-14 19:49:44 -0700351 0.0, initial_drivetrain_.right -
Alex Perrycb7da4b2019-08-28 19:35:56 -0700352 drivetrain_status_fetcher_->profiled_right_position_goal(),
Austin Schuh0aae9242018-03-14 19:49:44 -0700353 0.0, 0.0, 0.0, 0.0)
354 .finished();
355 const Eigen::Matrix<double, 2, 1> angular_error =
356 dt_config_.LeftRightToAngular(current_error);
357
Austin Schuhbd0a40f2019-06-30 14:56:31 -0700358 if (drivetrain_status_fetcher_.get()) {
Austin Schuh0aae9242018-03-14 19:49:44 -0700359 if (::std::abs(angular_error(0)) < tolerance) {
Austin Schuhf257f3c2019-10-27 21:00:43 -0700360 AOS_LOG(INFO, "Finished turn\n");
Austin Schuh546a0382017-04-16 19:10:18 -0700361 return true;
362 }
363 }
364 }
365}
366
Austin Schuh0aae9242018-03-14 19:49:44 -0700367bool BaseAutonomousActor::WaitForTurnProfileDone() {
368 constexpr double kProfileTolerance = 0.001;
369 return WaitForTurnProfileNear(kProfileTolerance);
370}
371
Austin Schuh546a0382017-04-16 19:10:18 -0700372double BaseAutonomousActor::DriveDistanceLeft() {
Austin Schuhbd0a40f2019-06-30 14:56:31 -0700373 drivetrain_status_fetcher_.Fetch();
374 if (drivetrain_status_fetcher_.get()) {
Austin Schuh546a0382017-04-16 19:10:18 -0700375 const double left_error =
376 (initial_drivetrain_.left -
Alex Perrycb7da4b2019-08-28 19:35:56 -0700377 drivetrain_status_fetcher_->estimated_left_position());
Austin Schuh546a0382017-04-16 19:10:18 -0700378 const double right_error =
379 (initial_drivetrain_.right -
Alex Perrycb7da4b2019-08-28 19:35:56 -0700380 drivetrain_status_fetcher_->estimated_right_position());
Austin Schuh546a0382017-04-16 19:10:18 -0700381
382 return (left_error + right_error) / 2.0;
383 } else {
384 return 0;
385 }
386}
387
James Kuszmaul838040b2019-04-13 15:51:02 -0700388bool BaseAutonomousActor::SplineHandle::SplineDistanceRemaining(
389 double distance) {
Austin Schuhbd0a40f2019-06-30 14:56:31 -0700390 base_autonomous_actor_->drivetrain_status_fetcher_.Fetch();
391 if (base_autonomous_actor_->drivetrain_status_fetcher_.get()) {
392 return base_autonomous_actor_->drivetrain_status_fetcher_
Alex Perrycb7da4b2019-08-28 19:35:56 -0700393 ->trajectory_logging()
394 ->is_executing() &&
Austin Schuhbd0a40f2019-06-30 14:56:31 -0700395 base_autonomous_actor_->drivetrain_status_fetcher_
Alex Perrycb7da4b2019-08-28 19:35:56 -0700396 ->trajectory_logging()
397 ->distance_remaining() < distance;
James Kuszmaul838040b2019-04-13 15:51:02 -0700398 }
399 return false;
400}
401bool BaseAutonomousActor::SplineHandle::WaitForSplineDistanceRemaining(
402 double distance) {
Austin Schuhd32b3622019-06-23 18:49:06 -0700403 ::aos::time::PhasedLoop phased_loop(
404 ::std::chrono::milliseconds(5),
405 base_autonomous_actor_->event_loop()->monotonic_now(),
406 ::std::chrono::milliseconds(5) / 2);
James Kuszmaul838040b2019-04-13 15:51:02 -0700407 while (true) {
408 if (base_autonomous_actor_->ShouldCancel()) {
409 return false;
410 }
411 phased_loop.SleepUntilNext();
412 if (SplineDistanceRemaining(distance)) {
413 return true;
414 }
415 }
416}
417
Alex Perrycb7da4b2019-08-28 19:35:56 -0700418void BaseAutonomousActor::LineFollowAtVelocity(
419 double velocity, y2019::control_loops::drivetrain::SelectionHint hint) {
420 {
421 auto builder = drivetrain_goal_sender_.MakeBuilder();
422 drivetrain::Goal::Builder goal_builder =
423 builder.MakeBuilder<drivetrain::Goal>();
424 goal_builder.add_controller_type(
Austin Schuh872723c2019-12-25 14:38:09 -0800425 drivetrain::ControllerType::SPLINE_FOLLOWER);
Alex Perrycb7da4b2019-08-28 19:35:56 -0700426 // TODO(james): Currently the 4.0 is copied from the
427 // line_follow_drivetrain.cc, but it is somewhat year-specific, so we should
428 // factor it out in some way.
429 goal_builder.add_throttle(velocity / 4.0);
430 builder.Send(goal_builder.Finish());
431 }
432
433 {
434 auto builder = target_selector_hint_sender_.MakeBuilder();
435 ::y2019::control_loops::drivetrain::TargetSelectorHint::Builder
436 target_hint_builder = builder.MakeBuilder<
437 ::y2019::control_loops::drivetrain::TargetSelectorHint>();
438
439 target_hint_builder.add_suggested_target(hint);
440 builder.Send(target_hint_builder.Finish());
441 }
James Kuszmaul838040b2019-04-13 15:51:02 -0700442}
443
Austin Schuh6bcc2302019-03-23 22:28:06 -0700444BaseAutonomousActor::SplineHandle BaseAutonomousActor::PlanSpline(
Alex Perrycb7da4b2019-08-28 19:35:56 -0700445 std::function<flatbuffers::Offset<frc971::MultiSpline>(
446 aos::Sender<frc971::control_loops::drivetrain::Goal>::Builder *builder)>
447 &&multispline_builder,
448 SplineDirection direction) {
Austin Schuhf257f3c2019-10-27 21:00:43 -0700449 AOS_LOG(INFO, "Planning spline\n");
Austin Schuh6bcc2302019-03-23 22:28:06 -0700450
451 int32_t spline_handle = (++spline_handle_) | ((getpid() & 0xFFFF) << 15);
452
Austin Schuhbd0a40f2019-06-30 14:56:31 -0700453 drivetrain_goal_fetcher_.Fetch();
Austin Schuh6bcc2302019-03-23 22:28:06 -0700454
Alex Perrycb7da4b2019-08-28 19:35:56 -0700455 auto builder = drivetrain_goal_sender_.MakeBuilder();
James Kuszmaulc864bcf2019-05-01 20:17:34 -0700456
Alex Perrycb7da4b2019-08-28 19:35:56 -0700457 flatbuffers::Offset<frc971::MultiSpline> multispline_offset =
458 multispline_builder(&builder);
459
460 drivetrain::SplineGoal::Builder spline_builder =
461 builder.MakeBuilder<drivetrain::SplineGoal>();
462 spline_builder.add_spline_idx(spline_handle);
463 spline_builder.add_drive_spline_backwards(direction ==
464 SplineDirection::kBackward);
465 spline_builder.add_spline(multispline_offset);
466
467 flatbuffers::Offset<drivetrain::SplineGoal> spline_offset =
468 spline_builder.Finish();
469
470 drivetrain::Goal::Builder goal_builder =
471 builder.MakeBuilder<drivetrain::Goal>();
472
473 drivetrain::ControllerType controller_type =
Austin Schuh872723c2019-12-25 14:38:09 -0800474 drivetrain::ControllerType::SPLINE_FOLLOWER;
Austin Schuhbd0a40f2019-06-30 14:56:31 -0700475 if (drivetrain_goal_fetcher_.get()) {
Alex Perrycb7da4b2019-08-28 19:35:56 -0700476 controller_type = drivetrain_goal_fetcher_->controller_type();
477 goal_builder.add_throttle(drivetrain_goal_fetcher_->throttle());
James Kuszmaulc864bcf2019-05-01 20:17:34 -0700478 }
Alex Perrycb7da4b2019-08-28 19:35:56 -0700479 goal_builder.add_controller_type(controller_type);
480 goal_builder.add_spline_handle(goal_spline_handle_);
Austin Schuh6bcc2302019-03-23 22:28:06 -0700481
Alex Perrycb7da4b2019-08-28 19:35:56 -0700482 goal_builder.add_spline(spline_offset);
Austin Schuh6bcc2302019-03-23 22:28:06 -0700483
Alex Perrycb7da4b2019-08-28 19:35:56 -0700484 builder.Send(goal_builder.Finish());
Austin Schuh6bcc2302019-03-23 22:28:06 -0700485
486 return BaseAutonomousActor::SplineHandle(spline_handle, this);
487}
488
489bool BaseAutonomousActor::SplineHandle::IsPlanned() {
Austin Schuhbd0a40f2019-06-30 14:56:31 -0700490 base_autonomous_actor_->drivetrain_status_fetcher_.Fetch();
Alex Perrycb7da4b2019-08-28 19:35:56 -0700491 VLOG(1) << aos::FlatbufferToJson(
492 base_autonomous_actor_->drivetrain_status_fetcher_.get());
493
Austin Schuhbd0a40f2019-06-30 14:56:31 -0700494 if (base_autonomous_actor_->drivetrain_status_fetcher_.get() &&
Alex Perrycb7da4b2019-08-28 19:35:56 -0700495 ((base_autonomous_actor_->drivetrain_status_fetcher_->trajectory_logging()
496 ->planning_spline_idx() == spline_handle_ &&
497 base_autonomous_actor_->drivetrain_status_fetcher_->trajectory_logging()
Austin Schuh872723c2019-12-25 14:38:09 -0800498 ->planning_state() == drivetrain::PlanningState::PLANNED) ||
Alex Perrycb7da4b2019-08-28 19:35:56 -0700499 base_autonomous_actor_->drivetrain_status_fetcher_->trajectory_logging()
500 ->current_spline_idx() == spline_handle_)) {
Austin Schuh6bcc2302019-03-23 22:28:06 -0700501 return true;
502 }
503 return false;
504}
505
506bool BaseAutonomousActor::SplineHandle::WaitForPlan() {
Austin Schuhd32b3622019-06-23 18:49:06 -0700507 ::aos::time::PhasedLoop phased_loop(
508 ::std::chrono::milliseconds(5),
509 base_autonomous_actor_->event_loop()->monotonic_now(),
510 ::std::chrono::milliseconds(5) / 2);
Austin Schuh6bcc2302019-03-23 22:28:06 -0700511 while (true) {
512 if (base_autonomous_actor_->ShouldCancel()) {
513 return false;
514 }
515 phased_loop.SleepUntilNext();
516 if (IsPlanned()) {
517 return true;
518 }
519 }
520}
521
522void BaseAutonomousActor::SplineHandle::Start() {
Alex Perrycb7da4b2019-08-28 19:35:56 -0700523 auto builder = base_autonomous_actor_->drivetrain_goal_sender_.MakeBuilder();
524 drivetrain::Goal::Builder goal_builder =
525 builder.MakeBuilder<drivetrain::Goal>();
Austin Schuh872723c2019-12-25 14:38:09 -0800526 goal_builder.add_controller_type(drivetrain::ControllerType::SPLINE_FOLLOWER);
Austin Schuh6bcc2302019-03-23 22:28:06 -0700527
Austin Schuhf257f3c2019-10-27 21:00:43 -0700528 AOS_LOG(INFO, "Starting spline\n");
Austin Schuh6bcc2302019-03-23 22:28:06 -0700529
Alex Perrycb7da4b2019-08-28 19:35:56 -0700530 goal_builder.add_spline_handle(spline_handle_);
Austin Schuh6bcc2302019-03-23 22:28:06 -0700531 base_autonomous_actor_->goal_spline_handle_ = spline_handle_;
532
Alex Perrycb7da4b2019-08-28 19:35:56 -0700533 builder.Send(goal_builder.Finish());
Austin Schuh6bcc2302019-03-23 22:28:06 -0700534}
535
536bool BaseAutonomousActor::SplineHandle::IsDone() {
Austin Schuhbd0a40f2019-06-30 14:56:31 -0700537 base_autonomous_actor_->drivetrain_status_fetcher_.Fetch();
Austin Schuh6bcc2302019-03-23 22:28:06 -0700538
James Kuszmaulc73bb222019-04-07 12:15:35 -0700539 // We check that the spline we are waiting on is neither currently planning
James Kuszmaul29e417d2019-04-13 10:03:35 -0700540 // nor executing (we check is_executed because it is possible to receive
541 // status messages with is_executing false before the execution has started).
542 // We check for planning so that the user can go straight from starting the
543 // planner to executing without a WaitForPlan in between.
Austin Schuhbd0a40f2019-06-30 14:56:31 -0700544 if (base_autonomous_actor_->drivetrain_status_fetcher_.get() &&
Alex Perrycb7da4b2019-08-28 19:35:56 -0700545 ((!base_autonomous_actor_->drivetrain_status_fetcher_
546 ->trajectory_logging()
547 ->is_executed() &&
548 base_autonomous_actor_->drivetrain_status_fetcher_->trajectory_logging()
549 ->current_spline_idx() == spline_handle_) ||
550 base_autonomous_actor_->drivetrain_status_fetcher_->trajectory_logging()
551 ->planning_spline_idx() == spline_handle_)) {
Austin Schuh6bcc2302019-03-23 22:28:06 -0700552 return false;
553 }
554 return true;
555}
556
557bool BaseAutonomousActor::SplineHandle::WaitForDone() {
Austin Schuhd32b3622019-06-23 18:49:06 -0700558 ::aos::time::PhasedLoop phased_loop(
559 ::std::chrono::milliseconds(5),
560 base_autonomous_actor_->event_loop()->monotonic_now(),
561 ::std::chrono::milliseconds(5) / 2);
Austin Schuh6bcc2302019-03-23 22:28:06 -0700562 while (true) {
563 if (base_autonomous_actor_->ShouldCancel()) {
564 return false;
565 }
566 phased_loop.SleepUntilNext();
567 if (IsDone()) {
568 return true;
569 }
570 }
571}
572
Philipp Schrader4bd29b12017-02-22 04:42:27 +0000573} // namespace autonomous
574} // namespace frc971