blob: 5ec6e6370f6cf0a172b7cc82fc765a4566d5c985 [file] [log] [blame]
Austin Schuh80ff2e12014-03-08 12:06:19 -08001#include <stdio.h>
2
3#include <memory>
Austin Schuh47017412013-03-10 11:50:46 -07004
Brian3afd6fc2014-04-02 20:41:49 -07005#include "aos/common/util/phased_loop.h"
Austin Schuh47017412013-03-10 11:50:46 -07006#include "aos/common/time.h"
Austin Schuh6be011a2013-03-19 10:07:02 +00007#include "aos/common/util/trapezoid_profile.h"
Brian Silverman598800f2013-05-09 17:08:42 -07008#include "aos/common/logging/logging.h"
Brian Silverman6f621542014-04-06 16:00:41 -07009#include "aos/common/logging/queue_logging.h"
Brian Silverman598800f2013-05-09 17:08:42 -070010
11#include "frc971/autonomous/auto.q.h"
Austin Schuh6be011a2013-03-19 10:07:02 +000012#include "frc971/constants.h"
13#include "frc971/control_loops/drivetrain/drivetrain.q.h"
Daniel Petti3b1e48f2015-02-15 15:57:53 -080014#include "frc971/actors/drivetrain_actor.h"
Ben Fredrickson0a6ad252015-03-15 18:51:42 -070015#include "frc971/control_loops/claw/claw.q.h"
16#include "frc971/actors/pickup_actor.h"
17#include "frc971/actors/stack_actor.h"
Austin Schuh47017412013-03-10 11:50:46 -070018
19using ::aos::time::Time;
Ben Fredrickson0a6ad252015-03-15 18:51:42 -070020using ::frc971::control_loops::claw_queue;
Austin Schuh47017412013-03-10 11:50:46 -070021
22namespace frc971 {
23namespace autonomous {
24
Ben Fredrickson0a6ad252015-03-15 18:51:42 -070025constexpr double kClawAutoVelocity = 3.00;
26constexpr double kClawAutoAcceleration = 6.0;
27constexpr double kAngleEpsilon = 0.10;
28double kClawTotePackAngle = 0.95;
29
Austin Schuh80ff2e12014-03-08 12:06:19 -080030namespace time = ::aos::time;
31
Brian Silverman3b89ed82013-03-22 18:59:16 -070032static double left_initial_position, right_initial_position;
33
Austin Schuh6be011a2013-03-19 10:07:02 +000034bool ShouldExitAuto() {
35 ::frc971::autonomous::autonomous.FetchLatest();
36 bool ans = !::frc971::autonomous::autonomous->run_auto;
37 if (ans) {
38 LOG(INFO, "Time to exit auto mode\n");
39 }
40 return ans;
41}
42
Austin Schuh6be011a2013-03-19 10:07:02 +000043void StopDrivetrain() {
44 LOG(INFO, "Stopping the drivetrain\n");
Brian Silvermanada5f2c2015-02-01 02:41:14 -050045 control_loops::drivetrain_queue.goal.MakeWithBuilder()
Brian Silverman3b89ed82013-03-22 18:59:16 -070046 .control_loop_driving(true)
Brian Silvermance86bac2013-03-31 19:07:24 -070047 .left_goal(left_initial_position)
48 .left_velocity_goal(0)
49 .right_goal(right_initial_position)
50 .right_velocity_goal(0)
51 .quickturn(false)
52 .Send();
53}
54
55void ResetDrivetrain() {
56 LOG(INFO, "resetting the drivetrain\n");
Brian Silvermanada5f2c2015-02-01 02:41:14 -050057 control_loops::drivetrain_queue.goal.MakeWithBuilder()
Brian Silvermance86bac2013-03-31 19:07:24 -070058 .control_loop_driving(false)
Brian Silverman93335ae2015-01-26 20:43:39 -050059 //.highgear(false)
Austin Schuh6be011a2013-03-19 10:07:02 +000060 .steering(0.0)
61 .throttle(0.0)
Brian Silverman38ea9bf2014-04-19 22:57:54 -070062 .left_goal(left_initial_position)
63 .left_velocity_goal(0)
64 .right_goal(right_initial_position)
65 .right_velocity_goal(0)
Austin Schuh6be011a2013-03-19 10:07:02 +000066 .Send();
67}
68
Brian Silverman3b89ed82013-03-22 18:59:16 -070069void DriveSpin(double radians) {
70 LOG(INFO, "going to spin %f\n", radians);
71
Ben Fredrickson9fb2ab12015-02-16 16:42:08 -080072 // TODO(sensors): update this time thing maybe?
Brian Silverman3b89ed82013-03-22 18:59:16 -070073 ::aos::util::TrapezoidProfile profile(::aos::time::Time::InMS(10));
74 ::Eigen::Matrix<double, 2, 1> driveTrainState;
75 const double goal_velocity = 0.0;
76 const double epsilon = 0.01;
Brian Silverman13be6682013-03-22 21:02:07 -070077 // in drivetrain "meters"
Brian Silverman3b89ed82013-03-22 18:59:16 -070078 const double kRobotWidth = 0.4544;
79
Brian Silverman7992d6e2013-03-24 19:20:54 -070080 profile.set_maximum_acceleration(1.5);
81 profile.set_maximum_velocity(0.8);
Brian Silverman3b89ed82013-03-22 18:59:16 -070082
83 const double side_offset = kRobotWidth * radians / 2.0;
84
85 while (true) {
Brian Silverman547abb32015-02-16 00:37:48 -050086 ::aos::time::PhasedLoopXMS(5, 2500);
Brian Silverman3b89ed82013-03-22 18:59:16 -070087 driveTrainState = profile.Update(side_offset, goal_velocity);
88
89 if (::std::abs(driveTrainState(0, 0) - side_offset) < epsilon) break;
90 if (ShouldExitAuto()) return;
91
92 LOG(DEBUG, "Driving left to %f, right to %f\n",
Brian Silverman7992d6e2013-03-24 19:20:54 -070093 left_initial_position - driveTrainState(0, 0),
94 right_initial_position + driveTrainState(0, 0));
Brian Silvermanada5f2c2015-02-01 02:41:14 -050095 control_loops::drivetrain_queue.goal.MakeWithBuilder()
Brian Silverman3b89ed82013-03-22 18:59:16 -070096 .control_loop_driving(true)
Brian Silverman93335ae2015-01-26 20:43:39 -050097 //.highgear(false)
Brian Silverman7992d6e2013-03-24 19:20:54 -070098 .left_goal(left_initial_position - driveTrainState(0, 0))
99 .right_goal(right_initial_position + driveTrainState(0, 0))
100 .left_velocity_goal(-driveTrainState(1, 0))
101 .right_velocity_goal(driveTrainState(1, 0))
Brian Silverman3b89ed82013-03-22 18:59:16 -0700102 .Send();
103 }
Brian Silverman7992d6e2013-03-24 19:20:54 -0700104 left_initial_position -= side_offset;
105 right_initial_position += side_offset;
Brian Silverman3b89ed82013-03-22 18:59:16 -0700106 LOG(INFO, "Done moving\n");
107}
108
Ben Fredricksond69f38b2015-01-28 20:06:15 -0800109void WaitUntilDoneOrCanceled(aos::common::actions::Action *action) {
Austin Schuh80ff2e12014-03-08 12:06:19 -0800110 while (true) {
111 // Poll the running bit and auto done bits.
Brian Silverman547abb32015-02-16 00:37:48 -0500112 ::aos::time::PhasedLoopXMS(5, 2500);
Austin Schuh80ff2e12014-03-08 12:06:19 -0800113 if (!action->Running() || ShouldExitAuto()) {
114 return;
115 }
116 }
117}
118
Ben Fredrickson9fb2ab12015-02-16 16:42:08 -0800119::std::unique_ptr<::frc971::actors::DrivetrainAction> SetDriveGoal(
120 double distance, bool slow_acceleration, double maximum_velocity = 1.7,
121 double theta = 0) {
Austin Schuha4faacc2014-03-09 00:50:50 -0800122 LOG(INFO, "Driving to %f\n", distance);
Ben Fredrickson9fb2ab12015-02-16 16:42:08 -0800123
124 ::frc971::actors::DrivetrainActionParams params;
125 params.left_initial_position = left_initial_position;
126 params.right_initial_position = right_initial_position;
127 params.y_offset = distance;
128 params.theta_offset = theta;
129 params.maximum_velocity = maximum_velocity;
130 params.maximum_acceleration = slow_acceleration ? 2.5 : 3.0;
131 auto drivetrain_action = actors::MakeDrivetrainAction(params);
132
Austin Schuh80ff2e12014-03-08 12:06:19 -0800133 drivetrain_action->Start();
Brian Silvermanad9e0002014-04-13 14:55:57 -0700134 left_initial_position +=
135 distance - theta * constants::GetValues().turn_width / 2.0;
136 right_initial_position +=
Daniel Pettib0733be2014-11-14 22:44:03 -0800137 distance + theta * constants::GetValues().turn_width / 2.0;
Austin Schuh80ff2e12014-03-08 12:06:19 -0800138 return ::std::move(drivetrain_action);
139}
140
141void InitializeEncoders() {
Brian Silvermanada5f2c2015-02-01 02:41:14 -0500142 control_loops::drivetrain_queue.status.FetchLatest();
143 while (!control_loops::drivetrain_queue.status.get()) {
Brian Silverman2c1e0342014-04-11 16:15:01 -0700144 LOG(WARNING,
145 "No previous drivetrain position packet, trying to fetch again\n");
Brian Silvermanada5f2c2015-02-01 02:41:14 -0500146 control_loops::drivetrain_queue.status.FetchNextBlocking();
Brian Silverman3b89ed82013-03-22 18:59:16 -0700147 }
148 left_initial_position =
Brian Silvermanada5f2c2015-02-01 02:41:14 -0500149 control_loops::drivetrain_queue.status->filtered_left_position;
Brian Silverman3b89ed82013-03-22 18:59:16 -0700150 right_initial_position =
Brian Silvermanada5f2c2015-02-01 02:41:14 -0500151 control_loops::drivetrain_queue.status->filtered_right_position;
Austin Schuh80ff2e12014-03-08 12:06:19 -0800152}
153
Ben Fredrickson0a6ad252015-03-15 18:51:42 -0700154void SetClawState(double angle, double intake_voltage, double rollers_closed) {
155 auto message = control_loops::claw_queue.goal.MakeMessage();
156 message->angle = angle;
157 message->max_velocity = kClawAutoVelocity;
158 message->max_acceleration = kClawAutoAcceleration;
159 message->angular_velocity = 0.0;
160 message->intake = intake_voltage;
161 message->rollers_closed = rollers_closed;
162
163 LOG_STRUCT(DEBUG, "Sending claw goal", *message);
164 message.Send();
165
166 while (true) {
167 control_loops::claw_queue.status.FetchAnother();
168 const double current_angle = control_loops::claw_queue.status->angle;
169 LOG_STRUCT(DEBUG, "Got claw status", *control_loops::claw_queue.status);
170
171 // I believe all we can care about here is the angle. Other values will
172 // either be set or not, but there is nothing we can do about it. If it
173 // never gets there we do not care, auto is over for us.
174 if (::std::abs(current_angle - angle) < kAngleEpsilon) {
175 break;
176 }
177 }
178}
179
Austin Schuh80ff2e12014-03-08 12:06:19 -0800180void HandleAuto() {
Austin Schuh577edf62014-04-13 10:33:05 -0700181 ::aos::time::Time start_time = ::aos::time::Time::Now();
Brian Silverman20141f92015-01-05 17:39:01 -0800182 LOG(INFO, "Handling auto mode at %f\n", start_time.ToSeconds());
Ben Fredrickson0a6ad252015-03-15 18:51:42 -0700183 ::std::unique_ptr<::frc971::actors::DrivetrainAction> drive;
184 ::std::unique_ptr<::frc971::actors::PickupAction> pickup;
185 ::std::unique_ptr<::frc971::actors::StackAction> stack;
186 // TODO(austin): Score!
187 //::std::unique_ptr<ScoreAction> score;
Brian Silverman6f621542014-04-06 16:00:41 -0700188
Austin Schuh80ff2e12014-03-08 12:06:19 -0800189 ResetDrivetrain();
190
191 if (ShouldExitAuto()) return;
192 InitializeEncoders();
Ben Fredrickson0a6ad252015-03-15 18:51:42 -0700193
194 if (true) {
195 // basic can push out of the way
196 SetClawState(0.0, -7.0, true);
197 drive = SetDriveGoal(1.0, false);
198 WaitUntilDoneOrCanceled(drive.get());
199 SetClawState(0.0, 0.0, true);
200 }
201
202 if (ShouldExitAuto()) return;
203
204 if (false) {
205 // drive up to the next tote
206 drive = SetDriveGoal(1.0, false);
207 WaitUntilDoneOrCanceled(drive.get());
208 if (ShouldExitAuto()) return;
209
210 // suck in the tote
211 SetClawState(0.0, 7.0, true);
212 drive = SetDriveGoal(0.2, false);
213 WaitUntilDoneOrCanceled(drive.get());
214 SetClawState(0.0, 0.0, true);
215 if (ShouldExitAuto()) return;
216
217 // now pick it up
218 {
219 actors::PickupParams params;
220 // Lift to here initially.
221 params.pickup_angle = 0.9;
222 // Start sucking here
223 params.suck_angle = 0.8;
224 // Go back down to here to finish sucking.
225 params.suck_angle_finish = 0.4;
226 // Pack the box back in here.
227 params.pickup_finish_angle = kClawTotePackAngle;
228 params.intake_time = 0.8;
229 params.intake_voltage = 7.0;
230 pickup = actors::MakePickupAction(params);
231 WaitUntilDoneOrCanceled(pickup.get());
232 }
233 if (ShouldExitAuto()) return;
234
235 // we should have the tote, now stack it
236 {
237 actors::StackParams params;
238 params.claw_out_angle = 0.6;
239 params.bottom = 0.020;
240 params.over_box_before_place_height = 0.39;
241 stack = actors::MakeStackAction(params);
242 WaitUntilDoneOrCanceled(stack.get());
243 }
244 if (ShouldExitAuto()) return;
245
246 // turn 90
247 DriveSpin(M_PI / 4.0);
248 if (ShouldExitAuto()) return;
249
250 // place the new stack
251 // TODO(austin): Score!
252 // score = MakeScoreAction(score_params);
253 // WaitUntilDoneOrCanceled(score.get());
254 }
Austin Schuh47017412013-03-10 11:50:46 -0700255}
256
257} // namespace autonomous
258} // namespace frc971