blob: a5827c30ee776bc45db068200da5634ff8d8d06e [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
137 const double throttle =
138 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
144 if (!data.GetControlBit(ControlBit::kEnabled)) {
145 high_gear_ = default_high_gear_;
Sabina Davis92d2efa2017-11-04 22:35:25 -0700146 }
147
Austin Schuh2b1fce02018-03-02 20:05:20 -0800148 if (data.PosEdge(shift_low_)) {
149 high_gear_ = false;
Sabina Davis92d2efa2017-11-04 22:35:25 -0700150 }
Sabina Davis92d2efa2017-11-04 22:35:25 -0700151
Austin Schuh2b1fce02018-03-02 20:05:20 -0800152 if (data.PosEdge(shift_high_)) {
153 high_gear_ = true;
154 }
Sabina Davis92d2efa2017-11-04 22:35:25 -0700155
Austin Schuh2b1fce02018-03-02 20:05:20 -0800156 return DrivetrainInputReader::WheelAndThrottle{
157 wheel, wheel_velocity, wheel_torque,
158 throttle, throttle_velocity, throttle_torque,
159 high_gear_};
Sabina Davis92d2efa2017-11-04 22:35:25 -0700160}
161
162DrivetrainInputReader::WheelAndThrottle
163XboxDrivetrainInputReader::GetWheelAndThrottle(
164 const ::aos::input::driver_station::Data &data) {
165 // xbox
166 constexpr double kWheelDeadband = 0.05;
167 constexpr double kThrottleDeadband = 0.05;
168 const double wheel =
Austin Schuh2b1fce02018-03-02 20:05:20 -0800169 aos::Deadband(-data.GetAxis(wheel_), kWheelDeadband, 1.0);
Sabina Davis92d2efa2017-11-04 22:35:25 -0700170
171 const double unmodified_throttle =
Austin Schuh2b1fce02018-03-02 20:05:20 -0800172 aos::Deadband(-data.GetAxis(throttle_), kThrottleDeadband, 1.0);
Sabina Davis92d2efa2017-11-04 22:35:25 -0700173
174 // Apply a sin function that's scaled to make it feel better.
175 constexpr double throttle_range = M_PI_2 * 0.9;
176
177 double throttle = ::std::sin(throttle_range * unmodified_throttle) /
178 ::std::sin(throttle_range);
179 throttle = ::std::sin(throttle_range * throttle) / ::std::sin(throttle_range);
180 throttle = 2.0 * unmodified_throttle - throttle;
Austin Schuh2b1fce02018-03-02 20:05:20 -0800181 return DrivetrainInputReader::WheelAndThrottle{wheel, 0.0, 0.0, throttle,
182 0.0, 0.0, true};
Sabina Davis92d2efa2017-11-04 22:35:25 -0700183}
184
185std::unique_ptr<SteeringWheelDrivetrainInputReader>
Sabina Davis82b19182017-11-10 09:30:25 -0800186SteeringWheelDrivetrainInputReader::Make(bool default_high_gear) {
Sabina Davis92d2efa2017-11-04 22:35:25 -0700187 const JoystickAxis kSteeringWheel(1, 1), kDriveThrottle(2, 2);
188 const ButtonLocation kQuickTurn(1, 5);
189 const ButtonLocation kTurn1(1, 7);
190 const ButtonLocation kTurn2(1, 11);
191 std::unique_ptr<SteeringWheelDrivetrainInputReader> result(
192 new SteeringWheelDrivetrainInputReader(kSteeringWheel, kDriveThrottle,
193 kQuickTurn, kTurn1, kTurn2));
Sabina Davis82b19182017-11-10 09:30:25 -0800194 result.get()->set_default_high_gear(default_high_gear);
195
Sabina Davis92d2efa2017-11-04 22:35:25 -0700196 return result;
197}
198
Austin Schuh2b1fce02018-03-02 20:05:20 -0800199std::unique_ptr<PistolDrivetrainInputReader> PistolDrivetrainInputReader::Make(
200 bool default_high_gear) {
Sabina Davis92d2efa2017-11-04 22:35:25 -0700201 // Pistol Grip controller
Austin Schuh2b1fce02018-03-02 20:05:20 -0800202 const JoystickAxis kTriggerHigh(1, 1), kTriggerLow(1, 4),
203 kTriggerVelocityHigh(1, 2), kTriggerVelocityLow(1, 5),
204 kTriggerTorqueHigh(1, 3), kTriggerTorqueLow(1, 6);
205
206 const JoystickAxis kWheelHigh(2, 1), kWheelLow(2, 4),
207 kWheelVelocityHigh(2, 2), kWheelVelocityLow(2, 5), kWheelTorqueHigh(2, 3),
208 kWheelTorqueLow(2, 6);
209
Austin Schuhe8a54c02018-03-05 00:25:58 -0800210 const ButtonLocation kQuickTurn(1, 3);
211 const ButtonLocation kShiftHigh(1, 1);
212 const ButtonLocation kShiftLow(1, 2);
Sabina Davis92d2efa2017-11-04 22:35:25 -0700213
214 // Nop
Austin Schuh2b1fce02018-03-02 20:05:20 -0800215 const ButtonLocation kTurn1(1, 9);
216 const ButtonLocation kTurn2(1, 10);
Sabina Davis92d2efa2017-11-04 22:35:25 -0700217 std::unique_ptr<PistolDrivetrainInputReader> result(
Austin Schuh2b1fce02018-03-02 20:05:20 -0800218 new PistolDrivetrainInputReader(
219 kWheelHigh, kWheelLow, kTriggerVelocityHigh, kTriggerVelocityLow,
220 kTriggerTorqueHigh, kTriggerTorqueLow, kTriggerHigh, kTriggerLow,
221 kWheelVelocityHigh, kWheelVelocityLow, kWheelTorqueHigh,
222 kWheelTorqueLow, kQuickTurn, kShiftHigh, kShiftLow, kTurn1, kTurn2));
223
224 result->set_default_high_gear(default_high_gear);
Sabina Davis92d2efa2017-11-04 22:35:25 -0700225 return result;
226}
227
228std::unique_ptr<XboxDrivetrainInputReader> XboxDrivetrainInputReader::Make() {
229 // xbox
230 const JoystickAxis kSteeringWheel(1, 5), kDriveThrottle(1, 2);
231 const ButtonLocation kQuickTurn(1, 5);
232
233 // Nop
234 const ButtonLocation kTurn1(1, 1);
235 const ButtonLocation kTurn2(1, 2);
236
237 std::unique_ptr<XboxDrivetrainInputReader> result(
238 new XboxDrivetrainInputReader(kSteeringWheel, kDriveThrottle, kQuickTurn,
239 kTurn1, kTurn2));
240 return result;
241}
242::std::unique_ptr<DrivetrainInputReader> DrivetrainInputReader::Make(
Sabina Davis82b19182017-11-10 09:30:25 -0800243 InputType type,
244 const ::frc971::control_loops::drivetrain::DrivetrainConfig &dt_config) {
Sabina Davis92d2efa2017-11-04 22:35:25 -0700245 std::unique_ptr<DrivetrainInputReader> drivetrain_input_reader;
246
247 using InputType = DrivetrainInputReader::InputType;
Sabina Davis82b19182017-11-10 09:30:25 -0800248
Sabina Davis92d2efa2017-11-04 22:35:25 -0700249 switch (type) {
250 case InputType::kSteeringWheel:
Sabina Davis82b19182017-11-10 09:30:25 -0800251 drivetrain_input_reader =
252 SteeringWheelDrivetrainInputReader::Make(dt_config.default_high_gear);
Sabina Davis92d2efa2017-11-04 22:35:25 -0700253 break;
254 case InputType::kPistol:
Austin Schuh2b1fce02018-03-02 20:05:20 -0800255 drivetrain_input_reader =
256 PistolDrivetrainInputReader::Make(dt_config.default_high_gear);
Sabina Davis92d2efa2017-11-04 22:35:25 -0700257 break;
258 case InputType::kXbox:
259 drivetrain_input_reader = XboxDrivetrainInputReader::Make();
260 break;
261 }
262 return drivetrain_input_reader;
263}
264
265} // namespace input
266} // namespace aos