blob: dee29319cb025f4b0d50d7318abd9c7cb9983322 [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_(
Alex Perrycb7da4b2019-08-28 19:35:56 -070039 event_loop->MakeFetcher<drivetrain::Goal>("/drivetrain")) {}
Philipp Schrader4bd29b12017-02-22 04:42:27 +000040
41void BaseAutonomousActor::ResetDrivetrain() {
Austin Schuhf257f3c2019-10-27 21:00:43 -070042 AOS_LOG(INFO, "resetting the drivetrain\n");
Austin Schuh0aae9242018-03-14 19:49:44 -070043 max_drivetrain_voltage_ = 12.0;
James Kuszmaulc73bb222019-04-07 12:15:35 -070044 goal_spline_handle_ = 0;
Austin Schuhbd0a40f2019-06-30 14:56:31 -070045
Alex Perrycb7da4b2019-08-28 19:35:56 -070046 auto builder = drivetrain_goal_sender_.MakeBuilder();
47
48 drivetrain::Goal::Builder goal_builder =
49 builder.MakeBuilder<drivetrain::Goal>();
50 goal_builder.add_controller_type(drivetrain::ControllerType_POLYDRIVE);
51 goal_builder.add_highgear(true);
52 goal_builder.add_wheel(0.0);
53 goal_builder.add_throttle(0.0);
54 goal_builder.add_left_goal(initial_drivetrain_.left);
55 goal_builder.add_right_goal(initial_drivetrain_.right);
56 goal_builder.add_max_ss_voltage(max_drivetrain_voltage_);
57 builder.Send(goal_builder.Finish());
Philipp Schrader4bd29b12017-02-22 04:42:27 +000058}
59
60void BaseAutonomousActor::InitializeEncoders() {
Austin Schuhbd0a40f2019-06-30 14:56:31 -070061 // Spin until we get a message.
62 WaitUntil([this]() { return drivetrain_status_fetcher_.Fetch(); });
63
64 initial_drivetrain_.left =
Alex Perrycb7da4b2019-08-28 19:35:56 -070065 drivetrain_status_fetcher_->estimated_left_position();
Austin Schuhbd0a40f2019-06-30 14:56:31 -070066 initial_drivetrain_.right =
Alex Perrycb7da4b2019-08-28 19:35:56 -070067 drivetrain_status_fetcher_->estimated_right_position();
Philipp Schrader4bd29b12017-02-22 04:42:27 +000068}
69
70void BaseAutonomousActor::StartDrive(double distance, double angle,
Alex Perrycb7da4b2019-08-28 19:35:56 -070071 ProfileParametersT linear,
72 ProfileParametersT angular) {
Austin Schuhf257f3c2019-10-27 21:00:43 -070073 AOS_LOG(INFO, "Driving distance %f, angle %f\n", distance, angle);
Philipp Schrader4bd29b12017-02-22 04:42:27 +000074 {
75 const double dangle = angle * dt_config_.robot_radius;
76 initial_drivetrain_.left += distance - dangle;
77 initial_drivetrain_.right += distance + dangle;
78 }
79
Alex Perrycb7da4b2019-08-28 19:35:56 -070080 auto builder = drivetrain_goal_sender_.MakeBuilder();
Philipp Schrader4bd29b12017-02-22 04:42:27 +000081
Alex Perrycb7da4b2019-08-28 19:35:56 -070082 auto linear_offset = ProfileParameters::Pack(*builder.fbb(), &linear);
83 auto angular_offset = ProfileParameters::Pack(*builder.fbb(), &angular);
Philipp Schrader4bd29b12017-02-22 04:42:27 +000084
Alex Perrycb7da4b2019-08-28 19:35:56 -070085 drivetrain::Goal::Builder goal_builder =
86 builder.MakeBuilder<drivetrain::Goal>();
87
88 goal_builder.add_controller_type(drivetrain::ControllerType_MOTION_PROFILE);
89 goal_builder.add_highgear(true);
90 goal_builder.add_wheel(0.0);
91 goal_builder.add_throttle(0.0);
92 goal_builder.add_left_goal(initial_drivetrain_.left);
93 goal_builder.add_right_goal(initial_drivetrain_.right);
94 goal_builder.add_max_ss_voltage(max_drivetrain_voltage_);
95 goal_builder.add_linear(linear_offset);
96 goal_builder.add_angular(angular_offset);
97
98 builder.Send(goal_builder.Finish());
Philipp Schrader4bd29b12017-02-22 04:42:27 +000099}
100
101void BaseAutonomousActor::WaitUntilDoneOrCanceled(
102 ::std::unique_ptr<aos::common::actions::Action> action) {
103 if (!action) {
Austin Schuhf257f3c2019-10-27 21:00:43 -0700104 AOS_LOG(ERROR, "No action, not waiting\n");
Philipp Schrader4bd29b12017-02-22 04:42:27 +0000105 return;
106 }
107
108 ::aos::time::PhasedLoop phased_loop(::std::chrono::milliseconds(5),
Austin Schuhd32b3622019-06-23 18:49:06 -0700109 event_loop()->monotonic_now(),
Philipp Schrader4bd29b12017-02-22 04:42:27 +0000110 ::std::chrono::milliseconds(5) / 2);
111 while (true) {
112 // Poll the running bit and see if we should cancel.
113 phased_loop.SleepUntilNext();
114 if (!action->Running() || ShouldCancel()) {
115 return;
116 }
117 }
118}
119
120bool BaseAutonomousActor::WaitForDriveDone() {
121 ::aos::time::PhasedLoop phased_loop(::std::chrono::milliseconds(5),
Austin Schuhd32b3622019-06-23 18:49:06 -0700122 event_loop()->monotonic_now(),
Philipp Schrader4bd29b12017-02-22 04:42:27 +0000123 ::std::chrono::milliseconds(5) / 2);
124
125 while (true) {
126 if (ShouldCancel()) {
127 return false;
128 }
129 phased_loop.SleepUntilNext();
Austin Schuhbd0a40f2019-06-30 14:56:31 -0700130 drivetrain_status_fetcher_.Fetch();
Philipp Schrader4bd29b12017-02-22 04:42:27 +0000131 if (IsDriveDone()) {
132 return true;
133 }
134 }
135}
136
137bool BaseAutonomousActor::IsDriveDone() {
Brian Silvermanf83678c2017-03-11 14:02:26 -0800138 static constexpr double kPositionTolerance = 0.02;
139 static constexpr double kVelocityTolerance = 0.10;
140 static constexpr double kProfileTolerance = 0.001;
Philipp Schrader4bd29b12017-02-22 04:42:27 +0000141
Austin Schuhbd0a40f2019-06-30 14:56:31 -0700142 if (drivetrain_status_fetcher_.get()) {
Alex Perrycb7da4b2019-08-28 19:35:56 -0700143 if (::std::abs(drivetrain_status_fetcher_->profiled_left_position_goal() -
Philipp Schrader4bd29b12017-02-22 04:42:27 +0000144 initial_drivetrain_.left) < kProfileTolerance &&
Alex Perrycb7da4b2019-08-28 19:35:56 -0700145 ::std::abs(drivetrain_status_fetcher_->profiled_right_position_goal() -
Philipp Schrader4bd29b12017-02-22 04:42:27 +0000146 initial_drivetrain_.right) < kProfileTolerance &&
Alex Perrycb7da4b2019-08-28 19:35:56 -0700147 ::std::abs(drivetrain_status_fetcher_->estimated_left_position() -
Philipp Schrader4bd29b12017-02-22 04:42:27 +0000148 initial_drivetrain_.left) < kPositionTolerance &&
Alex Perrycb7da4b2019-08-28 19:35:56 -0700149 ::std::abs(drivetrain_status_fetcher_->estimated_right_position() -
Philipp Schrader4bd29b12017-02-22 04:42:27 +0000150 initial_drivetrain_.right) < kPositionTolerance &&
Alex Perrycb7da4b2019-08-28 19:35:56 -0700151 ::std::abs(drivetrain_status_fetcher_->estimated_left_velocity()) <
Philipp Schrader4bd29b12017-02-22 04:42:27 +0000152 kVelocityTolerance &&
Alex Perrycb7da4b2019-08-28 19:35:56 -0700153 ::std::abs(drivetrain_status_fetcher_->estimated_right_velocity()) <
Philipp Schrader4bd29b12017-02-22 04:42:27 +0000154 kVelocityTolerance) {
Austin Schuhf257f3c2019-10-27 21:00:43 -0700155 AOS_LOG(INFO, "Finished drive\n");
Philipp Schrader4bd29b12017-02-22 04:42:27 +0000156 return true;
157 }
158 }
159 return false;
160}
161
162bool BaseAutonomousActor::WaitForAboveAngle(double angle) {
163 ::aos::time::PhasedLoop phased_loop(::std::chrono::milliseconds(5),
Austin Schuhd32b3622019-06-23 18:49:06 -0700164 event_loop()->monotonic_now(),
Philipp Schrader4bd29b12017-02-22 04:42:27 +0000165 ::std::chrono::milliseconds(5) / 2);
166 while (true) {
167 if (ShouldCancel()) {
168 return false;
169 }
170 phased_loop.SleepUntilNext();
Austin Schuhbd0a40f2019-06-30 14:56:31 -0700171 drivetrain_status_fetcher_.Fetch();
Philipp Schrader4bd29b12017-02-22 04:42:27 +0000172 if (IsDriveDone()) {
173 return true;
174 }
Austin Schuhbd0a40f2019-06-30 14:56:31 -0700175 if (drivetrain_status_fetcher_.get()) {
Alex Perrycb7da4b2019-08-28 19:35:56 -0700176 if (drivetrain_status_fetcher_->ground_angle() > angle) {
Philipp Schrader4bd29b12017-02-22 04:42:27 +0000177 return true;
178 }
179 }
180 }
181}
182
183bool BaseAutonomousActor::WaitForBelowAngle(double angle) {
184 ::aos::time::PhasedLoop phased_loop(::std::chrono::milliseconds(5),
Austin Schuhd32b3622019-06-23 18:49:06 -0700185 event_loop()->monotonic_now(),
Philipp Schrader4bd29b12017-02-22 04:42:27 +0000186 ::std::chrono::milliseconds(5) / 2);
187 while (true) {
188 if (ShouldCancel()) {
189 return false;
190 }
191 phased_loop.SleepUntilNext();
Austin Schuhbd0a40f2019-06-30 14:56:31 -0700192 drivetrain_status_fetcher_.Fetch();
Philipp Schrader4bd29b12017-02-22 04:42:27 +0000193 if (IsDriveDone()) {
194 return true;
195 }
Austin Schuhbd0a40f2019-06-30 14:56:31 -0700196 if (drivetrain_status_fetcher_.get()) {
Alex Perrycb7da4b2019-08-28 19:35:56 -0700197 if (drivetrain_status_fetcher_->ground_angle() < angle) {
Philipp Schrader4bd29b12017-02-22 04:42:27 +0000198 return true;
199 }
200 }
201 }
202}
203
204bool BaseAutonomousActor::WaitForMaxBy(double angle) {
205 ::aos::time::PhasedLoop phased_loop(::std::chrono::milliseconds(5),
Austin Schuhd32b3622019-06-23 18:49:06 -0700206 event_loop()->monotonic_now(),
Philipp Schrader4bd29b12017-02-22 04:42:27 +0000207 ::std::chrono::milliseconds(5) / 2);
208 double max_angle = -M_PI;
209 while (true) {
210 if (ShouldCancel()) {
211 return false;
212 }
213 phased_loop.SleepUntilNext();
Austin Schuhbd0a40f2019-06-30 14:56:31 -0700214 drivetrain_status_fetcher_.Fetch();
Philipp Schrader4bd29b12017-02-22 04:42:27 +0000215 if (IsDriveDone()) {
216 return true;
217 }
Austin Schuhbd0a40f2019-06-30 14:56:31 -0700218 if (drivetrain_status_fetcher_.get()) {
Alex Perrycb7da4b2019-08-28 19:35:56 -0700219 if (drivetrain_status_fetcher_->ground_angle() > max_angle) {
220 max_angle = drivetrain_status_fetcher_->ground_angle();
Philipp Schrader4bd29b12017-02-22 04:42:27 +0000221 }
Alex Perrycb7da4b2019-08-28 19:35:56 -0700222 if (drivetrain_status_fetcher_->ground_angle() < max_angle - angle) {
Philipp Schrader4bd29b12017-02-22 04:42:27 +0000223 return true;
224 }
225 }
226 }
227}
228
229bool BaseAutonomousActor::WaitForDriveNear(double distance, double angle) {
230 ::aos::time::PhasedLoop phased_loop(::std::chrono::milliseconds(5),
Austin Schuhd32b3622019-06-23 18:49:06 -0700231 event_loop()->monotonic_now(),
Philipp Schrader4bd29b12017-02-22 04:42:27 +0000232 ::std::chrono::milliseconds(5) / 2);
233 constexpr double kPositionTolerance = 0.02;
234 constexpr double kProfileTolerance = 0.001;
235
Austin Schuhe6af9992018-07-08 15:59:14 -0700236 bool drive_has_been_close = false;
237 bool turn_has_been_close = false;
238 bool printed_first = false;
239
Philipp Schrader4bd29b12017-02-22 04:42:27 +0000240 while (true) {
241 if (ShouldCancel()) {
242 return false;
243 }
244 phased_loop.SleepUntilNext();
Austin Schuhbd0a40f2019-06-30 14:56:31 -0700245 drivetrain_status_fetcher_.Fetch();
246 if (drivetrain_status_fetcher_.get()) {
Philipp Schrader4bd29b12017-02-22 04:42:27 +0000247 const double left_profile_error =
248 (initial_drivetrain_.left -
Alex Perrycb7da4b2019-08-28 19:35:56 -0700249 drivetrain_status_fetcher_->profiled_left_position_goal());
Philipp Schrader4bd29b12017-02-22 04:42:27 +0000250 const double right_profile_error =
251 (initial_drivetrain_.right -
Alex Perrycb7da4b2019-08-28 19:35:56 -0700252 drivetrain_status_fetcher_->profiled_right_position_goal());
Philipp Schrader4bd29b12017-02-22 04:42:27 +0000253
254 const double left_error =
255 (initial_drivetrain_.left -
Alex Perrycb7da4b2019-08-28 19:35:56 -0700256 drivetrain_status_fetcher_->estimated_left_position());
Philipp Schrader4bd29b12017-02-22 04:42:27 +0000257 const double right_error =
258 (initial_drivetrain_.right -
Alex Perrycb7da4b2019-08-28 19:35:56 -0700259 drivetrain_status_fetcher_->estimated_right_position());
Philipp Schrader4bd29b12017-02-22 04:42:27 +0000260
261 const double profile_distance_to_go =
262 (left_profile_error + right_profile_error) / 2.0;
263 const double profile_angle_to_go =
264 (right_profile_error - left_profile_error) /
265 (dt_config_.robot_radius * 2.0);
266
267 const double distance_to_go = (left_error + right_error) / 2.0;
268 const double angle_to_go =
269 (right_error - left_error) / (dt_config_.robot_radius * 2.0);
270
Austin Schuhe6af9992018-07-08 15:59:14 -0700271 const bool drive_close =
272 ::std::abs(profile_distance_to_go) < distance + kProfileTolerance &&
273 ::std::abs(distance_to_go) < distance + kPositionTolerance;
274 const bool turn_close =
Philipp Schrader4bd29b12017-02-22 04:42:27 +0000275 ::std::abs(profile_angle_to_go) < angle + kProfileTolerance &&
Austin Schuhe6af9992018-07-08 15:59:14 -0700276 ::std::abs(angle_to_go) < angle + kPositionTolerance;
277
278 drive_has_been_close |= drive_close;
279 turn_has_been_close |= turn_close;
280 if (drive_has_been_close && !turn_has_been_close && !printed_first) {
Austin Schuhf257f3c2019-10-27 21:00:43 -0700281 AOS_LOG(INFO, "Drive finished first\n");
Austin Schuhe6af9992018-07-08 15:59:14 -0700282 printed_first = true;
283 } else if (!drive_has_been_close && turn_has_been_close &&
284 !printed_first) {
Austin Schuhf257f3c2019-10-27 21:00:43 -0700285 AOS_LOG(INFO, "Turn finished first\n");
Austin Schuhe6af9992018-07-08 15:59:14 -0700286 printed_first = true;
287 }
288
289 if (drive_close && turn_close) {
Austin Schuhf257f3c2019-10-27 21:00:43 -0700290 AOS_LOG(INFO, "Closer than %f < %f distance, %f < %f angle\n",
291 distance_to_go, distance, angle_to_go, angle);
Philipp Schrader4bd29b12017-02-22 04:42:27 +0000292 return true;
293 }
294 }
295 }
296}
297
Austin Schuh0aae9242018-03-14 19:49:44 -0700298bool BaseAutonomousActor::WaitForDriveProfileNear(double tolerance) {
Philipp Schrader4bd29b12017-02-22 04:42:27 +0000299 ::aos::time::PhasedLoop phased_loop(::std::chrono::milliseconds(5),
Austin Schuhd32b3622019-06-23 18:49:06 -0700300 event_loop()->monotonic_now(),
Philipp Schrader4bd29b12017-02-22 04:42:27 +0000301 ::std::chrono::milliseconds(5) / 2);
Philipp Schrader4bd29b12017-02-22 04:42:27 +0000302 while (true) {
303 if (ShouldCancel()) {
304 return false;
305 }
306 phased_loop.SleepUntilNext();
Austin Schuhbd0a40f2019-06-30 14:56:31 -0700307 drivetrain_status_fetcher_.Fetch();
Austin Schuh0aae9242018-03-14 19:49:44 -0700308
309 const Eigen::Matrix<double, 7, 1> current_error =
310 (Eigen::Matrix<double, 7, 1>()
311 << initial_drivetrain_.left -
Alex Perrycb7da4b2019-08-28 19:35:56 -0700312 drivetrain_status_fetcher_->profiled_left_position_goal(),
Austin Schuh0aae9242018-03-14 19:49:44 -0700313 0.0, initial_drivetrain_.right -
Alex Perrycb7da4b2019-08-28 19:35:56 -0700314 drivetrain_status_fetcher_->profiled_right_position_goal(),
Austin Schuh0aae9242018-03-14 19:49:44 -0700315 0.0, 0.0, 0.0, 0.0)
316 .finished();
317 const Eigen::Matrix<double, 2, 1> linear_error =
318 dt_config_.LeftRightToLinear(current_error);
319
Austin Schuhbd0a40f2019-06-30 14:56:31 -0700320 if (drivetrain_status_fetcher_.get()) {
Austin Schuh0aae9242018-03-14 19:49:44 -0700321 if (::std::abs(linear_error(0)) < tolerance) {
Austin Schuhf257f3c2019-10-27 21:00:43 -0700322 AOS_LOG(INFO, "Finished drive\n");
Philipp Schrader4bd29b12017-02-22 04:42:27 +0000323 return true;
324 }
325 }
326 }
327}
328
Austin Schuh0aae9242018-03-14 19:49:44 -0700329bool BaseAutonomousActor::WaitForDriveProfileDone() {
330 constexpr double kProfileTolerance = 0.001;
331 return WaitForDriveProfileNear(kProfileTolerance);
332}
333
334bool BaseAutonomousActor::WaitForTurnProfileNear(double tolerance) {
Austin Schuh546a0382017-04-16 19:10:18 -0700335 ::aos::time::PhasedLoop phased_loop(::std::chrono::milliseconds(5),
Austin Schuhd32b3622019-06-23 18:49:06 -0700336 event_loop()->monotonic_now(),
Austin Schuh546a0382017-04-16 19:10:18 -0700337 ::std::chrono::milliseconds(5) / 2);
Austin Schuh546a0382017-04-16 19:10:18 -0700338 while (true) {
339 if (ShouldCancel()) {
340 return false;
341 }
342 phased_loop.SleepUntilNext();
Austin Schuhbd0a40f2019-06-30 14:56:31 -0700343 drivetrain_status_fetcher_.Fetch();
Austin Schuh0aae9242018-03-14 19:49:44 -0700344
345 const Eigen::Matrix<double, 7, 1> current_error =
346 (Eigen::Matrix<double, 7, 1>()
347 << initial_drivetrain_.left -
Alex Perrycb7da4b2019-08-28 19:35:56 -0700348 drivetrain_status_fetcher_->profiled_left_position_goal(),
Austin Schuh0aae9242018-03-14 19:49:44 -0700349 0.0, initial_drivetrain_.right -
Alex Perrycb7da4b2019-08-28 19:35:56 -0700350 drivetrain_status_fetcher_->profiled_right_position_goal(),
Austin Schuh0aae9242018-03-14 19:49:44 -0700351 0.0, 0.0, 0.0, 0.0)
352 .finished();
353 const Eigen::Matrix<double, 2, 1> angular_error =
354 dt_config_.LeftRightToAngular(current_error);
355
Austin Schuhbd0a40f2019-06-30 14:56:31 -0700356 if (drivetrain_status_fetcher_.get()) {
Austin Schuh0aae9242018-03-14 19:49:44 -0700357 if (::std::abs(angular_error(0)) < tolerance) {
Austin Schuhf257f3c2019-10-27 21:00:43 -0700358 AOS_LOG(INFO, "Finished turn\n");
Austin Schuh546a0382017-04-16 19:10:18 -0700359 return true;
360 }
361 }
362 }
363}
364
Austin Schuh0aae9242018-03-14 19:49:44 -0700365bool BaseAutonomousActor::WaitForTurnProfileDone() {
366 constexpr double kProfileTolerance = 0.001;
367 return WaitForTurnProfileNear(kProfileTolerance);
368}
369
Austin Schuh546a0382017-04-16 19:10:18 -0700370double BaseAutonomousActor::DriveDistanceLeft() {
Austin Schuhbd0a40f2019-06-30 14:56:31 -0700371 drivetrain_status_fetcher_.Fetch();
372 if (drivetrain_status_fetcher_.get()) {
Austin Schuh546a0382017-04-16 19:10:18 -0700373 const double left_error =
374 (initial_drivetrain_.left -
Alex Perrycb7da4b2019-08-28 19:35:56 -0700375 drivetrain_status_fetcher_->estimated_left_position());
Austin Schuh546a0382017-04-16 19:10:18 -0700376 const double right_error =
377 (initial_drivetrain_.right -
Alex Perrycb7da4b2019-08-28 19:35:56 -0700378 drivetrain_status_fetcher_->estimated_right_position());
Austin Schuh546a0382017-04-16 19:10:18 -0700379
380 return (left_error + right_error) / 2.0;
381 } else {
382 return 0;
383 }
384}
385
James Kuszmaul838040b2019-04-13 15:51:02 -0700386bool BaseAutonomousActor::SplineHandle::SplineDistanceRemaining(
387 double distance) {
Austin Schuhbd0a40f2019-06-30 14:56:31 -0700388 base_autonomous_actor_->drivetrain_status_fetcher_.Fetch();
389 if (base_autonomous_actor_->drivetrain_status_fetcher_.get()) {
390 return base_autonomous_actor_->drivetrain_status_fetcher_
Alex Perrycb7da4b2019-08-28 19:35:56 -0700391 ->trajectory_logging()
392 ->is_executing() &&
Austin Schuhbd0a40f2019-06-30 14:56:31 -0700393 base_autonomous_actor_->drivetrain_status_fetcher_
Alex Perrycb7da4b2019-08-28 19:35:56 -0700394 ->trajectory_logging()
395 ->distance_remaining() < distance;
James Kuszmaul838040b2019-04-13 15:51:02 -0700396 }
397 return false;
398}
399bool BaseAutonomousActor::SplineHandle::WaitForSplineDistanceRemaining(
400 double distance) {
Austin Schuhd32b3622019-06-23 18:49:06 -0700401 ::aos::time::PhasedLoop phased_loop(
402 ::std::chrono::milliseconds(5),
403 base_autonomous_actor_->event_loop()->monotonic_now(),
404 ::std::chrono::milliseconds(5) / 2);
James Kuszmaul838040b2019-04-13 15:51:02 -0700405 while (true) {
406 if (base_autonomous_actor_->ShouldCancel()) {
407 return false;
408 }
409 phased_loop.SleepUntilNext();
410 if (SplineDistanceRemaining(distance)) {
411 return true;
412 }
413 }
414}
415
Alex Perrycb7da4b2019-08-28 19:35:56 -0700416void BaseAutonomousActor::LineFollowAtVelocity(
417 double velocity, y2019::control_loops::drivetrain::SelectionHint hint) {
418 {
419 auto builder = drivetrain_goal_sender_.MakeBuilder();
420 drivetrain::Goal::Builder goal_builder =
421 builder.MakeBuilder<drivetrain::Goal>();
422 goal_builder.add_controller_type(
423 drivetrain::ControllerType_SPLINE_FOLLOWER);
424 // TODO(james): Currently the 4.0 is copied from the
425 // line_follow_drivetrain.cc, but it is somewhat year-specific, so we should
426 // factor it out in some way.
427 goal_builder.add_throttle(velocity / 4.0);
428 builder.Send(goal_builder.Finish());
429 }
430
431 {
432 auto builder = target_selector_hint_sender_.MakeBuilder();
433 ::y2019::control_loops::drivetrain::TargetSelectorHint::Builder
434 target_hint_builder = builder.MakeBuilder<
435 ::y2019::control_loops::drivetrain::TargetSelectorHint>();
436
437 target_hint_builder.add_suggested_target(hint);
438 builder.Send(target_hint_builder.Finish());
439 }
James Kuszmaul838040b2019-04-13 15:51:02 -0700440}
441
Austin Schuh6bcc2302019-03-23 22:28:06 -0700442BaseAutonomousActor::SplineHandle BaseAutonomousActor::PlanSpline(
Alex Perrycb7da4b2019-08-28 19:35:56 -0700443 std::function<flatbuffers::Offset<frc971::MultiSpline>(
444 aos::Sender<frc971::control_loops::drivetrain::Goal>::Builder *builder)>
445 &&multispline_builder,
446 SplineDirection direction) {
Austin Schuhf257f3c2019-10-27 21:00:43 -0700447 AOS_LOG(INFO, "Planning spline\n");
Austin Schuh6bcc2302019-03-23 22:28:06 -0700448
449 int32_t spline_handle = (++spline_handle_) | ((getpid() & 0xFFFF) << 15);
450
Austin Schuhbd0a40f2019-06-30 14:56:31 -0700451 drivetrain_goal_fetcher_.Fetch();
Austin Schuh6bcc2302019-03-23 22:28:06 -0700452
Alex Perrycb7da4b2019-08-28 19:35:56 -0700453 auto builder = drivetrain_goal_sender_.MakeBuilder();
James Kuszmaulc864bcf2019-05-01 20:17:34 -0700454
Alex Perrycb7da4b2019-08-28 19:35:56 -0700455 flatbuffers::Offset<frc971::MultiSpline> multispline_offset =
456 multispline_builder(&builder);
457
458 drivetrain::SplineGoal::Builder spline_builder =
459 builder.MakeBuilder<drivetrain::SplineGoal>();
460 spline_builder.add_spline_idx(spline_handle);
461 spline_builder.add_drive_spline_backwards(direction ==
462 SplineDirection::kBackward);
463 spline_builder.add_spline(multispline_offset);
464
465 flatbuffers::Offset<drivetrain::SplineGoal> spline_offset =
466 spline_builder.Finish();
467
468 drivetrain::Goal::Builder goal_builder =
469 builder.MakeBuilder<drivetrain::Goal>();
470
471 drivetrain::ControllerType controller_type =
472 drivetrain::ControllerType_SPLINE_FOLLOWER;
Austin Schuhbd0a40f2019-06-30 14:56:31 -0700473 if (drivetrain_goal_fetcher_.get()) {
Alex Perrycb7da4b2019-08-28 19:35:56 -0700474 controller_type = drivetrain_goal_fetcher_->controller_type();
475 goal_builder.add_throttle(drivetrain_goal_fetcher_->throttle());
James Kuszmaulc864bcf2019-05-01 20:17:34 -0700476 }
Alex Perrycb7da4b2019-08-28 19:35:56 -0700477 goal_builder.add_controller_type(controller_type);
478 goal_builder.add_spline_handle(goal_spline_handle_);
Austin Schuh6bcc2302019-03-23 22:28:06 -0700479
Alex Perrycb7da4b2019-08-28 19:35:56 -0700480 goal_builder.add_spline(spline_offset);
Austin Schuh6bcc2302019-03-23 22:28:06 -0700481
Alex Perrycb7da4b2019-08-28 19:35:56 -0700482 builder.Send(goal_builder.Finish());
Austin Schuh6bcc2302019-03-23 22:28:06 -0700483
484 return BaseAutonomousActor::SplineHandle(spline_handle, this);
485}
486
487bool BaseAutonomousActor::SplineHandle::IsPlanned() {
Austin Schuhbd0a40f2019-06-30 14:56:31 -0700488 base_autonomous_actor_->drivetrain_status_fetcher_.Fetch();
Alex Perrycb7da4b2019-08-28 19:35:56 -0700489 VLOG(1) << aos::FlatbufferToJson(
490 base_autonomous_actor_->drivetrain_status_fetcher_.get());
491
Austin Schuhbd0a40f2019-06-30 14:56:31 -0700492 if (base_autonomous_actor_->drivetrain_status_fetcher_.get() &&
Alex Perrycb7da4b2019-08-28 19:35:56 -0700493 ((base_autonomous_actor_->drivetrain_status_fetcher_->trajectory_logging()
494 ->planning_spline_idx() == spline_handle_ &&
495 base_autonomous_actor_->drivetrain_status_fetcher_->trajectory_logging()
496 ->planning_state() == 3) ||
497 base_autonomous_actor_->drivetrain_status_fetcher_->trajectory_logging()
498 ->current_spline_idx() == spline_handle_)) {
Austin Schuh6bcc2302019-03-23 22:28:06 -0700499 return true;
500 }
501 return false;
502}
503
504bool BaseAutonomousActor::SplineHandle::WaitForPlan() {
Austin Schuhd32b3622019-06-23 18:49:06 -0700505 ::aos::time::PhasedLoop phased_loop(
506 ::std::chrono::milliseconds(5),
507 base_autonomous_actor_->event_loop()->monotonic_now(),
508 ::std::chrono::milliseconds(5) / 2);
Austin Schuh6bcc2302019-03-23 22:28:06 -0700509 while (true) {
510 if (base_autonomous_actor_->ShouldCancel()) {
511 return false;
512 }
513 phased_loop.SleepUntilNext();
514 if (IsPlanned()) {
515 return true;
516 }
517 }
518}
519
520void BaseAutonomousActor::SplineHandle::Start() {
Alex Perrycb7da4b2019-08-28 19:35:56 -0700521 auto builder = base_autonomous_actor_->drivetrain_goal_sender_.MakeBuilder();
522 drivetrain::Goal::Builder goal_builder =
523 builder.MakeBuilder<drivetrain::Goal>();
524 goal_builder.add_controller_type(drivetrain::ControllerType_SPLINE_FOLLOWER);
Austin Schuh6bcc2302019-03-23 22:28:06 -0700525
Austin Schuhf257f3c2019-10-27 21:00:43 -0700526 AOS_LOG(INFO, "Starting spline\n");
Austin Schuh6bcc2302019-03-23 22:28:06 -0700527
Alex Perrycb7da4b2019-08-28 19:35:56 -0700528 goal_builder.add_spline_handle(spline_handle_);
Austin Schuh6bcc2302019-03-23 22:28:06 -0700529 base_autonomous_actor_->goal_spline_handle_ = spline_handle_;
530
Alex Perrycb7da4b2019-08-28 19:35:56 -0700531 builder.Send(goal_builder.Finish());
Austin Schuh6bcc2302019-03-23 22:28:06 -0700532}
533
534bool BaseAutonomousActor::SplineHandle::IsDone() {
Austin Schuhbd0a40f2019-06-30 14:56:31 -0700535 base_autonomous_actor_->drivetrain_status_fetcher_.Fetch();
Austin Schuh6bcc2302019-03-23 22:28:06 -0700536
James Kuszmaulc73bb222019-04-07 12:15:35 -0700537 // We check that the spline we are waiting on is neither currently planning
James Kuszmaul29e417d2019-04-13 10:03:35 -0700538 // nor executing (we check is_executed because it is possible to receive
539 // status messages with is_executing false before the execution has started).
540 // We check for planning so that the user can go straight from starting the
541 // planner to executing without a WaitForPlan in between.
Austin Schuhbd0a40f2019-06-30 14:56:31 -0700542 if (base_autonomous_actor_->drivetrain_status_fetcher_.get() &&
Alex Perrycb7da4b2019-08-28 19:35:56 -0700543 ((!base_autonomous_actor_->drivetrain_status_fetcher_
544 ->trajectory_logging()
545 ->is_executed() &&
546 base_autonomous_actor_->drivetrain_status_fetcher_->trajectory_logging()
547 ->current_spline_idx() == spline_handle_) ||
548 base_autonomous_actor_->drivetrain_status_fetcher_->trajectory_logging()
549 ->planning_spline_idx() == spline_handle_)) {
Austin Schuh6bcc2302019-03-23 22:28:06 -0700550 return false;
551 }
552 return true;
553}
554
555bool BaseAutonomousActor::SplineHandle::WaitForDone() {
Austin Schuhd32b3622019-06-23 18:49:06 -0700556 ::aos::time::PhasedLoop phased_loop(
557 ::std::chrono::milliseconds(5),
558 base_autonomous_actor_->event_loop()->monotonic_now(),
559 ::std::chrono::milliseconds(5) / 2);
Austin Schuh6bcc2302019-03-23 22:28:06 -0700560 while (true) {
561 if (base_autonomous_actor_->ShouldCancel()) {
562 return false;
563 }
564 phased_loop.SleepUntilNext();
565 if (IsDone()) {
566 return true;
567 }
568 }
569}
570
Philipp Schrader4bd29b12017-02-22 04:42:27 +0000571} // namespace autonomous
572} // namespace frc971