blob: afd64ea1b89841aeb50feb13d889f73c85f9402b [file] [log] [blame]
Austin Schuh60e77942022-05-16 17:48:24 -07001#include "aos/util/trapezoid_profile.h"
briansf0165ca2013-03-02 06:17:47 +00002
3#include "Eigen/Dense"
Austin Schuh60e77942022-05-16 17:48:24 -07004#include "gtest/gtest.h"
briansf0165ca2013-03-02 06:17:47 +00005
6namespace aos {
7namespace util {
8namespace testing {
9
10class TrapezoidProfileTest : public ::testing::Test {
11 public:
12 EIGEN_MAKE_ALIGNED_OPERATOR_NEW;
13
14 protected:
15 TrapezoidProfileTest() : profile_(delta_time) {
16 position_.setZero();
17 profile_.set_maximum_acceleration(0.75);
18 profile_.set_maximum_velocity(1.75);
19 }
20
21 // Runs an iteration.
Austin Schuh60e77942022-05-16 17:48:24 -070022 void RunIteration(double goal_position, double goal_velocity) {
23 position_ = profile_.Update(goal_position, goal_velocity);
briansf0165ca2013-03-02 06:17:47 +000024 }
25
26 const Eigen::Matrix<double, 2, 1> &position() { return position_; }
27
28 TrapezoidProfile profile_;
29
30 ::testing::AssertionResult At(double position, double velocity) {
briansd412b3f2013-03-03 21:13:44 +000031 static const double kDoubleNear = 0.00001;
32 if (::std::abs(velocity - position_(1)) > kDoubleNear) {
Austin Schuh60e77942022-05-16 17:48:24 -070033 return ::testing::AssertionFailure()
34 << "velocity is " << position_(1) << " not " << velocity;
briansf0165ca2013-03-02 06:17:47 +000035 }
briansd412b3f2013-03-03 21:13:44 +000036 if (::std::abs(position - position_(0)) > kDoubleNear) {
Austin Schuh60e77942022-05-16 17:48:24 -070037 return ::testing::AssertionFailure()
38 << "position is " << position_(0) << " not " << position;
briansf0165ca2013-03-02 06:17:47 +000039 }
Austin Schuh60e77942022-05-16 17:48:24 -070040 return ::testing::AssertionSuccess()
41 << "at " << position << " moving at " << velocity;
briansf0165ca2013-03-02 06:17:47 +000042 }
43
44 private:
Austin Schuh214e9c12016-11-25 17:26:20 -080045 static constexpr ::std::chrono::nanoseconds delta_time =
46 ::std::chrono::milliseconds(10);
briansf0165ca2013-03-02 06:17:47 +000047
48 Eigen::Matrix<double, 2, 1> position_;
49};
Austin Schuh214e9c12016-11-25 17:26:20 -080050
51constexpr ::std::chrono::nanoseconds TrapezoidProfileTest::delta_time;
briansf0165ca2013-03-02 06:17:47 +000052
53TEST_F(TrapezoidProfileTest, ReachesGoal) {
54 for (int i = 0; i < 450; ++i) {
55 RunIteration(3, 0);
56 }
57 EXPECT_TRUE(At(3, 0));
58}
59
Ben Fredricksonf33d6532015-03-15 00:29:29 -070060// Tests that decresing the maximum velocity in the middle when it is already
61// moving faster than the new max is handled correctly.
62TEST_F(TrapezoidProfileTest, ContinousUnderVelChange) {
63 profile_.set_maximum_velocity(1.75);
64 RunIteration(12.0, 0);
65 double last_pos = position()(0);
66 double last_vel = 1.75;
67 for (int i = 0; i < 1600; ++i) {
68 if (i == 400) {
69 profile_.set_maximum_velocity(0.75);
70 }
71 RunIteration(12.0, 0);
72 if (i >= 400) {
73 EXPECT_TRUE(::std::abs(last_pos - position()(0)) <= 1.75 * 0.01);
74 EXPECT_NEAR(last_vel, ::std::abs(last_pos - position()(0)), 0.0001);
75 }
76 last_vel = ::std::abs(last_pos - position()(0));
77 last_pos = position()(0);
78 }
79 EXPECT_TRUE(At(12.0, 0));
80}
81
briansf0165ca2013-03-02 06:17:47 +000082// There is some somewhat tricky code for dealing with going backwards.
83TEST_F(TrapezoidProfileTest, Backwards) {
84 for (int i = 0; i < 400; ++i) {
85 RunIteration(-2, 0);
86 }
87 EXPECT_TRUE(At(-2, 0));
88}
89
90TEST_F(TrapezoidProfileTest, SwitchGoalInMiddle) {
91 for (int i = 0; i < 200; ++i) {
92 RunIteration(-2, 0);
93 }
94 EXPECT_FALSE(At(-2, 0));
95 for (int i = 0; i < 550; ++i) {
96 RunIteration(0, 0);
97 }
98 EXPECT_TRUE(At(0, 0));
99}
100
101// Checks to make sure that it hits top speed.
102TEST_F(TrapezoidProfileTest, TopSpeed) {
103 for (int i = 0; i < 200; ++i) {
104 RunIteration(4, 0);
105 }
106 EXPECT_NEAR(1.5, position()(1), 10e-5);
107 for (int i = 0; i < 2000; ++i) {
108 RunIteration(4, 0);
109 }
110 EXPECT_TRUE(At(4, 0));
111}
112
Austin Schuh5d571d02017-02-11 12:28:17 -0800113// Tests that the position and velocity exactly match at the end. Some code we
114// have assumes this to be true as a simplification.
115TEST_F(TrapezoidProfileTest, ExactlyReachesGoal) {
116 for (int i = 0; i < 450; ++i) {
117 RunIteration(1, 0);
118 }
119 EXPECT_EQ(position()(1), 0.0);
120 EXPECT_EQ(position()(0), 1.0);
121}
122
briansf0165ca2013-03-02 06:17:47 +0000123} // namespace testing
124} // namespace util
125} // namespace aos