2022-04-08 21:20:53 -07:00
|
|
|
// Copyright (c) FIRST and other WPILib contributors.
|
|
|
|
|
// Open Source Software; you can modify and/or share it under the terms of
|
|
|
|
|
// the WPILib BSD license file in the root directory of this project.
|
|
|
|
|
|
|
|
|
|
#include "frc/ComputerVisionUtil.h"
|
|
|
|
|
|
2022-10-26 22:20:08 -07:00
|
|
|
#include "frc/geometry/Rotation3d.h"
|
2022-04-08 21:20:53 -07:00
|
|
|
#include "units/math.h"
|
|
|
|
|
|
|
|
|
|
namespace frc {
|
|
|
|
|
|
|
|
|
|
units::meter_t CalculateDistanceToTarget(units::meter_t cameraHeight,
|
|
|
|
|
units::meter_t targetHeight,
|
|
|
|
|
units::radian_t cameraPitch,
|
2022-05-06 18:36:58 +03:00
|
|
|
units::radian_t targetPitch,
|
|
|
|
|
units::radian_t targetYaw) {
|
2022-04-08 21:20:53 -07:00
|
|
|
return (targetHeight - cameraHeight) /
|
2022-05-06 18:36:58 +03:00
|
|
|
(units::math::tan(cameraPitch + targetPitch) *
|
|
|
|
|
units::math::cos(targetYaw));
|
2022-04-08 21:20:53 -07:00
|
|
|
}
|
|
|
|
|
|
2022-10-26 22:20:08 -07:00
|
|
|
frc::Pose3d EstimateFieldToRobot(
|
2022-04-08 21:20:53 -07:00
|
|
|
units::meter_t cameraHeight, units::meter_t targetHeight,
|
|
|
|
|
units::radian_t cameraPitch, units::radian_t targetPitch,
|
|
|
|
|
const frc::Rotation2d& targetYaw, const frc::Rotation2d& gyroAngle,
|
2022-10-26 22:20:08 -07:00
|
|
|
const frc::Pose3d& fieldToTarget, const frc::Transform3d& cameraToRobot) {
|
|
|
|
|
auto distanceAlongGround =
|
|
|
|
|
CalculateDistanceToTarget(cameraHeight, targetHeight, cameraPitch,
|
|
|
|
|
targetPitch, targetYaw.Radians());
|
|
|
|
|
auto range =
|
|
|
|
|
units::math::hypot(distanceAlongGround, targetHeight - cameraHeight);
|
2022-04-08 21:20:53 -07:00
|
|
|
return EstimateFieldToRobot(
|
2022-05-06 18:36:58 +03:00
|
|
|
EstimateCameraToTarget(
|
2022-10-26 22:20:08 -07:00
|
|
|
Translation3d{range,
|
|
|
|
|
Rotation3d{0_rad, targetPitch, targetYaw.Radians()}},
|
2022-05-06 18:36:58 +03:00
|
|
|
fieldToTarget, gyroAngle),
|
2022-04-08 21:20:53 -07:00
|
|
|
fieldToTarget, cameraToRobot);
|
|
|
|
|
}
|
|
|
|
|
|
2022-10-26 22:20:08 -07:00
|
|
|
frc::Pose3d EstimateFieldToRobot(const frc::Transform3d& cameraToTarget,
|
|
|
|
|
const frc::Pose3d& fieldToTarget,
|
|
|
|
|
const frc::Transform3d& cameraToRobot) {
|
2022-04-08 21:20:53 -07:00
|
|
|
return EstimateFieldToCamera(cameraToTarget, fieldToTarget)
|
|
|
|
|
.TransformBy(cameraToRobot);
|
|
|
|
|
}
|
|
|
|
|
|
2022-10-26 22:20:08 -07:00
|
|
|
frc::Transform3d EstimateCameraToTarget(
|
|
|
|
|
const frc::Translation3d& cameraToTargetTranslation,
|
|
|
|
|
const frc::Pose3d& fieldToTarget, const frc::Rotation2d& gyroAngle) {
|
2022-04-08 21:20:53 -07:00
|
|
|
// Map our camera at the origin out to our target, in the robot reference
|
|
|
|
|
// frame. Gyro angle is needed because there's a circle of possible camera
|
|
|
|
|
// poses for which the camera has the same yaw from camera to target.
|
2022-10-26 22:20:08 -07:00
|
|
|
return Transform3d{cameraToTargetTranslation,
|
|
|
|
|
Rotation3d{0_rad, 0_rad, -gyroAngle.Radians()} -
|
|
|
|
|
fieldToTarget.Rotation()};
|
2022-04-08 21:20:53 -07:00
|
|
|
}
|
|
|
|
|
|
2022-10-26 22:20:08 -07:00
|
|
|
frc::Pose3d EstimateFieldToCamera(const frc::Transform3d& cameraToTarget,
|
|
|
|
|
const frc::Pose3d& fieldToTarget) {
|
2022-04-08 21:20:53 -07:00
|
|
|
auto targetToCamera = cameraToTarget.Inverse();
|
|
|
|
|
return fieldToTarget.TransformBy(targetToCamera);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
} // namespace frc
|