2025-Robot
Robot code for 2025 FRC season by Argos, FRC team #1756
Loading...
Searching...
No Matches
LimelightHelpers.h
Go to the documentation of this file.
1
4
5#pragma once
6
11
12#ifndef _WIN32
13#include <arpa/inet.h>
14#include <netinet/in.h>
15#include <sys/socket.h>
16#include <unistd.h>
17
18#endif
19
20// #include <curl/curl.h>
21#include <fcntl.h>
22#include <frc/geometry/Pose2d.h>
23#include <frc/geometry/Pose3d.h>
24#include <frc/geometry/Rotation2d.h>
25#include <frc/geometry/Rotation3d.h>
26#include <frc/geometry/Translation2d.h>
27#include <frc/geometry/Translation3d.h>
28#include <wpinet/PortForwarder.h>
29
30#include <chrono>
31#include <cstring>
32#include <iostream>
33#include <memory>
34#include <numbers>
35#include <string>
36#include <vector>
37
38#include "networktables/NetworkTable.h"
39#include "networktables/NetworkTableEntry.h"
40#include "networktables/NetworkTableInstance.h"
41#include "networktables/NetworkTableValue.h"
42#include "networktables/DoubleArrayTopic.h"
43#include "wpi/json.h"
44
50 inline std::string sanitizeName(const std::string& name) {
51 if (name == "") {
52 return "limelight";
53 }
54 return name;
55 }
56
63 inline frc::Pose3d toPose3D(const std::vector<double>& inData) {
64 if (inData.size() < 6) {
65 return frc::Pose3d();
66 }
67 return frc::Pose3d(
68 frc::Translation3d(
69 units::length::meter_t(inData[0]), units::length::meter_t(inData[1]), units::length::meter_t(inData[2])),
70 frc::Rotation3d(units::angle::radian_t(inData[3] * (std::numbers::pi / 180.0)),
71 units::angle::radian_t(inData[4] * (std::numbers::pi / 180.0)),
72 units::angle::radian_t(inData[5] * (std::numbers::pi / 180.0))));
73 }
74
82 inline frc::Pose2d toPose2D(const std::vector<double>& inData) {
83 if (inData.size() < 6) {
84 return frc::Pose2d();
85 }
86 return frc::Pose2d(frc::Translation2d(units::length::meter_t(inData[0]), units::length::meter_t(inData[1])),
87 frc::Rotation2d(units::angle::radian_t(inData[5] * (std::numbers::pi / 180.0))));
88 }
89
97 inline std::array<double, 6> pose3dToArray(const frc::Pose3d& pose) {
98 std::array<double, 6> result;
99 result[0] = pose.Translation().X().value();
100 result[1] = pose.Translation().Y().value();
101 result[2] = pose.Translation().Z().value();
102 result[3] = pose.Rotation().X().value() * (180.0 / std::numbers::pi);
103 result[4] = pose.Rotation().Y().value() * (180.0 / std::numbers::pi);
104 result[5] = pose.Rotation().Z().value() * (180.0 / std::numbers::pi);
105 return result;
106 }
107
116 inline std::array<double, 6> pose2dToArray(const frc::Pose2d& pose) {
117 std::array<double, 6> result;
118 result[0] = pose.Translation().X().value();
119 result[1] = pose.Translation().Y().value();
120 result[2] = 0;
121 result[3] = 0;
122 result[4] = 0;
123 result[5] = pose.Rotation().Degrees().value();
124 return result;
125 }
126
127 inline std::shared_ptr<nt::NetworkTable> getLimelightNTTable(const std::string& tableName) {
128 return nt::NetworkTableInstance::GetDefault().GetTable(sanitizeName(tableName));
129 }
130
131 inline void Flush() {
132 nt::NetworkTableInstance::GetDefault().Flush();
133 }
134
135 inline nt::NetworkTableEntry getLimelightNTTableEntry(const std::string& tableName, const std::string& entryName) {
136 return getLimelightNTTable(tableName)->GetEntry(entryName);
137 }
138
139 inline std::unordered_map<std::string, nt::DoubleArrayEntry> doubleArrayEntries;
140
141 inline nt::DoubleArrayEntry& getLimelightDoubleArrayEntry(const std::string& tableName,
142 const std::string& entryName) {
143 const std::string& key = tableName + "/" + entryName;
144 auto it = doubleArrayEntries.find(key);
145 if (it == doubleArrayEntries.end()) {
146 std::shared_ptr<nt::NetworkTable> table = getLimelightNTTable(tableName);
147 nt::DoubleArrayTopic daTopic = table->GetDoubleArrayTopic(entryName);
148 nt::DoubleArrayEntry entry = daTopic.GetEntry(std::span<double>{});
149 doubleArrayEntries.emplace(key, std::move(entry));
150 return doubleArrayEntries[key];
151 }
152 return it->second;
153 }
154
155 inline double getLimelightNTDouble(const std::string& tableName, const std::string& entryName) {
156 return getLimelightNTTableEntry(tableName, entryName).GetDouble(0.0);
157 }
158
159 inline std::vector<double> getLimelightNTDoubleArray(const std::string& tableName, const std::string& entryName) {
160 return getLimelightNTTableEntry(tableName, entryName).GetDoubleArray(std::span<double>{});
161 }
162
163 inline std::string getLimelightNTString(const std::string& tableName, const std::string& entryName) {
164 return getLimelightNTTableEntry(tableName, entryName).GetString("");
165 }
166
167 inline std::vector<std::string> getLimelightNTStringArray(const std::string& tableName,
168 const std::string& entryName) {
169 return getLimelightNTTableEntry(tableName, entryName).GetStringArray(std::span<std::string>{});
170 }
171
172 inline void setLimelightNTDouble(const std::string& tableName, const std::string entryName, double val) {
173 getLimelightNTTableEntry(tableName, entryName).SetDouble(val);
174 }
175
176 inline void setLimelightNTDoubleArray(const std::string& tableName,
177 const std::string& entryName,
178 const std::span<const double>& vals) {
179 getLimelightNTTableEntry(tableName, entryName).SetDoubleArray(vals);
180 }
181
187 inline bool getTV(const std::string& limelightName = "") {
188 return getLimelightNTDouble(limelightName, "tv") == 1.0;
189 }
190
196 inline double getTX(const std::string& limelightName = "") {
197 return getLimelightNTDouble(limelightName, "tx");
198 }
199
205 inline double getTY(const std::string& limelightName = "") {
206 return getLimelightNTDouble(limelightName, "ty");
207 }
208
214 inline double getTXNC(const std::string& limelightName) {
215 return getLimelightNTDouble(limelightName, "txnc");
216 }
217
223 inline double getTYNC(const std::string& limelightName) {
224 return getLimelightNTDouble(limelightName, "tync");
225 }
226
233 inline double getTA(const std::string& limelightName = "") {
234 return getLimelightNTDouble(limelightName, "ta");
235 }
236
243 inline std::vector<double> getT2DArray(const std::string& limelightName) {
244 return getLimelightNTDoubleArray(limelightName, "t2d");
245 }
246
252 inline int getTargetCount(const std::string& limelightName) {
253 std::vector<double> t2d = getT2DArray(limelightName);
254 if (t2d.size() == 17) {
255 return (int)t2d[1];
256 }
257 return 0;
258 }
259
265 inline int getClassifierClassIndex(const std::string& limelightName) {
266 std::vector<double> t2d = getT2DArray(limelightName);
267 if (t2d.size() == 17) {
268 return (int)t2d[10];
269 }
270 return 0;
271 }
272
278 inline int getDetectorClassIndex(const std::string& limelightName) {
279 std::vector<double> t2d = getT2DArray(limelightName);
280 if (t2d.size() == 17) {
281 return (int)t2d[11];
282 }
283 return 0;
284 }
285
291 inline const std::string getClassifierClass(const std::string& limelightName) {
292 return getLimelightNTString(limelightName, "tcclass");
293 }
294
300 inline const std::string getDetectorClass(const std::string& limelightName) {
301 return getLimelightNTString(limelightName, "tdclass");
302 }
303
310 inline double getLatency_Pipeline(const std::string& limelightName = "") {
311 return getLimelightNTDouble(limelightName, "tl");
312 }
313
319 inline double getLatency_Capture(const std::string& limelightName = "") {
320 return getLimelightNTDouble(limelightName, "cl");
321 }
327 inline double getCurrentPipelineIndex(const std::string& limelightName) {
328 return getLimelightNTDouble(limelightName, "getpipe");
329 }
330
336 inline const std::string getCurrentPipelineType(const std::string& limelightName) {
337 return getLimelightNTString(limelightName, "getpipetype");
338 }
339
345 inline std::string getJSONDump(const std::string& limelightName = "") {
346 return getLimelightNTString(limelightName, "json");
347 }
348
349 inline std::vector<double> getBotpose(const std::string& limelightName = "") {
350 return getLimelightNTDoubleArray(limelightName, "botpose");
351 }
352
353 inline std::vector<double> getBotpose_wpiRed(const std::string& limelightName = "") {
354 return getLimelightNTDoubleArray(limelightName, "botpose_wpired");
355 }
356
357 inline std::vector<double> getBotpose_wpiBlue(const std::string& limelightName = "") {
358 return getLimelightNTDoubleArray(limelightName, "botpose_wpiblue");
359 }
360
361 inline std::vector<double> getBotpose_TargetSpace(const std::string& limelightName = "") {
362 return getLimelightNTDoubleArray(limelightName, "botpose_targetspace");
363 }
364
365 inline std::vector<double> getCameraPose_TargetSpace(const std::string& limelightName = "") {
366 return getLimelightNTDoubleArray(limelightName, "camerapose_targetspace");
367 }
368
369 inline std::vector<double> getCameraPose_RobotSpace(const std::string& limelightName = "") {
370 return getLimelightNTDoubleArray(limelightName, "camerapose_robotspace");
371 }
372
373 inline std::vector<double> getTargetPose_CameraSpace(const std::string& limelightName = "") {
374 return getLimelightNTDoubleArray(limelightName, "targetpose_cameraspace");
375 }
376
377 inline std::vector<double> getTargetPose_RobotSpace(const std::string& limelightName = "") {
378 return getLimelightNTDoubleArray(limelightName, "targetpose_robotspace");
379 }
380
381 inline std::vector<double> getTargetColor(const std::string& limelightName = "") {
382 return getLimelightNTDoubleArray(limelightName, "tc");
383 }
384
385 inline double getFiducialID(const std::string& limelightName = "") {
386 return getLimelightNTDouble(limelightName, "tid");
387 }
388
389 inline std::string getNeuralClassID(const std::string& limelightName = "") {
390 return getLimelightNTString(limelightName, "tclass");
391 }
392
393 inline std::vector<std::string> getRawBarcodeData(const std::string& limelightName = "") {
394 return getLimelightNTStringArray(limelightName, "rawbarcodes");
395 }
396
397 inline void setPipelineIndex(const std::string& limelightName, int index) {
398 setLimelightNTDouble(limelightName, "pipeline", index);
399 }
400
401 inline void setPriorityTagID(const std::string& limelightName, int ID) {
402 setLimelightNTDouble(limelightName, "priorityid", ID);
403 }
404
405 inline void setLEDMode_PipelineControl(const std::string& limelightName = "") {
406 setLimelightNTDouble(limelightName, "ledMode", 0);
407 }
408
409 inline void setLEDMode_ForceOff(const std::string& limelightName = "") {
410 setLimelightNTDouble(limelightName, "ledMode", 1);
411 }
412
413 inline void setLEDMode_ForceBlink(const std::string& limelightName = "") {
414 setLimelightNTDouble(limelightName, "ledMode", 2);
415 }
416
417 inline void setLEDMode_ForceOn(const std::string& limelightName = "") {
418 setLimelightNTDouble(limelightName, "ledMode", 3);
419 }
420
421 inline void setStreamMode_Standard(const std::string& limelightName = "") {
422 setLimelightNTDouble(limelightName, "stream", 0);
423 }
424
425 inline void setStreamMode_PiPMain(const std::string& limelightName = "") {
426 setLimelightNTDouble(limelightName, "stream", 1);
427 }
428
429 inline void setStreamMode_PiPSecondary(const std::string& limelightName = "") {
430 setLimelightNTDouble(limelightName, "stream", 2);
431 }
432
441 inline void setCropWindow(
442 const std::string& limelightName, double cropXMin, double cropXMax, double cropYMin, double cropYMax) {
443 double cropWindow[4]{cropXMin, cropXMax, cropYMin, cropYMax};
444 setLimelightNTDoubleArray(limelightName, "crop", cropWindow);
445 }
446
450 inline void setFiducial3DOffset(const std::string& limelightName, double offsetX, double offsetY, double offsetZ) {
451 std::array<double, 3> entries;
452 entries[0] = offsetX;
453 entries[1] = offsetY;
454 entries[2] = offsetZ;
455 setLimelightNTDoubleArray(limelightName, "fiducial_offset_set", entries);
456 }
457
458 inline void SetRobotOrientation_INTERNAL(const std::string& limelightName,
459 double yaw,
460 double yawRate,
461 double pitch,
462 double pitchRate,
463 double roll,
464 double rollRate,
465 bool flush) {
466 std::array<double, 6> entries;
467 entries[0] = yaw;
468 entries[1] = yawRate;
469 entries[2] = pitch;
470 entries[3] = pitchRate;
471 entries[4] = roll;
472 entries[5] = rollRate;
473 setLimelightNTDoubleArray(limelightName, "robot_orientation_set", entries);
474 if (flush) {
475 Flush();
476 }
477 }
478
482 inline void SetRobotOrientation(const std::string& limelightName,
483 double yaw,
484 double yawRate,
485 double pitch,
486 double pitchRate,
487 double roll,
488 double rollRate) {
489 SetRobotOrientation_INTERNAL(limelightName, yaw, yawRate, pitch, pitchRate, roll, rollRate, true);
490 }
491
492 inline void SetRobotOrientation_NoFlush(const std::string& limelightName,
493 double yaw,
494 double yawRate,
495 double pitch,
496 double pitchRate,
497 double roll,
498 double rollRate) {
499 SetRobotOrientation_INTERNAL(limelightName, yaw, yawRate, pitch, pitchRate, roll, rollRate, false);
500 }
501
508 inline void SetIMUMode(const std::string& limelightName, int mode) {
509 setLimelightNTDouble(limelightName, "imumode_set", mode);
510 }
511
521 inline void SetFidcuial3DOffset(const std::string& limelightName, double x, double y, double z) {
522 std::array<double, 3> entries;
523 entries[0] = x;
524 entries[1] = y;
525 entries[2] = z;
526 setLimelightNTDoubleArray(limelightName, "fiducial_offset_set", entries);
527 }
528
529 inline void SetFiducialIDFiltersOverride(const std::string& limelightName, const std::vector<int>& validIDs) {
530 std::vector<double> validIDsDouble(validIDs.begin(), validIDs.end());
531 setLimelightNTDoubleArray(limelightName, "fiducial_id_filters_set", validIDsDouble);
532 }
533
538 const std::string& limelightName, double forward, double side, double up, double roll, double pitch, double yaw) {
539 double entries[6] = {forward, side, up, roll, pitch, yaw};
540 setLimelightNTDoubleArray(limelightName, "camerapose_robotspace_set", entries);
541 }
542
543 inline void setPythonScriptData(const std::string& limelightName, const std::vector<double>& outgoingPythonData) {
545 limelightName, "llrobot", std::span{outgoingPythonData.begin(), outgoingPythonData.size()});
546 }
547
548 inline std::vector<double> getPythonScriptData(const std::string& limelightName = "") {
549 return getLimelightNTDoubleArray(limelightName, "llpython");
550 }
551
552 // Take async snapshot
553
554 inline double extractBotPoseEntry(const std::vector<double>& inData, int position) {
555 if (inData.size() < static_cast<size_t>(position + 1)) {
556 return 0.0;
557 }
558 return inData[position];
559 }
560
562 public:
563 int id{0};
564 double txnc{0.0};
565 double tync{0.0};
566 double ta{0.0};
567 double distToCamera{0.0};
568 double distToRobot{0.0};
569 double ambiguity{0.0};
570
571 RawFiducial(int id, double txnc, double tync, double ta, double distToCamera, double distToRobot, double ambiguity)
572 : id(id)
573 , txnc(txnc)
574 , tync(tync)
575 , ta(ta)
578 , ambiguity(ambiguity) {}
579 };
580
585 public:
586 frc::Pose2d pose;
587 units::time::second_t timestampSeconds{0.0};
588 double latency{0.0};
589 int tagCount{0};
590 double tagSpan{0.0};
591 double avgTagDist{0.0};
592 double avgTagArea{0.0};
593 std::vector<RawFiducial> rawFiducials;
595
596 PoseEstimate() = default;
597
598 PoseEstimate(const frc::Pose2d& pose,
599 units::time::second_t timestampSeconds,
600 double latency,
601 int tagCount,
602 double tagSpan,
603 double avgTagDist,
604 double avgTagArea,
605 const std::vector<RawFiducial>& rawFiducials,
606 bool isMegaTag2)
607 : pose(pose)
616 };
617
618 inline bool validPoseEstimate(const PoseEstimate& pose) {
619 return !pose.rawFiducials.empty();
620 }
621
625 class IMUData {
626 public:
627 double robotYaw{0.0};
628 double Roll{0.0};
629 double Pitch{0.0};
630 double Yaw{0.0};
631 double gyroX{0.0};
632 double gyroY{0.0};
633 double gyroZ{0.0};
634 double accelX{0.0};
635 double accelY{0.0};
636 double accelZ{0.0};
637
638 IMUData() = default;
639
640 IMUData(double imuData[10]) {
641 if (imuData != nullptr) {
642 robotYaw = imuData[0];
643 Roll = imuData[1];
644 Pitch = imuData[2];
645 Yaw = imuData[3];
646 gyroX = imuData[4];
647 gyroY = imuData[5];
648 gyroZ = imuData[6];
649 accelX = imuData[7];
650 accelY = imuData[8];
651 accelZ = imuData[9];
652 }
653 }
654 };
655
656 inline PoseEstimate getBotPoseEstimate(const std::string& limelightName,
657 const std::string& entryName,
658 bool isMegaTag2) {
659 nt::DoubleArrayEntry& poseEntry = getLimelightDoubleArrayEntry(limelightName, entryName);
660 auto tsValue = poseEntry.GetAtomic();
661
662 std::vector<double> poseArray = tsValue.value;
663 auto timestamp = tsValue.time;
664
665 if (poseArray.size() == 0) {
666 return PoseEstimate();
667 }
668
669 frc::Pose2d pose = toPose2D(poseArray);
670
671 double latency = extractBotPoseEntry(poseArray, 6);
672 int tagCount = static_cast<int>(extractBotPoseEntry(poseArray, 7));
673 double tagSpan = extractBotPoseEntry(poseArray, 8);
674 double tagDist = extractBotPoseEntry(poseArray, 9);
675 double tagArea = extractBotPoseEntry(poseArray, 10);
676
677 double adjustedTimestamp = (timestamp / 1000000.0) - (latency / 1000.0);
678
679 std::vector<RawFiducial> rawFiducials;
680 int valsPerFiducial = 7;
681 size_t expectedTotalVals = 11 + valsPerFiducial * tagCount;
682
683 if (poseArray.size() == expectedTotalVals) {
684 for (int i = 0; i < tagCount; i++) {
685 int baseIndex = 11 + (i * valsPerFiducial);
686 int id = static_cast<int>(extractBotPoseEntry(poseArray, baseIndex));
687 double txnc = extractBotPoseEntry(poseArray, baseIndex + 1);
688 double tync = extractBotPoseEntry(poseArray, baseIndex + 2);
689 double ta = extractBotPoseEntry(poseArray, baseIndex + 3);
690 double distToCamera = extractBotPoseEntry(poseArray, baseIndex + 4);
691 double distToRobot = extractBotPoseEntry(poseArray, baseIndex + 5);
692 double ambiguity = extractBotPoseEntry(poseArray, baseIndex + 6);
693 rawFiducials.emplace_back(id, txnc, tync, ta, distToCamera, distToRobot, ambiguity);
694 }
695 }
696
697 return PoseEstimate(pose,
698 units::time::second_t(adjustedTimestamp),
699 latency,
700 tagCount,
701 tagSpan,
702 tagDist,
703 tagArea,
704 rawFiducials,
705 isMegaTag2);
706 }
707
708 inline PoseEstimate getBotPoseEstimate_wpiBlue(const std::string& limelightName = "") {
709 return getBotPoseEstimate(limelightName, "botpose_wpiblue", false);
710 }
711
712 inline PoseEstimate getBotPoseEstimate_wpiRed(const std::string& limelightName = "") {
713 return getBotPoseEstimate(limelightName, "botpose_wpired", false);
714 }
715
716 inline PoseEstimate getBotPoseEstimate_wpiBlue_MegaTag2(const std::string& limelightName = "") {
717 return getBotPoseEstimate(limelightName, "botpose_orb_wpiblue", true);
718 }
719
720 inline PoseEstimate getBotPoseEstimate_wpiRed_MegaTag2(const std::string& limelightName = "") {
721 return getBotPoseEstimate(limelightName, "botpose_orb_wpired", true);
722 }
723
732 inline IMUData getIMUData(const std::string& limelightName) {
733 std::vector<double> imuData = getLimelightNTDoubleArray(limelightName, "imu");
734 if (imuData.empty() || imuData.size() < 10) {
735 return IMUData(); // Returns object with all zeros
736 }
737 return IMUData(imuData.data());
738 }
739
740 inline const double INVALID_TARGET = 0.0;
772
774
776 public:
778 std::string m_family{""};
779 };
780
782 public:
783 std::string m_family{""};
784 std::string m_data{""};
785
786 // Should these actually use m_TargetXNormalizedCrosshairAdjusted and be part of SingleTargetingResultClass?
789 };
790
792 public:
793 int m_classID{-1};
794 std::string m_className{""};
795 double m_confidence{0};
796
797 // Should these actually use m_TargetXNormalizedCrosshairAdjusted and be part of SingleTargetingResultClass?
800 };
801
803 public:
804 int m_classID{-1};
805 std::string m_className{""};
806 double m_confidence{0};
807 };
808
810 public:
811 std::vector<RetroreflectiveResultClass> RetroResults;
812 std::vector<FiducialResultClass> FiducialResults;
813 std::vector<DetectionResultClass> DetectionResults;
814 std::vector<ClassificationResultClass> ClassificationResults;
815 std::vector<BarcodeResultClass> BarcodeResults;
816 double m_timeStamp{-1.0};
819 double m_latencyJSON{0};
820 double m_pipelineIndex{-1.0};
821 int valid{0};
822 std::vector<double> botPose{6, 0.0};
823 std::vector<double> botPose_wpired{6, 0.0};
824 std::vector<double> botPose_wpiblue{6, 0.0};
825 void Clear() {
826 RetroResults.clear();
827 FiducialResults.clear();
828 DetectionResults.clear();
829 ClassificationResults.clear();
830 botPose.clear();
831 botPose_wpired.clear();
832 botPose_wpiblue.clear();
833 m_timeStamp = -1.0;
835
836 m_pipelineIndex = -1.0;
837 }
838 };
839
844
845 namespace internal {
846 inline const std::string _key_timestamp{"ts"};
847 inline const std::string _key_latency_pipeline{"tl"};
848 inline const std::string _key_latency_capture{"cl"};
849
850 inline const std::string _key_pipelineIndex{"pID"};
851 inline const std::string _key_TargetXDegrees{"txdr"};
852 inline const std::string _key_TargetYDegrees{"tydr"};
853 inline const std::string _key_TargetXNormalized{"txnr"};
854 inline const std::string _key_TargetYNormalized{"tynr"};
855 inline const std::string _key_TargetXPixels{"txp"};
856 inline const std::string _key_TargetYPixels{"typ"};
857
858 inline const std::string _key_TargetXDegreesCrosshair{"tx"};
859 inline const std::string _key_TargetXDegreesNoCrosshair{"tx_nocross"};
860 inline const std::string _key_TargetYDegreesCrosshair{"ty"};
861 inline const std::string _key_TargetYDegreesNoCrosshair{"ty_nocross"};
862 inline const std::string _key_TargetXNormalizedCrosshair{"txn"};
863 inline const std::string _key_TargetYNormalizedCrosshair{"tyn"};
864 inline const std::string _key_TargetAreaNormalized{"ta"};
865 inline const std::string _key_TargetAreaPixels{"tap"};
866 inline const std::string _key_className{"class"};
867 inline const std::string _key_classID{"classID"};
868 inline const std::string _key_confidence{"conf"};
869 inline const std::string _key_fiducialID{"fID"};
870 inline const std::string _key_corners{"pts"};
871 inline const std::string _key_transformCAMERAPOSE_TARGETSPACE{"t6c_ts"};
872 inline const std::string _key_transformCAMERAPOSE_ROBOTSPACE{"t6c_rs"};
873
874 inline const std::string _key_transformTARGETPOSE_CAMERASPACE{"t6t_cs"};
875 inline const std::string _key_transformROBOTPOSE_TARGETSPACE{"t6r_ts"};
876 inline const std::string _key_transformTARGETPOSE_ROBOTSPACE{"t6t_rs"};
877
878 inline const std::string _key_botpose{"botpose"};
879 inline const std::string _key_botpose_wpiblue{"botpose_wpiblue"};
880 inline const std::string _key_botpose_wpired{"botpose_wpired"};
881
882 inline const std::string _key_transformROBOTPOSE_FIELDSPACE{"t6r_fs"};
883 inline const std::string _key_skew{"skew"};
884 inline const std::string _key_ffamily{"fam"};
885 inline const std::string _key_data{"data"};
886 inline const std::string _key_colorRGB{"cRGB"};
887 inline const std::string _key_colorHSV{"cHSV"};
888 } // namespace internal
889
890#ifndef _WIN32
891 inline void PhoneHome() {
892 static int sockfd = -1;
893 static struct sockaddr_in servaddr, cliaddr;
894
895 if (sockfd == -1) {
896 sockfd = socket(AF_INET, SOCK_DGRAM, 0);
897 if (sockfd < 0) {
898 std::cerr << "Socket creation failed" << std::endl;
899 return;
900 }
901
902 std::memset(&servaddr, 0, sizeof(servaddr));
903 servaddr.sin_family = AF_INET;
904 servaddr.sin_addr.s_addr = inet_addr("255.255.255.255");
905 servaddr.sin_port = htons(5809);
906
907 // Set socket for broadcast
908 int broadcast = 1;
909 if (setsockopt(sockfd, SOL_SOCKET, SO_BROADCAST, &broadcast, sizeof(broadcast)) < 0) {
910 std::cerr << "Error in setting Broadcast option" << std::endl;
911 close(sockfd);
912 sockfd = -1;
913 return;
914 }
915
916 // Set socket to non-blocking
917 if (fcntl(sockfd, F_SETFL, O_NONBLOCK) < 0) {
918 std::cerr << "Error setting socket to non-blocking" << std::endl;
919 close(sockfd);
920 sockfd = -1;
921 return;
922 }
923
924 const char* msg = "LLPhoneHome";
925 sendto(sockfd, msg, std::strlen(msg), 0, (const struct sockaddr*)&servaddr, sizeof(servaddr));
926 }
927
928 char receiveData[1024];
929 socklen_t len = sizeof(cliaddr);
930
931 ssize_t n = recvfrom(sockfd, reinterpret_cast<char*>(receiveData), 1024, 0, (struct sockaddr*)&cliaddr, &len);
932 if (n > 0) {
933 receiveData[n] = '\0'; // Null-terminate the received string
934 std::string received(receiveData, n);
935 std::cout << "Received response: " << received << std::endl;
936 } else if (n < 0 && errno != EWOULDBLOCK && errno != EAGAIN) {
937 std::cerr << "Error receiving data" << std::endl;
938 close(sockfd);
939 sockfd = -1;
940 }
941 }
942#endif
943
944 inline void SetupPortForwarding(const std::string& limelightName) {
945 auto& portForwarder = wpi::PortForwarder::GetInstance();
946 portForwarder.Add(5800, sanitizeName(limelightName), 5800);
947 portForwarder.Add(5801, sanitizeName(limelightName), 5801);
948 portForwarder.Add(5802, sanitizeName(limelightName), 5802);
949 portForwarder.Add(5803, sanitizeName(limelightName), 5803);
950 portForwarder.Add(5804, sanitizeName(limelightName), 5804);
951 portForwarder.Add(5805, sanitizeName(limelightName), 5805);
952 portForwarder.Add(5806, sanitizeName(limelightName), 5806);
953 portForwarder.Add(5807, sanitizeName(limelightName), 5807);
954 portForwarder.Add(5808, sanitizeName(limelightName), 5808);
955 portForwarder.Add(5809, sanitizeName(limelightName), 5809);
956 }
957
958 template <typename T, typename KeyType>
959 T SafeJSONAccess(const wpi::json& jsonData, const KeyType& key, const T& defaultValue) {
960 try {
961 return jsonData.at(key).template get<T>();
962 } catch (wpi::json::exception& e) {
963 return defaultValue;
964 } catch (...) {
965 return defaultValue;
966 }
967 }
968
972 inline void from_json(const wpi::json& j, RetroreflectiveResultClass& t) {
973 std::vector<double> defaultValueVector(6, 0.0);
978
987
994 SafeJSONAccess<std::vector<std::vector<double>>>(j, internal::_key_corners, std::vector<std::vector<double>>{});
995 }
996
1000 inline void from_json(const wpi::json& j, FiducialResultClass& t) {
1001 std::vector<double> defaultValueVector(6, 0.0);
1016
1022 t.m_TargetCorners =
1023 SafeJSONAccess<std::vector<std::vector<double>>>(j, internal::_key_corners, std::vector<std::vector<double>>{});
1024 }
1025
1041
1067
1083
1084 inline void from_json(const wpi::json& j, VisionResultsClass& t) {
1089 t.valid = SafeJSONAccess<double>(j, "v", 0.0);
1090
1091 std::vector<double> defaultVector{};
1095
1096 t.RetroResults =
1097 SafeJSONAccess<std::vector<RetroreflectiveResultClass>>(j, "Retro", std::vector<RetroreflectiveResultClass>{});
1098 t.FiducialResults =
1099 SafeJSONAccess<std::vector<FiducialResultClass>>(j, "Fiducial", std::vector<FiducialResultClass>{});
1101 SafeJSONAccess<std::vector<DetectionResultClass>>(j, "Detector", std::vector<DetectionResultClass>{});
1103 SafeJSONAccess<std::vector<ClassificationResultClass>>(j, "Detector", std::vector<ClassificationResultClass>{});
1104 t.BarcodeResults = SafeJSONAccess<std::vector<BarcodeResultClass>>(j, "Barcode", std::vector<BarcodeResultClass>{});
1105 }
1106
1114
1115 inline LimelightResultsClass getLatestResults(const std::string& limelightName = "", bool profile = false) {
1116 auto start = std::chrono::high_resolution_clock::now();
1117 std::string jsonString = getJSONDump(limelightName);
1118 wpi::json data;
1119 try {
1120 data = wpi::json::parse(jsonString);
1121 } catch (const std::exception& e) {
1122 return LimelightResultsClass();
1123 }
1124
1125 auto end = std::chrono::high_resolution_clock::now();
1126 double nanos = std::chrono::duration_cast<std::chrono::nanoseconds>(end - start).count();
1127 double millis = (nanos * 0.000001);
1128 try {
1130 out.targetingResults.m_latencyJSON = millis;
1131 if (profile) {
1132 std::cout << "lljson: " << millis << std::endl;
1133 }
1134 return out;
1135 } catch (...) {
1136 return LimelightResultsClass();
1137 }
1138 }
1139} // namespace LimelightHelpers
Definition LimelightHelpers.h:781
double m_TargetYDegreesNoCrosshairAdjusted
Definition LimelightHelpers.h:788
std::string m_data
Definition LimelightHelpers.h:784
double m_TargetXDegreesNoCrosshairAdjusted
Definition LimelightHelpers.h:787
std::string m_family
Definition LimelightHelpers.h:783
Definition LimelightHelpers.h:802
int m_classID
Definition LimelightHelpers.h:804
std::string m_className
Definition LimelightHelpers.h:805
double m_confidence
Definition LimelightHelpers.h:806
Definition LimelightHelpers.h:791
double m_TargetXDegreesNoCrosshairAdjusted
Definition LimelightHelpers.h:798
int m_classID
Definition LimelightHelpers.h:793
std::string m_className
Definition LimelightHelpers.h:794
double m_TargetYDegreesNoCrosshairAdjusted
Definition LimelightHelpers.h:799
double m_confidence
Definition LimelightHelpers.h:795
Definition LimelightHelpers.h:775
std::string m_family
Definition LimelightHelpers.h:778
int m_fiducialID
Definition LimelightHelpers.h:777
Definition LimelightHelpers.h:625
double gyroZ
Definition LimelightHelpers.h:633
double accelZ
Definition LimelightHelpers.h:636
double gyroY
Definition LimelightHelpers.h:632
IMUData(double imuData[10])
Definition LimelightHelpers.h:640
double gyroX
Definition LimelightHelpers.h:631
double robotYaw
Definition LimelightHelpers.h:627
double accelX
Definition LimelightHelpers.h:634
double Roll
Definition LimelightHelpers.h:628
double Yaw
Definition LimelightHelpers.h:630
double Pitch
Definition LimelightHelpers.h:629
double accelY
Definition LimelightHelpers.h:635
Definition LimelightHelpers.h:840
VisionResultsClass targetingResults
Definition LimelightHelpers.h:842
Definition LimelightHelpers.h:584
double latency
Definition LimelightHelpers.h:588
double avgTagDist
Definition LimelightHelpers.h:591
PoseEstimate(const frc::Pose2d &pose, units::time::second_t timestampSeconds, double latency, int tagCount, double tagSpan, double avgTagDist, double avgTagArea, const std::vector< RawFiducial > &rawFiducials, bool isMegaTag2)
Definition LimelightHelpers.h:598
int tagCount
Definition LimelightHelpers.h:589
frc::Pose2d pose
Definition LimelightHelpers.h:586
double avgTagArea
Definition LimelightHelpers.h:592
std::vector< RawFiducial > rawFiducials
Definition LimelightHelpers.h:593
bool isMegaTag2
Definition LimelightHelpers.h:594
double tagSpan
Definition LimelightHelpers.h:590
units::time::second_t timestampSeconds
Definition LimelightHelpers.h:587
Definition LimelightHelpers.h:561
double ambiguity
Definition LimelightHelpers.h:569
RawFiducial(int id, double txnc, double tync, double ta, double distToCamera, double distToRobot, double ambiguity)
Definition LimelightHelpers.h:571
int id
Definition LimelightHelpers.h:563
double txnc
Definition LimelightHelpers.h:564
double tync
Definition LimelightHelpers.h:565
double distToCamera
Definition LimelightHelpers.h:567
double ta
Definition LimelightHelpers.h:566
double distToRobot
Definition LimelightHelpers.h:568
Definition LimelightHelpers.h:773
Definition LimelightHelpers.h:741
std::vector< double > m_TargetTransform6DROBOTSPACE
Definition LimelightHelpers.h:767
double m_pipelineIndex
Definition LimelightHelpers.h:762
double m_TargetAreaNormalizedPercentage
Definition LimelightHelpers.h:757
double m_TargetYDegreesCrosshairAdjusted
Definition LimelightHelpers.h:753
double m_TargetYNormalizedCrosshairAdjusted
Definition LimelightHelpers.h:750
double m_TargetXDegreesCrosshairAdjusted
Definition LimelightHelpers.h:752
std::vector< double > m_CAMERATransform6DTARGETSPACE
Definition LimelightHelpers.h:765
double m_TargetXNormalized
Definition LimelightHelpers.h:746
double m_TargetAreaNormalized
Definition LimelightHelpers.h:756
double m_TargetYNormalized
Definition LimelightHelpers.h:747
std::vector< double > m_ROBOTTransform6DFIELDSPACE
Definition LimelightHelpers.h:769
double m_TargetXNormalizedCrosshairAdjusted
Definition LimelightHelpers.h:749
std::vector< double > m_CAMERATransform6DROBOTSPACE
Definition LimelightHelpers.h:770
double m_TargetXPixels
Definition LimelightHelpers.h:743
std::vector< double > m_ROBOTTransform6DTARGETSPACE
Definition LimelightHelpers.h:768
double m_timeStamp
Definition LimelightHelpers.h:760
std::vector< std::vector< double > > m_TargetCorners
Definition LimelightHelpers.h:763
std::vector< double > m_TargetTransform6DCAMERASPACE
Definition LimelightHelpers.h:766
double m_TargetYPixels
Definition LimelightHelpers.h:744
double m_TargetAreaPixels
Definition LimelightHelpers.h:755
double m_latency
Definition LimelightHelpers.h:761
Definition LimelightHelpers.h:809
std::vector< double > botPose_wpired
Definition LimelightHelpers.h:823
double m_latencyJSON
Definition LimelightHelpers.h:819
std::vector< ClassificationResultClass > ClassificationResults
Definition LimelightHelpers.h:814
double m_latencyPipeline
Definition LimelightHelpers.h:817
std::vector< double > botPose_wpiblue
Definition LimelightHelpers.h:824
std::vector< double > botPose
Definition LimelightHelpers.h:822
int valid
Definition LimelightHelpers.h:821
std::vector< BarcodeResultClass > BarcodeResults
Definition LimelightHelpers.h:815
double m_latencyCapture
Definition LimelightHelpers.h:818
double m_timeStamp
Definition LimelightHelpers.h:816
void Clear()
Definition LimelightHelpers.h:825
std::vector< RetroreflectiveResultClass > RetroResults
Definition LimelightHelpers.h:811
std::vector< FiducialResultClass > FiducialResults
Definition LimelightHelpers.h:812
std::vector< DetectionResultClass > DetectionResults
Definition LimelightHelpers.h:813
double m_pipelineIndex
Definition LimelightHelpers.h:820
const std::string _key_transformTARGETPOSE_ROBOTSPACE
Definition LimelightHelpers.h:876
const std::string _key_data
Definition LimelightHelpers.h:885
const std::string _key_TargetYNormalizedCrosshair
Definition LimelightHelpers.h:863
const std::string _key_TargetAreaNormalized
Definition LimelightHelpers.h:864
const std::string _key_pipelineIndex
Definition LimelightHelpers.h:850
const std::string _key_latency_pipeline
Definition LimelightHelpers.h:847
const std::string _key_TargetXPixels
Definition LimelightHelpers.h:855
const std::string _key_TargetYDegreesCrosshair
Definition LimelightHelpers.h:860
const std::string _key_TargetAreaPixels
Definition LimelightHelpers.h:865
const std::string _key_TargetYPixels
Definition LimelightHelpers.h:856
const std::string _key_TargetXDegreesCrosshair
Definition LimelightHelpers.h:858
const std::string _key_skew
Definition LimelightHelpers.h:883
const std::string _key_timestamp
Definition LimelightHelpers.h:846
const std::string _key_transformCAMERAPOSE_ROBOTSPACE
Definition LimelightHelpers.h:872
const std::string _key_corners
Definition LimelightHelpers.h:870
const std::string _key_botpose_wpired
Definition LimelightHelpers.h:880
const std::string _key_TargetXNormalized
Definition LimelightHelpers.h:853
const std::string _key_transformTARGETPOSE_CAMERASPACE
Definition LimelightHelpers.h:874
const std::string _key_TargetYNormalized
Definition LimelightHelpers.h:854
const std::string _key_latency_capture
Definition LimelightHelpers.h:848
const std::string _key_transformROBOTPOSE_TARGETSPACE
Definition LimelightHelpers.h:875
const std::string _key_confidence
Definition LimelightHelpers.h:868
const std::string _key_TargetXDegrees
Definition LimelightHelpers.h:851
const std::string _key_TargetXNormalizedCrosshair
Definition LimelightHelpers.h:862
const std::string _key_TargetYDegreesNoCrosshair
Definition LimelightHelpers.h:861
const std::string _key_botpose_wpiblue
Definition LimelightHelpers.h:879
const std::string _key_ffamily
Definition LimelightHelpers.h:884
const std::string _key_TargetXDegreesNoCrosshair
Definition LimelightHelpers.h:859
const std::string _key_colorHSV
Definition LimelightHelpers.h:887
const std::string _key_className
Definition LimelightHelpers.h:866
const std::string _key_classID
Definition LimelightHelpers.h:867
const std::string _key_transformCAMERAPOSE_TARGETSPACE
Definition LimelightHelpers.h:871
const std::string _key_transformROBOTPOSE_FIELDSPACE
Definition LimelightHelpers.h:882
const std::string _key_fiducialID
Definition LimelightHelpers.h:869
const std::string _key_botpose
Definition LimelightHelpers.h:878
const std::string _key_TargetYDegrees
Definition LimelightHelpers.h:852
const std::string _key_colorRGB
Definition LimelightHelpers.h:886
Definition LimelightHelpers.h:49
const std::string getDetectorClass(const std::string &limelightName)
Definition LimelightHelpers.h:300
std::vector< double > getCameraPose_TargetSpace(const std::string &limelightName="")
Definition LimelightHelpers.h:365
void setPipelineIndex(const std::string &limelightName, int index)
Definition LimelightHelpers.h:397
double getLatency_Pipeline(const std::string &limelightName="")
Definition LimelightHelpers.h:310
nt::NetworkTableEntry getLimelightNTTableEntry(const std::string &tableName, const std::string &entryName)
Definition LimelightHelpers.h:135
void SetIMUMode(const std::string &limelightName, int mode)
Definition LimelightHelpers.h:508
void SetupPortForwarding(const std::string &limelightName)
Definition LimelightHelpers.h:944
double getTY(const std::string &limelightName="")
Definition LimelightHelpers.h:205
std::vector< double > getBotpose_wpiRed(const std::string &limelightName="")
Definition LimelightHelpers.h:353
std::vector< double > getBotpose_wpiBlue(const std::string &limelightName="")
Definition LimelightHelpers.h:357
PoseEstimate getBotPoseEstimate_wpiRed(const std::string &limelightName="")
Definition LimelightHelpers.h:712
T SafeJSONAccess(const wpi::json &jsonData, const KeyType &key, const T &defaultValue)
Definition LimelightHelpers.h:959
void setLEDMode_ForceBlink(const std::string &limelightName="")
Definition LimelightHelpers.h:413
LimelightResultsClass getLatestResults(const std::string &limelightName="", bool profile=false)
Definition LimelightHelpers.h:1115
PoseEstimate getBotPoseEstimate(const std::string &limelightName, const std::string &entryName, bool isMegaTag2)
Definition LimelightHelpers.h:656
std::vector< double > getCameraPose_RobotSpace(const std::string &limelightName="")
Definition LimelightHelpers.h:369
void SetRobotOrientation(const std::string &limelightName, double yaw, double yawRate, double pitch, double pitchRate, double roll, double rollRate)
Definition LimelightHelpers.h:482
bool getTV(const std::string &limelightName="")
Definition LimelightHelpers.h:187
PoseEstimate getBotPoseEstimate_wpiBlue_MegaTag2(const std::string &limelightName="")
Definition LimelightHelpers.h:716
double getTX(const std::string &limelightName="")
Definition LimelightHelpers.h:196
void setLimelightNTDoubleArray(const std::string &tableName, const std::string &entryName, const std::span< const double > &vals)
Definition LimelightHelpers.h:176
int getClassifierClassIndex(const std::string &limelightName)
Definition LimelightHelpers.h:265
void Flush()
Definition LimelightHelpers.h:131
std::vector< double > getLimelightNTDoubleArray(const std::string &tableName, const std::string &entryName)
Definition LimelightHelpers.h:159
PoseEstimate getBotPoseEstimate_wpiBlue(const std::string &limelightName="")
Definition LimelightHelpers.h:708
void SetRobotOrientation_INTERNAL(const std::string &limelightName, double yaw, double yawRate, double pitch, double pitchRate, double roll, double rollRate, bool flush)
Definition LimelightHelpers.h:458
IMUData getIMUData(const std::string &limelightName)
Definition LimelightHelpers.h:732
std::shared_ptr< nt::NetworkTable > getLimelightNTTable(const std::string &tableName)
Definition LimelightHelpers.h:127
nt::DoubleArrayEntry & getLimelightDoubleArrayEntry(const std::string &tableName, const std::string &entryName)
Definition LimelightHelpers.h:141
std::vector< double > getT2DArray(const std::string &limelightName)
Definition LimelightHelpers.h:243
int getDetectorClassIndex(const std::string &limelightName)
Definition LimelightHelpers.h:278
double getLimelightNTDouble(const std::string &tableName, const std::string &entryName)
Definition LimelightHelpers.h:155
std::vector< double > getBotpose(const std::string &limelightName="")
Definition LimelightHelpers.h:349
frc::Pose2d toPose2D(const std::vector< double > &inData)
Definition LimelightHelpers.h:82
const double INVALID_TARGET
Definition LimelightHelpers.h:740
void setStreamMode_PiPMain(const std::string &limelightName="")
Definition LimelightHelpers.h:425
void setLimelightNTDouble(const std::string &tableName, const std::string entryName, double val)
Definition LimelightHelpers.h:172
void setPythonScriptData(const std::string &limelightName, const std::vector< double > &outgoingPythonData)
Definition LimelightHelpers.h:543
double getFiducialID(const std::string &limelightName="")
Definition LimelightHelpers.h:385
void from_json(const wpi::json &j, RetroreflectiveResultClass &t)
Definition LimelightHelpers.h:972
void setCameraPose_RobotSpace(const std::string &limelightName, double forward, double side, double up, double roll, double pitch, double yaw)
Definition LimelightHelpers.h:537
void setLEDMode_ForceOn(const std::string &limelightName="")
Definition LimelightHelpers.h:417
std::vector< double > getTargetPose_RobotSpace(const std::string &limelightName="")
Definition LimelightHelpers.h:377
PoseEstimate getBotPoseEstimate_wpiRed_MegaTag2(const std::string &limelightName="")
Definition LimelightHelpers.h:720
double getLatency_Capture(const std::string &limelightName="")
Definition LimelightHelpers.h:319
std::string getLimelightNTString(const std::string &tableName, const std::string &entryName)
Definition LimelightHelpers.h:163
void setStreamMode_Standard(const std::string &limelightName="")
Definition LimelightHelpers.h:421
void SetFidcuial3DOffset(const std::string &limelightName, double x, double y, double z)
Definition LimelightHelpers.h:521
double getTXNC(const std::string &limelightName)
Definition LimelightHelpers.h:214
int getTargetCount(const std::string &limelightName)
Definition LimelightHelpers.h:252
std::array< double, 6 > pose2dToArray(const frc::Pose2d &pose)
Definition LimelightHelpers.h:116
const std::string getCurrentPipelineType(const std::string &limelightName)
Definition LimelightHelpers.h:336
const std::string getClassifierClass(const std::string &limelightName)
Definition LimelightHelpers.h:291
std::string sanitizeName(const std::string &name)
Definition LimelightHelpers.h:50
void setFiducial3DOffset(const std::string &limelightName, double offsetX, double offsetY, double offsetZ)
Definition LimelightHelpers.h:450
void setStreamMode_PiPSecondary(const std::string &limelightName="")
Definition LimelightHelpers.h:429
std::string getNeuralClassID(const std::string &limelightName="")
Definition LimelightHelpers.h:389
std::array< double, 6 > pose3dToArray(const frc::Pose3d &pose)
Definition LimelightHelpers.h:97
std::vector< double > getPythonScriptData(const std::string &limelightName="")
Definition LimelightHelpers.h:548
frc::Pose3d toPose3D(const std::vector< double > &inData)
Definition LimelightHelpers.h:63
void setLEDMode_PipelineControl(const std::string &limelightName="")
Definition LimelightHelpers.h:405
std::vector< double > getBotpose_TargetSpace(const std::string &limelightName="")
Definition LimelightHelpers.h:361
double getTYNC(const std::string &limelightName)
Definition LimelightHelpers.h:223
void SetFiducialIDFiltersOverride(const std::string &limelightName, const std::vector< int > &validIDs)
Definition LimelightHelpers.h:529
std::unordered_map< std::string, nt::DoubleArrayEntry > doubleArrayEntries
Definition LimelightHelpers.h:139
std::vector< double > getTargetPose_CameraSpace(const std::string &limelightName="")
Definition LimelightHelpers.h:373
void PhoneHome()
Definition LimelightHelpers.h:891
void setCropWindow(const std::string &limelightName, double cropXMin, double cropXMax, double cropYMin, double cropYMax)
Definition LimelightHelpers.h:441
double getTA(const std::string &limelightName="")
Definition LimelightHelpers.h:233
std::vector< std::string > getLimelightNTStringArray(const std::string &tableName, const std::string &entryName)
Definition LimelightHelpers.h:167
void setLEDMode_ForceOff(const std::string &limelightName="")
Definition LimelightHelpers.h:409
void setPriorityTagID(const std::string &limelightName, int ID)
Definition LimelightHelpers.h:401
bool validPoseEstimate(const PoseEstimate &pose)
Definition LimelightHelpers.h:618
std::vector< double > getTargetColor(const std::string &limelightName="")
Definition LimelightHelpers.h:381
std::string getJSONDump(const std::string &limelightName="")
Definition LimelightHelpers.h:345
double extractBotPoseEntry(const std::vector< double > &inData, int position)
Definition LimelightHelpers.h:554
double getCurrentPipelineIndex(const std::string &limelightName)
Definition LimelightHelpers.h:327
void SetRobotOrientation_NoFlush(const std::string &limelightName, double yaw, double yawRate, double pitch, double pitchRate, double roll, double rollRate)
Definition LimelightHelpers.h:492
std::vector< std::string > getRawBarcodeData(const std::string &limelightName="")
Definition LimelightHelpers.h:393
Definition position.h:65