mirror of
https://github.com/PhotonVision/photonvision
synced 2026-06-24 01:31:44 +00:00
Send corners of min area rectangles (#382)
Adds a new corners entry to targets. Breaks byte-packed backwards compatibility. Co-authored-by: Tyler Veness <calcmogul@gmail.com>
This commit is contained in:
@@ -20,7 +20,9 @@ import edu.wpi.first.math.geometry.Pose2d;
|
||||
import edu.wpi.first.math.geometry.Transform2d;
|
||||
import edu.wpi.first.math.util.Units;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import org.photonvision.targeting.PhotonTrackedTarget;
|
||||
import org.photonvision.targeting.TargetCorner;
|
||||
|
||||
public class SimVisionSystem {
|
||||
SimPhotonCamera cam;
|
||||
@@ -151,8 +153,17 @@ public class SimVisionSystem {
|
||||
- this.camPitchDegrees;
|
||||
|
||||
if (camCanSeeTarget(distMeters, yawDegrees, pitchDegrees, area)) {
|
||||
// TODO simulate target corners
|
||||
visibleTgtList.add(
|
||||
new PhotonTrackedTarget(yawDegrees, pitchDegrees, area, 0.0, camToTargetTrans));
|
||||
new PhotonTrackedTarget(
|
||||
yawDegrees,
|
||||
pitchDegrees,
|
||||
area,
|
||||
0.0,
|
||||
camToTargetTrans,
|
||||
List.of(
|
||||
new TargetCorner(0, 0), new TargetCorner(0, 0),
|
||||
new TargetCorner(0, 0), new TargetCorner(0, 0))));
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
@@ -18,19 +18,28 @@
|
||||
#include "photonlib/PhotonTrackedTarget.h"
|
||||
|
||||
#include <iostream>
|
||||
#include <utility>
|
||||
|
||||
#include <frc/geometry/Translation2d.h>
|
||||
#include <wpi/SmallVector.h>
|
||||
|
||||
namespace photonlib {
|
||||
|
||||
PhotonTrackedTarget::PhotonTrackedTarget(double yaw, double pitch, double area,
|
||||
double skew,
|
||||
const frc::Transform2d& pose)
|
||||
: yaw(yaw), pitch(pitch), area(area), skew(skew), cameraToTarget(pose) {}
|
||||
PhotonTrackedTarget::PhotonTrackedTarget(
|
||||
double yaw, double pitch, double area, double skew,
|
||||
const frc::Transform2d& pose,
|
||||
const wpi::SmallVector<std::pair<double, double>, 4> corners)
|
||||
: yaw(yaw),
|
||||
pitch(pitch),
|
||||
area(area),
|
||||
skew(skew),
|
||||
cameraToTarget(pose),
|
||||
corners(corners) {}
|
||||
|
||||
bool PhotonTrackedTarget::operator==(const PhotonTrackedTarget& other) const {
|
||||
return other.yaw == yaw && other.pitch == pitch && other.area == area &&
|
||||
other.skew == skew && other.cameraToTarget == cameraToTarget;
|
||||
other.skew == skew && other.cameraToTarget == cameraToTarget &&
|
||||
other.corners == corners;
|
||||
}
|
||||
|
||||
bool PhotonTrackedTarget::operator!=(const PhotonTrackedTarget& other) const {
|
||||
@@ -38,10 +47,16 @@ bool PhotonTrackedTarget::operator!=(const PhotonTrackedTarget& other) const {
|
||||
}
|
||||
|
||||
Packet& operator<<(Packet& packet, const PhotonTrackedTarget& target) {
|
||||
return packet << target.yaw << target.pitch << target.area << target.skew
|
||||
<< target.cameraToTarget.Translation().X().value()
|
||||
<< target.cameraToTarget.Translation().Y().value()
|
||||
<< target.cameraToTarget.Rotation().Degrees().value();
|
||||
packet << target.yaw << target.pitch << target.area << target.skew
|
||||
<< target.cameraToTarget.Translation().X().value()
|
||||
<< target.cameraToTarget.Translation().Y().value()
|
||||
<< target.cameraToTarget.Rotation().Degrees().value();
|
||||
|
||||
for (int i = 0; i < 4; i++) {
|
||||
packet << target.corners[i].first << target.corners[i].second;
|
||||
}
|
||||
|
||||
return packet;
|
||||
}
|
||||
|
||||
Packet& operator>>(Packet& packet, PhotonTrackedTarget& target) {
|
||||
@@ -54,6 +69,15 @@ Packet& operator>>(Packet& packet, PhotonTrackedTarget& target) {
|
||||
target.cameraToTarget =
|
||||
frc::Transform2d(frc::Translation2d(units::meter_t(x), units::meter_t(y)),
|
||||
units::degree_t(rot));
|
||||
|
||||
target.corners.clear();
|
||||
for (int i = 0; i < 4; i++) {
|
||||
double first = 0;
|
||||
double second = 0;
|
||||
packet >> first >> second;
|
||||
target.corners.emplace_back(first, second);
|
||||
}
|
||||
|
||||
return packet;
|
||||
}
|
||||
|
||||
|
||||
@@ -86,7 +86,8 @@ void SimVisionSystem::ProcessFrame(frc::Pose2d robotPose) {
|
||||
|
||||
if (CamCanSeeTarget(distHypot, yawAngle, pitchAngle, area)) {
|
||||
PhotonTrackedTarget newTgt = PhotonTrackedTarget(
|
||||
yawAngle.value(), pitchAngle.value(), area, 0.0, camToTargetTrans);
|
||||
yawAngle.value(), pitchAngle.value(), area, 0.0, camToTargetTrans,
|
||||
{std::pair{1, 2}, std::pair{3, 4}, std::pair{5, 6}, std::pair{7, 8}});
|
||||
visibleTgtList.push_back(newTgt);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -19,9 +19,11 @@
|
||||
|
||||
#include <cstddef>
|
||||
#include <string>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
#include <frc/geometry/Transform2d.h>
|
||||
#include <wpi/SmallVector.h>
|
||||
|
||||
#include "photonlib/Packet.h"
|
||||
|
||||
@@ -43,9 +45,12 @@ class PhotonTrackedTarget {
|
||||
* @param area The area of the target.
|
||||
* @param skew The skew of the target.
|
||||
* @param pose The camera-relative pose of the target.
|
||||
* @Param corners The corners of the bounding rectangle.
|
||||
*/
|
||||
PhotonTrackedTarget(double yaw, double pitch, double area, double skew,
|
||||
const frc::Transform2d& pose);
|
||||
PhotonTrackedTarget(
|
||||
double yaw, double pitch, double area, double skew,
|
||||
const frc::Transform2d& pose,
|
||||
const wpi::SmallVector<std::pair<double, double>, 4> corners);
|
||||
|
||||
/**
|
||||
* Returns the target yaw (positive-left).
|
||||
@@ -71,6 +76,13 @@ class PhotonTrackedTarget {
|
||||
*/
|
||||
double GetSkew() const { return skew; }
|
||||
|
||||
/**
|
||||
* Returns the corners of the minimum area rectangle bounding this target.
|
||||
*/
|
||||
wpi::SmallVector<std::pair<double, double>, 4> GetCorners() const {
|
||||
return corners;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the pose of the target relative to the robot.
|
||||
* @return The pose of the target relative to the robot.
|
||||
@@ -89,5 +101,6 @@ class PhotonTrackedTarget {
|
||||
double area = 0;
|
||||
double skew = 0;
|
||||
frc::Transform2d cameraToTarget;
|
||||
wpi::SmallVector<std::pair<double, double>, 4> corners;
|
||||
};
|
||||
} // namespace photonlib
|
||||
|
||||
@@ -26,13 +26,23 @@ import org.junit.jupiter.api.Test;
|
||||
import org.photonvision.common.dataflow.structures.Packet;
|
||||
import org.photonvision.targeting.PhotonPipelineResult;
|
||||
import org.photonvision.targeting.PhotonTrackedTarget;
|
||||
import org.photonvision.targeting.TargetCorner;
|
||||
|
||||
class PacketTest {
|
||||
@Test
|
||||
void testSimpleTrackedTarget() {
|
||||
var target =
|
||||
new PhotonTrackedTarget(
|
||||
3.0, 4.0, 9.0, -5.0, new Transform2d(new Translation2d(1, 2), new Rotation2d(1.5)));
|
||||
3.0,
|
||||
4.0,
|
||||
9.0,
|
||||
-5.0,
|
||||
new Transform2d(new Translation2d(1, 2), new Rotation2d(1.5)),
|
||||
List.of(
|
||||
new TargetCorner(1, 2),
|
||||
new TargetCorner(3, 4),
|
||||
new TargetCorner(5, 6),
|
||||
new TargetCorner(7, 8)));
|
||||
var p = new Packet(PhotonTrackedTarget.PACK_SIZE_BYTES);
|
||||
target.populatePacket(p);
|
||||
|
||||
@@ -62,13 +72,23 @@ class PacketTest {
|
||||
-4.0,
|
||||
9.0,
|
||||
4.0,
|
||||
new Transform2d(new Translation2d(1, 2), new Rotation2d(1.5))),
|
||||
new Transform2d(new Translation2d(1, 2), new Rotation2d(1.5)),
|
||||
List.of(
|
||||
new TargetCorner(1, 2),
|
||||
new TargetCorner(3, 4),
|
||||
new TargetCorner(5, 6),
|
||||
new TargetCorner(7, 8))),
|
||||
new PhotonTrackedTarget(
|
||||
3.0,
|
||||
-4.0,
|
||||
9.1,
|
||||
6.7,
|
||||
new Transform2d(new Translation2d(1, 5), new Rotation2d(1.5)))));
|
||||
new Transform2d(new Translation2d(1, 5), new Rotation2d(1.5)),
|
||||
List.of(
|
||||
new TargetCorner(1, 2),
|
||||
new TargetCorner(3, 4),
|
||||
new TargetCorner(5, 6),
|
||||
new TargetCorner(7, 8)))));
|
||||
var p2 = new Packet(result2.getPacketSize());
|
||||
result2.populatePacket(p2);
|
||||
|
||||
@@ -77,46 +97,4 @@ class PacketTest {
|
||||
|
||||
Assertions.assertEquals(result2, b2);
|
||||
}
|
||||
|
||||
@Test
|
||||
void testBytePackFromCpp() {
|
||||
byte[] bytePack = {
|
||||
64, 8, 0, 0, 0, 0, 0, 0, 64, 16, 0, 0, 0, 0, 0, 0, 64, 34, 0, 0, 0, 0, 0, 0, -64, 20, 0, 0, 0,
|
||||
0, 0, 0, 63, -16, 0, 0, 0, 0, 0, 0, 64, 0, 0, 0, 0, 0, 0, 0, 64, 85, 124, 101, 19, -54, -47,
|
||||
122
|
||||
};
|
||||
var t = new PhotonTrackedTarget();
|
||||
t.createFromPacket(new Packet(bytePack));
|
||||
|
||||
var target =
|
||||
new PhotonTrackedTarget(
|
||||
3.0, 4.0, 9.0, -5.0, new Transform2d(new Translation2d(1, 2), new Rotation2d(1.5)));
|
||||
|
||||
Assertions.assertEquals(t, target);
|
||||
}
|
||||
|
||||
@Test
|
||||
void testPacketv2021_1_6() {
|
||||
// From v2021.1.6
|
||||
var simplified =
|
||||
new PhotonPipelineResult(
|
||||
12.34,
|
||||
List.of(
|
||||
new PhotonTrackedTarget(
|
||||
-23, -10, 6, 1, new Transform2d(new Translation2d(1, 2), new Rotation2d(3)))));
|
||||
byte[] bytes = {
|
||||
64, 40, -82, 20, 122, -31, 71, -82, 1, -64, 55, 0, 0, 0, 0, 0, 0, -64, 36, 0, 0, 0, 0, 0, 0,
|
||||
64, 24, 0, 0, 0, 0, 0, 0, 63, -16, 0, 0, 0, 0, 0, 0, 63, -16, 0, 0, 0, 0, 0, 0, 64, 0, 0, 0,
|
||||
0, 0, 0, 0, 64, 101, 124, 101, 19, -54, -47, 122, 0
|
||||
};
|
||||
|
||||
// Let's check that those bytes still mean the same thing
|
||||
Packet packet = new Packet(1);
|
||||
packet.clear();
|
||||
packet.setData(bytes);
|
||||
var ret = new PhotonPipelineResult();
|
||||
ret.createFromPacket(packet);
|
||||
System.out.println(ret);
|
||||
Assertions.assertEquals(simplified, ret);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -25,8 +25,13 @@
|
||||
|
||||
TEST(PacketTest, PhotonTrackedTarget) {
|
||||
photonlib::PhotonTrackedTarget target{
|
||||
3.0, 4.0, 9.0, -5.0,
|
||||
frc::Transform2d(frc::Translation2d(1_m, 2_m), 1.5_rad)};
|
||||
3.0,
|
||||
4.0,
|
||||
9.0,
|
||||
-5.0,
|
||||
frc::Transform2d(frc::Translation2d(1_m, 2_m), 1.5_rad),
|
||||
{std::pair{1, 2}, std::pair{3, 4}, std::pair{5, 6}, std::pair{7, 8}}};
|
||||
|
||||
photonlib::Packet p;
|
||||
p << target;
|
||||
|
||||
@@ -52,11 +57,20 @@ TEST(PacketTest, PhotonPipelineResult) {
|
||||
|
||||
wpi::SmallVector<photonlib::PhotonTrackedTarget, 2> targets{
|
||||
photonlib::PhotonTrackedTarget{
|
||||
3.0, -4.0, 9.0, 4.0,
|
||||
frc::Transform2d(frc::Translation2d(1_m, 2_m), 1.5_rad)},
|
||||
3.0,
|
||||
-4.0,
|
||||
9.0,
|
||||
4.0,
|
||||
frc::Transform2d(frc::Translation2d(1_m, 2_m), 1.5_rad),
|
||||
{std::pair{1, 2}, std::pair{3, 4}, std::pair{5, 6}, std::pair{7, 8}}},
|
||||
photonlib::PhotonTrackedTarget{
|
||||
3.0, -4.0, 9.1, 6.7,
|
||||
frc::Transform2d(frc::Translation2d(1_m, 5_m), 1.5_rad)}};
|
||||
3.0,
|
||||
-4.0,
|
||||
9.1,
|
||||
6.7,
|
||||
frc::Transform2d(frc::Translation2d(1_m, 5_m), 1.5_rad),
|
||||
{std::pair{1, 2}, std::pair{3, 4}, std::pair{5, 6},
|
||||
std::pair{7, 8}}}};
|
||||
|
||||
photonlib::PhotonPipelineResult result2{2_s, targets};
|
||||
photonlib::Packet p2;
|
||||
@@ -67,25 +81,3 @@ TEST(PacketTest, PhotonPipelineResult) {
|
||||
|
||||
EXPECT_EQ(result2, b2);
|
||||
}
|
||||
|
||||
TEST(PacketTest, BytePackFromJava) {
|
||||
std::vector<signed char> bytePack{
|
||||
64, 8, 0, 0, 0, 0, 0, 0, 64, 16, 0, 0, 0, 0,
|
||||
0, 0, 64, 34, 0, 0, 0, 0, 0, 0, -64, 20, 0, 0,
|
||||
0, 0, 0, 0, 63, -16, 0, 0, 0, 0, 0, 0, 64, 0,
|
||||
0, 0, 0, 0, 0, 0, 64, 85, 124, 101, 19, -54, -47, 122};
|
||||
|
||||
std::vector<char> bytes;
|
||||
for (auto a : bytePack) bytes.emplace_back(static_cast<char>(a));
|
||||
|
||||
photonlib::Packet packet{bytes};
|
||||
|
||||
photonlib::PhotonTrackedTarget res;
|
||||
packet >> res;
|
||||
|
||||
photonlib::PhotonTrackedTarget target{
|
||||
3.0, 4.0, 9.0, -5.0,
|
||||
frc::Transform2d(frc::Translation2d(1_m, 2_m), 1.5_rad)};
|
||||
|
||||
EXPECT_EQ(res, target);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user