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