Skip to content

Commit 5db58aa

Browse files
committed
add trapezoidal profile tests
1 parent bcee015 commit 5db58aa

File tree

1 file changed

+180
-0
lines changed

1 file changed

+180
-0
lines changed
Lines changed: 180 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,180 @@
1+
# Copyright (c) FIRST and other WPILib contributors.
2+
# Open Source Software; you can modify and/or share it under the terms of
3+
# the WPILib BSD license file in the root directory of this project.
4+
5+
6+
import math
7+
8+
from wpimath.trajectory import TrapezoidProfile
9+
10+
kDt = 0.01 # 10 ms
11+
12+
def expect_near_units(val1, val2, eps):
13+
assert abs(val1 - val2) <= eps
14+
15+
def expect_lt_or_near_units(val1, val2, eps):
16+
if val1 <= val2:
17+
assert val1 <= val2
18+
else:
19+
expect_near_units(val1, val2, eps)
20+
21+
22+
def test_reaches_goal():
23+
constraints = TrapezoidProfile.Constraints(1.75, 0.75)
24+
goal = TrapezoidProfile.State(3.0, 0.0)
25+
state = TrapezoidProfile.State()
26+
27+
profile = TrapezoidProfile(constraints)
28+
for _ in range(450):
29+
state = profile.calculate(kDt, state, goal)
30+
assert state == goal
31+
32+
33+
def test_pos_continuous_under_vel_change():
34+
constraints = TrapezoidProfile.Constraints(1.75, 0.75)
35+
goal = TrapezoidProfile.State(12.0, 0.0)
36+
profile = TrapezoidProfile(constraints)
37+
state = profile.calculate(kDt, TrapezoidProfile.State(), goal)
38+
39+
last_pos = state.position
40+
for i in range(1600):
41+
if i == 400:
42+
constraints = TrapezoidProfile.Constraints(0.75, 0.75)
43+
profile = TrapezoidProfile(constraints)
44+
45+
state = profile.calculate(kDt, state, goal)
46+
estimated_vel = (state.position - last_pos) / kDt
47+
48+
if i >= 400:
49+
expect_lt_or_near_units(estimated_vel, constraints.maxVelocity, 1e-4)
50+
assert state.velocity <= constraints.maxVelocity
51+
52+
last_pos = state.position
53+
54+
assert state == goal
55+
56+
57+
def test_backwards():
58+
constraints = TrapezoidProfile.Constraints(0.75, 0.75)
59+
goal = TrapezoidProfile.State(-2.0, 0.0)
60+
state = TrapezoidProfile.State()
61+
profile = TrapezoidProfile(constraints)
62+
63+
for _ in range(400):
64+
state = profile.calculate(kDt, state, goal)
65+
assert state == goal
66+
67+
68+
def test_switch_goal_in_middle():
69+
constraints = TrapezoidProfile.Constraints(0.75, 0.75)
70+
goal = TrapezoidProfile.State(-2.0, 0.0)
71+
state = TrapezoidProfile.State()
72+
profile = TrapezoidProfile(constraints)
73+
74+
for _ in range(200):
75+
state = profile.calculate(kDt, state, goal)
76+
assert state != goal
77+
78+
goal = TrapezoidProfile.State(0.0, 0.0)
79+
profile = TrapezoidProfile(constraints)
80+
for _ in range(550):
81+
state = profile.calculate(kDt, state, goal)
82+
assert state == goal
83+
84+
85+
def test_top_speed():
86+
constraints = TrapezoidProfile.Constraints(0.75, 0.75)
87+
goal = TrapezoidProfile.State(4.0, 0.0)
88+
state = TrapezoidProfile.State()
89+
profile = TrapezoidProfile(constraints)
90+
91+
for _ in range(200):
92+
state = profile.calculate(kDt, state, goal)
93+
expect_near_units(constraints.maxVelocity, state.velocity, 1e-4)
94+
95+
profile = TrapezoidProfile(constraints)
96+
for _ in range(2000):
97+
state = profile.calculate(kDt, state, goal)
98+
assert state == goal
99+
100+
101+
def test_timing_to_current():
102+
constraints = TrapezoidProfile.Constraints(0.75, 0.75)
103+
goal = TrapezoidProfile.State(2.0, 0.0)
104+
state = TrapezoidProfile.State()
105+
profile = TrapezoidProfile(constraints)
106+
107+
for _ in range(400):
108+
state = profile.calculate(kDt, state, goal)
109+
expect_near_units(profile.timeLeftUntil(state.position), 0.0, 0.02)
110+
111+
112+
def test_timing_to_goal():
113+
constraints = TrapezoidProfile.Constraints(0.75, 0.75)
114+
goal = TrapezoidProfile.State(2.0, 0.0)
115+
profile = TrapezoidProfile(constraints)
116+
117+
state = profile.calculate(kDt, goal, TrapezoidProfile.State())
118+
predicted_time_left = profile.timeLeftUntil(goal.position)
119+
120+
reached_goal = False
121+
for i in range(400):
122+
state = profile.calculate(kDt, state, goal)
123+
if not reached_goal and state == goal:
124+
assert math.isclose(predicted_time_left, i * kDt, abs_tol=0.25)
125+
reached_goal = True
126+
127+
128+
def test_timing_before_goal():
129+
constraints = TrapezoidProfile.Constraints(0.75, 0.75)
130+
goal = TrapezoidProfile.State(2.0, 0.0)
131+
profile = TrapezoidProfile(constraints)
132+
133+
state = profile.calculate(kDt, goal, TrapezoidProfile.State())
134+
predicted_time_left = profile.timeLeftUntil(1.0)
135+
136+
reached_goal = False
137+
for i in range(400):
138+
state = profile.calculate(kDt, state, goal)
139+
if not reached_goal and abs(state.velocity - 1.0) < 1e-4:
140+
assert math.isclose(predicted_time_left, i * kDt, abs_tol=0.02)
141+
reached_goal = True
142+
143+
144+
def test_timing_to_negative_goal():
145+
constraints = TrapezoidProfile.Constraints(0.75, 0.75)
146+
goal = TrapezoidProfile.State(-2.0, 0.0)
147+
profile = TrapezoidProfile(constraints)
148+
149+
state = profile.calculate(kDt, goal, TrapezoidProfile.State())
150+
predicted_time_left = profile.timeLeftUntil(goal.position)
151+
152+
reached_goal = False
153+
for i in range(400):
154+
state = profile.calculate(kDt, state, goal)
155+
if not reached_goal and state == goal:
156+
assert math.isclose(predicted_time_left, i * kDt, abs_tol=0.25)
157+
reached_goal = True
158+
159+
160+
def test_timing_before_negative_goal():
161+
constraints = TrapezoidProfile.Constraints(0.75, 0.75)
162+
goal = TrapezoidProfile.State(-2.0, 0.0)
163+
profile = TrapezoidProfile(constraints)
164+
165+
state = profile.calculate(kDt, goal, TrapezoidProfile.State())
166+
predicted_time_left = profile.timeLeftUntil(-1.0)
167+
168+
reached_goal = False
169+
for i in range(400):
170+
state = profile.calculate(kDt, state, goal)
171+
if not reached_goal and abs(state.velocity + 1.0) < 1e-4:
172+
assert math.isclose(predicted_time_left, i * kDt, abs_tol=0.02)
173+
reached_goal = True
174+
175+
176+
def test_initialization_of_current_state():
177+
constraints = TrapezoidProfile.Constraints(1.0, 1.0)
178+
profile = TrapezoidProfile(constraints)
179+
expect_near_units(profile.timeLeftUntil(0.0), 0.0, 1e-10)
180+
expect_near_units(profile.totalTime(), 0.0, 1e-10)

0 commit comments

Comments
 (0)