RIT VEXU Core API
Loading...
Searching...
No Matches
lift.h
1#pragma once
2
3#include "../core/include/utils/controls/pid.h"
4#include "vex.h"
5#include <atomic>
6#include <iostream>
7#include <map>
8#include <vector>
9
10using namespace vex;
11using namespace std;
12
20template <typename T> class Lift {
21public:
28 struct lift_cfg_t {
29 double up_speed, down_speed;
30 double softstop_up, softstop_down;
31
32 PID::pid_config_t lift_pid_cfg;
33 };
34
56 Lift(motor_group &lift_motors, lift_cfg_t &lift_cfg, map<T, double> &setpoint_map, limit *homing_switch = NULL)
57 : lift_motors(lift_motors), cfg(lift_cfg), lift_pid(cfg.lift_pid_cfg), setpoint_map(setpoint_map),
58 homing_switch(homing_switch) {
59
60 is_async = true;
61 setpoint = 0;
62
63 // Create a background task that is constantly updating the lift PID, if requested.
64 // Set once, and forget.
65 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 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(rev);
97 else
98 cur_pos = get_sensor();
99
100 if (up_ctrl && cur_pos < cfg.softstop_up) {
101 lift_motors.spin(directionType::fwd, cfg.up_speed, 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(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(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(directionType::fwd, volt_up, voltageUnits::volt);
149 else if (down_btn && rev > cfg.softstop_down && !down_hold)
150 lift_motors.spin(directionType::rev, volt_down, voltageUnits::volt);
151 else
152 lift_motors.spin(directionType::fwd, 0, 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
222 double get_setpoint() { return this->setpoint; }
223
228 void hold() {
229 lift_pid.set_target(setpoint);
230 // std::cout << "DEBUG OUT: SETPOINT " << setpoint << "\n";
231
232 if (get_sensor != NULL)
233 lift_pid.update(get_sensor());
234 else
235 lift_pid.update(lift_motors.position(rev));
236
237 // std::cout << "DEBUG OUT: ROTATION " << lift_motors.rotation(rev) << "\n\n";
238
239 lift_motors.spin(fwd, lift_pid.get(), volt);
240 }
241
246 void home() {
247 static timer tmr;
248 tmr.reset();
249
250 while (tmr.time(sec) < 3) {
251 lift_motors.spin(directionType::rev, 6, volt);
252
253 if (homing_switch == NULL && lift_motors.current(currentUnits::amp) > 1.5)
254 break;
255 else if (homing_switch != NULL && homing_switch->pressing())
256 break;
257 }
258
259 if (reset_sensor != NULL)
260 reset_sensor();
261
262 lift_motors.resetPosition();
263 lift_motors.stop();
264 }
265
269 bool get_async() { return is_async; }
270
276 void set_async(bool val) { this->is_async = val; }
277
287 void set_sensor_function(double (*fn_ptr)(void)) { this->get_sensor = fn_ptr; }
288
295 void set_sensor_reset(void (*fn_ptr)(void)) { this->reset_sensor = fn_ptr; }
296
297private:
298 motor_group &lift_motors;
299 lift_cfg_t &cfg;
300 PID lift_pid;
301 map<T, double> &setpoint_map;
302 limit *homing_switch;
303
304 atomic<double> setpoint;
305 atomic<bool> is_async;
306
307 double (*get_sensor)(void) = NULL;
308 void (*reset_sensor)(void) = NULL;
309};
Definition lift.h:20
void set_sensor_function(double(*fn_ptr)(void))
Definition lift.h:287
bool set_setpoint(double val)
Definition lift.h:214
bool get_async()
Definition lift.h:269
void set_sensor_reset(void(*fn_ptr)(void))
Definition lift.h:295
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:276
void hold()
Definition lift.h:228
Lift(motor_group &lift_motors, lift_cfg_t &lift_cfg, map< T, double > &setpoint_map, limit *homing_switch=NULL)
Definition lift.h:56
bool set_position(T pos)
Definition lift.h:201
void home()
Definition lift.h:246
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:222
void control_continuous(bool up_ctrl, bool down_ctrl)
Definition lift.h:89
Definition pid.h:23
void set_target(double target)
Definition pid.cpp:109
double update(double sensor_val) override
Definition pid.cpp:23
double get() override
Definition pid.cpp:92
bool is_on_target() override
Definition pid.cpp:124
double get_target() const
Definition pid.cpp:104
Definition lift.h:28
Definition pid.h:43