// 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 #include #include "TestBench.h" #include "frc/ADXL345_SPI.h" #include "frc/AnalogGyro.h" #include "frc/Servo.h" #include "frc/Timer.h" #include "gtest/gtest.h" static constexpr double kTiltSetpoint0 = 0.22; static constexpr double kTiltSetpoint45 = 0.45; static constexpr double kTiltSetpoint90 = 0.68; /** * A fixture for the camera with two servos and a gyro */ class TiltPanCameraTest : public testing::Test { protected: frc::Servo m_tilt{TestBench::kCameraTiltChannel}; frc::Servo m_pan{TestBench::kCameraPanChannel}; frc::ADXL345_SPI m_spiAccel{frc::SPI::kOnboardCS1}; TiltPanCameraTest() { m_tilt.Set(kTiltSetpoint45); m_pan.SetAngle(0.0); // Wait for servos to reset frc::Wait(2_s); } /** * Test if the servo turns 90 degrees and the gyroscope measures this angle * Note servo on TestBench is not the same type of servo that servo class * was designed for so setAngle is significantly off. This has been calibrated * for the servo on the rig. */ void GyroTests(frc::AnalogGyro& gyro) { gyro.SetSensitivity(0.013); gyro.Reset(); // Accumulator needs a small amount of time to reset before being tested frc::Wait(1_ms); // Verify the gyro angle defaults to 0 immediately after being reset EXPECT_NEAR(0.0, gyro.GetAngle(), 1.0); // Make sure that the gyro doesn't get jerked when the servo goes to zero. m_pan.SetAngle(0.0); frc::Wait(0.5_s); gyro.Reset(); for (int32_t i = 0; i < 600; i++) { m_pan.Set(i / 1000.0); frc::Wait(1_ms); } double gyroAngle = gyro.GetAngle(); EXPECT_NEAR(gyroAngle, 90.0, 10.0) << "Gyro measured " << gyroAngle << " degrees, servo should have turned 90 degrees"; } }; TEST_F(TiltPanCameraTest, Gyro) { int cCenter; double cOffset; { frc::AnalogGyro gyro{TestBench::kCameraGyroChannel}; GyroTests(gyro); // Gets calibrated parameters from previously calibrated gyro, allocates a // new gyro with the given parameters for center and offset, and re-runs // tests on the new gyro. cCenter = gyro.GetCenter(); cOffset = gyro.GetOffset(); } frc::AnalogGyro gyro{TestBench::kCameraGyroChannel, cCenter, cOffset}; GyroTests(gyro); } /** * Test if the accelerometer measures gravity along the correct axes when the * camera rotates */ TEST_F(TiltPanCameraTest, SPIAccelerometer) { static constexpr auto kTiltTime = 1_s; static constexpr double kAccelerometerTolerance = 0.2; m_tilt.Set(kTiltSetpoint0); frc::Wait(kTiltTime); EXPECT_NEAR(-1.0, m_spiAccel.GetX(), kAccelerometerTolerance); EXPECT_NEAR(0.0, m_spiAccel.GetY(), kAccelerometerTolerance); EXPECT_NEAR(0.0, m_spiAccel.GetZ(), kAccelerometerTolerance); m_tilt.Set(kTiltSetpoint45); frc::Wait(kTiltTime); EXPECT_NEAR(-std::sqrt(0.5), m_spiAccel.GetX(), kAccelerometerTolerance); EXPECT_NEAR(0.0, m_spiAccel.GetY(), kAccelerometerTolerance); EXPECT_NEAR(std::sqrt(0.5), m_spiAccel.GetZ(), kAccelerometerTolerance); m_tilt.Set(kTiltSetpoint90); frc::Wait(kTiltTime); EXPECT_NEAR(0.0, m_spiAccel.GetX(), kAccelerometerTolerance); EXPECT_NEAR(0.0, m_spiAccel.GetY(), kAccelerometerTolerance); EXPECT_NEAR(1.0, m_spiAccel.GetZ(), kAccelerometerTolerance); }