blob: 9f4f8b77e733b27a40afc92a769bc053be73395d [file] [log] [blame]
Yash Chainani10b7b022023-02-22 14:34:04 -08001#include <string>
2
Austin Schuh99f7c6a2024-06-25 22:07:44 -07003#include "absl/log/check.h"
4#include "absl/log/log.h"
Philipp Schrader790cb542023-07-05 21:06:52 -07005#include "gtest/gtest.h"
6
Yash Chainani10b7b022023-02-22 14:34:04 -08007#include "aos/events/simulated_event_loop.h"
8#include "aos/flatbuffer_merge.h"
9#include "aos/json_to_flatbuffer.h"
10#include "aos/testing/path.h"
Yash Chainani10b7b022023-02-22 14:34:04 -080011#include "frc971/constants/constants_sender_lib.h"
12#include "frc971/vision/target_mapper.h"
13#include "frc971/vision/vision_generated.h"
Yash Chainani10b7b022023-02-22 14:34:04 -080014#include "y2023/constants/constants_generated.h"
15#include "y2023/constants/constants_list_generated.h"
Philipp Schrader790cb542023-07-05 21:06:52 -070016#include "y2023/vision/aprilrobotics.h"
Yash Chainani10b7b022023-02-22 14:34:04 -080017
18namespace y2023::vision::testing {
19class AprilDetectionTest : public ::testing::Test {
20 public:
21 AprilDetectionTest()
22 : config_(aos::configuration::ReadConfig("y2023/aos_config.json")),
23 event_loop_factory_(&config_.message()),
24 pi_(aos::configuration::GetNode(event_loop_factory_.configuration(),
25 "pi4")),
26 send_pose_event_loop_(
27 event_loop_factory_.MakeEventLoop("Send pose", pi_)),
28 receive_pose_event_loop_(
29 event_loop_factory_.MakeEventLoop("Receive pose", pi_)),
30 april_pose_fetcher_(
31 receive_pose_event_loop_->MakeFetcher<frc971::vision::TargetMap>(
32 "/camera")),
33 image_sender_(
34 receive_pose_event_loop_->MakeSender<frc971::vision::CameraImage>(
35 "/camera")),
36 constants_sender_(receive_pose_event_loop_.get(),
37 "y2023/constants/constants.json", 7971, "/constants"),
38 detector_(
Austin Schuhd027bf52024-05-12 22:24:12 -070039 AprilRoboticsDetector(send_pose_event_loop_.get(), "/camera")) {
40 event_loop_factory_.RunFor(std::chrono::milliseconds(5));
41 }
Yash Chainani10b7b022023-02-22 14:34:04 -080042
43 void SendImage(std::string path) {
44 aos::FlatbufferVector<frc971::vision::CameraImage> image =
45 aos::FileToFlatbuffer<frc971::vision::CameraImage>(
46 "external/apriltag_test_bfbs_images/" + path);
47
48 auto builder = image_sender_.MakeBuilder();
49 flatbuffers::Offset<frc971::vision::CameraImage> image_fbs =
50 aos::CopyFlatBuffer(image, builder.fbb());
51
52 builder.CheckOk(builder.Send(image_fbs));
53 }
54
55 void TestDistanceAngle(std::string image_path, double expected_distance,
56 double expected_angle) {
Austin Schuhd027bf52024-05-12 22:24:12 -070057 SendImage(image_path);
Yash Chainani10b7b022023-02-22 14:34:04 -080058 event_loop_factory_.RunFor(std::chrono::milliseconds(5));
59
60 ASSERT_TRUE(april_pose_fetcher_.Fetch());
61 ASSERT_EQ(april_pose_fetcher_->target_poses()->size(), 1);
62
63 frc971::vision::TargetMapper::TargetPose target_pose =
64 frc971::vision::PoseUtils::TargetPoseFromFbs(
65 *april_pose_fetcher_->target_poses()->Get(0));
66
67 ASSERT_EQ(april_pose_fetcher_->target_poses()->Get(0)->id(), 8);
68
69 // Height
70 EXPECT_NEAR(target_pose.pose.p.y(), -0.28, 0.05);
71
72 // Tag to camera horizontal distance
73 double distance_norm =
74 sqrt(pow(target_pose.pose.p.x(), 2) + pow(target_pose.pose.p.z(), 2));
75 EXPECT_NEAR(distance_norm, expected_distance, 0.1);
76
77 Eigen::Vector3d rotation_euler =
78 frc971::vision::PoseUtils::QuaternionToEulerAngles(target_pose.pose.q);
79
80 EXPECT_NEAR(rotation_euler[0], 0, 0.1);
81 EXPECT_NEAR(rotation_euler[1], expected_angle, 0.05);
82 EXPECT_NEAR(rotation_euler[2], 0, 0.1);
83 }
84
85 aos::FlatbufferDetachedBuffer<aos::Configuration> config_;
86 aos::SimulatedEventLoopFactory event_loop_factory_;
87 const aos::Node *const pi_;
88 ::std::unique_ptr<::aos::EventLoop> send_pose_event_loop_;
89 ::std::unique_ptr<::aos::EventLoop> receive_pose_event_loop_;
90 aos::Fetcher<frc971::vision::TargetMap> april_pose_fetcher_;
91 aos::Sender<frc971::vision::CameraImage> image_sender_;
92 frc971::constants::ConstantSender<y2023::Constants, y2023::ConstantsList>
93 constants_sender_;
94 AprilRoboticsDetector detector_;
95};
96
97TEST_F(AprilDetectionTest, CheckPose5Feet) {
98 TestDistanceAngle("bfbs-capture-2013-01-18_08-54-09.501047728.bfbs", 1.5, 0);
99 TestDistanceAngle("bfbs-capture-2013-01-18_08-54-16.869057537.bfbs", 1.5,
100 0.22);
101 TestDistanceAngle("bfbs-capture-2013-01-18_08-54-24.931661979.bfbs", 1.5,
102 -0.37);
103}
104
105TEST_F(AprilDetectionTest, CheckPose10Feet) {
106 TestDistanceAngle("bfbs-capture-2013-01-18_08-51-24.861065764.bfbs", 3.07, 0);
107 TestDistanceAngle("bfbs-capture-2013-01-18_08-52-01.846912552.bfbs", 3.07,
108 0.31);
109 TestDistanceAngle("bfbs-capture-2013-01-18_08-52-33.462848049.bfbs", 3.07,
110 -0.27);
111}
112
113TEST_F(AprilDetectionTest, CheckPose15Feet) {
114 // The camera was not at a perfect angle of 0, so the angle is -0.15 radians
115 // instead of 0
116 TestDistanceAngle("bfbs-capture-2013-01-18_09-29-16.806073486.bfbs", 4.57,
117 -0.15);
118 TestDistanceAngle("bfbs-capture-2013-01-18_09-33-00.993756514.bfbs", 4.57,
119 0.38);
120}
121
122TEST_F(AprilDetectionTest, CheckPose20Feet) {
123 // The camera was not at a perfect angle of 0, so the angle is 0.09 radians
124 // instead of 0
125 TestDistanceAngle("bfbs-capture-2013-01-18_08-57-00.171120695.bfbs", 6.06,
126 0.09);
127 TestDistanceAngle("bfbs-capture-2013-01-18_08-57-17.858752817.bfbs", 6.06,
128 0.35);
129 TestDistanceAngle("bfbs-capture-2013-01-18_08-57-08.096597542.bfbs", 6.06,
130 -0.45);
131}
132} // namespace y2023::vision::testing