blob: ca9db9243dcc8624eb1fe280023a4df10df2e1b1 [file] [log] [blame]
Daniel Petti1f448512013-10-19 19:35:55 +00001#include "bot3/control_loops/drivetrain/drivetrain.h"
2
3#include <stdio.h>
4#include <sched.h>
5#include <cmath>
6#include <memory>
7
8#include "aos/common/logging/logging.h"
9#include "aos/common/queue.h"
10#include "bot3/control_loops/drivetrain/drivetrain_motor_plant.h"
11#include "bot3/control_loops/drivetrain/drivetrain.q.h"
12#include "frc971/control_loops/state_feedback_loop.h"
13#include "frc971/queues/GyroAngle.q.h"
14#include "frc971/queues/Piston.q.h"
15
16using frc971::sensors::gyro;
17using ::frc971::control_loops::shifters;
18
19namespace bot3 {
20namespace control_loops {
21
22// Width of the robot.
23const double width = 22.0 / 100.0 * 2.54;
24
Daniel Petti1f448512013-10-19 19:35:55 +000025class DrivetrainMotorsOL {
26 public:
27 DrivetrainMotorsOL() {
28 _old_wheel = 0.0;
29 _wheel = 0.0;
30 _throttle = 0.0;
31 _quickturn = false;
32 _highgear = true;
33 _neg_inertia_accumulator = 0.0;
34 _left_pwm = 0.0;
35 _right_pwm = 0.0;
36 }
37 void SetGoal(double wheel, double throttle, bool quickturn, bool highgear) {
38 _wheel = wheel;
39 _throttle = throttle;
40 _quickturn = quickturn;
41 _highgear = highgear;
42 _left_pwm = 0.0;
43 _right_pwm = 0.0;
44 }
45 void Update(void) {
46 double overPower;
47 float sensitivity = 1.7;
48 float angular_power;
49 float linear_power;
50 double wheel;
51
52 double neg_inertia = _wheel - _old_wheel;
53 _old_wheel = _wheel;
54
55 double wheelNonLinearity;
56 if (_highgear) {
57 wheelNonLinearity = 0.1; // used to be csvReader->TURN_NONLIN_HIGH
58 // Apply a sin function that's scaled to make it feel better.
59 const double angular_range = M_PI / 2.0 * wheelNonLinearity;
60 wheel = sin(angular_range * _wheel) / sin(angular_range);
61 wheel = sin(angular_range * wheel) / sin(angular_range);
62 } else {
63 wheelNonLinearity = 0.2; // used to be csvReader->TURN_NONLIN_LOW
64 // Apply a sin function that's scaled to make it feel better.
65 const double angular_range = M_PI / 2.0 * wheelNonLinearity;
66 wheel = sin(angular_range * _wheel) / sin(angular_range);
67 wheel = sin(angular_range * wheel) / sin(angular_range);
68 wheel = sin(angular_range * wheel) / sin(angular_range);
69 }
70
71 static const double kThrottleDeadband = 0.05;
72 if (::std::abs(_throttle) < kThrottleDeadband) {
73 _throttle = 0;
74 } else {
75 _throttle = copysign((::std::abs(_throttle) - kThrottleDeadband) /
76 (1.0 - kThrottleDeadband), _throttle);
77 }
78
79 double neg_inertia_scalar;
80 if (_highgear) {
81 neg_inertia_scalar = 8.0; // used to be csvReader->NEG_INTERTIA_HIGH
82 sensitivity = 1.22; // used to be csvReader->SENSE_HIGH
83 } else {
84 if (wheel * neg_inertia > 0) {
85 neg_inertia_scalar = 5; // used to be csvReader->NEG_INERTIA_LOW_MORE
86 } else {
87 if (::std::abs(wheel) > 0.65) {
88 neg_inertia_scalar = 5; // used to be csvReader->NEG_INTERTIA_LOW_LESS_EXT
89 } else {
90 neg_inertia_scalar = 5; // used to be csvReader->NEG_INTERTIA_LOW_LESS
91 }
92 }
93 sensitivity = 1.24; // used to be csvReader->SENSE_LOW
94 }
95 double neg_inertia_power = neg_inertia * neg_inertia_scalar;
96 _neg_inertia_accumulator += neg_inertia_power;
97
98 wheel = wheel + _neg_inertia_accumulator;
99 if (_neg_inertia_accumulator > 1) {
100 _neg_inertia_accumulator -= 1;
101 } else if (_neg_inertia_accumulator < -1) {
102 _neg_inertia_accumulator += 1;
103 } else {
104 _neg_inertia_accumulator = 0;
105 }
106
107 linear_power = _throttle;
108
109 if (_quickturn) {
110 double qt_angular_power = wheel;
111 if (::std::abs(linear_power) < 0.2) {
112 if (qt_angular_power > 1) qt_angular_power = 1.0;
113 if (qt_angular_power < -1) qt_angular_power = -1.0;
114 } else {
115 qt_angular_power = 0.0;
116 }
117 overPower = 1.0;
118 if (_highgear) {
119 sensitivity = 1.0;
120 } else {
121 sensitivity = 1.0;
122 }
123 angular_power = wheel;
124 } else {
125 overPower = 0.0;
126 angular_power = ::std::abs(_throttle) * wheel * sensitivity;
127 }
Daniel Petti96c1b572013-11-12 05:47:16 +0000128 LOG(DEBUG, "Angular power: %f\n", angular_power);
Daniel Petti1f448512013-10-19 19:35:55 +0000129
130 _right_pwm = _left_pwm = linear_power;
131 _left_pwm += angular_power;
132 _right_pwm -= angular_power;
133
134 if (_left_pwm > 1.0) {
135 _right_pwm -= overPower*(_left_pwm - 1.0);
136 _left_pwm = 1.0;
137 } else if (_right_pwm > 1.0) {
138 _left_pwm -= overPower*(_right_pwm - 1.0);
139 _right_pwm = 1.0;
140 } else if (_left_pwm < -1.0) {
141 _right_pwm += overPower*(-1.0 - _left_pwm);
142 _left_pwm = -1.0;
143 } else if (_right_pwm < -1.0) {
144 _left_pwm += overPower*(-1.0 - _right_pwm);
145 _right_pwm = -1.0;
146 }
147 }
148
149 void SendMotors(Drivetrain::Output *output) {
150 LOG(DEBUG, "left pwm: %f right pwm: %f wheel: %f throttle: %f\n",
151 _left_pwm, _right_pwm, _wheel, _throttle);
152 if (output) {
153 output->left_voltage = _left_pwm * 12.0;
154 output->right_voltage = _right_pwm * 12.0;
155 }
156 if (_highgear) {
157 shifters.MakeWithBuilder().set(false).Send();
158 } else {
159 shifters.MakeWithBuilder().set(true).Send();
160 }
161 }
162
163 private:
164 double _old_wheel;
165 double _wheel;
166 double _throttle;
167 bool _quickturn;
168 bool _highgear;
169 double _neg_inertia_accumulator;
170 double _left_pwm;
171 double _right_pwm;
172};
173
174void DrivetrainLoop::RunIteration(const Drivetrain::Goal *goal,
Daniel Petti96c1b572013-11-12 05:47:16 +0000175 const Drivetrain::Position * /*position*/,
Daniel Petti1f448512013-10-19 19:35:55 +0000176 Drivetrain::Output *output,
177 Drivetrain::Status * /*status*/) {
178 // TODO(aschuh): These should be members of the class.
Daniel Petti1f448512013-10-19 19:35:55 +0000179 static DrivetrainMotorsOL dt_openloop;
180
Daniel Petti1f448512013-10-19 19:35:55 +0000181 double wheel = goal->steering;
182 double throttle = goal->throttle;
183 bool quickturn = goal->quickturn;
184 bool highgear = goal->highgear;
185
Daniel Petti1f448512013-10-19 19:35:55 +0000186 dt_openloop.SetGoal(wheel, throttle, quickturn, highgear);
187 dt_openloop.Update();
Daniel Petti96c1b572013-11-12 05:47:16 +0000188 dt_openloop.SendMotors(output);
Daniel Petti1f448512013-10-19 19:35:55 +0000189}
190
191} // namespace control_loops
192} // namespace bot3