-
Notifications
You must be signed in to change notification settings - Fork 49
/
test_pd_control.jl
134 lines (112 loc) · 5.05 KB
/
test_pd_control.jl
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
@testset "pd" begin
@testset "scalar" begin
@test pd(PDGains(1, 2), 3, 4) == -11
end
@testset "vector" begin
gains = PDGains(1, 2)
e = [3; 4; 5]
ė = [6; 7; 8]
@test pd(gains, e, ė) == ((e, ė) -> pd(gains, e, ė)).(e, ė)
end
@testset "specifying desireds" begin
gains = PDGains(5, 6)
x = SVector(1, 2)
ẋ = SVector(5, 6)
@test pd(gains, x, ẋ) == pd(gains, x, zero(x), ẋ, zero(ẋ))
end
@testset "x-axis rotation" begin
Random.seed!(56)
gains = PDGains(2, 3)
e = RotX(rand())
ė = rand() * SVector(1, 0, 0)
@test pd(gains, e, ė)[1] ≈ pd(gains, e.theta, ė[1])
end
@testset "orientation control" begin
Random.seed!(57)
mechanism = rand_floating_tree_mechanism(Float64) # single floating body
joint = first(tree_joints(mechanism))
body = successor(joint, mechanism)
base = root_body(mechanism)
state = MechanismState(mechanism)
rand!(state)
Rdes = rand(RotMatrix{3})
ωdes = zero(SVector{3})
gains = PDGains(100, 20)
v̇des = similar(velocity(state))
control_dynamics_result = DynamicsResult(mechanism)
function control!(torques::SegmentedVector, t, state::MechanismState)
H = transform_to_root(state, body)
T = transform(twist_wrt_world(state, body), inv(H))
R = rotation(H)
ω = T.angular
ωddes = pd(gains, R, Rdes, ω, ωdes)
v̇desjoint = v̇des[joint]
v̇desjoint .= SVector([ωddes; zero(ωddes)])
wrenches = control_dynamics_result.jointwrenches
accelerations = control_dynamics_result.accelerations
inverse_dynamics!(torques, wrenches, accelerations, state, v̇des)
end
final_time = 3.
simulate(state, final_time, control!; Δt = 1e-3)
H = transform_to_root(state, body)
T = transform(twist_wrt_world(state, body), inv(H))
R = rotation(H)
ω = T.angular
@test isapprox(R * Rdes', one(typeof(Rdes)); atol = 1e-8)
@test isapprox(ω, zero(ω); atol = 1e-8)
end
@testset "pose control" begin
Random.seed!(58)
mechanism = rand_floating_tree_mechanism(Float64) # single floating body
joint = first(tree_joints(mechanism))
body = successor(joint, mechanism)
base = root_body(mechanism)
baseframe = default_frame(base)
desiredframe = CartesianFrame3D("desired")
actualframe = frame_after(joint)
state = MechanismState(mechanism)
rand!(state)
xdes = rand(Transform3D, desiredframe, baseframe)
vdes = zero(Twist{Float64}, desiredframe, baseframe, actualframe)
v̇des = similar(velocity(state))
gains = SE3PDGains(baseframe, PDGains(100 * one(SMatrix{3, 3}), 20), PDGains(100., 20.)) # world-fixed gains
control_dynamics_result = DynamicsResult(mechanism)
function control!(torques::SegmentedVector, t, state::MechanismState)
x = transform_to_root(state, body)
invx = inv(x)
v = transform(twist_wrt_world(state, body), invx)
v̇desjoint = v̇des[joint]
v̇desjoint .= SVector(pd(transform(gains, invx), x, xdes, v, vdes))
wrenches = control_dynamics_result.jointwrenches
accelerations = control_dynamics_result.accelerations
inverse_dynamics!(torques, wrenches, accelerations, state, v̇des)
end
final_time = 3.
simulate(state, final_time, control!; Δt = 1e-3)
x = transform_to_root(state, body)
v = transform(twist_wrt_world(state, body), inv(x))
@test isapprox(x, xdes * one(Transform3D, actualframe, desiredframe), atol = 1e-6)
@test isapprox(v, vdes + zero(Twist{Float64}, actualframe, desiredframe, actualframe), atol = 1e-6)
end
@testset "linearized SE(3) control" begin
Random.seed!(59)
for i = 1 : 100
randpsd3() = (x = rand(SMatrix{3, 3}); x' * x)
baseframe = CartesianFrame3D("base")
bodyframe = CartesianFrame3D("body")
gains = SE3PDGains(bodyframe, PDGains(randpsd3(), randpsd3()), PDGains(randpsd3(), randpsd3()))
xdes = rand(Transform3D{Float64}, bodyframe, baseframe)
Tdes = rand(Twist{Float64}, bodyframe, baseframe, bodyframe)
ϵ = 1e-2
x = xdes * Transform3D(bodyframe, bodyframe, AngleAxis(ϵ, randn(), randn(), randn()), ϵ * randn(SVector{3}))
T = rand(Twist{Float64}, bodyframe, baseframe, bodyframe)
accel_nonlin = pd(gains, x, xdes, T, Tdes)
accel_lin = pd(gains, x, xdes, T, Tdes, SE3PDMethod{:Linearized}())
@test isapprox(accel_nonlin, accel_lin; atol = 1e-6)
T = Tdes
accel_nonlin = pd(gains, x, xdes, T, Tdes)
accel_lin = pd(gains, x, xdes, T, Tdes, SE3PDMethod{:Linearized}())
@test isapprox(accel_nonlin, accel_lin; atol = 1e-6)
end
end
end