blob: 67ee9f3add93076dda80cb72e9bc6f20edf00b5a [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
John Park33858a32018-09-28 23:05:48 -07008#include "aos/commonmath.h"
9#include "aos/input/driver_station_data.h"
10#include "aos/logging/logging.h"
Sabina Davis92d2efa2017-11-04 22:35:25 -070011#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_);
Austin Schuh78379ea2019-01-04 20:39:45 -080064 new_drivetrain_goal->controller_type = is_control_loop_driving ? 1 : 0;
Sabina Davis92d2efa2017-11-04 22:35:25 -070065 new_drivetrain_goal->left_goal = current_left_goal;
66 new_drivetrain_goal->right_goal = current_right_goal;
Sabina Davis92d2efa2017-11-04 22:35:25 -070067
68 new_drivetrain_goal->linear.max_velocity = 3.0;
69 new_drivetrain_goal->linear.max_acceleration = 20.0;
70
71 if (!new_drivetrain_goal.Send()) {
72 LOG(WARNING, "sending stick values failed\n");
73 }
74}
75
76DrivetrainInputReader::WheelAndThrottle
77SteeringWheelDrivetrainInputReader::GetWheelAndThrottle(
78 const ::aos::input::driver_station::Data &data) {
Austin Schuh2b1fce02018-03-02 20:05:20 -080079 const double wheel = -data.GetAxis(wheel_);
80 const double throttle = -data.GetAxis(throttle_);
Sabina Davis82b19182017-11-10 09:30:25 -080081
82 if (!data.GetControlBit(ControlBit::kEnabled)) {
83 high_gear_ = default_high_gear_;
84 }
85
86 if (data.PosEdge(kShiftLow)) {
87 high_gear_ = false;
88 }
89
90 if (data.PosEdge(kShiftHigh) || data.PosEdge(kShiftHigh2)) {
91 high_gear_ = true;
92 }
93
Austin Schuh2b1fce02018-03-02 20:05:20 -080094 return DrivetrainInputReader::WheelAndThrottle{
95 wheel, 0.0, 0.0, throttle, 0.0, 0.0, high_gear_};
96}
97
98double UnwrappedAxis(const ::aos::input::driver_station::Data &data,
99 const JoystickAxis &high_bits,
100 const JoystickAxis &low_bits) {
101 const float high_bits_data = data.GetAxis(high_bits);
102 const float low_bits_data = data.GetAxis(low_bits);
103 const int16_t high_bits_data_int =
104 (high_bits_data < 0.0f ? high_bits_data * 128.0f
105 : high_bits_data * 127.0f);
106 const int16_t low_bits_data_int =
107 (low_bits_data < 0.0f ? low_bits_data * 128.0f : low_bits_data * 127.0f);
108
109 const uint16_t high_bits_data_uint =
110 ((static_cast<uint16_t>(high_bits_data_int) & 0xff) + 0x80) & 0xff;
111 const uint16_t low_bits_data_uint =
112 ((static_cast<uint16_t>(low_bits_data_int) & 0xff) + 0x80) & 0xff;
113
114 const uint16_t data_uint = (high_bits_data_uint << 8) | low_bits_data_uint;
115
116 const int32_t data_int = static_cast<int32_t>(data_uint) - 0x8000;
117
118 if (data_int < 0) {
119 return static_cast<double>(data_int) / static_cast<double>(0x8000);
120 } else {
121 return static_cast<double>(data_int) / static_cast<double>(0x7fff);
122 }
Sabina Davis92d2efa2017-11-04 22:35:25 -0700123}
124
125DrivetrainInputReader::WheelAndThrottle
126PistolDrivetrainInputReader::GetWheelAndThrottle(
127 const ::aos::input::driver_station::Data &data) {
Austin Schuh2b1fce02018-03-02 20:05:20 -0800128 const double wheel =
129 -UnwrappedAxis(data, wheel_, wheel_low_);
130 const double wheel_velocity =
131 -UnwrappedAxis(data, wheel_velocity_high_, wheel_velocity_low_) * 50.0;
132 const double wheel_torque =
133 -UnwrappedAxis(data, wheel_torque_high_, wheel_torque_low_) / 2.0;
134
Austin Schuh876b4f02018-03-10 19:16:59 -0800135 double throttle =
Austin Schuh2b1fce02018-03-02 20:05:20 -0800136 UnwrappedAxis(data, throttle_, throttle_low_);
137 const double throttle_velocity =
138 UnwrappedAxis(data, throttle_velocity_high_, throttle_velocity_low_) * 50.0;
139 const double throttle_torque =
140 UnwrappedAxis(data, throttle_torque_high_, throttle_torque_low_) / 2.0;
141
Austin Schuh876b4f02018-03-10 19:16:59 -0800142 // TODO(austin): Deal with haptics here.
143 if (throttle < 0) {
144 throttle = ::std::max(-1.0, throttle / 0.7);
145 }
146
Austin Schuh2b1fce02018-03-02 20:05:20 -0800147 if (!data.GetControlBit(ControlBit::kEnabled)) {
148 high_gear_ = default_high_gear_;
Sabina Davis92d2efa2017-11-04 22:35:25 -0700149 }
150
Austin Schuh2b1fce02018-03-02 20:05:20 -0800151 if (data.PosEdge(shift_low_)) {
152 high_gear_ = false;
Sabina Davis92d2efa2017-11-04 22:35:25 -0700153 }
Sabina Davis92d2efa2017-11-04 22:35:25 -0700154
Austin Schuh2b1fce02018-03-02 20:05:20 -0800155 if (data.PosEdge(shift_high_)) {
156 high_gear_ = true;
157 }
Sabina Davis92d2efa2017-11-04 22:35:25 -0700158
Austin Schuh2b1fce02018-03-02 20:05:20 -0800159 return DrivetrainInputReader::WheelAndThrottle{
160 wheel, wheel_velocity, wheel_torque,
161 throttle, throttle_velocity, throttle_torque,
162 high_gear_};
Sabina Davis92d2efa2017-11-04 22:35:25 -0700163}
164
165DrivetrainInputReader::WheelAndThrottle
166XboxDrivetrainInputReader::GetWheelAndThrottle(
167 const ::aos::input::driver_station::Data &data) {
168 // xbox
169 constexpr double kWheelDeadband = 0.05;
170 constexpr double kThrottleDeadband = 0.05;
171 const double wheel =
Austin Schuh2b1fce02018-03-02 20:05:20 -0800172 aos::Deadband(-data.GetAxis(wheel_), kWheelDeadband, 1.0);
Sabina Davis92d2efa2017-11-04 22:35:25 -0700173
174 const double unmodified_throttle =
Austin Schuh2b1fce02018-03-02 20:05:20 -0800175 aos::Deadband(-data.GetAxis(throttle_), kThrottleDeadband, 1.0);
Sabina Davis92d2efa2017-11-04 22:35:25 -0700176
177 // Apply a sin function that's scaled to make it feel better.
178 constexpr double throttle_range = M_PI_2 * 0.9;
179
180 double throttle = ::std::sin(throttle_range * unmodified_throttle) /
181 ::std::sin(throttle_range);
182 throttle = ::std::sin(throttle_range * throttle) / ::std::sin(throttle_range);
183 throttle = 2.0 * unmodified_throttle - throttle;
Austin Schuh2b1fce02018-03-02 20:05:20 -0800184 return DrivetrainInputReader::WheelAndThrottle{wheel, 0.0, 0.0, throttle,
185 0.0, 0.0, true};
Sabina Davis92d2efa2017-11-04 22:35:25 -0700186}
187
188std::unique_ptr<SteeringWheelDrivetrainInputReader>
Sabina Davis82b19182017-11-10 09:30:25 -0800189SteeringWheelDrivetrainInputReader::Make(bool default_high_gear) {
Sabina Davis92d2efa2017-11-04 22:35:25 -0700190 const JoystickAxis kSteeringWheel(1, 1), kDriveThrottle(2, 2);
191 const ButtonLocation kQuickTurn(1, 5);
192 const ButtonLocation kTurn1(1, 7);
193 const ButtonLocation kTurn2(1, 11);
194 std::unique_ptr<SteeringWheelDrivetrainInputReader> result(
195 new SteeringWheelDrivetrainInputReader(kSteeringWheel, kDriveThrottle,
196 kQuickTurn, kTurn1, kTurn2));
Sabina Davis82b19182017-11-10 09:30:25 -0800197 result.get()->set_default_high_gear(default_high_gear);
198
Sabina Davis92d2efa2017-11-04 22:35:25 -0700199 return result;
200}
201
Austin Schuh2b1fce02018-03-02 20:05:20 -0800202std::unique_ptr<PistolDrivetrainInputReader> PistolDrivetrainInputReader::Make(
203 bool default_high_gear) {
Sabina Davis92d2efa2017-11-04 22:35:25 -0700204 // Pistol Grip controller
Austin Schuh2b1fce02018-03-02 20:05:20 -0800205 const JoystickAxis kTriggerHigh(1, 1), kTriggerLow(1, 4),
206 kTriggerVelocityHigh(1, 2), kTriggerVelocityLow(1, 5),
207 kTriggerTorqueHigh(1, 3), kTriggerTorqueLow(1, 6);
208
209 const JoystickAxis kWheelHigh(2, 1), kWheelLow(2, 4),
210 kWheelVelocityHigh(2, 2), kWheelVelocityLow(2, 5), kWheelTorqueHigh(2, 3),
211 kWheelTorqueLow(2, 6);
212
Austin Schuhe8a54c02018-03-05 00:25:58 -0800213 const ButtonLocation kQuickTurn(1, 3);
214 const ButtonLocation kShiftHigh(1, 1);
215 const ButtonLocation kShiftLow(1, 2);
Sabina Davis92d2efa2017-11-04 22:35:25 -0700216
217 // Nop
Austin Schuh2b1fce02018-03-02 20:05:20 -0800218 const ButtonLocation kTurn1(1, 9);
219 const ButtonLocation kTurn2(1, 10);
Sabina Davis92d2efa2017-11-04 22:35:25 -0700220 std::unique_ptr<PistolDrivetrainInputReader> result(
Austin Schuh2b1fce02018-03-02 20:05:20 -0800221 new PistolDrivetrainInputReader(
222 kWheelHigh, kWheelLow, kTriggerVelocityHigh, kTriggerVelocityLow,
223 kTriggerTorqueHigh, kTriggerTorqueLow, kTriggerHigh, kTriggerLow,
224 kWheelVelocityHigh, kWheelVelocityLow, kWheelTorqueHigh,
225 kWheelTorqueLow, kQuickTurn, kShiftHigh, kShiftLow, kTurn1, kTurn2));
226
227 result->set_default_high_gear(default_high_gear);
Sabina Davis92d2efa2017-11-04 22:35:25 -0700228 return result;
229}
230
231std::unique_ptr<XboxDrivetrainInputReader> XboxDrivetrainInputReader::Make() {
232 // xbox
233 const JoystickAxis kSteeringWheel(1, 5), kDriveThrottle(1, 2);
234 const ButtonLocation kQuickTurn(1, 5);
235
236 // Nop
237 const ButtonLocation kTurn1(1, 1);
238 const ButtonLocation kTurn2(1, 2);
239
240 std::unique_ptr<XboxDrivetrainInputReader> result(
241 new XboxDrivetrainInputReader(kSteeringWheel, kDriveThrottle, kQuickTurn,
242 kTurn1, kTurn2));
243 return result;
244}
245::std::unique_ptr<DrivetrainInputReader> DrivetrainInputReader::Make(
Sabina Davis82b19182017-11-10 09:30:25 -0800246 InputType type,
Austin Schuhbcce26a2018-03-26 23:41:24 -0700247 const ::frc971::control_loops::drivetrain::DrivetrainConfig<double>
248 &dt_config) {
Sabina Davis92d2efa2017-11-04 22:35:25 -0700249 std::unique_ptr<DrivetrainInputReader> drivetrain_input_reader;
250
251 using InputType = DrivetrainInputReader::InputType;
Sabina Davis82b19182017-11-10 09:30:25 -0800252
Sabina Davis92d2efa2017-11-04 22:35:25 -0700253 switch (type) {
254 case InputType::kSteeringWheel:
Sabina Davis82b19182017-11-10 09:30:25 -0800255 drivetrain_input_reader =
256 SteeringWheelDrivetrainInputReader::Make(dt_config.default_high_gear);
Sabina Davis92d2efa2017-11-04 22:35:25 -0700257 break;
258 case InputType::kPistol:
Austin Schuh2b1fce02018-03-02 20:05:20 -0800259 drivetrain_input_reader =
260 PistolDrivetrainInputReader::Make(dt_config.default_high_gear);
Sabina Davis92d2efa2017-11-04 22:35:25 -0700261 break;
262 case InputType::kXbox:
263 drivetrain_input_reader = XboxDrivetrainInputReader::Make();
264 break;
265 }
266 return drivetrain_input_reader;
267}
268
269} // namespace input
270} // namespace aos