blob: a0d95cf81d0d09889661b56c994834b0413bae13 [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
22void DrivetrainInputReader::HandleDrivetrain(
23 const ::aos::input::driver_station::Data &data) {
24 bool is_control_loop_driving = false;
25
26 const auto wheel_and_throttle = GetWheelAndThrottle(data);
27 const double wheel = wheel_and_throttle.wheel;
28 const double throttle = wheel_and_throttle.throttle;
29
30 drivetrain_queue.status.FetchLatest();
31 if (drivetrain_queue.status.get()) {
32 robot_velocity_ = drivetrain_queue.status->robot_speed;
33 }
34
35 if (data.PosEdge(kTurn1) || data.PosEdge(kTurn2)) {
36 if (drivetrain_queue.status.get()) {
37 left_goal_ = drivetrain_queue.status->estimated_left_position;
38 right_goal_ = drivetrain_queue.status->estimated_right_position;
39 }
40 }
41 const double current_left_goal =
42 left_goal_ - wheel * wheel_multiplier_ + throttle * 0.3;
43 const double current_right_goal =
44 right_goal_ + wheel * wheel_multiplier_ + throttle * 0.3;
45 if (data.IsPressed(kTurn1) || data.IsPressed(kTurn2)) {
46 is_control_loop_driving = true;
47 }
48 auto new_drivetrain_goal = drivetrain_queue.goal.MakeMessage();
49 new_drivetrain_goal->steering = wheel;
50 new_drivetrain_goal->throttle = throttle;
51 new_drivetrain_goal->quickturn = data.IsPressed(kQuickTurn);
52 new_drivetrain_goal->control_loop_driving = is_control_loop_driving;
53 new_drivetrain_goal->left_goal = current_left_goal;
54 new_drivetrain_goal->right_goal = current_right_goal;
55 new_drivetrain_goal->left_velocity_goal = 0;
56 new_drivetrain_goal->right_velocity_goal = 0;
57
58 new_drivetrain_goal->linear.max_velocity = 3.0;
59 new_drivetrain_goal->linear.max_acceleration = 20.0;
60
61 if (!new_drivetrain_goal.Send()) {
62 LOG(WARNING, "sending stick values failed\n");
63 }
64}
65
66DrivetrainInputReader::WheelAndThrottle
67SteeringWheelDrivetrainInputReader::GetWheelAndThrottle(
68 const ::aos::input::driver_station::Data &data) {
69 const double wheel = -data.GetAxis(kSteeringWheel);
70 const double throttle = -data.GetAxis(kDriveThrottle);
71 return DrivetrainInputReader::WheelAndThrottle{wheel, throttle};
72}
73
74DrivetrainInputReader::WheelAndThrottle
75PistolDrivetrainInputReader::GetWheelAndThrottle(
76 const ::aos::input::driver_station::Data &data) {
77 const double unscaled_wheel = data.GetAxis(kSteeringWheel);
78 double wheel;
79 if (unscaled_wheel < 0.0) {
80 wheel = unscaled_wheel / 0.484375;
81 } else {
82 wheel = unscaled_wheel / 0.385827;
83 }
84
85 const double unscaled_throttle = -data.GetAxis(kDriveThrottle);
86 double unmodified_throttle;
87 if (unscaled_throttle < 0.0) {
88 unmodified_throttle = unscaled_throttle / 0.086614;
89 } else {
90 unmodified_throttle = unscaled_throttle / 0.265625;
91 }
92 unmodified_throttle = aos::Deadband(unmodified_throttle, 0.1, 1.0);
93
94 // Apply a sin function that's scaled to make it feel better.
95 constexpr double throttle_range = M_PI_2 * 0.5;
96
97 double throttle = ::std::sin(throttle_range * unmodified_throttle) /
98 ::std::sin(throttle_range);
99 throttle = ::std::sin(throttle_range * throttle) / ::std::sin(throttle_range);
100 throttle = 2.0 * unmodified_throttle - throttle;
101 return DrivetrainInputReader::WheelAndThrottle{wheel, throttle};
102}
103
104DrivetrainInputReader::WheelAndThrottle
105XboxDrivetrainInputReader::GetWheelAndThrottle(
106 const ::aos::input::driver_station::Data &data) {
107 // xbox
108 constexpr double kWheelDeadband = 0.05;
109 constexpr double kThrottleDeadband = 0.05;
110 const double wheel =
111 aos::Deadband(-data.GetAxis(kSteeringWheel), kWheelDeadband, 1.0);
112
113 const double unmodified_throttle =
114 aos::Deadband(-data.GetAxis(kDriveThrottle), kThrottleDeadband, 1.0);
115
116 // Apply a sin function that's scaled to make it feel better.
117 constexpr double throttle_range = M_PI_2 * 0.9;
118
119 double throttle = ::std::sin(throttle_range * unmodified_throttle) /
120 ::std::sin(throttle_range);
121 throttle = ::std::sin(throttle_range * throttle) / ::std::sin(throttle_range);
122 throttle = 2.0 * unmodified_throttle - throttle;
123 return DrivetrainInputReader::WheelAndThrottle{wheel, throttle};
124}
125
126std::unique_ptr<SteeringWheelDrivetrainInputReader>
127SteeringWheelDrivetrainInputReader::Make() {
128 const JoystickAxis kSteeringWheel(1, 1), kDriveThrottle(2, 2);
129 const ButtonLocation kQuickTurn(1, 5);
130 const ButtonLocation kTurn1(1, 7);
131 const ButtonLocation kTurn2(1, 11);
132 std::unique_ptr<SteeringWheelDrivetrainInputReader> result(
133 new SteeringWheelDrivetrainInputReader(kSteeringWheel, kDriveThrottle,
134 kQuickTurn, kTurn1, kTurn2));
135 return result;
136}
137
138std::unique_ptr<PistolDrivetrainInputReader>
139PistolDrivetrainInputReader::Make() {
140 // Pistol Grip controller
141 const JoystickAxis kSteeringWheel(1, 2), kDriveThrottle(1, 1);
142 const ButtonLocation kQuickTurn(1, 7);
143 const ButtonLocation kTurn1(1, 8);
144
145 // Nop
146 const ButtonLocation kTurn2(1, 9);
147 std::unique_ptr<PistolDrivetrainInputReader> result(
148 new PistolDrivetrainInputReader(kSteeringWheel, kDriveThrottle,
149 kQuickTurn, kTurn1, kTurn2));
150 result->set_wheel_multiplier(0.2);
151 return result;
152}
153
154std::unique_ptr<XboxDrivetrainInputReader> XboxDrivetrainInputReader::Make() {
155 // xbox
156 const JoystickAxis kSteeringWheel(1, 5), kDriveThrottle(1, 2);
157 const ButtonLocation kQuickTurn(1, 5);
158
159 // Nop
160 const ButtonLocation kTurn1(1, 1);
161 const ButtonLocation kTurn2(1, 2);
162
163 std::unique_ptr<XboxDrivetrainInputReader> result(
164 new XboxDrivetrainInputReader(kSteeringWheel, kDriveThrottle, kQuickTurn,
165 kTurn1, kTurn2));
166 return result;
167}
168::std::unique_ptr<DrivetrainInputReader> DrivetrainInputReader::Make(
169 InputType type) {
170 std::unique_ptr<DrivetrainInputReader> drivetrain_input_reader;
171
172 using InputType = DrivetrainInputReader::InputType;
173 switch (type) {
174 case InputType::kSteeringWheel:
175 drivetrain_input_reader = SteeringWheelDrivetrainInputReader::Make();
176 break;
177 case InputType::kPistol:
178 drivetrain_input_reader = PistolDrivetrainInputReader::Make();
179 break;
180 case InputType::kXbox:
181 drivetrain_input_reader = XboxDrivetrainInputReader::Make();
182 break;
183 }
184 return drivetrain_input_reader;
185}
186
187} // namespace input
188} // namespace aos