blob: 91873eb74331f888be9424fb72ab064c96f63579 [file] [log] [blame]
Brian Silvermanb691f5e2015-08-02 11:37:55 -07001#include "y2015/actors/drivetrain_actor.h"
Ben Fredricksond69f38b2015-01-28 20:06:15 -08002
Austin Schuh80ff2e12014-03-08 12:06:19 -08003#include <functional>
4#include <numeric>
5
6#include <Eigen/Dense>
7
Brian3afd6fc2014-04-02 20:41:49 -07008#include "aos/common/util/phased_loop.h"
Austin Schuh80ff2e12014-03-08 12:06:19 -08009#include "aos/common/logging/logging.h"
10#include "aos/common/util/trapezoid_profile.h"
Brian Silvermanb94069c2014-04-17 14:34:24 -070011#include "aos/common/commonmath.h"
Ben Fredricksond69f38b2015-01-28 20:06:15 -080012#include "aos/common/time.h"
Austin Schuh80ff2e12014-03-08 12:06:19 -080013
Austin Schuh70810b92016-11-26 14:55:34 -080014#include "frc971/control_loops/drivetrain/drivetrain.q.h"
Brian Silvermanb691f5e2015-08-02 11:37:55 -070015#include "y2015/actors/drivetrain_actor.h"
16#include "y2015/constants.h"
Austin Schuh80ff2e12014-03-08 12:06:19 -080017
Austin Schuh88af0852016-12-04 20:31:32 -080018namespace y2015 {
Daniel Petti3b1e48f2015-02-15 15:57:53 -080019namespace actors {
Austin Schuh80ff2e12014-03-08 12:06:19 -080020
Austin Schuh214e9c12016-11-25 17:26:20 -080021namespace chrono = ::std::chrono;
Austin Schuh88af0852016-12-04 20:31:32 -080022using ::frc971::control_loops::drivetrain_queue;
Austin Schuh214e9c12016-11-25 17:26:20 -080023
Daniel Petti3b1e48f2015-02-15 15:57:53 -080024DrivetrainActor::DrivetrainActor(actors::DrivetrainActionQueueGroup* s)
25 : aos::common::actions::ActorBase<actors::DrivetrainActionQueueGroup>(s) {}
Austin Schuh80ff2e12014-03-08 12:06:19 -080026
Ben Fredrickson9fb2ab12015-02-16 16:42:08 -080027bool DrivetrainActor::RunAction(const actors::DrivetrainActionParams &params) {
Austin Schuh32501832017-02-25 18:32:56 -080028 static const auto K =
29 constants::GetValues().make_drivetrain_loop().controller().K();
Brian Silvermanb94069c2014-04-17 14:34:24 -070030
Ben Fredrickson9fb2ab12015-02-16 16:42:08 -080031 const double yoffset = params.y_offset;
Brian Silvermanad9e0002014-04-13 14:55:57 -070032 const double turn_offset =
Ben Fredrickson9fb2ab12015-02-16 16:42:08 -080033 params.theta_offset * constants::GetValues().turn_width / 2.0;
Brian Silvermanad9e0002014-04-13 14:55:57 -070034 LOG(INFO, "Going to move %f and turn %f\n", yoffset, turn_offset);
Austin Schuh80ff2e12014-03-08 12:06:19 -080035
36 // Measured conversion to get the distance right.
Austin Schuh214e9c12016-11-25 17:26:20 -080037 ::aos::util::TrapezoidProfile profile(chrono::milliseconds(5));
38 ::aos::util::TrapezoidProfile turn_profile(chrono::milliseconds(5));
Austin Schuh80ff2e12014-03-08 12:06:19 -080039 const double goal_velocity = 0.0;
40 const double epsilon = 0.01;
Brian Silvermanad9e0002014-04-13 14:55:57 -070041 ::Eigen::Matrix<double, 2, 1> left_goal_state, right_goal_state;
Austin Schuh80ff2e12014-03-08 12:06:19 -080042
Ben Fredrickson9fb2ab12015-02-16 16:42:08 -080043 profile.set_maximum_acceleration(params.maximum_acceleration);
44 profile.set_maximum_velocity(params.maximum_velocity);
Austin Schuh3fc6d5f2015-04-18 22:59:20 -070045 turn_profile.set_maximum_acceleration(params.maximum_turn_acceleration *
46 constants::GetValues().turn_width /
47 2.0);
48 turn_profile.set_maximum_velocity(params.maximum_turn_velocity *
49 constants::GetValues().turn_width / 2.0);
Austin Schuh80ff2e12014-03-08 12:06:19 -080050
Austin Schuhf2a50ba2016-12-24 16:16:26 -080051 ::aos::time::PhasedLoop phased_loop(::std::chrono::milliseconds(5),
52 ::std::chrono::milliseconds(5) / 2);
Austin Schuh80ff2e12014-03-08 12:06:19 -080053 while (true) {
Austin Schuhf2a50ba2016-12-24 16:16:26 -080054 phased_loop.SleepUntilNext();
Austin Schuh80ff2e12014-03-08 12:06:19 -080055
Austin Schuh88af0852016-12-04 20:31:32 -080056 drivetrain_queue.status.FetchLatest();
57 if (drivetrain_queue.status.get()) {
58 const auto& status = *drivetrain_queue.status;
Brian Silvermanb94069c2014-04-17 14:34:24 -070059 if (::std::abs(status.uncapped_left_voltage -
Ben Fredricksond69f38b2015-01-28 20:06:15 -080060 status.uncapped_right_voltage) > 24) {
Brian Silverman38ea9bf2014-04-19 22:57:54 -070061 LOG(DEBUG, "spinning in place\n");
Brian Silvermanb94069c2014-04-17 14:34:24 -070062 // They're more than 24V apart, so stop moving forwards and let it deal
63 // with spinning first.
64 profile.SetGoal(
Austin Schuh093535c2016-03-05 23:21:00 -080065 (status.estimated_left_position + status.estimated_right_position -
Austin Schuhc76c5e62015-04-18 22:59:45 -070066 params.left_initial_position - params.right_initial_position) /
Brian Silvermanb94069c2014-04-17 14:34:24 -070067 2.0);
68 } else {
Brian Silverman38ea9bf2014-04-19 22:57:54 -070069 static const double divisor = K(0, 0) + K(0, 2);
Brian Silvermanb94069c2014-04-17 14:34:24 -070070 double dx_left, dx_right;
71 if (status.uncapped_left_voltage > 12.0) {
72 dx_left = (status.uncapped_left_voltage - 12.0) / divisor;
73 } else if (status.uncapped_left_voltage < -12.0) {
74 dx_left = (status.uncapped_left_voltage + 12.0) / divisor;
75 } else {
76 dx_left = 0;
77 }
78 if (status.uncapped_right_voltage > 12.0) {
79 dx_right = (status.uncapped_right_voltage - 12.0) / divisor;
80 } else if (status.uncapped_right_voltage < -12.0) {
81 dx_right = (status.uncapped_right_voltage + 12.0) / divisor;
82 } else {
83 dx_right = 0;
84 }
85 double dx;
86 if (dx_left == 0 && dx_right == 0) {
87 dx = 0;
88 } else if (dx_left != 0 && dx_right != 0 &&
89 ::aos::sign(dx_left) != ::aos::sign(dx_right)) {
90 // Both saturating in opposite directions. Don't do anything.
Austin Schuhc76c5e62015-04-18 22:59:45 -070091 LOG(DEBUG, "Saturating opposite ways, not adjusting\n");
Brian Silvermanb94069c2014-04-17 14:34:24 -070092 dx = 0;
93 } else if (::std::abs(dx_left) > ::std::abs(dx_right)) {
94 dx = dx_left;
95 } else {
96 dx = dx_right;
97 }
98 if (dx != 0) {
99 LOG(DEBUG, "adjusting goal by %f\n", dx);
100 profile.MoveGoal(-dx);
101 }
102 }
103 } else {
104 // If we ever get here, that's bad and we should just give up
Daniel Petti3b1e48f2015-02-15 15:57:53 -0800105 LOG(ERROR, "no drivetrain status!\n");
106 return false;
Brian Silvermanb94069c2014-04-17 14:34:24 -0700107 }
108
Brian Silverman38ea9bf2014-04-19 22:57:54 -0700109 const auto drive_profile_goal_state =
110 profile.Update(yoffset, goal_velocity);
111 const auto turn_profile_goal_state = turn_profile.Update(turn_offset, 0.0);
112 left_goal_state = drive_profile_goal_state - turn_profile_goal_state;
113 right_goal_state = drive_profile_goal_state + turn_profile_goal_state;
114
Brian Silvermanad9e0002014-04-13 14:55:57 -0700115 if (::std::abs(drive_profile_goal_state(0, 0) - yoffset) < epsilon &&
116 ::std::abs(turn_profile_goal_state(0, 0) - turn_offset) < epsilon) {
117 break;
118 }
Daniel Petti3b1e48f2015-02-15 15:57:53 -0800119
120 if (ShouldCancel()) return true;
Austin Schuh80ff2e12014-03-08 12:06:19 -0800121
122 LOG(DEBUG, "Driving left to %f, right to %f\n",
Ben Fredrickson9fb2ab12015-02-16 16:42:08 -0800123 left_goal_state(0, 0) + params.left_initial_position,
124 right_goal_state(0, 0) + params.right_initial_position);
Austin Schuh88af0852016-12-04 20:31:32 -0800125 drivetrain_queue.goal.MakeWithBuilder()
Austin Schuh80ff2e12014-03-08 12:06:19 -0800126 .control_loop_driving(true)
Brian Silverman93335ae2015-01-26 20:43:39 -0500127 //.highgear(false)
Ben Fredrickson9fb2ab12015-02-16 16:42:08 -0800128 .left_goal(left_goal_state(0, 0) + params.left_initial_position)
129 .right_goal(right_goal_state(0, 0) + params.right_initial_position)
Brian Silvermanad9e0002014-04-13 14:55:57 -0700130 .left_velocity_goal(left_goal_state(1, 0))
131 .right_velocity_goal(right_goal_state(1, 0))
Austin Schuh80ff2e12014-03-08 12:06:19 -0800132 .Send();
133 }
Daniel Petti3b1e48f2015-02-15 15:57:53 -0800134 if (ShouldCancel()) return true;
Austin Schuh88af0852016-12-04 20:31:32 -0800135 drivetrain_queue.status.FetchLatest();
136 while (!drivetrain_queue.status.get()) {
Austin Schuh577edf62014-04-13 10:33:05 -0700137 LOG(WARNING,
138 "No previous drivetrain status packet, trying to fetch again\n");
Austin Schuh88af0852016-12-04 20:31:32 -0800139 drivetrain_queue.status.FetchNextBlocking();
Daniel Petti3b1e48f2015-02-15 15:57:53 -0800140 if (ShouldCancel()) return true;
Austin Schuh577edf62014-04-13 10:33:05 -0700141 }
142 while (true) {
Daniel Petti3b1e48f2015-02-15 15:57:53 -0800143 if (ShouldCancel()) return true;
Austin Schuh577edf62014-04-13 10:33:05 -0700144 const double kPositionThreshold = 0.05;
145
Austin Schuh88af0852016-12-04 20:31:32 -0800146 const double left_error =
147 ::std::abs(drivetrain_queue.status->estimated_left_position -
148 (left_goal_state(0, 0) + params.left_initial_position));
149 const double right_error =
150 ::std::abs(drivetrain_queue.status->estimated_right_position -
151 (right_goal_state(0, 0) + params.right_initial_position));
Austin Schuh577edf62014-04-13 10:33:05 -0700152 const double velocity_error =
Austin Schuh88af0852016-12-04 20:31:32 -0800153 ::std::abs(drivetrain_queue.status->robot_speed);
Austin Schuh577edf62014-04-13 10:33:05 -0700154 if (left_error < kPositionThreshold && right_error < kPositionThreshold &&
155 velocity_error < 0.2) {
156 break;
157 } else {
158 LOG(DEBUG, "Drivetrain error is %f, %f, %f\n", left_error, right_error,
159 velocity_error);
160 }
Austin Schuh88af0852016-12-04 20:31:32 -0800161 drivetrain_queue.status.FetchNextBlocking();
Austin Schuh577edf62014-04-13 10:33:05 -0700162 }
Austin Schuh80ff2e12014-03-08 12:06:19 -0800163 LOG(INFO, "Done moving\n");
Daniel Petti3b1e48f2015-02-15 15:57:53 -0800164 return true;
Austin Schuh80ff2e12014-03-08 12:06:19 -0800165}
166
Ben Fredrickson9fb2ab12015-02-16 16:42:08 -0800167::std::unique_ptr<DrivetrainAction> MakeDrivetrainAction(
Austin Schuh88af0852016-12-04 20:31:32 -0800168 const ::y2015::actors::DrivetrainActionParams& params) {
Ben Fredrickson9fb2ab12015-02-16 16:42:08 -0800169 return ::std::unique_ptr<DrivetrainAction>(
Austin Schuh88af0852016-12-04 20:31:32 -0800170 new DrivetrainAction(&::y2015::actors::drivetrain_action, params));
Austin Schuh80ff2e12014-03-08 12:06:19 -0800171}
172
Daniel Petti3b1e48f2015-02-15 15:57:53 -0800173} // namespace actors
Austin Schuh88af0852016-12-04 20:31:32 -0800174} // namespace y2015