blob: 7e50b096474da5119d3bacbf4d050db0bd2e24fd [file] [log] [blame]
#include <string>
#include "absl/log/check.h"
#include "absl/log/log.h"
#include "gtest/gtest.h"
#include "aos/events/simulated_event_loop.h"
#include "aos/flatbuffer_merge.h"
#include "aos/json_to_flatbuffer.h"
#include "aos/testing/path.h"
#include "frc971/constants/constants_sender_lib.h"
#include "frc971/vision/target_mapper.h"
#include "frc971/vision/vision_generated.h"
#include "frc971/vision/vision_util_lib.h"
#include "y2023/constants/constants_generated.h"
#include "y2023/constants/constants_list_generated.h"
#include "y2023/vision/aprilrobotics.h"
namespace y2023::vision::testing {
class AprilDetectionTest : public ::testing::Test {
public:
AprilDetectionTest()
: config_(aos::configuration::ReadConfig("y2023/aos_config.json")),
event_loop_factory_(&config_.message()),
pi_(aos::configuration::GetNode(event_loop_factory_.configuration(),
"pi4")),
send_pose_event_loop_(
event_loop_factory_.MakeEventLoop("Send pose", pi_)),
receive_pose_event_loop_(
event_loop_factory_.MakeEventLoop("Receive pose", pi_)),
april_pose_fetcher_(
receive_pose_event_loop_->MakeFetcher<frc971::vision::TargetMap>(
"/camera")),
image_sender_(
receive_pose_event_loop_->MakeSender<frc971::vision::CameraImage>(
"/camera")),
constants_sender_(receive_pose_event_loop_.get(),
"y2023/constants/constants.json", 7971, "/constants"),
detector_(
AprilRoboticsDetector(send_pose_event_loop_.get(), "/camera")) {
event_loop_factory_.RunFor(std::chrono::milliseconds(5));
}
void SendImage(std::string path) {
aos::FlatbufferVector<frc971::vision::CameraImage> image =
aos::FileToFlatbuffer<frc971::vision::CameraImage>(
"external/apriltag_test_bfbs_images/" + path);
auto builder = image_sender_.MakeBuilder();
flatbuffers::Offset<frc971::vision::CameraImage> image_fbs =
aos::CopyFlatBuffer(image, builder.fbb());
builder.CheckOk(builder.Send(image_fbs));
}
void TestDistanceAngle(std::string image_path, double expected_distance,
double expected_angle) {
SendImage(image_path);
event_loop_factory_.RunFor(std::chrono::milliseconds(5));
ASSERT_TRUE(april_pose_fetcher_.Fetch());
ASSERT_EQ(april_pose_fetcher_->target_poses()->size(), 1);
frc971::vision::TargetMapper::TargetPose target_pose =
frc971::vision::TargetMapper::TargetPoseFromFbs(
*april_pose_fetcher_->target_poses()->Get(0));
ASSERT_EQ(april_pose_fetcher_->target_poses()->Get(0)->id(), 8);
// Height
EXPECT_NEAR(target_pose.pose.p.y(), -0.28, 0.05);
// Tag to camera horizontal distance
double distance_norm =
sqrt(pow(target_pose.pose.p.x(), 2) + pow(target_pose.pose.p.z(), 2));
EXPECT_NEAR(distance_norm, expected_distance, 0.1);
Eigen::Vector3d rotation_euler =
frc971::vision::PoseUtils::QuaternionToEulerAngles(target_pose.pose.q);
EXPECT_NEAR(rotation_euler[0], 0, 0.1);
EXPECT_NEAR(rotation_euler[1], expected_angle, 0.05);
EXPECT_NEAR(rotation_euler[2], 0, 0.1);
}
aos::FlatbufferDetachedBuffer<aos::Configuration> config_;
aos::SimulatedEventLoopFactory event_loop_factory_;
const aos::Node *const pi_;
::std::unique_ptr<::aos::EventLoop> send_pose_event_loop_;
::std::unique_ptr<::aos::EventLoop> receive_pose_event_loop_;
aos::Fetcher<frc971::vision::TargetMap> april_pose_fetcher_;
aos::Sender<frc971::vision::CameraImage> image_sender_;
frc971::constants::ConstantSender<y2023::Constants, y2023::ConstantsList>
constants_sender_;
AprilRoboticsDetector detector_;
};
TEST_F(AprilDetectionTest, CheckPose5Feet) {
TestDistanceAngle("bfbs-capture-2013-01-18_08-54-09.501047728.bfbs", 1.5, 0);
TestDistanceAngle("bfbs-capture-2013-01-18_08-54-16.869057537.bfbs", 1.5,
0.22);
TestDistanceAngle("bfbs-capture-2013-01-18_08-54-24.931661979.bfbs", 1.5,
-0.37);
}
TEST_F(AprilDetectionTest, CheckPose10Feet) {
TestDistanceAngle("bfbs-capture-2013-01-18_08-51-24.861065764.bfbs", 3.07, 0);
TestDistanceAngle("bfbs-capture-2013-01-18_08-52-01.846912552.bfbs", 3.07,
0.31);
TestDistanceAngle("bfbs-capture-2013-01-18_08-52-33.462848049.bfbs", 3.07,
-0.27);
}
TEST_F(AprilDetectionTest, CheckPose15Feet) {
// The camera was not at a perfect angle of 0, so the angle is -0.15 radians
// instead of 0
TestDistanceAngle("bfbs-capture-2013-01-18_09-29-16.806073486.bfbs", 4.57,
-0.15);
TestDistanceAngle("bfbs-capture-2013-01-18_09-33-00.993756514.bfbs", 4.57,
0.38);
}
TEST_F(AprilDetectionTest, CheckPose20Feet) {
// The camera was not at a perfect angle of 0, so the angle is 0.09 radians
// instead of 0
TestDistanceAngle("bfbs-capture-2013-01-18_08-57-00.171120695.bfbs", 6.06,
0.09);
TestDistanceAngle("bfbs-capture-2013-01-18_08-57-17.858752817.bfbs", 6.06,
0.35);
TestDistanceAngle("bfbs-capture-2013-01-18_08-57-08.096597542.bfbs", 6.06,
-0.45);
}
} // namespace y2023::vision::testing