blob: 35b8d2971252ef0bd81f48affce4fe38de252e7a [file] [log] [blame]
Brian Silverman26e4e522015-12-17 01:56:40 -05001/*----------------------------------------------------------------------------*/
2/* Copyright (c) FIRST 2014. All Rights Reserved. */
3/* Open Source Software - may be modified and shared by FRC teams. The code */
4/* must be accompanied by the FIRST BSD license file in the root directory of */
5/* the project. */
6/*----------------------------------------------------------------------------*/
7
8#include <ADXL345_SPI.h>
9#include <AnalogGyro.h>
10#include <Servo.h>
11#include <Timer.h>
12#include "gtest/gtest.h"
13#include "TestBench.h"
14
15static constexpr double kServoResetTime = 2.0;
16
17static constexpr double kTestAngle = 90.0;
18
19static constexpr double kTiltSetpoint0 = 0.22;
20static constexpr double kTiltSetpoint45 = 0.45;
21static constexpr double kTiltSetpoint90 = 0.68;
22static constexpr double kTiltTime = 1.0;
23static constexpr double kAccelerometerTolerance = 0.2;
24static constexpr double kSensitivity = 0.013;
25
26/**
27 * A fixture for the camera with two servos and a gyro
28 * @author Thomas Clark
29 */
30class TiltPanCameraTest : public testing::Test {
31 protected:
32 static AnalogGyro *m_gyro;
33 Servo *m_tilt, *m_pan;
34 Accelerometer *m_spiAccel;
35
36 static void SetUpTestCase() {
37 // The gyro object blocks for 5 seconds in the constructor, so only
38 // construct it once for the whole test case
39 m_gyro = new AnalogGyro(TestBench::kCameraGyroChannel);
40 m_gyro->SetSensitivity(kSensitivity);
41 }
42
43 static void TearDownTestCase() { delete m_gyro; }
44
45 virtual void SetUp() override {
46 m_tilt = new Servo(TestBench::kCameraTiltChannel);
47 m_pan = new Servo(TestBench::kCameraPanChannel);
48 m_spiAccel = new ADXL345_SPI(SPI::kOnboardCS0);
49
50 m_tilt->Set(kTiltSetpoint45);
51 m_pan->SetAngle(0.0f);
52
53 Wait(kServoResetTime);
54
55 m_gyro->Reset();
56 }
57
58 void DefaultGyroAngle();
59 void GyroAngle();
60 void GyroCalibratedParameters();
61
62 virtual void TearDown() override {
63 delete m_tilt;
64 delete m_pan;
65 delete m_spiAccel;
66 }
67};
68
69AnalogGyro *TiltPanCameraTest::m_gyro = nullptr;
70
71/**
72 * Test if the gyro angle defaults to 0 immediately after being reset.
73 */
74void TiltPanCameraTest::DefaultGyroAngle() {
75 EXPECT_NEAR(0.0f, m_gyro->GetAngle(), 1.0f);
76}
77
78/**
79 * Test if the servo turns 90 degrees and the gyroscope measures this angle
80 * Note servo on TestBench is not the same type of servo that servo class
81 * was designed for so setAngle is significantly off. This has been calibrated
82 * for the servo on the rig.
83 */
84void TiltPanCameraTest::GyroAngle() {
85 // Make sure that the gyro doesn't get jerked when the servo goes to zero.
86 m_pan->SetAngle(0.0);
87 Wait(0.5);
88 m_gyro->Reset();
89
90 for (int i = 0; i < 600; i++) {
91 m_pan->Set(i / 1000.0);
92 Wait(0.001);
93 }
94
95 double gyroAngle = m_gyro->GetAngle();
96
97 EXPECT_NEAR(gyroAngle, kTestAngle, 10.0)
98 << "Gyro measured " << gyroAngle << " degrees, servo should have turned "
99 << kTestAngle << " degrees";
100}
101
102/**
103 * Gets calibrated parameters from previously calibrated gyro, allocates a new
104 * gyro with the given parameters for center and offset, and re-runs tests on
105 * the new gyro.
106 */
107void TiltPanCameraTest::GyroCalibratedParameters() {
108 uint32_t cCenter = m_gyro->GetCenter();
109 float cOffset = m_gyro->GetOffset();
110 delete m_gyro;
111 m_gyro = new AnalogGyro(TestBench::kCameraGyroChannel, cCenter, cOffset);
112 m_gyro->SetSensitivity(kSensitivity);
113
114 // Default gyro angle test
115 // Accumulator needs a small amount of time to reset before being tested
116 m_gyro->Reset();
117 Wait(.001);
118 EXPECT_NEAR(0.0f, m_gyro->GetAngle(), 1.0f);
119
120 // Gyro angle test
121 // Make sure that the gyro doesn't get jerked when the servo goes to zero.
122 m_pan->SetAngle(0.0);
123 Wait(0.5);
124 m_gyro->Reset();
125
126 for (int i = 0; i < 600; i++) {
127 m_pan->Set(i / 1000.0);
128 Wait(0.001);
129 }
130
131 double gyroAngle = m_gyro->GetAngle();
132
133 EXPECT_NEAR(gyroAngle, kTestAngle, 10.0)
134 << "Gyro measured " << gyroAngle << " degrees, servo should have turned "
135 << kTestAngle << " degrees";
136}
137
138/**
139 * Run all gyro tests in one function to make sure they are run in order.
140 */
141TEST_F(TiltPanCameraTest, TestAllGyroTests) {
142 DefaultGyroAngle();
143 GyroAngle();
144 GyroCalibratedParameters();
145}
146
147/**
148 * Test if the accelerometer measures gravity along the correct axes when the
149 * camera rotates
150 */
151TEST_F(TiltPanCameraTest, SPIAccelerometer) {
152 m_tilt->Set(kTiltSetpoint0);
153 Wait(kTiltTime);
154 EXPECT_NEAR(-1.0, m_spiAccel->GetX(), kAccelerometerTolerance);
155 EXPECT_NEAR(0.0, m_spiAccel->GetY(), kAccelerometerTolerance);
156 EXPECT_NEAR(0.0, m_spiAccel->GetZ(), kAccelerometerTolerance);
157
158 m_tilt->Set(kTiltSetpoint45);
159 Wait(kTiltTime);
160 EXPECT_NEAR(-std::sqrt(0.5), m_spiAccel->GetX(), kAccelerometerTolerance);
161 EXPECT_NEAR(0.0, m_spiAccel->GetY(), kAccelerometerTolerance);
162 EXPECT_NEAR(std::sqrt(0.5), m_spiAccel->GetZ(), kAccelerometerTolerance);
163
164 m_tilt->Set(kTiltSetpoint90);
165 Wait(kTiltTime);
166 EXPECT_NEAR(0.0, m_spiAccel->GetX(), kAccelerometerTolerance);
167 EXPECT_NEAR(0.0, m_spiAccel->GetY(), kAccelerometerTolerance);
168 EXPECT_NEAR(1.0, m_spiAccel->GetZ(), kAccelerometerTolerance);
169}