Skip to content

Commit 58ef7ab

Browse files
committed
feat: add forward_dynamics_aba! in-place variant (1.41μs, zero allocations)
1 parent 0fc7a18 commit 58ef7ab

3 files changed

Lines changed: 63 additions & 11 deletions

File tree

docs/src/lib/dynamics.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,8 @@ Pages = ["ModernRoboticsBook.jl"]
1111
Filter = t -> nameof(t) in [
1212
:ad, :inverse_dynamics_rnea, :inverse_dynamics_rnea!, :mass_matrix_crba, :mass_matrix_crba!,
1313
:mass_matrix_rnea, :velocity_quadratic_forces, :gravity_forces,
14-
:end_effector_forces, :forward_dynamics_aba, :forward_dynamics_crba, :forward_dynamics_rnea,
14+
:end_effector_forces, :forward_dynamics_aba, :forward_dynamics_aba!,
15+
:forward_dynamics_crba, :forward_dynamics_rnea,
1516
:euler_step, :inverse_dynamics_trajectory, :forward_dynamics_trajectory,
1617
]
1718
```

docs/src/man/benchmarks.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ This page compares the performance of ModernRoboticsBook.jl against [Pinocchio](
1212
| Mass matrix (CRBA) | 1.14 μs | **0.91 μs** | 0.65 μs | 0.14 μs |
1313
| Mass matrix (RNEA) | 6.79 μs ||||
1414
| Gravity / dynamics bias | 1.19 μs || 0.48 μs | 0.55 μs |
15-
| Forward dynamics (ABA) | 1.60 μs | | 2.82 μs ||
15+
| Forward dynamics (ABA) | 1.65 μs | **1.41 μs** | 2.82 μs ||
1616
| Forward dynamics (CRBA) | 2.80 μs ||||
1717
| Forward dynamics (RNEA) | 5.44 μs ||||
1818

@@ -44,7 +44,7 @@ The textbook algorithm variants (`mass_matrix_rnea`, `forward_dynamics_rnea`) ar
4444
| Mass matrix (CRBA) | 9 | 4.6 KiB | **0 (0 B)** |
4545
| Mass matrix (RNEA) | 76 | 20.7 KiB ||
4646
| Gravity forces | 17 | 3.6 KiB ||
47-
| Forward dynamics (ABA) | 23 | 6.1 KiB | |
47+
| Forward dynamics (ABA) | 23 | 6.1 KiB | **0 (0 B)** |
4848
| Forward dynamics (CRBA) | 32 | 8.8 KiB ||
4949
| Forward dynamics (RNEA) | 78 | 19.6 KiB ||
5050

src/ModernRoboticsBook.jl

Lines changed: 59 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@ export near_zero,
4545
gravity_forces,
4646
end_effector_forces,
4747
forward_dynamics_aba,
48+
forward_dynamics_aba!,
4849
forward_dynamics_crba,
4950
forward_dynamics_rnea,
5051
euler_step,
@@ -1379,6 +1380,8 @@ function inverse_dynamics_rnea!(
13791380
Fi = SVector{6}(tip_wrench)
13801381
for i = n:-1:1
13811382
Gi = SMatrix{6,6}(spatial_inertias[i])
1383+
# The -ad(V)'*G*V term is Featherstone's v ×* (Iv): the force cross product
1384+
# is the negative transpose of the motion cross product (twist/wrench duality).
13821385
Fi = AdTi[i+1]' * Fi + Gi * Vdi[i+1] - ad(Vi[i+1])' * Gi * Vi[i+1]
13831386
joint_torques[i] = Fi' * Ai[i]
13841387
end
@@ -1911,16 +1914,69 @@ function forward_dynamics_aba(
19111914
screw_axes::AbstractMatrix,
19121915
)
19131916
n = length(joint_positions)
1914-
1915-
# Pass 1 (outward): velocities, bias accelerations, bias forces
1916-
Mi = SMatrix{4,4,Float64}(LA.I)
1917+
ddq = zeros(n)
19171918
Ai = Vector{SVector{6,Float64}}(undef, n)
19181919
AdTi = Vector{SMatrix{6,6,Float64,36}}(undef, n + 1)
19191920
Vi = Vector{SVector{6,Float64}}(undef, n + 1)
19201921
ci = Vector{SVector{6,Float64}}(undef, n)
19211922
IA = Vector{SMatrix{6,6,Float64,36}}(undef, n)
19221923
pA = Vector{SVector{6,Float64}}(undef, n)
1924+
U = Vector{SVector{6,Float64}}(undef, n)
1925+
D = Vector{Float64}(undef, n)
1926+
u = Vector{Float64}(undef, n)
1927+
forward_dynamics_aba!(
1928+
ddq,
1929+
joint_positions,
1930+
joint_velocities,
1931+
joint_torques,
1932+
gravity,
1933+
tip_wrench,
1934+
link_frames,
1935+
spatial_inertias,
1936+
screw_axes,
1937+
Ai,
1938+
AdTi,
1939+
Vi,
1940+
ci,
1941+
IA,
1942+
pA,
1943+
U,
1944+
D,
1945+
u,
1946+
)
1947+
end
1948+
1949+
"""
1950+
forward_dynamics_aba!(ddq, joint_positions, joint_velocities, joint_torques, gravity, tip_wrench, link_frames, spatial_inertias, screw_axes, Ai, AdTi, Vi, ci, IA, pA, U, D, u)
19231951
1952+
In-place version of [`forward_dynamics_aba`](@ref). Writes the result into `ddq`.
1953+
The workspace vectors must be pre-allocated: `Ai` (n), `AdTi` (n+1), `Vi` (n+1),
1954+
`ci` (n), `IA` (n), `pA` (n), `U` (n), `D` (n), `u` (n).
1955+
"""
1956+
function forward_dynamics_aba!(
1957+
ddq::AbstractVector,
1958+
joint_positions::AbstractVector,
1959+
joint_velocities::AbstractVector,
1960+
joint_torques::AbstractVector,
1961+
gravity::AbstractVector,
1962+
tip_wrench::AbstractVector,
1963+
link_frames::AbstractVector,
1964+
spatial_inertias::AbstractVector,
1965+
screw_axes::AbstractMatrix,
1966+
Ai::AbstractVector{SVector{6,Float64}},
1967+
AdTi::AbstractVector{SMatrix{6,6,Float64,36}},
1968+
Vi::AbstractVector{SVector{6,Float64}},
1969+
ci::AbstractVector{SVector{6,Float64}},
1970+
IA::AbstractVector{SMatrix{6,6,Float64,36}},
1971+
pA::AbstractVector{SVector{6,Float64}},
1972+
U::AbstractVector{SVector{6,Float64}},
1973+
D::AbstractVector{Float64},
1974+
u::AbstractVector{Float64},
1975+
)
1976+
n = length(joint_positions)
1977+
1978+
# Pass 1 (outward): velocities, bias accelerations, bias forces
1979+
Mi = SMatrix{4,4,Float64}(LA.I)
19241980
Vi[1] = @SVector zeros(6)
19251981
AdTi[n+1] = adjoint_representation(transform_inv(link_frames[n+1]))
19261982

@@ -1946,10 +2002,6 @@ function forward_dynamics_aba(
19462002
pA[n] = pA[n] + AdTi[n+1]' * SVector{6}(tip_wrench)
19472003

19482004
# Pass 2 (inward): articulated body inertias and bias forces
1949-
U = Vector{SVector{6,Float64}}(undef, n)
1950-
D = Vector{Float64}(undef, n)
1951-
u = Vector{Float64}(undef, n)
1952-
19532005
for i = n:-1:1
19542006
U[i] = IA[i] * Ai[i]
19552007
D[i] = Ai[i]' * U[i]
@@ -1963,7 +2015,6 @@ function forward_dynamics_aba(
19632015
end
19642016

19652017
# Pass 3 (outward): joint accelerations
1966-
ddq = zeros(n)
19672018
a0 = SA[0.0, 0.0, 0.0, -gravity[1], -gravity[2], -gravity[3]]
19682019
a = AdTi[1] * a0
19692020

0 commit comments

Comments
 (0)