Compare commits

..

4 Commits

Author SHA1 Message Date
Matt M
e613e75db6 Backport maven changes 2024-08-02 08:18:44 -07:00
Matt
eca3cea82d Sort object detection results and reduce code duplication (#1173)
* Sort object detection results and reduce code dup.

* Filter objdet results by ratio and area

* Address code review

---------

Co-authored-by: Mohammad Durrani <46766905+mdurrani808@users.noreply.github.com>
2024-01-23 14:10:31 -05:00
Craig Schardt
cbbfbda59d clean up debugging println (#1193) 2024-01-22 22:59:42 -05:00
Drew Williams
a3e1dda3aa Fixed cpp sim apriltag layout and cleaned up cpp sim example (#1190)
* Fixed cpp sim apriltag layout and cleaned up cpp sim example

* changed layout for photoncamerasim

---------

Co-authored-by: Drew Williams <DrewW@iARx.com>
2024-01-22 15:38:25 -05:00
16 changed files with 273 additions and 130 deletions

View File

@@ -11,6 +11,16 @@ const currentPipelineSettings = computed<ActivePipelineSettings>(
() => useCameraSettingsStore().currentPipelineSettings
);
// TODO fix pv-range-slider so that store access doesn't need to be deferred
const contourArea = computed<[number, number]>({
get: () => Object.values(useCameraSettingsStore().currentPipelineSettings.contourArea) as [number, number],
set: (v) => (useCameraSettingsStore().currentPipelineSettings.contourArea = v)
});
const contourRatio = computed<[number, number]>({
get: () => Object.values(useCameraSettingsStore().currentPipelineSettings.contourRatio) as [number, number],
set: (v) => (useCameraSettingsStore().currentPipelineSettings.contourRatio = v)
});
const interactiveCols = computed(() =>
(getCurrentInstance()?.proxy.$vuetify.breakpoint.mdAndDown || false) &&
(!useStateStore().sidebarFolded || useCameraSettingsStore().isDriverMode)
@@ -32,5 +42,42 @@ const interactiveCols = computed(() =>
:step="0.01"
@input="(value) => useCameraSettingsStore().changeCurrentPipelineSetting({ confidence: value }, false)"
/>
<pv-range-slider
v-model="contourArea"
label="Area"
:min="0"
:max="100"
:slider-cols="interactiveCols"
:step="0.01"
@input="(value) => useCameraSettingsStore().changeCurrentPipelineSetting({ contourArea: value }, false)"
/>
<pv-range-slider
v-model="contourRatio"
label="Ratio (W/H)"
tooltip="Min and max ratio between the width and height of a contour's bounding rectangle"
:min="0"
:max="100"
:slider-cols="interactiveCols"
:step="0.01"
@input="(value) => useCameraSettingsStore().changeCurrentPipelineSetting({ contourRatio: value }, false)"
/>
<pv-select
v-model="useCameraSettingsStore().currentPipelineSettings.contourTargetOrientation"
label="Target Orientation"
tooltip="Used to determine how to calculate target landmarks, as well as aspect ratio"
:items="['Portrait', 'Landscape']"
:select-cols="interactiveCols"
@input="
(value) => useCameraSettingsStore().changeCurrentPipelineSetting({ contourTargetOrientation: value }, false)
"
/>
<pv-select
v-model="currentPipelineSettings.contourSortMode"
label="Target Sort"
tooltip="Chooses the sorting mode used to determine the 'best' targets to provide to user code"
:select-cols="interactiveCols"
:items="['Largest', 'Smallest', 'Highest', 'Lowest', 'Rightmost', 'Leftmost', 'Centermost']"
@input="(value) => useCameraSettingsStore().changeCurrentPipelineSetting({ contourSortMode: value }, false)"
/>
</div>
</template>

View File

@@ -47,6 +47,16 @@ public class Contour implements Releasable {
this.mat = mat;
}
public Contour(Rect2d box) {
// no easy way to convert a Rect2d to Mat, diy it. Order is tl tr br bl
this.mat =
new MatOfPoint(
box.tl(),
new Point(box.x + box.width, box.y),
box.br(),
new Point(box.x, box.y + box.height));
}
public MatOfPoint2f getMat2f() {
if (mat2f == null) {
mat2f = new MatOfPoint2f(mat.toArray());

View File

@@ -25,15 +25,15 @@ public enum ContourSortMode {
Comparator.comparingDouble(PotentialTarget::getArea)
.reversed()), // reversed so that zero index has the largest size
Smallest(Largest.getComparator().reversed()),
Highest(Comparator.comparingDouble(rect -> rect.getMinAreaRect().center.y)),
Highest(Comparator.comparingDouble(tgt -> tgt.getMinAreaRect().center.y)),
Lowest(Highest.getComparator().reversed()),
Leftmost(Comparator.comparingDouble(target -> target.getMinAreaRect().center.x * -1)),
Leftmost(Comparator.comparingDouble(tgt -> tgt.getMinAreaRect().center.x * -1)),
Rightmost(Leftmost.getComparator().reversed()),
Centermost(
Comparator.comparingDouble(
rect ->
(Math.pow(rect.getMinAreaRect().center.y, 2)
+ Math.pow(rect.getMinAreaRect().center.x, 2))));
tgt ->
(Math.pow(tgt.getMinAreaRect().center.y, 2)
+ Math.pow(tgt.getMinAreaRect().center.x, 2))));
private final Comparator<PotentialTarget> m_comparator;

View File

@@ -0,0 +1,89 @@
/*
* Copyright (C) Photon Vision.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package org.photonvision.vision.pipe.impl;
import java.util.ArrayList;
import java.util.List;
import org.photonvision.common.util.numbers.DoubleCouple;
import org.photonvision.vision.frame.FrameStaticProperties;
import org.photonvision.vision.pipe.CVPipe;
public class FilterObjectDetectionsPipe
extends CVPipe<
List<NeuralNetworkPipeResult>,
List<NeuralNetworkPipeResult>,
FilterObjectDetectionsPipe.FilterContoursParams> {
List<NeuralNetworkPipeResult> m_filteredContours = new ArrayList<>();
@Override
protected List<NeuralNetworkPipeResult> process(List<NeuralNetworkPipeResult> in) {
m_filteredContours.clear();
for (var contour : in) {
filterContour(contour);
}
return m_filteredContours;
}
private void filterContour(NeuralNetworkPipeResult contour) {
var boc = contour.box;
// Area filtering
double areaPercentage = boc.area() / params.getFrameStaticProperties().imageArea * 100.0;
double minAreaPercentage = params.getArea().getFirst();
double maxAreaPercentage = params.getArea().getSecond();
if (areaPercentage < minAreaPercentage || areaPercentage > maxAreaPercentage) return;
// Aspect ratio filtering; much simpler since always axis-aligned
double aspectRatio = boc.width / boc.height;
if (aspectRatio < params.getRatio().getFirst() || aspectRatio > params.getRatio().getSecond())
return;
m_filteredContours.add(contour);
}
public static class FilterContoursParams {
private final DoubleCouple m_area;
private final DoubleCouple m_ratio;
private final FrameStaticProperties m_frameStaticProperties;
public final boolean isLandscape;
public FilterContoursParams(
DoubleCouple area,
DoubleCouple ratio,
FrameStaticProperties camProperties,
boolean isLandscape) {
this.m_area = area;
this.m_ratio = ratio;
this.m_frameStaticProperties = camProperties;
this.isLandscape = isLandscape;
}
public DoubleCouple getArea() {
return m_area;
}
public DoubleCouple getRatio() {
return m_ratio;
}
public FrameStaticProperties getFrameStaticProperties() {
return m_frameStaticProperties;
}
}
}

View File

@@ -42,6 +42,7 @@ public class SortContoursPipe
if (params.getSortMode() != ContourSortMode.Centermost) {
m_sortedContours.sort(params.getSortMode().getComparator());
} else {
// we need knowledge of camera properties to calculate this distance -- do it ourselves
m_sortedContours.sort(Comparator.comparingDouble(this::calcSquareCenterDistance));
}
}
@@ -50,10 +51,10 @@ public class SortContoursPipe
m_sortedContours.subList(0, Math.min(in.size(), params.getMaxTargets())));
}
private double calcSquareCenterDistance(PotentialTarget rect) {
private double calcSquareCenterDistance(PotentialTarget tgt) {
return Math.sqrt(
Math.pow(params.getCamProperties().centerX - rect.getMinAreaRect().center.x, 2)
+ Math.pow(params.getCamProperties().centerY - rect.getMinAreaRect().center.y, 2));
Math.pow(params.getCamProperties().centerX - tgt.getMinAreaRect().center.x, 2)
+ Math.pow(params.getCamProperties().centerY - tgt.getMinAreaRect().center.y, 2));
}
public static class SortContoursParams {

View File

@@ -26,6 +26,8 @@ import org.photonvision.vision.pipeline.result.CVPipelineResult;
public abstract class CVPipeline<R extends CVPipelineResult, S extends CVPipelineSettings>
implements Releasable {
static final int MAX_MULTI_TARGET_RESULTS = 10;
protected S settings;
protected FrameStaticProperties frameStaticProperties;
protected QuirkyCamera cameraQuirks;

View File

@@ -109,7 +109,7 @@ public class ColoredShapePipeline
SortContoursPipe.SortContoursParams sortContoursParams =
new SortContoursPipe.SortContoursParams(
settings.contourSortMode,
settings.outputShowMultipleTargets ? 5 : 1,
settings.outputShowMultipleTargets ? MAX_MULTI_TARGET_RESULTS : 1,
frameStaticProperties); // TODO don't hardcode?
sortContoursPipe.setParams(sortContoursParams);

View File

@@ -17,21 +17,26 @@
package org.photonvision.vision.pipeline;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;
import org.photonvision.vision.frame.Frame;
import org.photonvision.vision.frame.FrameThresholdType;
import org.photonvision.vision.opencv.DualOffsetValues;
import org.photonvision.vision.pipe.CVPipe.CVPipeResult;
import org.photonvision.vision.pipe.impl.*;
import org.photonvision.vision.pipe.impl.RknnDetectionPipe.RknnDetectionPipeParams;
import org.photonvision.vision.pipeline.result.CVPipelineResult;
import org.photonvision.vision.target.PotentialTarget;
import org.photonvision.vision.target.TargetOrientation;
import org.photonvision.vision.target.TrackedTarget;
import org.photonvision.vision.target.TrackedTarget.TargetCalculationParameters;
public class ObjectDetectionPipeline
extends CVPipeline<CVPipelineResult, ObjectDetectionPipelineSettings> {
private final CalculateFPSPipe calculateFPSPipe = new CalculateFPSPipe();
private final RknnDetectionPipe rknnPipe = new RknnDetectionPipe();
private final SortContoursPipe sortContoursPipe = new SortContoursPipe();
private final Collect2dTargetsPipe collect2dTargetsPipe = new Collect2dTargetsPipe();
private final FilterObjectDetectionsPipe filterContoursPipe = new FilterObjectDetectionsPipe();
private static final FrameThresholdType PROCESSING_TYPE = FrameThresholdType.NONE;
@@ -52,6 +57,38 @@ public class ObjectDetectionPipeline
params.confidence = settings.confidence;
params.nms = settings.nms;
rknnPipe.setParams(params);
DualOffsetValues dualOffsetValues =
new DualOffsetValues(
settings.offsetDualPointA,
settings.offsetDualPointAArea,
settings.offsetDualPointB,
settings.offsetDualPointBArea);
SortContoursPipe.SortContoursParams sortContoursParams =
new SortContoursPipe.SortContoursParams(
settings.contourSortMode,
settings.outputShowMultipleTargets ? MAX_MULTI_TARGET_RESULTS : 1,
frameStaticProperties);
sortContoursPipe.setParams(sortContoursParams);
var filterContoursParams =
new FilterObjectDetectionsPipe.FilterContoursParams(
settings.contourArea,
settings.contourRatio,
frameStaticProperties,
settings.contourTargetOrientation == TargetOrientation.Landscape);
filterContoursPipe.setParams(filterContoursParams);
Collect2dTargetsPipe.Collect2dTargetsParams collect2dTargetsParams =
new Collect2dTargetsPipe.Collect2dTargetsParams(
settings.offsetRobotOffsetMode,
settings.offsetSinglePoint,
dualOffsetValues,
settings.contourTargetOffsetPointEdge,
settings.contourTargetOrientation,
frameStaticProperties);
collect2dTargetsPipe.setParams(collect2dTargetsParams);
}
@Override
@@ -60,31 +97,35 @@ public class ObjectDetectionPipeline
// ***************** change based on backend ***********************
CVPipeResult<List<NeuralNetworkPipeResult>> ret = rknnPipe.run(input_frame.colorImage);
sumPipeNanosElapsed += ret.nanosElapsed;
CVPipeResult<List<NeuralNetworkPipeResult>> rknnResult = rknnPipe.run(input_frame.colorImage);
sumPipeNanosElapsed += rknnResult.nanosElapsed;
List<NeuralNetworkPipeResult> targetList;
targetList = ret.output;
var names = rknnPipe.getClassNames();
input_frame.colorImage.getMat().copyTo(input_frame.processedImage.getMat());
// ***************** change based on backend ***********************
List<TrackedTarget> targets = new ArrayList<>();
var filterContoursResult = filterContoursPipe.run(rknnResult.output);
sumPipeNanosElapsed += filterContoursResult.nanosElapsed;
for (var t : targetList) {
targets.add(
new TrackedTarget(
t,
new TargetCalculationParameters(
false, null, null, null, null, frameStaticProperties)));
}
CVPipeResult<List<PotentialTarget>> sortContoursResult =
sortContoursPipe.run(
filterContoursResult.output.stream()
.map(shape -> new PotentialTarget(shape))
.collect(Collectors.toList()));
sumPipeNanosElapsed += sortContoursResult.nanosElapsed;
CVPipeResult<List<TrackedTarget>> collect2dTargetsResult =
collect2dTargetsPipe.run(sortContoursResult.output);
sumPipeNanosElapsed += collect2dTargetsResult.nanosElapsed;
var fpsResult = calculateFPSPipe.run(null);
var fps = fpsResult.output;
return new CVPipelineResult(sumPipeNanosElapsed, fps, targets, input_frame, names);
return new CVPipelineResult(
sumPipeNanosElapsed, fps, collect2dTargetsResult.output, input_frame, names);
}
@Override

View File

@@ -64,29 +64,6 @@ public class ReflectivePipeline extends CVPipeline<CVPipelineResult, ReflectiveP
settings.offsetDualPointB,
settings.offsetDualPointBArea);
// var rotateImageParams = new
// RotateImagePipe.RotateImageParams(settings.inputImageRotationMode);
// rotateImagePipe.setParams(rotateImageParams);
// if (cameraQuirks.hasQuirk(CameraQuirk.PiCam) && LibCameraJNI.isSupported()) {
// LibCameraJNI.setThresholds(
// settings.hsvHue.getFirst() / 180d,
// settings.hsvSaturation.getFirst() / 255d,
// settings.hsvValue.getFirst() / 255d,
// settings.hsvHue.getSecond() / 180d,
// settings.hsvSaturation.getSecond() / 255d,
// settings.hsvValue.getSecond() / 255d);
// // LibCameraJNI.setInvertHue(settings.hueInverted);
// LibCameraJNI.setRotation(settings.inputImageRotationMode.value);
// // LibCameraJNI.setShouldCopyColor(settings.inputShouldShow);
// } else {
// var hsvParams =
// new HSVPipe.HSVParams(
// settings.hsvHue, settings.hsvSaturation, settings.hsvValue,
// settings.hueInverted);
// hsvPipe.setParams(hsvParams);
// }
var findContoursParams = new FindContoursPipe.FindContoursParams();
findContoursPipe.setParams(findContoursParams);
@@ -113,7 +90,7 @@ public class ReflectivePipeline extends CVPipeline<CVPipelineResult, ReflectiveP
var sortContoursParams =
new SortContoursPipe.SortContoursParams(
settings.contourSortMode,
settings.outputShowMultipleTargets ? 8 : 1, // TODO don't hardcode?
settings.outputShowMultipleTargets ? MAX_MULTI_TARGET_RESULTS : 1,
frameStaticProperties);
sortContoursPipe.setParams(sortContoursParams);

View File

@@ -98,8 +98,7 @@ public class VisionRunner {
var pipelineResult = pipeline.run(frame, cameraQuirks);
pipelineResultConsumer.accept(pipelineResult);
} catch (Exception ex) {
logger.error("Exception on loop " + loopCount);
ex.printStackTrace();
logger.error("Exception on loop " + loopCount, ex);
}
loopCount++;

View File

@@ -21,7 +21,9 @@ import java.util.List;
import org.opencv.core.RotatedRect;
import org.photonvision.vision.opencv.CVShape;
import org.photonvision.vision.opencv.Contour;
import org.photonvision.vision.opencv.ContourShape;
import org.photonvision.vision.opencv.Releasable;
import org.photonvision.vision.pipe.impl.NeuralNetworkPipeResult;
public class PotentialTarget implements Releasable {
@@ -29,6 +31,10 @@ public class PotentialTarget implements Releasable {
public final List<Contour> m_subContours;
public final CVShape shape;
// additional metadata about object detections we need to keep around
public final double confidence;
public final int clsId;
public PotentialTarget(Contour inputContour) {
this(inputContour, List.of());
}
@@ -41,12 +47,26 @@ public class PotentialTarget implements Releasable {
m_mainContour = inputContour;
m_subContours = new ArrayList<>(subContours);
this.shape = shape;
this.clsId = -1;
this.confidence = -1;
}
public PotentialTarget(Contour inputContour, CVShape shape) {
this(inputContour, List.of(), shape);
}
public PotentialTarget(NeuralNetworkPipeResult det) {
this.shape = new CVShape(new Contour(det.box), ContourShape.Quadrilateral);
this.m_mainContour = this.shape.getContour();
m_subContours = List.of();
this.clsId = det.classIdx;
this.confidence = det.confidence;
}
public PotentialTarget(CVShape cvShape) {
this(cvShape.getContour(), cvShape);
}
public RotatedRect getMinAreaRect() {
return m_mainContour.getMinAreaRect();
}
@@ -61,7 +81,7 @@ public class PotentialTarget implements Releasable {
for (var sc : m_subContours) {
sc.release();
}
m_subContours.clear();
if (!m_subContours.isEmpty()) m_subContours.clear();
if (shape != null) shape.release();
}
}

View File

@@ -27,7 +27,6 @@ import org.opencv.core.Mat;
import org.opencv.core.MatOfPoint;
import org.opencv.core.MatOfPoint2f;
import org.opencv.core.Point;
import org.opencv.core.Rect2d;
import org.opencv.core.RotatedRect;
import org.photonvision.common.util.SerializationUtils;
import org.photonvision.common.util.math.MathUtils;
@@ -39,7 +38,6 @@ import org.photonvision.vision.opencv.CVShape;
import org.photonvision.vision.opencv.Contour;
import org.photonvision.vision.opencv.DualOffsetValues;
import org.photonvision.vision.opencv.Releasable;
import org.photonvision.vision.pipe.impl.NeuralNetworkPipeResult;
public class TrackedTarget implements Releasable {
public final Contour m_mainContour;
@@ -76,6 +74,9 @@ public class TrackedTarget implements Releasable {
this.m_subContours = origTarget.m_subContours;
this.m_shape = shape;
calculateValues(params);
this.m_classId = origTarget.clsId;
this.m_confidence = origTarget.confidence;
}
public TrackedTarget(
@@ -159,47 +160,6 @@ public class TrackedTarget implements Releasable {
m_robotOffsetPoint = new Point();
}
public TrackedTarget(
Rect2d box, int class_id, double confidence, TargetCalculationParameters params) {
m_targetOffsetPoint = new Point(box.x + box.width / 2.0, box.y + box.height / 2.0);
m_robotOffsetPoint = new Point();
var yawPitch =
TargetCalculations.calculateYawPitch(
params.cameraCenterPoint.x,
box.x + box.width / 2.0,
params.horizontalFocalLength,
params.cameraCenterPoint.y,
box.y + box.height / 2.0,
params.verticalFocalLength);
m_yaw = yawPitch.getFirst();
m_pitch = yawPitch.getSecond();
Point[] cornerPoints =
new Point[] {
// Box.x/y is the top-left corner, not the center
new Point(box.x, box.y), // tl
new Point(box.x + box.width, box.y), // tr
new Point(box.x + box.width, box.y + box.height), // br
new Point(box.x, box.y + box.height), // bl
};
m_targetCorners = List.of(cornerPoints);
MatOfPoint contourMat = new MatOfPoint(cornerPoints);
m_approximateBoundingPolygon = new MatOfPoint2f(cornerPoints);
m_mainContour = new Contour(contourMat);
m_area = m_mainContour.getArea() / params.imageArea * 100;
m_classId = class_id;
m_confidence = confidence;
}
public TrackedTarget(
NeuralNetworkPipeResult t, TargetCalculationParameters targetCalculationParameters) {
this(t.box, t.classIdx, t.confidence, targetCalculationParameters);
}
/**
* @return Returns the confidence of the detection ranging from 0 - 1.
*/

View File

@@ -435,7 +435,7 @@ class PhotonCameraSim {
double minTargetAreaPercent;
frc::AprilTagFieldLayout tagLayout{
frc::LoadAprilTagLayoutField(frc::AprilTagField::k2023ChargedUp)};
frc::LoadAprilTagLayoutField(frc::AprilTagField::k2024Crescendo)};
cs::CvSource videoSimRaw;
cv::Mat videoSimFrameRaw{};

View File

@@ -138,7 +138,6 @@ public class Server {
app.post("/api/calibration/importFromData", RequestHandler::onDataCalibrationImportRequest);
app.start(port);
System.out.println("hi");
}
/**

View File

@@ -35,48 +35,48 @@
namespace constants {
namespace Vision {
static constexpr std::string_view kCameraName{"YOUR CAMERA NAME"};
static const frc::Transform3d kRobotToCam{
inline constexpr std::string_view kCameraName{"YOUR CAMERA NAME"};
inline const frc::Transform3d kRobotToCam{
frc::Translation3d{0.5_m, 0.0_m, 0.5_m},
frc::Rotation3d{0_rad, 0_rad, 0_rad}};
static const frc::AprilTagFieldLayout kTagLayout{
frc::LoadAprilTagLayoutField(frc::AprilTagField::k2023ChargedUp)};
inline const frc::AprilTagFieldLayout kTagLayout{
frc::LoadAprilTagLayoutField(frc::AprilTagField::k2024Crescendo)};
static const Eigen::Matrix<double, 3, 1> kSingleTagStdDevs{4, 4, 8};
static const Eigen::Matrix<double, 3, 1> kMultiTagStdDevs{0.5, 0.5, 1};
inline const Eigen::Matrix<double, 3, 1> kSingleTagStdDevs{4, 4, 8};
inline const Eigen::Matrix<double, 3, 1> kMultiTagStdDevs{0.5, 0.5, 1};
} // namespace Vision
namespace Swerve {
static constexpr units::meter_t kTrackWidth{18.5_in};
static constexpr units::meter_t kTrackLength{18.5_in};
static constexpr units::meter_t kRobotWidth{25_in + 3.25_in * 2};
static constexpr units::meter_t kRobotLength{25_in + 3.25_in * 2};
static constexpr units::meters_per_second_t kMaxLinearSpeed{15.5_fps};
static constexpr units::radians_per_second_t kMaxAngularSpeed{720_deg_per_s};
static constexpr units::meter_t kWheelDiameter{4_in};
static constexpr units::meter_t kWheelCircumference{kWheelDiameter *
inline constexpr units::meter_t kTrackWidth{18.5_in};
inline constexpr units::meter_t kTrackLength{18.5_in};
inline constexpr units::meter_t kRobotWidth{25_in + 3.25_in * 2};
inline constexpr units::meter_t kRobotLength{25_in + 3.25_in * 2};
inline constexpr units::meters_per_second_t kMaxLinearSpeed{15.5_fps};
inline constexpr units::radians_per_second_t kMaxAngularSpeed{720_deg_per_s};
inline constexpr units::meter_t kWheelDiameter{4_in};
inline constexpr units::meter_t kWheelCircumference{kWheelDiameter *
std::numbers::pi};
static constexpr double kDriveGearRatio = 6.75;
static constexpr double kSteerGearRatio = 12.8;
inline constexpr double kDriveGearRatio = 6.75;
inline constexpr double kSteerGearRatio = 12.8;
static constexpr units::meter_t kDriveDistPerPulse =
inline constexpr units::meter_t kDriveDistPerPulse =
kWheelCircumference / 1024.0 / kDriveGearRatio;
static constexpr units::radian_t kSteerRadPerPulse =
inline constexpr units::radian_t kSteerRadPerPulse =
units::radian_t{2 * std::numbers::pi} / 1024.0;
static constexpr double kDriveKP = 1.0;
static constexpr double kDriveKI = 0.0;
static constexpr double kDriveKD = 0.0;
inline constexpr double kDriveKP = 1.0;
inline constexpr double kDriveKI = 0.0;
inline constexpr double kDriveKD = 0.0;
static constexpr double kSteerKP = 20.0;
static constexpr double kSteerKI = 0.0;
static constexpr double kSteerKD = 0.25;
inline constexpr double kSteerKP = 20.0;
inline constexpr double kSteerKI = 0.0;
inline constexpr double kSteerKD = 0.25;
static const frc::SimpleMotorFeedforward<units::meters> kDriveFF{
inline const frc::SimpleMotorFeedforward<units::meters> kDriveFF{
0.25_V, 2.5_V / 1_mps, 0.3_V / 1_mps_sq};
static const frc::SimpleMotorFeedforward<units::radians> kSteerFF{
inline const frc::SimpleMotorFeedforward<units::radians> kSteerFF{
0.5_V, 0.25_V / 1_rad_per_s, 0.01_V / 1_rad_per_s_sq};
struct ModuleConstants {
@@ -106,13 +106,13 @@ struct ModuleConstants {
centerOffset(frc::Translation2d{xOffset, yOffset}) {}
};
static const ModuleConstants FL_CONSTANTS{
inline const ModuleConstants FL_CONSTANTS{
1, 0, 0, 1, 1, 2, 3, 0, kTrackLength / 2, kTrackWidth / 2};
static const ModuleConstants FR_CONSTANTS{
inline const ModuleConstants FR_CONSTANTS{
2, 2, 4, 5, 3, 6, 7, 0, kTrackLength / 2, -kTrackWidth / 2};
static const ModuleConstants BL_CONSTANTS{
inline const ModuleConstants BL_CONSTANTS{
3, 4, 8, 9, 5, 10, 11, 0, -kTrackLength / 2, kTrackWidth / 2};
static const ModuleConstants BR_CONSTANTS{
inline const ModuleConstants BR_CONSTANTS{
4, 6, 12, 13, 7, 14, 15, 0, -kTrackLength / 2, -kTrackWidth / 2};
} // namespace Swerve
} // namespace constants

View File

@@ -61,7 +61,7 @@ class Vision {
cameraSim = std::make_shared<photon::PhotonCameraSim>(camera.get(),
*cameraProp.get());
visionSim->AddCamera(cameraSim.get(), robotToCam);
visionSim->AddCamera(cameraSim.get(), constants::Vision::kRobotToCam);
cameraSim->EnableDrawWireframe(true);
}
}
@@ -138,12 +138,10 @@ class Vision {
frc::Field2d& GetSimDebugField() { return visionSim->GetDebugField(); }
private:
frc::Transform3d robotToCam{frc::Translation3d{0.5_m, 0.5_m, 0.5_m},
frc::Rotation3d{}};
photon::PhotonPoseEstimator photonEstimator{
LoadAprilTagLayoutField(frc::AprilTagField::k2023ChargedUp),
constants::Vision::kTagLayout,
photon::PoseStrategy::MULTI_TAG_PNP_ON_COPROCESSOR,
photon::PhotonCamera{"photonvision"}, robotToCam};
photon::PhotonCamera{"photonvision"}, constants::Vision::kRobotToCam};
std::shared_ptr<photon::PhotonCamera> camera{photonEstimator.GetCamera()};
std::unique_ptr<photon::VisionSystemSim> visionSim;
std::unique_ptr<photon::SimCameraProperties> cameraProp;