Comran Morshed | e68e373 | 2016-03-12 14:12:11 +0000 | [diff] [blame] | 1 | #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 Morshed | 435f111 | 2016-03-12 14:20:45 +0000 | [diff] [blame^] | 7 | |
| 8 | #include "frc971/control_loops/drivetrain/drivetrain.q.h" |
| 9 | #include "y2016/control_loops/drivetrain/drivetrain_base.h" |
Comran Morshed | e68e373 | 2016-03-12 14:12:11 +0000 | [diff] [blame] | 10 | |
| 11 | namespace y2016 { |
| 12 | namespace actors { |
Comran Morshed | 435f111 | 2016-03-12 14:20:45 +0000 | [diff] [blame^] | 13 | using ::frc971::control_loops::ProfileParameters; |
| 14 | using ::frc971::control_loops::drivetrain_queue; |
| 15 | |
| 16 | namespace { |
| 17 | const ProfileParameters kSlowDrive = {1.0, 1.0}; |
| 18 | const ProfileParameters kFastDrive = {3.0, 2.5}; |
| 19 | |
| 20 | const ProfileParameters kSlowTurn = {1.7, 3.0}; |
| 21 | const ProfileParameters kFastTurn = {3.0, 10.0}; |
| 22 | } // namespace |
Comran Morshed | e68e373 | 2016-03-12 14:12:11 +0000 | [diff] [blame] | 23 | |
| 24 | AutonomousActor::AutonomousActor(actors::AutonomousActionQueueGroup *s) |
Comran Morshed | 435f111 | 2016-03-12 14:20:45 +0000 | [diff] [blame^] | 25 | : 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 | |
| 30 | void 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 | |
| 44 | void 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 | |
| 73 | void 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 | |
| 79 | void 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 | |
| 97 | bool 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 Morshed | e68e373 | 2016-03-12 14:12:11 +0000 | [diff] [blame] | 129 | |
| 130 | bool AutonomousActor::RunAction(const actors::AutonomousActionParams ¶ms) { |
| 131 | LOG(INFO, "Starting autonomous action with mode %" PRId32 "\n", params.mode); |
| 132 | |
Comran Morshed | 435f111 | 2016-03-12 14:20:45 +0000 | [diff] [blame^] | 133 | 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 Morshed | e68e373 | 2016-03-12 14:12:11 +0000 | [diff] [blame] | 148 | } |
Comran Morshed | 435f111 | 2016-03-12 14:20:45 +0000 | [diff] [blame^] | 149 | LOG(DEBUG, "Done running\n"); |
Comran Morshed | e68e373 | 2016-03-12 14:12:11 +0000 | [diff] [blame] | 150 | |
| 151 | return true; |
| 152 | } |
| 153 | |
| 154 | ::std::unique_ptr<AutonomousAction> MakeAutonomousAction( |
| 155 | const ::y2016::actors::AutonomousActionParams ¶ms) { |
| 156 | return ::std::unique_ptr<AutonomousAction>( |
| 157 | new AutonomousAction(&::y2016::actors::autonomous_action, params)); |
| 158 | } |
| 159 | |
| 160 | } // namespace actors |
| 161 | } // namespace y2016 |