Skip to content

Commit d89b4b8

Browse files
committed
feat: add in-place FK and Jacobian variants (zero-allocation)
1 parent 8b36e69 commit d89b4b8

4 files changed

Lines changed: 96 additions & 20 deletions

File tree

docs/src/lib/forward-kinematics.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,5 +5,5 @@
55
```@autodocs
66
Modules = [ModernRoboticsBook]
77
Pages = ["ModernRoboticsBook.jl"]
8-
Filter = t -> nameof(t) in [:forward_kinematics_body, :forward_kinematics_space]
8+
Filter = t -> nameof(t) in [:forward_kinematics_body, :forward_kinematics_body!, :forward_kinematics_space, :forward_kinematics_space!]
99
```

docs/src/lib/velocity-kinematics.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,5 +5,5 @@
55
```@autodocs
66
Modules = [ModernRoboticsBook]
77
Pages = ["ModernRoboticsBook.jl"]
8-
Filter = t -> nameof(t) in [:jacobian_body, :jacobian_space]
8+
Filter = t -> nameof(t) in [:jacobian_body, :jacobian_body!, :jacobian_space, :jacobian_space!]
99
```

src/ModernRoboticsBook.jl

Lines changed: 72 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -26,9 +26,13 @@ export near_zero,
2626
is_so3,
2727
is_se3,
2828
forward_kinematics_body,
29+
forward_kinematics_body!,
2930
forward_kinematics_space,
31+
forward_kinematics_space!,
3032
jacobian_body,
33+
jacobian_body!,
3134
jacobian_space,
35+
jacobian_space!,
3236
inverse_kinematics_body,
3337
inverse_kinematics_space,
3438
ad,
@@ -797,7 +801,7 @@ julia> body_screw_axes = [ 0 0 -1 2 0 0 ;
797801
julia> joint_positions = [ π/2, 3, π ];
798802
799803
julia> forward_kinematics_body(home_ee_pose, body_screw_axes, joint_positions)
800-
4×4 StaticArraysCore.SMatrix{4, 4, Float64, 16} with indices SOneTo(4)×SOneTo(4):
804+
4×4 Matrix{Float64}:
801805
-1.14424e-17 1.0 0.0 -5.0
802806
1.0 1.14424e-17 0.0 4.0
803807
0.0 0.0 -1.0 1.68584
@@ -809,11 +813,27 @@ function forward_kinematics_body(
809813
body_screw_axes::AbstractMatrix,
810814
joint_positions::AbstractVector,
811815
)
812-
T = SMatrix{4,4}(home_ee_pose)
816+
T = similar(home_ee_pose, Float64, 4, 4)
817+
forward_kinematics_body!(T, home_ee_pose, body_screw_axes, joint_positions)
818+
end
819+
820+
"""
821+
forward_kinematics_body!(T, home_ee_pose, body_screw_axes, joint_positions)
822+
823+
In-place version of [`forward_kinematics_body`](@ref). Writes the result into `T`.
824+
"""
825+
function forward_kinematics_body!(
826+
T::AbstractMatrix,
827+
home_ee_pose::AbstractMatrix,
828+
body_screw_axes::AbstractMatrix,
829+
joint_positions::AbstractVector,
830+
)
831+
Ts = SMatrix{4,4}(home_ee_pose)
813832
for i in eachindex(joint_positions)
814833
Bi = SVector{6}(@view body_screw_axes[:, i])
815-
T = T * matrix_exp6(vec_to_se3(Bi * joint_positions[i]))
834+
Ts = Ts * matrix_exp6(vec_to_se3(Bi * joint_positions[i]))
816835
end
836+
T .= Ts
817837
T
818838
end
819839

@@ -859,7 +879,7 @@ julia> screw_axes = [ 0 0 1 4 0 0 ;
859879
julia> joint_positions = [ π/2, 3, π ];
860880
861881
julia> forward_kinematics_space(home_ee_pose, screw_axes, joint_positions)
862-
4×4 StaticArraysCore.SMatrix{4, 4, Float64, 16} with indices SOneTo(4)×SOneTo(4):
882+
4×4 Matrix{Float64}:
863883
-1.14424e-17 1.0 0.0 -5.0
864884
1.0 1.14424e-17 0.0 4.0
865885
0.0 0.0 -1.0 1.68584
@@ -871,11 +891,27 @@ function forward_kinematics_space(
871891
screw_axes::AbstractMatrix,
872892
joint_positions::AbstractVector,
873893
)
874-
T = SMatrix{4,4}(home_ee_pose)
894+
T = similar(home_ee_pose, Float64, 4, 4)
895+
forward_kinematics_space!(T, home_ee_pose, screw_axes, joint_positions)
896+
end
897+
898+
"""
899+
forward_kinematics_space!(T, home_ee_pose, screw_axes, joint_positions)
900+
901+
In-place version of [`forward_kinematics_space`](@ref). Writes the result into `T`.
902+
"""
903+
function forward_kinematics_space!(
904+
T::AbstractMatrix,
905+
home_ee_pose::AbstractMatrix,
906+
screw_axes::AbstractMatrix,
907+
joint_positions::AbstractVector,
908+
)
909+
Ts = SMatrix{4,4}(home_ee_pose)
875910
for i in reverse(eachindex(joint_positions))
876911
Si = SVector{6}(@view screw_axes[:, i])
877-
T = matrix_exp6(vec_to_se3(Si * joint_positions[i])) * T
912+
Ts = matrix_exp6(vec_to_se3(Si * joint_positions[i])) * Ts
878913
end
914+
T .= Ts
879915
T
880916
end
881917

@@ -921,8 +957,22 @@ julia> jacobian_body(body_screw_axes, joint_positions)
921957
```
922958
"""
923959
function jacobian_body(body_screw_axes::AbstractMatrix, joint_positions::AbstractVector)
960+
Jb = similar(body_screw_axes, Float64)
961+
jacobian_body!(Jb, body_screw_axes, joint_positions)
962+
end
963+
964+
"""
965+
jacobian_body!(Jb, body_screw_axes, joint_positions)
966+
967+
In-place version of [`jacobian_body`](@ref). Writes the result into `Jb`.
968+
"""
969+
function jacobian_body!(
970+
Jb::AbstractMatrix,
971+
body_screw_axes::AbstractMatrix,
972+
joint_positions::AbstractVector,
973+
)
974+
Jb .= body_screw_axes
924975
T = SMatrix{4,4,Float64}(LA.I)
925-
Jb = copy(body_screw_axes)
926976
for i in Iterators.reverse(firstindex(joint_positions):(lastindex(joint_positions)-1))
927977
Bi1 = SVector{6}(@view body_screw_axes[:, i+1])
928978
T = T * matrix_exp6(vec_to_se3(Bi1 * -joint_positions[i+1]))
@@ -970,8 +1020,22 @@ julia> jacobian_space(screw_axes, joint_positions)
9701020
```
9711021
"""
9721022
function jacobian_space(screw_axes::AbstractMatrix, joint_positions::AbstractVector)
1023+
Js = similar(screw_axes, Float64)
1024+
jacobian_space!(Js, screw_axes, joint_positions)
1025+
end
1026+
1027+
"""
1028+
jacobian_space!(Js, screw_axes, joint_positions)
1029+
1030+
In-place version of [`jacobian_space`](@ref). Writes the result into `Js`.
1031+
"""
1032+
function jacobian_space!(
1033+
Js::AbstractMatrix,
1034+
screw_axes::AbstractMatrix,
1035+
joint_positions::AbstractVector,
1036+
)
1037+
Js .= screw_axes
9731038
T = SMatrix{4,4,Float64}(LA.I)
974-
Js = copy(screw_axes)
9751039
for i = (firstindex(joint_positions)+1):lastindex(joint_positions)
9761040
Si1 = SVector{6}(@view screw_axes[:, i-1])
9771041
T = T * matrix_exp6(vec_to_se3(Si1 * joint_positions[i-1]))

src/robot.jl

Lines changed: 22 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -100,25 +100,37 @@ end
100100
# Convenience wrappers: kinematics
101101

102102
forward_kinematics_body(robot::Robot, joint_positions::AbstractVector) =
103-
forward_kinematics_body(
104-
copy(robot.home_ee_pose),
105-
robot.screw_axes_body,
106-
joint_positions,
107-
)
103+
forward_kinematics_body(robot.home_ee_pose, robot.screw_axes_body, joint_positions)
104+
105+
forward_kinematics_body!(T::AbstractMatrix, robot::Robot, joint_positions::AbstractVector) =
106+
forward_kinematics_body!(T, robot.home_ee_pose, robot.screw_axes_body, joint_positions)
108107

109108
forward_kinematics_space(robot::Robot, joint_positions::AbstractVector) =
110-
forward_kinematics_space(
111-
copy(robot.home_ee_pose),
112-
robot.screw_axes_space,
113-
joint_positions,
114-
)
109+
forward_kinematics_space(robot.home_ee_pose, robot.screw_axes_space, joint_positions)
110+
111+
forward_kinematics_space!(
112+
T::AbstractMatrix,
113+
robot::Robot,
114+
joint_positions::AbstractVector,
115+
) = forward_kinematics_space!(
116+
T,
117+
robot.home_ee_pose,
118+
robot.screw_axes_space,
119+
joint_positions,
120+
)
115121

116122
jacobian_body(robot::Robot, joint_positions::AbstractVector) =
117123
jacobian_body(robot.screw_axes_body, joint_positions)
118124

125+
jacobian_body!(J::AbstractMatrix, robot::Robot, joint_positions::AbstractVector) =
126+
jacobian_body!(J, robot.screw_axes_body, joint_positions)
127+
119128
jacobian_space(robot::Robot, joint_positions::AbstractVector) =
120129
jacobian_space(robot.screw_axes_space, joint_positions)
121130

131+
jacobian_space!(J::AbstractMatrix, robot::Robot, joint_positions::AbstractVector) =
132+
jacobian_space!(J, robot.screw_axes_space, joint_positions)
133+
122134
inverse_kinematics_body(
123135
robot::Robot,
124136
target_config::AbstractMatrix,

0 commit comments

Comments
 (0)