blob: ad361bbc83be3cfdaab7dc0db0161497c9dd052f [file] [log] [blame]
Comran Morshede68e3732016-03-12 14:12:11 +00001#include "y2016/actors/autonomous_actor.h"
2
3#include <inttypes.h>
4
5#include "aos/common/util/phased_loop.h"
6#include "aos/common/logging/logging.h"
Comran Morshed435f1112016-03-12 14:20:45 +00007
8#include "frc971/control_loops/drivetrain/drivetrain.q.h"
9#include "y2016/control_loops/drivetrain/drivetrain_base.h"
Comran Morshede68e3732016-03-12 14:12:11 +000010
11namespace y2016 {
12namespace actors {
Comran Morshed435f1112016-03-12 14:20:45 +000013using ::frc971::control_loops::ProfileParameters;
14using ::frc971::control_loops::drivetrain_queue;
15
16namespace {
17const ProfileParameters kSlowDrive = {1.0, 1.0};
18const ProfileParameters kFastDrive = {3.0, 2.5};
19
20const ProfileParameters kSlowTurn = {1.7, 3.0};
21const ProfileParameters kFastTurn = {3.0, 10.0};
22} // namespace
Comran Morshede68e3732016-03-12 14:12:11 +000023
24AutonomousActor::AutonomousActor(actors::AutonomousActionQueueGroup *s)
Comran Morshed435f1112016-03-12 14:20:45 +000025 : aos::common::actions::ActorBase<actors::AutonomousActionQueueGroup>(s),
26 left_initial_position_(0.0),
27 right_initial_position_(0.0),
28 dt_config_(control_loops::drivetrain::GetDrivetrainConfig()) {}
29
30void AutonomousActor::ResetDrivetrain() {
31 LOG(INFO, "resetting the drivetrain\n");
32 drivetrain_queue.goal.MakeWithBuilder()
33 .control_loop_driving(false)
34 .highgear(true)
35 .steering(0.0)
36 .throttle(0.0)
37 .left_goal(left_initial_position_)
38 .left_velocity_goal(0)
39 .right_goal(right_initial_position_)
40 .right_velocity_goal(0)
41 .Send();
42}
43
44void AutonomousActor::StartDrive(double distance, double angle,
45 ProfileParameters linear,
46 ProfileParameters angular) {
47 {
48 {
49 const double dangle = angle * dt_config_.robot_radius;
50 left_initial_position_ += distance - dangle;
51 right_initial_position_ += distance + dangle;
52 }
53
54 auto drivetrain_message =
55 drivetrain_queue.goal.MakeMessage();
56 drivetrain_message->control_loop_driving = true;
57 drivetrain_message->highgear = true;
58 drivetrain_message->steering = 0.0;
59 drivetrain_message->throttle = 0.0;
60 drivetrain_message->left_goal = left_initial_position_;
61 drivetrain_message->left_velocity_goal = 0;
62 drivetrain_message->right_goal = right_initial_position_;
63 drivetrain_message->right_velocity_goal = 0;
64 drivetrain_message->linear = linear;
65 drivetrain_message->angular = angular;
66
67 LOG_STRUCT(DEBUG, "drivetrain_goal", *drivetrain_message);
68
69 drivetrain_message.Send();
70 }
71}
72
73void AutonomousActor::InitializeEncoders() {
74 drivetrain_queue.status.FetchAnother();
75 left_initial_position_ = drivetrain_queue.status->estimated_left_position;
76 right_initial_position_ = drivetrain_queue.status->estimated_right_position;
77}
78
79void AutonomousActor::WaitUntilDoneOrCanceled(
80 ::std::unique_ptr<aos::common::actions::Action> action) {
81 if (!action) {
82 LOG(ERROR, "No action, not waiting\n");
83 return;
84 }
85
86 ::aos::time::PhasedLoop phased_loop(::aos::time::Time::InMS(5),
87 ::aos::time::Time::InMS(5) / 2);
88 while (true) {
89 // Poll the running bit and see if we should cancel.
90 phased_loop.SleepUntilNext();
91 if (!action->Running() || ShouldCancel()) {
92 return;
93 }
94 }
95}
96
97bool AutonomousActor::WaitForDriveDone() {
98 ::aos::time::PhasedLoop phased_loop(::aos::time::Time::InMS(5),
99 ::aos::time::Time::InMS(5) / 2);
100 constexpr double kPositionTolerance = 0.02;
101 constexpr double kVelocityTolerance = 0.10;
102 constexpr double kProfileTolerance = 0.001;
103
104 while (true) {
105 if (ShouldCancel()) {
106 return false;
107 }
108 phased_loop.SleepUntilNext();
109 drivetrain_queue.status.FetchLatest();
110 if (drivetrain_queue.status.get()) {
111 if (::std::abs(drivetrain_queue.status->profiled_left_position_goal -
112 left_initial_position_) < kProfileTolerance &&
113 ::std::abs(drivetrain_queue.status->profiled_right_position_goal -
114 right_initial_position_) < kProfileTolerance &&
115 ::std::abs(drivetrain_queue.status->estimated_left_position -
116 left_initial_position_) < kPositionTolerance &&
117 ::std::abs(drivetrain_queue.status->estimated_right_position -
118 right_initial_position_) < kPositionTolerance &&
119 ::std::abs(drivetrain_queue.status->estimated_left_velocity) <
120 kVelocityTolerance &&
121 ::std::abs(drivetrain_queue.status->estimated_right_velocity) <
122 kVelocityTolerance) {
123 LOG(INFO, "Finished drive\n");
124 return true;
125 }
126 }
127 }
128}
Comran Morshede68e3732016-03-12 14:12:11 +0000129
130bool AutonomousActor::RunAction(const actors::AutonomousActionParams &params) {
131 LOG(INFO, "Starting autonomous action with mode %" PRId32 "\n", params.mode);
132
Comran Morshed435f1112016-03-12 14:20:45 +0000133 InitializeEncoders();
134 ResetDrivetrain();
135
136 StartDrive(1.0, 0.0, kSlowDrive, kSlowTurn);
137
138 if (!WaitForDriveDone()) return true;
139
140 StartDrive(0.0, M_PI, kSlowDrive, kSlowTurn);
141
142 if (!WaitForDriveDone()) return true;
143
144 ::aos::time::PhasedLoop phased_loop(::aos::time::Time::InMS(5),
145 ::aos::time::Time::InMS(5) / 2);
146 while (!ShouldCancel()) {
147 phased_loop.SleepUntilNext();
Comran Morshede68e3732016-03-12 14:12:11 +0000148 }
Comran Morshed435f1112016-03-12 14:20:45 +0000149 LOG(DEBUG, "Done running\n");
Comran Morshede68e3732016-03-12 14:12:11 +0000150
151 return true;
152}
153
154::std::unique_ptr<AutonomousAction> MakeAutonomousAction(
155 const ::y2016::actors::AutonomousActionParams &params) {
156 return ::std::unique_ptr<AutonomousAction>(
157 new AutonomousAction(&::y2016::actors::autonomous_action, params));
158}
159
160} // namespace actors
161} // namespace y2016