Tyler Chatow | 37ecdcd | 2019-01-26 20:18:42 -0800 | [diff] [blame] | 1 | #include "y2019/constants.h" |
| 2 | |
Tyler Chatow | bf0609c | 2021-07-31 16:13:27 -0700 | [diff] [blame] | 3 | #include <cinttypes> |
Tyler Chatow | 37ecdcd | 2019-01-26 20:18:42 -0800 | [diff] [blame] | 4 | #include <map> |
| 5 | |
| 6 | #if __has_feature(address_sanitizer) |
| 7 | #include "sanitizer/lsan_interface.h" |
| 8 | #endif |
| 9 | |
John Park | b859cf0 | 2019-11-20 19:52:05 -0800 | [diff] [blame] | 10 | #include "absl/base/call_once.h" |
Austin Schuh | 99f7c6a | 2024-06-25 22:07:44 -0700 | [diff] [blame] | 11 | #include "absl/log/check.h" |
| 12 | #include "absl/log/log.h" |
Philipp Schrader | 790cb54 | 2023-07-05 21:06:52 -0700 | [diff] [blame] | 13 | |
Brian Silverman | 1463c09 | 2020-10-30 17:28:24 -0700 | [diff] [blame] | 14 | #include "aos/network/team_number.h" |
| 15 | #include "aos/stl_mutex/stl_mutex.h" |
James Kuszmaul | ec635d2 | 2023-08-12 18:39:24 -0700 | [diff] [blame] | 16 | #include "frc971/zeroing/absolute_encoder.h" |
| 17 | #include "frc971/zeroing/pot_and_absolute_encoder.h" |
Theo Bafrali | 00e4227 | 2019-02-12 01:07:46 -0800 | [diff] [blame] | 18 | #include "y2019/control_loops/superstructure/elevator/integral_elevator_plant.h" |
| 19 | #include "y2019/control_loops/superstructure/intake/integral_intake_plant.h" |
| 20 | #include "y2019/control_loops/superstructure/stilts/integral_stilts_plant.h" |
| 21 | #include "y2019/control_loops/superstructure/wrist/integral_wrist_plant.h" |
James Kuszmaul | e2c71ea | 2019-03-04 08:14:21 -0800 | [diff] [blame] | 22 | #include "y2019/vision/constants.h" |
Tyler Chatow | 37ecdcd | 2019-01-26 20:18:42 -0800 | [diff] [blame] | 23 | |
Stephan Pleines | f63bde8 | 2024-01-13 15:59:33 -0800 | [diff] [blame] | 24 | namespace y2019::constants { |
Tyler Chatow | 37ecdcd | 2019-01-26 20:18:42 -0800 | [diff] [blame] | 25 | |
Theo Bafrali | 00e4227 | 2019-02-12 01:07:46 -0800 | [diff] [blame] | 26 | using ::frc971::zeroing::PotAndAbsoluteEncoderZeroingEstimator; |
| 27 | |
Tyler Chatow | 37ecdcd | 2019-01-26 20:18:42 -0800 | [diff] [blame] | 28 | const int Values::kZeroingSampleSize; |
James Kuszmaul | 09f564a | 2019-02-18 17:37:09 -0800 | [diff] [blame] | 29 | constexpr size_t Values::kNumCameras; |
Tyler Chatow | 37ecdcd | 2019-01-26 20:18:42 -0800 | [diff] [blame] | 30 | |
| 31 | namespace { |
| 32 | |
| 33 | const uint16_t kCompTeamNumber = 971; |
| 34 | const uint16_t kPracticeTeamNumber = 9971; |
Alex Perry | 5fb5ff2 | 2019-02-09 21:53:17 -0800 | [diff] [blame] | 35 | const uint16_t kCodingRobotTeamNumber = 7971; |
Tyler Chatow | 37ecdcd | 2019-01-26 20:18:42 -0800 | [diff] [blame] | 36 | |
Tyler Chatow | a109af6 | 2019-10-23 21:19:52 -0700 | [diff] [blame] | 37 | constexpr double FeetToMeters(double ft) { return 0.3048 * ft; } |
| 38 | constexpr double InchToMeters(double in) { return 0.0254 * in; } |
| 39 | constexpr double DegToRad(double deg) { return deg * M_PI / 180.0; } |
James Kuszmaul | 22c5ab3 | 2019-02-09 14:45:58 -0800 | [diff] [blame] | 40 | |
James Kuszmaul | e2c71ea | 2019-03-04 08:14:21 -0800 | [diff] [blame] | 41 | // Populates camera Pose information from the calibrated vision constants. |
| 42 | void FillCameraPoses( |
| 43 | uint32_t teensy_processor_id, |
| 44 | ::std::array<Values::CameraCalibration, Values::kNumCameras> *cameras) { |
| 45 | ::std::array<int, 5> camera_ids = |
| 46 | vision::CameraSerialNumbers(teensy_processor_id); |
| 47 | for (size_t ii = 0; ii < camera_ids.size(); ++ii) { |
| 48 | const vision::CameraCalibration *calibration = |
| 49 | vision::GetCamera(camera_ids[ii]); |
| 50 | if (calibration != nullptr) { |
| 51 | vision::CameraGeometry geometry = calibration->geometry; |
| 52 | *cameras->at(ii).pose.mutable_pos() << geometry.location[0], |
| 53 | geometry.location[1], geometry.location[2]; |
| 54 | cameras->at(ii).pose.set_theta(geometry.heading); |
| 55 | } |
| 56 | } |
| 57 | } |
| 58 | |
Tyler Chatow | 37ecdcd | 2019-01-26 20:18:42 -0800 | [diff] [blame] | 59 | const Values *DoGetValuesForTeam(uint16_t team) { |
| 60 | Values *const r = new Values(); |
Alex Perry | 5fb5ff2 | 2019-02-09 21:53:17 -0800 | [diff] [blame] | 61 | Values::PotAndAbsConstants *const elevator = &r->elevator; |
Theo Bafrali | 00e4227 | 2019-02-12 01:07:46 -0800 | [diff] [blame] | 62 | ::frc971::control_loops::StaticZeroingSingleDOFProfiledSubsystemParams< |
| 63 | ::frc971::zeroing::PotAndAbsoluteEncoderZeroingEstimator> |
| 64 | *const elevator_params = &(elevator->subsystem_params); |
Alex Perry | 5fb5ff2 | 2019-02-09 21:53:17 -0800 | [diff] [blame] | 65 | Values::PotAndAbsConstants *const stilts = &r->stilts; |
Theo Bafrali | 00e4227 | 2019-02-12 01:07:46 -0800 | [diff] [blame] | 66 | ::frc971::control_loops::StaticZeroingSingleDOFProfiledSubsystemParams< |
| 67 | ::frc971::zeroing::PotAndAbsoluteEncoderZeroingEstimator> |
| 68 | *const stilts_params = &(stilts->subsystem_params); |
Alex Perry | 5fb5ff2 | 2019-02-09 21:53:17 -0800 | [diff] [blame] | 69 | Values::PotAndAbsConstants *const wrist = &r->wrist; |
Theo Bafrali | 00e4227 | 2019-02-12 01:07:46 -0800 | [diff] [blame] | 70 | ::frc971::control_loops::StaticZeroingSingleDOFProfiledSubsystemParams< |
| 71 | ::frc971::zeroing::PotAndAbsoluteEncoderZeroingEstimator> |
| 72 | *const wrist_params = &(wrist->subsystem_params); |
| 73 | ::frc971::control_loops::StaticZeroingSingleDOFProfiledSubsystemParams< |
| 74 | ::frc971::zeroing::AbsoluteEncoderZeroingEstimator> *const intake = |
| 75 | &r->intake; |
Alex Perry | 5fb5ff2 | 2019-02-09 21:53:17 -0800 | [diff] [blame] | 76 | |
Theo Bafrali | 00e4227 | 2019-02-12 01:07:46 -0800 | [diff] [blame] | 77 | // Elevator constants. |
Austin Schuh | 7f87b47 | 2019-02-15 23:20:57 -0800 | [diff] [blame] | 78 | elevator_params->zeroing_voltage = 3.0; |
Theo Bafrali | 00e4227 | 2019-02-12 01:07:46 -0800 | [diff] [blame] | 79 | elevator_params->operating_voltage = 12.0; |
James Kuszmaul | 31c4535 | 2024-01-14 18:07:42 -0800 | [diff] [blame] | 80 | elevator_params->zeroing_profile_params = {{}, 0.1, 1.0}; |
| 81 | elevator_params->default_profile_params = {{}, 4.0, 13.0}; |
Theo Bafrali | 00e4227 | 2019-02-12 01:07:46 -0800 | [diff] [blame] | 82 | elevator_params->range = Values::kElevatorRange(); |
| 83 | elevator_params->make_integral_loop = |
| 84 | &control_loops::superstructure::elevator::MakeIntegralElevatorLoop; |
| 85 | elevator_params->zeroing_constants.average_filter_size = |
| 86 | Values::kZeroingSampleSize; |
| 87 | elevator_params->zeroing_constants.one_revolution_distance = |
Alex Perry | 5fb5ff2 | 2019-02-09 21:53:17 -0800 | [diff] [blame] | 88 | M_PI * 2.0 * constants::Values::kElevatorEncoderRatio(); |
Theo Bafrali | 00e4227 | 2019-02-12 01:07:46 -0800 | [diff] [blame] | 89 | elevator_params->zeroing_constants.zeroing_threshold = 0.005; |
| 90 | elevator_params->zeroing_constants.moving_buffer_size = 20; |
| 91 | elevator_params->zeroing_constants.allowable_encoder_error = 0.9; |
Alex Perry | 5fb5ff2 | 2019-02-09 21:53:17 -0800 | [diff] [blame] | 92 | |
Theo Bafrali | 00e4227 | 2019-02-12 01:07:46 -0800 | [diff] [blame] | 93 | // Wrist constants. |
| 94 | wrist_params->zeroing_voltage = 4.0; |
| 95 | wrist_params->operating_voltage = 12.0; |
James Kuszmaul | 31c4535 | 2024-01-14 18:07:42 -0800 | [diff] [blame] | 96 | wrist_params->zeroing_profile_params = {{}, 0.5, 2.0}; |
| 97 | wrist_params->default_profile_params = {{}, 10.0, 40.0}; |
Theo Bafrali | 00e4227 | 2019-02-12 01:07:46 -0800 | [diff] [blame] | 98 | wrist_params->range = Values::kWristRange(); |
| 99 | wrist_params->make_integral_loop = |
| 100 | &control_loops::superstructure::wrist::MakeIntegralWristLoop; |
| 101 | wrist_params->zeroing_constants.average_filter_size = |
| 102 | Values::kZeroingSampleSize; |
| 103 | wrist_params->zeroing_constants.one_revolution_distance = |
Alex Perry | 5fb5ff2 | 2019-02-09 21:53:17 -0800 | [diff] [blame] | 104 | M_PI * 2.0 * constants::Values::kWristEncoderRatio(); |
Theo Bafrali | 00e4227 | 2019-02-12 01:07:46 -0800 | [diff] [blame] | 105 | wrist_params->zeroing_constants.zeroing_threshold = 0.0005; |
| 106 | wrist_params->zeroing_constants.moving_buffer_size = 20; |
| 107 | wrist_params->zeroing_constants.allowable_encoder_error = 0.9; |
| 108 | |
| 109 | // Intake constants. |
Austin Schuh | 7f87b47 | 2019-02-15 23:20:57 -0800 | [diff] [blame] | 110 | intake->zeroing_voltage = 3.0; |
Theo Bafrali | 00e4227 | 2019-02-12 01:07:46 -0800 | [diff] [blame] | 111 | intake->operating_voltage = 12.0; |
James Kuszmaul | 31c4535 | 2024-01-14 18:07:42 -0800 | [diff] [blame] | 112 | intake->zeroing_profile_params = {{}, 0.5, 3.0}; |
| 113 | intake->default_profile_params = {{}, 6.0, 30.0}; |
Theo Bafrali | 00e4227 | 2019-02-12 01:07:46 -0800 | [diff] [blame] | 114 | intake->range = Values::kIntakeRange(); |
| 115 | intake->make_integral_loop = |
| 116 | control_loops::superstructure::intake::MakeIntegralIntakeLoop; |
| 117 | intake->zeroing_constants.average_filter_size = Values::kZeroingSampleSize; |
| 118 | intake->zeroing_constants.one_revolution_distance = |
| 119 | M_PI * 2.0 * constants::Values::kIntakeEncoderRatio(); |
| 120 | intake->zeroing_constants.zeroing_threshold = 0.0005; |
| 121 | intake->zeroing_constants.moving_buffer_size = 20; |
| 122 | intake->zeroing_constants.allowable_encoder_error = 0.9; |
Austin Schuh | c9c157a | 2019-02-19 13:36:22 -0800 | [diff] [blame] | 123 | intake->zeroing_constants.middle_position = Values::kIntakeRange().middle(); |
Theo Bafrali | 00e4227 | 2019-02-12 01:07:46 -0800 | [diff] [blame] | 124 | |
| 125 | // Stilts constants. |
Austin Schuh | 7f87b47 | 2019-02-15 23:20:57 -0800 | [diff] [blame] | 126 | stilts_params->zeroing_voltage = 3.0; |
Theo Bafrali | 00e4227 | 2019-02-12 01:07:46 -0800 | [diff] [blame] | 127 | stilts_params->operating_voltage = 12.0; |
James Kuszmaul | 31c4535 | 2024-01-14 18:07:42 -0800 | [diff] [blame] | 128 | stilts_params->zeroing_profile_params = {{}, 0.1, 0.5}; |
| 129 | stilts_params->default_profile_params = {{}, 0.15, 0.5}; |
Theo Bafrali | 00e4227 | 2019-02-12 01:07:46 -0800 | [diff] [blame] | 130 | stilts_params->range = Values::kStiltsRange(); |
| 131 | stilts_params->make_integral_loop = |
| 132 | &control_loops::superstructure::stilts::MakeIntegralStiltsLoop; |
| 133 | stilts_params->zeroing_constants.average_filter_size = |
| 134 | Values::kZeroingSampleSize; |
| 135 | stilts_params->zeroing_constants.one_revolution_distance = |
| 136 | M_PI * 2.0 * constants::Values::kStiltsEncoderRatio(); |
| 137 | stilts_params->zeroing_constants.zeroing_threshold = 0.0005; |
| 138 | stilts_params->zeroing_constants.moving_buffer_size = 20; |
| 139 | stilts_params->zeroing_constants.allowable_encoder_error = 0.9; |
Tyler Chatow | 37ecdcd | 2019-01-26 20:18:42 -0800 | [diff] [blame] | 140 | |
James Kuszmaul | 09f564a | 2019-02-18 17:37:09 -0800 | [diff] [blame] | 141 | r->camera_noise_parameters = {.max_viewable_distance = 10.0, |
James Kuszmaul | 074429e | 2019-03-23 16:01:49 -0700 | [diff] [blame] | 142 | .heading_noise = 0.1, |
| 143 | .nominal_distance_noise = 0.15, |
James Kuszmaul | 7f1a408 | 2019-04-14 10:50:44 -0700 | [diff] [blame] | 144 | .nominal_skew_noise = 0.75, |
James Kuszmaul | 09f564a | 2019-02-18 17:37:09 -0800 | [diff] [blame] | 145 | .nominal_height_noise = 0.01}; |
| 146 | |
James Kuszmaul | e2c71ea | 2019-03-04 08:14:21 -0800 | [diff] [blame] | 147 | // Deliberately make FOV a bit large so that we are overly conservative in |
| 148 | // our EKF. |
| 149 | for (auto &camera : r->cameras) { |
James Kuszmaul | 074429e | 2019-03-23 16:01:49 -0700 | [diff] [blame] | 150 | camera.fov = M_PI_2 * 1.5; |
James Kuszmaul | e2c71ea | 2019-03-04 08:14:21 -0800 | [diff] [blame] | 151 | } |
| 152 | |
Tyler Chatow | 37ecdcd | 2019-01-26 20:18:42 -0800 | [diff] [blame] | 153 | switch (team) { |
| 154 | // A set of constants for tests. |
| 155 | case 1: |
Theo Bafrali | 00e4227 | 2019-02-12 01:07:46 -0800 | [diff] [blame] | 156 | elevator_params->zeroing_constants.measured_absolute_position = 0.0; |
Alex Perry | 5fb5ff2 | 2019-02-09 21:53:17 -0800 | [diff] [blame] | 157 | elevator->potentiometer_offset = 0.0; |
| 158 | |
Theo Bafrali | 00e4227 | 2019-02-12 01:07:46 -0800 | [diff] [blame] | 159 | intake->zeroing_constants.measured_absolute_position = 0.0; |
Alex Perry | 5fb5ff2 | 2019-02-09 21:53:17 -0800 | [diff] [blame] | 160 | |
Theo Bafrali | 00e4227 | 2019-02-12 01:07:46 -0800 | [diff] [blame] | 161 | wrist_params->zeroing_constants.measured_absolute_position = 0.0; |
Alex Perry | 5fb5ff2 | 2019-02-09 21:53:17 -0800 | [diff] [blame] | 162 | wrist->potentiometer_offset = 0.0; |
Theo Bafrali | 00e4227 | 2019-02-12 01:07:46 -0800 | [diff] [blame] | 163 | |
| 164 | stilts_params->zeroing_constants.measured_absolute_position = 0.0; |
| 165 | stilts->potentiometer_offset = 0.0; |
James Kuszmaul | 09f564a | 2019-02-18 17:37:09 -0800 | [diff] [blame] | 166 | |
James Kuszmaul | e2c71ea | 2019-03-04 08:14:21 -0800 | [diff] [blame] | 167 | // For the simulation, just place cameras at the center of the robot with |
| 168 | // nominal angles (back/sides + 15 degree offset front cameras). |
James Kuszmaul | 09f564a | 2019-02-18 17:37:09 -0800 | [diff] [blame] | 169 | r->cameras[0].pose.set_theta(M_PI); |
| 170 | r->cameras[1].pose.set_theta(0.26); |
| 171 | r->cameras[2].pose.set_theta(-0.26); |
| 172 | r->cameras[3].pose.set_theta(M_PI_2); |
| 173 | r->cameras[4].pose.set_theta(-M_PI_2); |
Tyler Chatow | 37ecdcd | 2019-01-26 20:18:42 -0800 | [diff] [blame] | 174 | break; |
| 175 | |
| 176 | case kCompTeamNumber: |
Austin Schuh | 13d5830 | 2019-05-08 20:10:20 -0700 | [diff] [blame] | 177 | elevator_params->zeroing_constants.measured_absolute_position = 0.145498; |
Austin Schuh | 37c102e | 2019-03-17 18:13:50 -0700 | [diff] [blame] | 178 | elevator->potentiometer_offset = |
| 179 | -0.075017 + 0.015837 + 0.009793 - 0.012017 + 0.019915 + 0.010126 + |
Austin Schuh | 13d5830 | 2019-05-08 20:10:20 -0700 | [diff] [blame] | 180 | 0.005541 + 0.006088 - 0.039687 + 0.005843 + 0.009007 + 0.008604 - |
| 181 | 0.004621 + 0.003305; |
Alex Perry | 5fb5ff2 | 2019-02-09 21:53:17 -0800 | [diff] [blame] | 182 | |
Austin Schuh | 85d758b | 2019-06-29 17:35:26 -0700 | [diff] [blame] | 183 | intake->zeroing_constants.measured_absolute_position = 1.273143; |
Alex Perry | 5fb5ff2 | 2019-02-09 21:53:17 -0800 | [diff] [blame] | 184 | |
Austin Schuh | 85d758b | 2019-06-29 17:35:26 -0700 | [diff] [blame] | 185 | wrist_params->zeroing_constants.measured_absolute_position = 0.155868; |
Austin Schuh | 588e10b | 2021-06-20 14:52:33 -0700 | [diff] [blame] | 186 | wrist->potentiometer_offset = |
| 187 | -4.257454 - 0.058039 + 0.270233 - 0.661464 + 0.872911951453577; |
Theo Bafrali | 00e4227 | 2019-02-12 01:07:46 -0800 | [diff] [blame] | 188 | |
Austin Schuh | 37c102e | 2019-03-17 18:13:50 -0700 | [diff] [blame] | 189 | stilts_params->zeroing_constants.measured_absolute_position = 0.066843; |
| 190 | stilts->potentiometer_offset = -0.015760 + 0.011604 - 0.061213 + 0.006690; |
Austin Schuh | 48d3a96 | 2019-03-17 18:12:32 -0700 | [diff] [blame] | 191 | FillCameraPoses(vision::CompBotTeensyId(), &r->cameras); |
Tyler Chatow | 37ecdcd | 2019-01-26 20:18:42 -0800 | [diff] [blame] | 192 | break; |
| 193 | |
| 194 | case kPracticeTeamNumber: |
Tyler Chatow | a109af6 | 2019-10-23 21:19:52 -0700 | [diff] [blame] | 195 | elevator_params->zeroing_constants.measured_absolute_position = 0.131568; |
| 196 | elevator->potentiometer_offset = -0.022320 + 0.020567 - 0.022355 - |
| 197 | 0.006497 + 0.019690 + 0.009151 - |
| 198 | 0.007513 + 0.007311; |
Alex Perry | 5fb5ff2 | 2019-02-09 21:53:17 -0800 | [diff] [blame] | 199 | |
Tyler Chatow | a109af6 | 2019-10-23 21:19:52 -0700 | [diff] [blame] | 200 | intake->zeroing_constants.measured_absolute_position = |
| 201 | 1.928755 + 0.205352; |
Austin Schuh | ed7f863 | 2019-02-15 23:12:20 -0800 | [diff] [blame] | 202 | |
Tyler Chatow | a109af6 | 2019-10-23 21:19:52 -0700 | [diff] [blame] | 203 | wrist_params->zeroing_constants.measured_absolute_position = 0.180039; |
Sabina Davis | fe2e712 | 2019-03-08 20:45:54 -0800 | [diff] [blame] | 204 | wrist->potentiometer_offset = -4.200894 - 0.187134; |
Austin Schuh | ed7f863 | 2019-02-15 23:12:20 -0800 | [diff] [blame] | 205 | |
Tyler Chatow | a109af6 | 2019-10-23 21:19:52 -0700 | [diff] [blame] | 206 | stilts_params->zeroing_constants.measured_absolute_position = 0.050556; |
| 207 | stilts->potentiometer_offset = |
| 208 | -0.093820 + 0.0124 - 0.008334 + 0.004507 - 0.007973 + -0.001221; |
James Kuszmaul | fedc461 | 2019-03-10 11:24:51 -0700 | [diff] [blame] | 209 | |
| 210 | FillCameraPoses(vision::PracticeBotTeensyId(), &r->cameras); |
Alex Perry | 5fb5ff2 | 2019-02-09 21:53:17 -0800 | [diff] [blame] | 211 | break; |
| 212 | |
| 213 | case kCodingRobotTeamNumber: |
Theo Bafrali | 00e4227 | 2019-02-12 01:07:46 -0800 | [diff] [blame] | 214 | elevator_params->zeroing_constants.measured_absolute_position = 0.0; |
Alex Perry | 5fb5ff2 | 2019-02-09 21:53:17 -0800 | [diff] [blame] | 215 | elevator->potentiometer_offset = 0.0; |
| 216 | |
Theo Bafrali | 00e4227 | 2019-02-12 01:07:46 -0800 | [diff] [blame] | 217 | intake->zeroing_constants.measured_absolute_position = 0.0; |
Alex Perry | 5fb5ff2 | 2019-02-09 21:53:17 -0800 | [diff] [blame] | 218 | |
Theo Bafrali | 00e4227 | 2019-02-12 01:07:46 -0800 | [diff] [blame] | 219 | wrist_params->zeroing_constants.measured_absolute_position = 0.0; |
Alex Perry | 5fb5ff2 | 2019-02-09 21:53:17 -0800 | [diff] [blame] | 220 | wrist->potentiometer_offset = 0.0; |
Theo Bafrali | 00e4227 | 2019-02-12 01:07:46 -0800 | [diff] [blame] | 221 | |
| 222 | stilts_params->zeroing_constants.measured_absolute_position = 0.0; |
| 223 | stilts->potentiometer_offset = 0.0; |
James Kuszmaul | 81df16a | 2019-03-03 17:17:34 -0800 | [diff] [blame] | 224 | |
James Kuszmaul | e2c71ea | 2019-03-04 08:14:21 -0800 | [diff] [blame] | 225 | FillCameraPoses(vision::CodeBotTeensyId(), &r->cameras); |
| 226 | |
Tyler Chatow | 37ecdcd | 2019-01-26 20:18:42 -0800 | [diff] [blame] | 227 | break; |
| 228 | |
| 229 | default: |
Brian Silverman | f4d329c | 2021-11-04 19:32:10 -0700 | [diff] [blame] | 230 | LOG(FATAL) << "unknown team: " << team; |
Tyler Chatow | 37ecdcd | 2019-01-26 20:18:42 -0800 | [diff] [blame] | 231 | } |
| 232 | |
| 233 | return r; |
| 234 | } |
| 235 | |
Brian Silverman | 1463c09 | 2020-10-30 17:28:24 -0700 | [diff] [blame] | 236 | void DoGetValues(const Values **result) { |
Tyler Chatow | 37ecdcd | 2019-01-26 20:18:42 -0800 | [diff] [blame] | 237 | uint16_t team = ::aos::network::GetTeamNumber(); |
Brian Silverman | f4d329c | 2021-11-04 19:32:10 -0700 | [diff] [blame] | 238 | LOG(INFO) << "creating a Constants for team: " << team; |
John Park | b859cf0 | 2019-11-20 19:52:05 -0800 | [diff] [blame] | 239 | *result = DoGetValuesForTeam(team); |
Tyler Chatow | 37ecdcd | 2019-01-26 20:18:42 -0800 | [diff] [blame] | 240 | } |
| 241 | |
| 242 | } // namespace |
| 243 | |
| 244 | const Values &GetValues() { |
John Park | 9372a68 | 2019-11-27 18:07:48 -0800 | [diff] [blame] | 245 | static absl::once_flag once; |
Brian Silverman | 1463c09 | 2020-10-30 17:28:24 -0700 | [diff] [blame] | 246 | static const Values *result; |
John Park | 9372a68 | 2019-11-27 18:07:48 -0800 | [diff] [blame] | 247 | absl::call_once(once, DoGetValues, &result); |
John Park | b859cf0 | 2019-11-20 19:52:05 -0800 | [diff] [blame] | 248 | return *result; |
Tyler Chatow | 37ecdcd | 2019-01-26 20:18:42 -0800 | [diff] [blame] | 249 | } |
| 250 | |
| 251 | const Values &GetValuesForTeam(uint16_t team_number) { |
Brian Silverman | 1463c09 | 2020-10-30 17:28:24 -0700 | [diff] [blame] | 252 | static aos::stl_mutex mutex; |
| 253 | std::unique_lock<aos::stl_mutex> locker(mutex); |
Tyler Chatow | 37ecdcd | 2019-01-26 20:18:42 -0800 | [diff] [blame] | 254 | |
| 255 | // IMPORTANT: This declaration has to stay after the mutex is locked to avoid |
| 256 | // race conditions. |
| 257 | static ::std::map<uint16_t, const Values *> values; |
| 258 | |
| 259 | if (values.count(team_number) == 0) { |
| 260 | values[team_number] = DoGetValuesForTeam(team_number); |
| 261 | #if __has_feature(address_sanitizer) |
| 262 | __lsan_ignore_object(values[team_number]); |
| 263 | #endif |
| 264 | } |
| 265 | return *values[team_number]; |
| 266 | } |
| 267 | |
James Kuszmaul | 22c5ab3 | 2019-02-09 14:45:58 -0800 | [diff] [blame] | 268 | constexpr size_t Field::kNumTargets; |
| 269 | constexpr size_t Field::kNumObstacles; |
| 270 | |
| 271 | Field::Field() { |
| 272 | // TODO(james): These values need to re-verified. I got them by skimming the |
| 273 | // manual and they all seem to be pretty much correct. |
| 274 | // |
| 275 | // Note: Per //frc971/control_loops/pose.h, coordinate system is: |
| 276 | // -In meters |
| 277 | // -Origin at center of our driver's station wall |
| 278 | // -Positive X-axis pointing straight out from driver's station |
| 279 | // -Positive Y-axis pointing straight left from the driver's perspective |
| 280 | // -Positive Z-axis is straight up. |
| 281 | // -The angle of the target is such that the angle is the angle you would |
| 282 | // need to be facing to see it straight-on. I.e., if the target angle is |
| 283 | // pi / 2.0, then you would be able to see it face on by facing straight |
| 284 | // left from the driver's point of view (if you were standing in the right |
| 285 | // spot). |
| 286 | constexpr double kCenterFieldX = FeetToMeters(27.0) + InchToMeters(1.125); |
| 287 | |
Tyler Chatow | a109af6 | 2019-10-23 21:19:52 -0700 | [diff] [blame] | 288 | constexpr double kFarSideCargoBayX = kCenterFieldX - InchToMeters(20.875); |
James Kuszmaul | 22c5ab3 | 2019-02-09 14:45:58 -0800 | [diff] [blame] | 289 | constexpr double kMidSideCargoBayX = kFarSideCargoBayX - InchToMeters(21.75); |
| 290 | constexpr double kNearSideCargoBayX = kMidSideCargoBayX - InchToMeters(21.75); |
| 291 | constexpr double kSideCargoBayY = InchToMeters(24 + 3 + 0.875); |
| 292 | constexpr double kSideCargoBayTheta = -M_PI_2; |
| 293 | |
| 294 | constexpr double kFaceCargoBayX = |
| 295 | kCenterFieldX - InchToMeters(7 * 12 + 11.75 + 9); |
| 296 | constexpr double kFaceCargoBayY = InchToMeters(10.875); |
| 297 | constexpr double kFaceCargoBayTheta = 0.0; |
| 298 | |
| 299 | constexpr double kRocketX = kCenterFieldX - FeetToMeters(8); |
| 300 | constexpr double kRocketY = InchToMeters((26 * 12 + 10.5) / 2.0); |
| 301 | |
| 302 | constexpr double kRocketPortX = kRocketX; |
| 303 | constexpr double kRocketPortY = kRocketY - 0.70; |
| 304 | constexpr double kRocketPortTheta = M_PI_2; |
| 305 | |
| 306 | // Half of portal + guess at width * cos(61.5 deg) |
| 307 | const double kRocketHatchXOffset = InchToMeters(14.634); |
| 308 | const double kRocketHatchY = kRocketPortY + InchToMeters(9.326); |
| 309 | const double kRocketNearX = kRocketX - kRocketHatchXOffset; |
| 310 | const double kRocketFarX = kRocketX + kRocketHatchXOffset; |
| 311 | constexpr double kRocketNearTheta = DegToRad(28.5); |
| 312 | constexpr double kRocketFarTheta = M_PI - kRocketNearTheta; |
| 313 | |
| 314 | constexpr double kHpSlotY = InchToMeters((26 * 12 + 10.5) / 2.0 - 25.9); |
| 315 | constexpr double kHpSlotTheta = M_PI; |
| 316 | |
James Kuszmaul | e093f51 | 2019-03-20 06:14:05 -0700 | [diff] [blame] | 317 | constexpr double kNormalZ = 0.80; |
| 318 | constexpr double kPortZ = 1.00; |
James Kuszmaul | 22c5ab3 | 2019-02-09 14:45:58 -0800 | [diff] [blame] | 319 | |
James Kuszmaul | e093f51 | 2019-03-20 06:14:05 -0700 | [diff] [blame] | 320 | constexpr double kDiscRadius = InchToMeters(19.0 / 2.0); |
James Kuszmaul | 22c5ab3 | 2019-02-09 14:45:58 -0800 | [diff] [blame] | 321 | |
James Kuszmaul | e093f51 | 2019-03-20 06:14:05 -0700 | [diff] [blame] | 322 | constexpr Target::GoalType kBothGoal = Target::GoalType::kBoth; |
| 323 | constexpr Target::GoalType kBallGoal = Target::GoalType::kBalls; |
| 324 | constexpr Target::GoalType kDiscGoal = Target::GoalType::kHatches; |
| 325 | constexpr Target::GoalType kNoneGoal = Target::GoalType::kNone; |
James Kuszmaul | 7d1ef44 | 2019-03-23 20:20:50 -0700 | [diff] [blame] | 326 | using TargetType = Target::TargetType; |
James Kuszmaul | 22c5ab3 | 2019-02-09 14:45:58 -0800 | [diff] [blame] | 327 | |
James Kuszmaul | e093f51 | 2019-03-20 06:14:05 -0700 | [diff] [blame] | 328 | const Target far_side_cargo_bay( |
| 329 | {{kFarSideCargoBayX, kSideCargoBayY, kNormalZ}, kSideCargoBayTheta}, |
James Kuszmaul | 7d1ef44 | 2019-03-23 20:20:50 -0700 | [diff] [blame] | 330 | kDiscRadius, TargetType::kFarSideCargoBay, kBothGoal); |
James Kuszmaul | e093f51 | 2019-03-20 06:14:05 -0700 | [diff] [blame] | 331 | const Target mid_side_cargo_bay( |
| 332 | {{kMidSideCargoBayX, kSideCargoBayY, kNormalZ}, kSideCargoBayTheta}, |
James Kuszmaul | 7d1ef44 | 2019-03-23 20:20:50 -0700 | [diff] [blame] | 333 | kDiscRadius, TargetType::kMidSideCargoBay, kBothGoal); |
James Kuszmaul | e093f51 | 2019-03-20 06:14:05 -0700 | [diff] [blame] | 334 | const Target near_side_cargo_bay( |
| 335 | {{kNearSideCargoBayX, kSideCargoBayY, kNormalZ}, kSideCargoBayTheta}, |
James Kuszmaul | 7d1ef44 | 2019-03-23 20:20:50 -0700 | [diff] [blame] | 336 | kDiscRadius, TargetType::kNearSideCargoBay, kBothGoal); |
James Kuszmaul | 22c5ab3 | 2019-02-09 14:45:58 -0800 | [diff] [blame] | 337 | |
James Kuszmaul | e093f51 | 2019-03-20 06:14:05 -0700 | [diff] [blame] | 338 | const Target face_cargo_bay( |
| 339 | {{kFaceCargoBayX, kFaceCargoBayY, kNormalZ}, kFaceCargoBayTheta}, |
James Kuszmaul | 7d1ef44 | 2019-03-23 20:20:50 -0700 | [diff] [blame] | 340 | kDiscRadius, TargetType::kFaceCargoBay, kBothGoal); |
James Kuszmaul | 22c5ab3 | 2019-02-09 14:45:58 -0800 | [diff] [blame] | 341 | |
James Kuszmaul | 7d1ef44 | 2019-03-23 20:20:50 -0700 | [diff] [blame] | 342 | // The rocket port, since it is only for balls, has no meaningful radius |
| 343 | // to work with (and is over-ridden with zero in target_selector). |
James Kuszmaul | e093f51 | 2019-03-20 06:14:05 -0700 | [diff] [blame] | 344 | const Target rocket_port( |
James Kuszmaul | 7d1ef44 | 2019-03-23 20:20:50 -0700 | [diff] [blame] | 345 | {{kRocketPortX, kRocketPortY, kPortZ}, kRocketPortTheta}, 0.0, |
| 346 | TargetType::kRocketPortal, kBallGoal); |
James Kuszmaul | 22c5ab3 | 2019-02-09 14:45:58 -0800 | [diff] [blame] | 347 | |
James Kuszmaul | e093f51 | 2019-03-20 06:14:05 -0700 | [diff] [blame] | 348 | const Target rocket_near( |
| 349 | {{kRocketNearX, kRocketHatchY, kNormalZ}, kRocketNearTheta}, kDiscRadius, |
James Kuszmaul | 7d1ef44 | 2019-03-23 20:20:50 -0700 | [diff] [blame] | 350 | TargetType::kNearRocket, kDiscGoal); |
James Kuszmaul | e093f51 | 2019-03-20 06:14:05 -0700 | [diff] [blame] | 351 | const Target rocket_far( |
| 352 | {{kRocketFarX, kRocketHatchY, kNormalZ}, kRocketFarTheta}, kDiscRadius, |
James Kuszmaul | 7d1ef44 | 2019-03-23 20:20:50 -0700 | [diff] [blame] | 353 | TargetType::kFarRocket, kDiscGoal); |
James Kuszmaul | e093f51 | 2019-03-20 06:14:05 -0700 | [diff] [blame] | 354 | |
James Kuszmaul | 074429e | 2019-03-23 16:01:49 -0700 | [diff] [blame] | 355 | const Target hp_slot({{0.0, kHpSlotY, kNormalZ}, kHpSlotTheta}, 0.00, |
James Kuszmaul | 7d1ef44 | 2019-03-23 20:20:50 -0700 | [diff] [blame] | 356 | TargetType::kHPSlot, kBothGoal); |
James Kuszmaul | e093f51 | 2019-03-20 06:14:05 -0700 | [diff] [blame] | 357 | |
| 358 | const ::std::array<Target, 8> quarter_field_targets{ |
James Kuszmaul | 22c5ab3 | 2019-02-09 14:45:58 -0800 | [diff] [blame] | 359 | {far_side_cargo_bay, mid_side_cargo_bay, near_side_cargo_bay, |
| 360 | face_cargo_bay, rocket_port, rocket_near, rocket_far, hp_slot}}; |
| 361 | |
| 362 | // Mirror across center field mid-line (short field axis): |
James Kuszmaul | e093f51 | 2019-03-20 06:14:05 -0700 | [diff] [blame] | 363 | ::std::array<Target, 16> half_field_targets; |
James Kuszmaul | 22c5ab3 | 2019-02-09 14:45:58 -0800 | [diff] [blame] | 364 | ::std::copy(quarter_field_targets.begin(), quarter_field_targets.end(), |
| 365 | half_field_targets.begin()); |
| 366 | for (int ii = 0; ii < 8; ++ii) { |
| 367 | const int jj = ii + 8; |
| 368 | half_field_targets[jj] = quarter_field_targets[ii]; |
James Kuszmaul | e093f51 | 2019-03-20 06:14:05 -0700 | [diff] [blame] | 369 | half_field_targets[jj].mutable_pose()->mutable_pos()->x() = |
| 370 | 2.0 * kCenterFieldX - half_field_targets[jj].pose().rel_pos().x(); |
| 371 | half_field_targets[jj].mutable_pose()->set_theta(aos::math::NormalizeAngle( |
| 372 | M_PI - half_field_targets[jj].pose().rel_theta())); |
| 373 | // Targets on the opposite side of the field can't be driven to. |
| 374 | half_field_targets[jj].set_goal_type(kNoneGoal); |
James Kuszmaul | 22c5ab3 | 2019-02-09 14:45:58 -0800 | [diff] [blame] | 375 | } |
| 376 | |
James Kuszmaul | 22c5ab3 | 2019-02-09 14:45:58 -0800 | [diff] [blame] | 377 | // Mirror across x-axis (long field axis): |
| 378 | ::std::copy(half_field_targets.begin(), half_field_targets.end(), |
James Kuszmaul | e093f51 | 2019-03-20 06:14:05 -0700 | [diff] [blame] | 379 | targets_.begin()); |
James Kuszmaul | 22c5ab3 | 2019-02-09 14:45:58 -0800 | [diff] [blame] | 380 | for (int ii = 0; ii < 16; ++ii) { |
| 381 | const int jj = ii + 16; |
James Kuszmaul | e093f51 | 2019-03-20 06:14:05 -0700 | [diff] [blame] | 382 | targets_[jj] = half_field_targets[ii]; |
| 383 | targets_[jj].mutable_pose()->mutable_pos()->y() *= -1; |
| 384 | targets_[jj].mutable_pose()->set_theta(-targets_[jj].pose().rel_theta()); |
James Kuszmaul | 22c5ab3 | 2019-02-09 14:45:58 -0800 | [diff] [blame] | 385 | } |
| 386 | |
| 387 | // Define rocket obstacles as just being a single line that should block any |
| 388 | // cameras trying to see through the rocket up and down the field. |
| 389 | // This line is parallel to the driver's station wall and extends behind |
| 390 | // the portal. |
| 391 | Obstacle rocket_obstacle({{kRocketPortX, kRocketY, 0.0}, 0.0}, |
| 392 | {{kRocketPortX, kRocketPortY + 0.01, 0.0}, 0.0}); |
| 393 | // First, we mirror rocket obstacles across x-axis: |
| 394 | Obstacle rocket_obstacle2({{kRocketPortX, -kRocketY, 0.0}, 0.0}, |
| 395 | {{kRocketPortX, -kRocketPortY - 0.01, 0.0}, 0.0}); |
| 396 | |
| 397 | // Define an obstacle for the Hab that extends striaght out a few feet from |
| 398 | // the driver's station wall. |
| 399 | // TODO(james): Does this actually block our view? |
| 400 | const double kHabL3X = FeetToMeters(4.0); |
| 401 | Obstacle hab_obstacle({}, {{kHabL3X, 0.0, 0.0}, 0.0}); |
| 402 | ::std::array<Obstacle, 3> half_obstacles{ |
| 403 | {rocket_obstacle, rocket_obstacle2, hab_obstacle}}; |
| 404 | ::std::copy(half_obstacles.begin(), half_obstacles.end(), obstacles_.begin()); |
| 405 | |
| 406 | // Next, we mirror across the mid-line (short axis) to duplicate the |
| 407 | // rockets and hab to opposite side of the field. |
| 408 | for (int ii = 0; ii < 3; ++ii) { |
| 409 | const int jj = ii + 3; |
| 410 | obstacles_[jj] = half_obstacles[ii]; |
| 411 | obstacles_[jj].mutable_pose1()->mutable_pos()->x() = |
| 412 | 2.0 * kCenterFieldX - obstacles_[jj].mutable_pose1()->rel_pos().x(); |
| 413 | obstacles_[jj].mutable_pose2()->mutable_pos()->x() = |
| 414 | 2.0 * kCenterFieldX - obstacles_[jj].mutable_pose2()->rel_pos().x(); |
| 415 | } |
| 416 | |
| 417 | // Finally, define a rectangular cargo ship. |
| 418 | const double kCargoCornerX = kFaceCargoBayX + 0.1; |
| 419 | const double kCargoCornerY = kSideCargoBayY - 0.1; |
| 420 | ::std::array<Pose, 4> cargo_corners{ |
| 421 | {{{kCargoCornerX, kCargoCornerY, 0.0}, 0.0}, |
| 422 | {{kCargoCornerX, -kCargoCornerY, 0.0}, 0.0}, |
| 423 | {{2.0 * kCenterFieldX - kCargoCornerX, -kCargoCornerY, 0.0}, 0.0}, |
| 424 | {{2.0 * kCenterFieldX - kCargoCornerX, kCargoCornerY, 0.0}, 0.0}}}; |
| 425 | for (int ii = 6; ii < 10; ++ii) { |
| 426 | obstacles_[ii] = Obstacle(cargo_corners[ii % cargo_corners.size()], |
| 427 | cargo_corners[(ii + 1) % cargo_corners.size()]); |
| 428 | } |
| 429 | } |
| 430 | |
Stephan Pleines | f63bde8 | 2024-01-13 15:59:33 -0800 | [diff] [blame] | 431 | } // namespace y2019::constants |