RIT VEXU Core API
Loading...
Searching...
No Matches
lift.h
1#pragma once
2
3#include "vex/vex.h"
4#include "core/math/controls/pid.h"
5#include <atomic>
6#include <map>
7#include <vector>
8
9using namespace std;
10
18template <typename T> class Lift {
19public:
27 struct lift_cfg_t {
28 double up_speed, down_speed;
29 double softstop_up, softstop_down;
30
31 PID lift_pid;
32 };
33
55 Lift(vex::motor_group &lift_motors, lift_cfg_t &lift_cfg, map<T, double> &setpoint_map, vex::limit *homing_switch = NULL)
56 : lift_motors(lift_motors), cfg(lift_cfg), lift_pid(cfg.lift_pid_cfg), setpoint_map(setpoint_map),
57 homing_switch(homing_switch) {
58
59 is_async = true;
60 setpoint = 0;
61 /*
62 * Create a background task that is constantly updating the lift PID, if requested.
63 * Set once, and forget.
64 */
65 vex::task t(
66 [](void *ptr) {
67 Lift &lift = *((Lift *)ptr);
68
69 while (true) {
70 if (lift.get_async())
71 lift.hold();
72
73 vexDelay(50);
74 }
75
76 return 0;
77 },
78 this);
79 }
80
89 void control_continuous(bool up_ctrl, bool down_ctrl) {
90 static vex::timer tmr;
91
92 double cur_pos = 0;
93
94 // Check if there's a hook for a custom sensor. If not, use the motors.
95 if (get_sensor == NULL)
96 cur_pos = lift_motors.position(vex::rev);
97 else
98 cur_pos = get_sensor();
99
100 if (up_ctrl && cur_pos < cfg.softstop_up) {
101 lift_motors.spin(vex::directionType::fwd, cfg.up_speed, vex::volt);
102 setpoint = cur_pos + .3;
103
104 // std::cout << "DEBUG OUT: UP " << setpoint << ", " << tmr.time(sec) << ", " << cfg.down_speed << "\n";
105
106 // Disable the PID while going UP.
107 is_async = false;
108 } else if (down_ctrl && cur_pos > cfg.softstop_down) {
109 // Lower the lift slowly, at a rate defined by down_speed
110 if (setpoint > cfg.softstop_down)
111 setpoint = setpoint - (tmr.time(vex::sec) * cfg.down_speed);
112 // std::cout << "DEBUG OUT: DOWN " << setpoint << ", " << tmr.time(sec) << ", " << cfg.down_speed << "\n";
113 is_async = true;
114 } else {
115 // Hold the lift at the last setpoint
116 is_async = true;
117 }
118
119 tmr.reset();
120 }
121
130 void control_manual(bool up_btn, bool down_btn, int volt_up, int volt_down) {
131 static bool down_hold = false;
132 static bool init = true;
133
134 // Allow for setting position while still calling this function
135 if (init || up_btn || down_btn) {
136 init = false;
137 is_async = false;
138 }
139
140 double rev = lift_motors.position(vex::rotationUnits::rev);
141
142 if (rev < cfg.softstop_down && down_btn)
143 down_hold = true;
144 else if (!down_btn)
145 down_hold = false;
146
147 if (up_btn && rev < cfg.softstop_up)
148 lift_motors.spin(vex::directionType::fwd, volt_up, vex::voltageUnits::volt);
149 else if (down_btn && rev > cfg.softstop_down && !down_hold)
150 lift_motors.spin(vex::directionType::rev, volt_down, vex::voltageUnits::volt);
151 else
152 lift_motors.spin(vex::directionType::fwd, 0, vex::voltageUnits::volt);
153 }
154
166 void control_setpoints(bool up_step, bool down_step, vector<T> pos_list) {
167 // Make sure inputs are only processed on the rising edge of the button
168 static bool up_last = up_step, down_last = down_step;
169
170 bool up_rising = up_step && !up_last;
171 bool down_rising = down_step && !down_last;
172
173 up_last = up_step;
174 down_last = down_step;
175
176 static int cur_index = 0;
177
178 // Avoid an index overflow. Shouldn't happen unless the user changes pos_list between calls.
179 if (cur_index >= pos_list.size())
180 cur_index = pos_list.size() - 1;
181
182 // Increment or decrement the index of the list, bringing it up or down.
183 if (up_rising && cur_index < (pos_list.size() - 1))
184 cur_index++;
185 else if (down_rising && cur_index > 0)
186 cur_index--;
187
188 // Set the lift to hold the position in the background with the PID loop
189 set_position(pos_list[cur_index]);
190 is_async = true;
191 }
192
201 bool set_position(T pos) {
202 this->setpoint = setpoint_map[pos];
203 is_async = true;
204
205 return (lift_pid.get_target() == this->setpoint) && lift_pid.is_on_target();
206 }
207
214 bool set_setpoint(double val) {
215 this->setpoint = val;
216 return (lift_pid.get_target() == this->setpoint) && lift_pid.is_on_target();
217 }
218
220 double get_setpoint() { return this->setpoint; }
221
226 void hold() {
227 lift_pid.set_target(setpoint);
228 // std::cout << "DEBUG OUT: SETPOINT " << setpoint << "\n";
229
230 if (get_sensor != NULL)
231 lift_pid.update(get_sensor());
232 else
233 lift_pid.update(lift_motors.position(vex::rev));
234
235 // std::cout << "DEBUG OUT: ROTATION " << lift_motors.rotation(rev) << "\n\n";
236
237 lift_motors.spin(vex::fwd, lift_pid.get(), vex::volt);
238 }
239
244 void home() {
245 static vex::timer tmr;
246 tmr.reset();
247
248 while (tmr.time(vex::sec) < 3) {
249 lift_motors.spin(vex::directionType::rev, 6, vex::volt);
250
251 if (homing_switch == NULL && lift_motors.current(vex::currentUnits::amp) > 1.5)
252 break;
253 else if (homing_switch != NULL && homing_switch->pressing())
254 break;
255 }
256
257 if (reset_sensor != NULL)
258 reset_sensor();
259
260 lift_motors.resetPosition();
261 lift_motors.stop();
262 }
263
265 bool get_async() { return is_async; }
266
272 void set_async(bool val) { this->is_async = val; }
273
283 void set_sensor_function(double (*fn_ptr)(void)) { this->get_sensor = fn_ptr; }
284
291 void set_sensor_reset(void (*fn_ptr)(void)) { this->reset_sensor = fn_ptr; }
292
293private:
294 vex::motor_group &lift_motors;
295 lift_cfg_t &cfg;
296 PID lift_pid;
297 map<T, double> &setpoint_map;
298 vex::limit *homing_switch;
299
300 atomic<double> setpoint;
301 atomic<bool> is_async;
302
303 double (*get_sensor)(void) = NULL;
304 void (*reset_sensor)(void) = NULL;
305};
void set_sensor_function(double(*fn_ptr)(void))
Definition lift.h:283
bool set_setpoint(double val)
Definition lift.h:214
bool get_async()
Definition lift.h:265
void set_sensor_reset(void(*fn_ptr)(void))
Definition lift.h:291
void control_setpoints(bool up_step, bool down_step, vector< T > pos_list)
Definition lift.h:166
void set_async(bool val)
Definition lift.h:272
void hold()
Definition lift.h:226
bool set_position(T pos)
Definition lift.h:201
void home()
Definition lift.h:244
Lift(vex::motor_group &lift_motors, lift_cfg_t &lift_cfg, map< T, double > &setpoint_map, vex::limit *homing_switch=NULL)
Definition lift.h:55
void control_manual(bool up_btn, bool down_btn, int volt_up, int volt_down)
Definition lift.h:130
double get_setpoint()
Definition lift.h:220
void control_continuous(bool up_ctrl, bool down_ctrl)
Definition lift.h:89
Definition pid.h:20
Definition lift.h:27