Skip to content

Commit 656aec2

Browse files
committed
operate on equations
1 parent f7d06d5 commit 656aec2

File tree

2 files changed

+14
-12
lines changed

2 files changed

+14
-12
lines changed

src/input_affine_form.jl

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -29,8 +29,8 @@ inputs = [u1, u2]
2929
3030
# Define system equations: ẋ = F(x, u)
3131
eqs = [
32-
-x1 + 2*x2 + u1,
33-
x1*x2 - x2 + u1 + 2*u2
32+
D(x1) ~ -x1 + 2*x2 + u1,
33+
D(x2) ~ x1*x2 - x2 + u1 + 2*u2
3434
]
3535
3636
# Extract control-affine form
@@ -42,7 +42,7 @@ The function assumes that the equations are affine in the inputs. If the equatio
4242
are nonlinear in the inputs, an error is thrown.
4343
"""
4444
function input_affine_form(eqs, inputs)
45-
g, f, flag = linear_expansion(eqs, inputs)
45+
g, f, flag = Symbolics.linear_expansion(getfield.(eqs, :rhs), inputs)
4646
flag || error("The system is not affine in the inputs.")
4747
return f, g
4848
end

test/input_affine_form.jl

Lines changed: 11 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -2,14 +2,16 @@ using ModelingToolkit, Test
22
using Symbolics
33
using StaticArrays
44

5+
rhs(eq) = simplify(eq.rhs)
6+
57
@testset "input_affine_form" begin
68
# Test with simple linear system
79
@testset "Simple linear system" begin
810
@variables x1 x2 u1 u2
911
state = [x1, x2]
1012
inputs = [u1, u2]
1113

12-
eqs = [
14+
eqs = D.(state) .~ [
1315
-x1 + 2*x2 + u1,
1416
x1*x2 - x2 + u1 + 2*u2
1517
]
@@ -18,7 +20,7 @@ using StaticArrays
1820

1921
# Verify reconstruction
2022
eqs_reconstructed = f + g * inputs
21-
@test isequal(Symbolics.simplify.(eqs_reconstructed), Symbolics.simplify.(eqs))
23+
@test isequal(Symbolics.simplify.(eqs_reconstructed), rhs.(eqs))
2224

2325
# Check dimensions
2426
@test length(f) == length(eqs)
@@ -41,7 +43,7 @@ using StaticArrays
4143
bt = 2 * 1.225
4244

4345
# Dynamics of Segway in Euler-Lagrange form
44-
D(q) = [m0 m*L*cos(q[2]); m*L*cos(q[2]) J0]
46+
Dq(q) = [m0 m*L*cos(q[2]); m*L*cos(q[2]) J0]
4547
function H(q, q̇)
4648
return SA[
4749
-m * L * sin(q[2]) * q̇[2] + bt * (q̇[1] - R * q̇[2]) / R,
@@ -53,25 +55,25 @@ using StaticArrays
5355
# Convert to control affine form
5456
function f_seg(x)
5557
q, q̇ = x[SA[1, 2]], x[SA[3, 4]]
56-
return [q̇; -D(q) \ H(q, q̇)]
58+
return [q̇; -Dq(q) \ H(q, q̇)]
5759
end
5860
function g_seg(x)
5961
q, q̇ = x[SA[1, 2]], x[SA[3, 4]]
60-
return [SA[0, 0]; D(q) \ B(q)]
62+
return [SA[0, 0]; Dq(q) \ B(q)]
6163
end
6264

6365
# Trace dynamics symbolically
6466
@variables q1 q2 qd1 qd2 u
6567
x = [q1; q2; qd1; qd2]
6668
inputs = [u]
67-
eqs = f_seg(x) + g_seg(x) * u
69+
eqs = D.(x) .~ f_seg(x) + g_seg(x) * u
6870

6971
# Extract control-affine form
7072
fe, ge = input_affine_form(eqs, inputs)
7173

7274
# Test reconstruction
7375
eqs2 = fe + ge * inputs
74-
diff = Symbolics.simplify.(eqs2 - eqs, expand = true)
76+
diff = Symbolics.simplify.(eqs2 - rhs.(eqs), expand = true)
7577

7678
# The difference should be zero or very close to zero symbolically
7779
# We test numerically since symbolic simplification might not be perfect
@@ -91,7 +93,7 @@ using StaticArrays
9193
state = [x1, x2, x3]
9294
inputs = [u1, u2]
9395

94-
eqs = [
96+
eqs = D.(state) .~ [
9597
x2,
9698
x3,
9799
-x1 - 2*x2 - x3 + u1 + 3*u2
@@ -118,7 +120,7 @@ using StaticArrays
118120
state = [x1, x2]
119121
inputs = [u]
120122

121-
eqs = [
123+
eqs = D.(state) .~ [
122124
x2,
123125
-sin(x1) - x2 + u
124126
]

0 commit comments

Comments
 (0)