blob: 852b94e8bee45e9a7adfea91dbcdda403a74b4b2 [file] [log] [blame]
Sabina Davis92d2efa2017-11-04 22:35:25 -07001#include "aos/input/drivetrain_input.h"
2
3#include <math.h>
4#include <stdio.h>
5#include <string.h>
6#include <cmath>
7
8#include "aos/common/commonmath.h"
9#include "aos/common/input/driver_station_data.h"
10#include "aos/common/logging/logging.h"
11#include "frc971/control_loops/drivetrain/drivetrain.q.h"
12
13using ::frc971::control_loops::drivetrain_queue;
14using ::aos::input::driver_station::ButtonLocation;
15using ::aos::input::driver_station::ControlBit;
16using ::aos::input::driver_station::JoystickAxis;
17using ::aos::input::driver_station::POVLocation;
18
19namespace aos {
20namespace input {
21
Sabina Davis82b19182017-11-10 09:30:25 -080022const ButtonLocation kShiftHigh(2, 3), kShiftHigh2(2, 2), kShiftLow(2, 1);
23
Sabina Davis92d2efa2017-11-04 22:35:25 -070024void DrivetrainInputReader::HandleDrivetrain(
25 const ::aos::input::driver_station::Data &data) {
26 bool is_control_loop_driving = false;
27
28 const auto wheel_and_throttle = GetWheelAndThrottle(data);
29 const double wheel = wheel_and_throttle.wheel;
Austin Schuh2b1fce02018-03-02 20:05:20 -080030 const double wheel_velocity = wheel_and_throttle.wheel_velocity;
31 const double wheel_torque = wheel_and_throttle.wheel_torque;
Sabina Davis92d2efa2017-11-04 22:35:25 -070032 const double throttle = wheel_and_throttle.throttle;
Austin Schuh2b1fce02018-03-02 20:05:20 -080033 const double throttle_velocity = wheel_and_throttle.throttle_velocity;
34 const double throttle_torque = wheel_and_throttle.throttle_torque;
Sabina Davis82b19182017-11-10 09:30:25 -080035 const bool high_gear = wheel_and_throttle.high_gear;
Sabina Davis92d2efa2017-11-04 22:35:25 -070036
37 drivetrain_queue.status.FetchLatest();
38 if (drivetrain_queue.status.get()) {
39 robot_velocity_ = drivetrain_queue.status->robot_speed;
40 }
41
Sabina Davis82b19182017-11-10 09:30:25 -080042 if (data.PosEdge(turn1_) || data.PosEdge(turn2_)) {
Sabina Davis92d2efa2017-11-04 22:35:25 -070043 if (drivetrain_queue.status.get()) {
44 left_goal_ = drivetrain_queue.status->estimated_left_position;
45 right_goal_ = drivetrain_queue.status->estimated_right_position;
46 }
47 }
48 const double current_left_goal =
49 left_goal_ - wheel * wheel_multiplier_ + throttle * 0.3;
50 const double current_right_goal =
51 right_goal_ + wheel * wheel_multiplier_ + throttle * 0.3;
Sabina Davis82b19182017-11-10 09:30:25 -080052 if (data.IsPressed(turn1_) || data.IsPressed(turn2_)) {
Sabina Davis92d2efa2017-11-04 22:35:25 -070053 is_control_loop_driving = true;
54 }
55 auto new_drivetrain_goal = drivetrain_queue.goal.MakeMessage();
Austin Schuh2b1fce02018-03-02 20:05:20 -080056 new_drivetrain_goal->wheel = wheel;
57 new_drivetrain_goal->wheel_velocity = wheel_velocity;
58 new_drivetrain_goal->wheel_torque = wheel_torque;
Sabina Davis92d2efa2017-11-04 22:35:25 -070059 new_drivetrain_goal->throttle = throttle;
Austin Schuh2b1fce02018-03-02 20:05:20 -080060 new_drivetrain_goal->throttle_velocity = throttle_velocity;
61 new_drivetrain_goal->throttle_torque = throttle_torque;
Sabina Davis82b19182017-11-10 09:30:25 -080062 new_drivetrain_goal->highgear = high_gear;
63 new_drivetrain_goal->quickturn = data.IsPressed(quick_turn_);
Sabina Davis92d2efa2017-11-04 22:35:25 -070064 new_drivetrain_goal->control_loop_driving = is_control_loop_driving;
65 new_drivetrain_goal->left_goal = current_left_goal;
66 new_drivetrain_goal->right_goal = current_right_goal;
67 new_drivetrain_goal->left_velocity_goal = 0;
68 new_drivetrain_goal->right_velocity_goal = 0;
69
70 new_drivetrain_goal->linear.max_velocity = 3.0;
71 new_drivetrain_goal->linear.max_acceleration = 20.0;
72
73 if (!new_drivetrain_goal.Send()) {
74 LOG(WARNING, "sending stick values failed\n");
75 }
76}
77
78DrivetrainInputReader::WheelAndThrottle
79SteeringWheelDrivetrainInputReader::GetWheelAndThrottle(
80 const ::aos::input::driver_station::Data &data) {
Austin Schuh2b1fce02018-03-02 20:05:20 -080081 const double wheel = -data.GetAxis(wheel_);
82 const double throttle = -data.GetAxis(throttle_);
Sabina Davis82b19182017-11-10 09:30:25 -080083
84 if (!data.GetControlBit(ControlBit::kEnabled)) {
85 high_gear_ = default_high_gear_;
86 }
87
88 if (data.PosEdge(kShiftLow)) {
89 high_gear_ = false;
90 }
91
92 if (data.PosEdge(kShiftHigh) || data.PosEdge(kShiftHigh2)) {
93 high_gear_ = true;
94 }
95
Austin Schuh2b1fce02018-03-02 20:05:20 -080096 return DrivetrainInputReader::WheelAndThrottle{
97 wheel, 0.0, 0.0, throttle, 0.0, 0.0, high_gear_};
98}
99
100double UnwrappedAxis(const ::aos::input::driver_station::Data &data,
101 const JoystickAxis &high_bits,
102 const JoystickAxis &low_bits) {
103 const float high_bits_data = data.GetAxis(high_bits);
104 const float low_bits_data = data.GetAxis(low_bits);
105 const int16_t high_bits_data_int =
106 (high_bits_data < 0.0f ? high_bits_data * 128.0f
107 : high_bits_data * 127.0f);
108 const int16_t low_bits_data_int =
109 (low_bits_data < 0.0f ? low_bits_data * 128.0f : low_bits_data * 127.0f);
110
111 const uint16_t high_bits_data_uint =
112 ((static_cast<uint16_t>(high_bits_data_int) & 0xff) + 0x80) & 0xff;
113 const uint16_t low_bits_data_uint =
114 ((static_cast<uint16_t>(low_bits_data_int) & 0xff) + 0x80) & 0xff;
115
116 const uint16_t data_uint = (high_bits_data_uint << 8) | low_bits_data_uint;
117
118 const int32_t data_int = static_cast<int32_t>(data_uint) - 0x8000;
119
120 if (data_int < 0) {
121 return static_cast<double>(data_int) / static_cast<double>(0x8000);
122 } else {
123 return static_cast<double>(data_int) / static_cast<double>(0x7fff);
124 }
Sabina Davis92d2efa2017-11-04 22:35:25 -0700125}
126
127DrivetrainInputReader::WheelAndThrottle
128PistolDrivetrainInputReader::GetWheelAndThrottle(
129 const ::aos::input::driver_station::Data &data) {
Austin Schuh2b1fce02018-03-02 20:05:20 -0800130 const double wheel =
131 -UnwrappedAxis(data, wheel_, wheel_low_);
132 const double wheel_velocity =
133 -UnwrappedAxis(data, wheel_velocity_high_, wheel_velocity_low_) * 50.0;
134 const double wheel_torque =
135 -UnwrappedAxis(data, wheel_torque_high_, wheel_torque_low_) / 2.0;
136
Austin Schuh876b4f02018-03-10 19:16:59 -0800137 double throttle =
Austin Schuh2b1fce02018-03-02 20:05:20 -0800138 UnwrappedAxis(data, throttle_, throttle_low_);
139 const double throttle_velocity =
140 UnwrappedAxis(data, throttle_velocity_high_, throttle_velocity_low_) * 50.0;
141 const double throttle_torque =
142 UnwrappedAxis(data, throttle_torque_high_, throttle_torque_low_) / 2.0;
143
Austin Schuh876b4f02018-03-10 19:16:59 -0800144 // TODO(austin): Deal with haptics here.
145 if (throttle < 0) {
146 throttle = ::std::max(-1.0, throttle / 0.7);
147 }
148
Austin Schuh2b1fce02018-03-02 20:05:20 -0800149 if (!data.GetControlBit(ControlBit::kEnabled)) {
150 high_gear_ = default_high_gear_;
Sabina Davis92d2efa2017-11-04 22:35:25 -0700151 }
152
Austin Schuh2b1fce02018-03-02 20:05:20 -0800153 if (data.PosEdge(shift_low_)) {
154 high_gear_ = false;
Sabina Davis92d2efa2017-11-04 22:35:25 -0700155 }
Sabina Davis92d2efa2017-11-04 22:35:25 -0700156
Austin Schuh2b1fce02018-03-02 20:05:20 -0800157 if (data.PosEdge(shift_high_)) {
158 high_gear_ = true;
159 }
Sabina Davis92d2efa2017-11-04 22:35:25 -0700160
Austin Schuh2b1fce02018-03-02 20:05:20 -0800161 return DrivetrainInputReader::WheelAndThrottle{
162 wheel, wheel_velocity, wheel_torque,
163 throttle, throttle_velocity, throttle_torque,
164 high_gear_};
Sabina Davis92d2efa2017-11-04 22:35:25 -0700165}
166
167DrivetrainInputReader::WheelAndThrottle
168XboxDrivetrainInputReader::GetWheelAndThrottle(
169 const ::aos::input::driver_station::Data &data) {
170 // xbox
171 constexpr double kWheelDeadband = 0.05;
172 constexpr double kThrottleDeadband = 0.05;
173 const double wheel =
Austin Schuh2b1fce02018-03-02 20:05:20 -0800174 aos::Deadband(-data.GetAxis(wheel_), kWheelDeadband, 1.0);
Sabina Davis92d2efa2017-11-04 22:35:25 -0700175
176 const double unmodified_throttle =
Austin Schuh2b1fce02018-03-02 20:05:20 -0800177 aos::Deadband(-data.GetAxis(throttle_), kThrottleDeadband, 1.0);
Sabina Davis92d2efa2017-11-04 22:35:25 -0700178
179 // Apply a sin function that's scaled to make it feel better.
180 constexpr double throttle_range = M_PI_2 * 0.9;
181
182 double throttle = ::std::sin(throttle_range * unmodified_throttle) /
183 ::std::sin(throttle_range);
184 throttle = ::std::sin(throttle_range * throttle) / ::std::sin(throttle_range);
185 throttle = 2.0 * unmodified_throttle - throttle;
Austin Schuh2b1fce02018-03-02 20:05:20 -0800186 return DrivetrainInputReader::WheelAndThrottle{wheel, 0.0, 0.0, throttle,
187 0.0, 0.0, true};
Sabina Davis92d2efa2017-11-04 22:35:25 -0700188}
189
190std::unique_ptr<SteeringWheelDrivetrainInputReader>
Sabina Davis82b19182017-11-10 09:30:25 -0800191SteeringWheelDrivetrainInputReader::Make(bool default_high_gear) {
Sabina Davis92d2efa2017-11-04 22:35:25 -0700192 const JoystickAxis kSteeringWheel(1, 1), kDriveThrottle(2, 2);
193 const ButtonLocation kQuickTurn(1, 5);
194 const ButtonLocation kTurn1(1, 7);
195 const ButtonLocation kTurn2(1, 11);
196 std::unique_ptr<SteeringWheelDrivetrainInputReader> result(
197 new SteeringWheelDrivetrainInputReader(kSteeringWheel, kDriveThrottle,
198 kQuickTurn, kTurn1, kTurn2));
Sabina Davis82b19182017-11-10 09:30:25 -0800199 result.get()->set_default_high_gear(default_high_gear);
200
Sabina Davis92d2efa2017-11-04 22:35:25 -0700201 return result;
202}
203
Austin Schuh2b1fce02018-03-02 20:05:20 -0800204std::unique_ptr<PistolDrivetrainInputReader> PistolDrivetrainInputReader::Make(
205 bool default_high_gear) {
Sabina Davis92d2efa2017-11-04 22:35:25 -0700206 // Pistol Grip controller
Austin Schuh2b1fce02018-03-02 20:05:20 -0800207 const JoystickAxis kTriggerHigh(1, 1), kTriggerLow(1, 4),
208 kTriggerVelocityHigh(1, 2), kTriggerVelocityLow(1, 5),
209 kTriggerTorqueHigh(1, 3), kTriggerTorqueLow(1, 6);
210
211 const JoystickAxis kWheelHigh(2, 1), kWheelLow(2, 4),
212 kWheelVelocityHigh(2, 2), kWheelVelocityLow(2, 5), kWheelTorqueHigh(2, 3),
213 kWheelTorqueLow(2, 6);
214
Austin Schuhe8a54c02018-03-05 00:25:58 -0800215 const ButtonLocation kQuickTurn(1, 3);
216 const ButtonLocation kShiftHigh(1, 1);
217 const ButtonLocation kShiftLow(1, 2);
Sabina Davis92d2efa2017-11-04 22:35:25 -0700218
219 // Nop
Austin Schuh2b1fce02018-03-02 20:05:20 -0800220 const ButtonLocation kTurn1(1, 9);
221 const ButtonLocation kTurn2(1, 10);
Sabina Davis92d2efa2017-11-04 22:35:25 -0700222 std::unique_ptr<PistolDrivetrainInputReader> result(
Austin Schuh2b1fce02018-03-02 20:05:20 -0800223 new PistolDrivetrainInputReader(
224 kWheelHigh, kWheelLow, kTriggerVelocityHigh, kTriggerVelocityLow,
225 kTriggerTorqueHigh, kTriggerTorqueLow, kTriggerHigh, kTriggerLow,
226 kWheelVelocityHigh, kWheelVelocityLow, kWheelTorqueHigh,
227 kWheelTorqueLow, kQuickTurn, kShiftHigh, kShiftLow, kTurn1, kTurn2));
228
229 result->set_default_high_gear(default_high_gear);
Sabina Davis92d2efa2017-11-04 22:35:25 -0700230 return result;
231}
232
233std::unique_ptr<XboxDrivetrainInputReader> XboxDrivetrainInputReader::Make() {
234 // xbox
235 const JoystickAxis kSteeringWheel(1, 5), kDriveThrottle(1, 2);
236 const ButtonLocation kQuickTurn(1, 5);
237
238 // Nop
239 const ButtonLocation kTurn1(1, 1);
240 const ButtonLocation kTurn2(1, 2);
241
242 std::unique_ptr<XboxDrivetrainInputReader> result(
243 new XboxDrivetrainInputReader(kSteeringWheel, kDriveThrottle, kQuickTurn,
244 kTurn1, kTurn2));
245 return result;
246}
247::std::unique_ptr<DrivetrainInputReader> DrivetrainInputReader::Make(
Sabina Davis82b19182017-11-10 09:30:25 -0800248 InputType type,
Austin Schuhbcce26a2018-03-26 23:41:24 -0700249 const ::frc971::control_loops::drivetrain::DrivetrainConfig<double>
250 &dt_config) {
Sabina Davis92d2efa2017-11-04 22:35:25 -0700251 std::unique_ptr<DrivetrainInputReader> drivetrain_input_reader;
252
253 using InputType = DrivetrainInputReader::InputType;
Sabina Davis82b19182017-11-10 09:30:25 -0800254
Sabina Davis92d2efa2017-11-04 22:35:25 -0700255 switch (type) {
256 case InputType::kSteeringWheel:
Sabina Davis82b19182017-11-10 09:30:25 -0800257 drivetrain_input_reader =
258 SteeringWheelDrivetrainInputReader::Make(dt_config.default_high_gear);
Sabina Davis92d2efa2017-11-04 22:35:25 -0700259 break;
260 case InputType::kPistol:
Austin Schuh2b1fce02018-03-02 20:05:20 -0800261 drivetrain_input_reader =
262 PistolDrivetrainInputReader::Make(dt_config.default_high_gear);
Sabina Davis92d2efa2017-11-04 22:35:25 -0700263 break;
264 case InputType::kXbox:
265 drivetrain_input_reader = XboxDrivetrainInputReader::Make();
266 break;
267 }
268 return drivetrain_input_reader;
269}
270
271} // namespace input
272} // namespace aos