1516X Push Back 1.0
1516X's robot code for the 2025-2026 VEX Robotics Competition
Loading...
Searching...
No Matches
distanceReset.cpp
Go to the documentation of this file.
1#include "globals.h"
2#include "lemlib/util.hpp"
3#include <numeric>
4
5const double MM_TO_IN = 0.0393701;
6const double FIELD_WIDTH = 3657.6 * MM_TO_IN;
7const double FIELD_HEIGHT = 3657.6 * MM_TO_IN;
8const double HALF_WIDTH = FIELD_WIDTH / 2.0;
9const double HALF_HEIGHT = FIELD_HEIGHT / 2.0;
10const double MAX_SENSOR_RANGE = 1500 * MM_TO_IN;
11const double MIN_SENSOR_RANGE = 10 * MM_TO_IN;
12
14
20
21const SensorConfig front_sensor_cfg = {-0.75, -3, 0};
22const SensorConfig left_sensor_cfg = {-0.5, -6.4, 90};
23const SensorConfig right_sensor_cfg = {-0.5, 6.3, -90};
24const SensorConfig back_sensor_cfg = {-10.5, -3, 180};
25
27 double dist_mm;
30};
31
33 double x;
34 double y;
37};
38
40 const SensorReadings& front_data,
41 const SensorReadings& left_data,
42 const SensorReadings& right_data,
43 const SensorReadings& back_data,
44 double heading_deg)
45{
46 lemlib::Pose current_pose = chassis.getPose();
47 double est_x = current_pose.x;
48 double est_y = current_pose.y;
49
50 // 1. Determine Quadrant based on current Odom
51 // If x >= 0, we are in the Right half (closer to +X wall)
52 // If y >= 0, we are in the Top half (closer to +Y wall)
53 bool use_pos_x_wall = (est_x >= 0);
54 bool use_pos_y_wall = (est_y >= 0);
55
56 bool using_odom_x = true;
57 bool using_odom_y = true;
58
59 struct SensorData { SensorConfig cfg; double dist_in; int confidence;};
60 const SensorData sensors[] = {
61 {front_sensor_cfg, front_data.dist_mm * MM_TO_IN, frontDistance.get_confidence()},
62 {left_sensor_cfg, left_data.dist_mm * MM_TO_IN, leftDistance.get_confidence()},
63 {right_sensor_cfg, right_data.dist_mm * MM_TO_IN, rightDistance.get_confidence()},
64 {back_sensor_cfg, back_data.dist_mm * MM_TO_IN, backDistance.get_confidence()}
65 };
66
67 // Helper to check validity (range and now Quadrant relevance)
68 auto is_valid = [&](int i) {
69 return (sensors[i].dist_in < MAX_SENSOR_RANGE &&
70 sensors[i].dist_in >= MIN_SENSOR_RANGE);
71 };
72
73 double norm_heading = std::fmod(heading_deg, 360.0);
74 if (norm_heading < 0) norm_heading += 360.0;
75 const double TOLERANCE = 40.0;
76
77 std::vector<double> x_cands;
78 std::vector<double> y_cands;
79
80 auto get_global_offsets = [&](const SensorConfig& cfg, double heading_rad) {
81 double cos_h = std::cos(heading_rad);
82 double sin_h = std::sin(heading_rad);
83 double global_offset_x = (cfg.forward_offset * sin_h) + (cfg.strafe_offset * cos_h);
84 double global_offset_y = (cfg.forward_offset * cos_h) - (cfg.strafe_offset * sin_h);
85 return std::make_pair(global_offset_x, global_offset_y);
86 };
87
88
89 if (norm_heading <= TOLERANCE || norm_heading >= 360.0 - TOLERANCE) {
90 double angle_off_rad = (norm_heading <= TOLERANCE) ?
91 lemlib::degToRad(norm_heading) : lemlib::degToRad(norm_heading - 360.0);
92 double heading_rad = angle_off_rad;
93 double perp_dist_0 = sensors[0].dist_in * std::cos(angle_off_rad);
94 double perp_dist_3 = sensors[3].dist_in * std::cos(angle_off_rad);
95 double perp_dist_1 = sensors[1].dist_in * std::cos(angle_off_rad);
96 double perp_dist_2 = sensors[2].dist_in * std::cos(angle_off_rad);
97
98 auto offset_0 = get_global_offsets(sensors[0].cfg, heading_rad);
99 auto offset_1 = get_global_offsets(sensors[1].cfg, heading_rad);
100 auto offset_2 = get_global_offsets(sensors[2].cfg, heading_rad);
101 auto offset_3 = get_global_offsets(sensors[3].cfg, heading_rad);
102
103 if (is_valid(0) && use_pos_y_wall) { y_cands.push_back(HALF_HEIGHT - perp_dist_0 - offset_0.second); }
104 if (is_valid(3) && !use_pos_y_wall) { y_cands.push_back(-HALF_HEIGHT + perp_dist_3 - offset_3.second); }
105 if (is_valid(1) && !use_pos_x_wall) { x_cands.push_back(-HALF_WIDTH + perp_dist_1 - offset_1.first); }
106 if (is_valid(2) && use_pos_x_wall) { x_cands.push_back(HALF_WIDTH - perp_dist_2 - offset_2.first); }
107 }
108 else if (std::fabs(norm_heading - 180.0) <= TOLERANCE) {
109 double angle_off_rad = lemlib::degToRad(norm_heading - 180.0);
110 double heading_rad = lemlib::degToRad(norm_heading);
111
112 double perp_dist_0 = sensors[0].dist_in * std::cos(angle_off_rad);
113 double perp_dist_3 = sensors[3].dist_in * std::cos(angle_off_rad);
114 double perp_dist_1 = sensors[1].dist_in * std::cos(angle_off_rad);
115 double perp_dist_2 = sensors[2].dist_in * std::cos(angle_off_rad);
116
117 auto offset_0 = get_global_offsets(sensors[0].cfg, heading_rad);
118 auto offset_1 = get_global_offsets(sensors[1].cfg, heading_rad);
119 auto offset_2 = get_global_offsets(sensors[2].cfg, heading_rad);
120 auto offset_3 = get_global_offsets(sensors[3].cfg, heading_rad);
121
122
123 if (is_valid(0) && !use_pos_y_wall) { y_cands.push_back(-HALF_HEIGHT + perp_dist_0 - offset_0.second); }
124 if (is_valid(3) && use_pos_y_wall) { y_cands.push_back(HALF_HEIGHT - perp_dist_3 - offset_3.second); }
125 if (is_valid(1) && use_pos_x_wall) { x_cands.push_back(HALF_WIDTH - perp_dist_1 - offset_1.first); }
126 if (is_valid(2) && !use_pos_x_wall) { x_cands.push_back(-HALF_WIDTH + perp_dist_2 - offset_2.first); }
127 }
128
129 else if (std::fabs(norm_heading - 90.0) <= TOLERANCE) {
130 double angle_off_rad = lemlib::degToRad(norm_heading - 90.0);
131 double heading_rad = lemlib::degToRad(norm_heading);
132
133 double perp_dist_0 = sensors[0].dist_in * std::cos(angle_off_rad);
134 double perp_dist_3 = sensors[3].dist_in * std::cos(angle_off_rad);
135 double perp_dist_1 = sensors[1].dist_in * std::cos(angle_off_rad);
136 double perp_dist_2 = sensors[2].dist_in * std::cos(angle_off_rad);
137
138 auto offset_0 = get_global_offsets(sensors[0].cfg, heading_rad);
139 auto offset_1 = get_global_offsets(sensors[1].cfg, heading_rad);
140 auto offset_2 = get_global_offsets(sensors[2].cfg, heading_rad);
141 auto offset_3 = get_global_offsets(sensors[3].cfg, heading_rad);
142
143
144 if (is_valid(0) && use_pos_x_wall) { x_cands.push_back(HALF_WIDTH - perp_dist_0 - offset_0.first); }
145 if (is_valid(3) && !use_pos_x_wall) { x_cands.push_back(-HALF_WIDTH + perp_dist_3 - offset_3.first); }
146 if (is_valid(1) && use_pos_y_wall) { y_cands.push_back(HALF_HEIGHT - perp_dist_1 - offset_1.second); }
147 if (is_valid(2) && !use_pos_y_wall) { y_cands.push_back(-HALF_HEIGHT + perp_dist_2 - offset_2.second); }
148 }
149
150 else if (std::fabs(norm_heading - 270.0) <= TOLERANCE) {
151 double angle_off_rad = lemlib::degToRad(norm_heading - 270.0);
152 double heading_rad = lemlib::degToRad(norm_heading);
153
154 double perp_dist_0 = sensors[0].dist_in * std::cos(angle_off_rad);
155 double perp_dist_3 = sensors[3].dist_in * std::cos(angle_off_rad);
156 double perp_dist_1 = sensors[1].dist_in * std::cos(angle_off_rad);
157 double perp_dist_2 = sensors[2].dist_in * std::cos(angle_off_rad);
158
159 auto offset_0 = get_global_offsets(sensors[0].cfg, heading_rad);
160 auto offset_1 = get_global_offsets(sensors[1].cfg, heading_rad);
161 auto offset_2 = get_global_offsets(sensors[2].cfg, heading_rad);
162 auto offset_3 = get_global_offsets(sensors[3].cfg, heading_rad);
163
164 if (is_valid(0) && !use_pos_x_wall) { x_cands.push_back(-HALF_WIDTH + perp_dist_0 - offset_0.first); }
165 if (is_valid(3) && use_pos_x_wall) { x_cands.push_back(HALF_WIDTH - perp_dist_3 - offset_3.first); }
166 if (is_valid(1) && !use_pos_y_wall) { y_cands.push_back(-HALF_HEIGHT + perp_dist_1 - offset_1.second); }
167 if (is_valid(2) && use_pos_y_wall) { y_cands.push_back(HALF_HEIGHT - perp_dist_2 - offset_2.second); }
168 }
169
170 if (!x_cands.empty()) {
171 est_x = std::accumulate(x_cands.begin(), x_cands.end(), 0.0) / x_cands.size();
172 using_odom_x = false;
173 }
174
175 if (!y_cands.empty()) {
176 est_y = std::accumulate(y_cands.begin(), y_cands.end(), 0.0) / y_cands.size();
177 using_odom_y = false;
178 }
179
180
181 distancePose pose;
182 pose.x = est_x;
183 pose.y = est_y;
184 pose.using_odom_x = using_odom_x;
185 pose.using_odom_y = using_odom_y;
186 return pose;
187}
188
189distancePose distanceReset(bool setPose = false) {
190 double heading_deg = chassis.getPose().theta;
191
192 const SensorReadings front_data = {(double)frontDistance.get_distance(), frontDistance.get_object_size(), frontDistance.get_confidence()};
193 const SensorReadings left_data = {(double)leftDistance.get_distance(), leftDistance.get_object_size(), leftDistance.get_confidence()};
194 const SensorReadings right_data = {(double)rightDistance.get_distance(), rightDistance.get_object_size(), rightDistance.get_confidence()};
195 const SensorReadings back_data = {(double)backDistance.get_distance(), backDistance.get_object_size(), backDistance.get_confidence()};
196
197 distancePose pose = calculateGlobalPosition(front_data, left_data, right_data, back_data, heading_deg);
198 if(setPose)
199 chassis.setPose(pose.x, pose.y, chassis.getPose().theta);
200 return pose;
201}
202
203distancePose distanceReset(bool left_use, bool right_use, bool front_use, bool back_use, bool setPose) {
204 double heading_deg = chassis.getPose().theta;
205
206 const int invalid_dist_mm = 10000;
207 const int invalid_confidence = 0;
208
209 SensorReadings front_data = front_use
210 ? SensorReadings{(double)frontDistance.get_distance(), frontDistance.get_object_size(), frontDistance.get_confidence()}
211 : SensorReadings{invalid_dist_mm, 0, invalid_confidence};
212
213 SensorReadings left_data = left_use
214 ? SensorReadings{(double)leftDistance.get_distance(), leftDistance.get_object_size(), leftDistance.get_confidence()}
215 : SensorReadings{invalid_dist_mm, 0, invalid_confidence};
216
217 SensorReadings right_data = right_use
218 ? SensorReadings{(double)rightDistance.get_distance(), rightDistance.get_object_size(), rightDistance.get_confidence()}
219 : SensorReadings{invalid_dist_mm, 0, invalid_confidence};
220
221 SensorReadings back_data = back_use
222 ? SensorReadings{(double)backDistance.get_distance() ,backDistance.get_object_size(), backDistance.get_confidence()}
223 : SensorReadings{invalid_dist_mm, 0, invalid_confidence};
224
225 distancePose pose = calculateGlobalPosition(front_data, left_data, right_data, back_data, heading_deg);
226 if(setPose)
227 chassis.setPose(pose.x, pose.y, chassis.getPose().theta);
228
229 return pose;
230}
const double MAX_SENSOR_RANGE
const double MM_TO_IN
const double FIELD_HEIGHT
bool controller_screen_avilable
const SensorConfig left_sensor_cfg
const SensorConfig back_sensor_cfg
distancePose distanceReset(bool setPose=false)
distancePose calculateGlobalPosition(const SensorReadings &front_data, const SensorReadings &left_data, const SensorReadings &right_data, const SensorReadings &back_data, double heading_deg)
const SensorConfig right_sensor_cfg
const double HALF_WIDTH
const SensorConfig front_sensor_cfg
const double FIELD_WIDTH
const double HALF_HEIGHT
const double MIN_SENSOR_RANGE
pros::Distance backDistance(11)
pros::Distance frontDistance(13)
pros::Distance leftDistance(12)
pros::Distance rightDistance(6)
lemlib::OdomSensors sensors
lemlib::Chassis chassis
double mounting_angle
double forward_offset