Skip to content

Commit 362b397

Browse files
committed
- Updated compat to GeometryBasics 0.5
- Change new_XXXXXX_cache behaviour to run kinematics/dynamics etc. once to ensure the cache is populated with valid data - Documentation fixes
1 parent 4167862 commit 362b397

File tree

12 files changed

+69
-76
lines changed

12 files changed

+69
-76
lines changed

Project.toml

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
name = "VMRobotControl"
22
uuid = "7d923390-5bb2-4b12-9c06-5b46ef7ec375"
33
authors = ["Daniel Larby <[email protected]>"]
4-
version = "0.1.0"
4+
version = "0.1.1"
55

66
[deps]
77
BenchmarkTools = "6e4b80f9-dd63-53aa-95a3-0cdb28fa8baf"
@@ -51,17 +51,17 @@ Colors = "0.12, 0.13"
5151
DataStructures = "0.18"
5252
DiffResults = "1"
5353
DifferentialEquations = "7"
54-
DigitalAssetExchangeFormatIO = "1.1.2"
54+
DigitalAssetExchangeFormatIO = "1.1.3"
5555
EzXML = "1"
5656
FileIO = "1"
5757
ForwardDiff = "0.10"
5858
FunctionWrappers = "1"
59-
GeometryBasics = "0.4"
59+
GeometryBasics = "0.5"
6060
Graphs = "1"
6161
JSON = "0.21"
6262
LoopVectorization = "0.12"
63-
Makie = "0.21"
64-
MeshIO = "0.4"
63+
Makie = "0.22"
64+
MeshIO = "0.5"
6565
Observables = "0.5"
6666
OrderedCollections = "1"
6767
Pkg = "1"

docs/src/api/api.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -135,12 +135,13 @@ VMRobotControl.CoordinateData
135135
configuration
136136
velocity
137137
jacobian
138-
vpa
138+
acceleration
139139
```
140140

141141
### Coordinate types
142142
```@docs
143143
CoordDifference
144+
CoordNorm
144145
CoordStack
145146
CoordSlice
146147
CoordSum

docs/src/developer/developer.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,7 @@ VMRobotControl.Spherical
7878
VMRobotControl.Inertance
7979
VMRobotControl.rigid_joint_twist
8080
VMRobotControl._add_jacobian_transpose_times_force!
81+
VMRobotControl._add_opspace_force!
8182
VMRobotControl.jacobian_column
8283
VMRobotControl.state_idxs
8384
VMRobotControl.remake

docs/src/index.md

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -73,7 +73,7 @@ Please cite this library as
7373
and also consider citing the authors works on [optimal virtual model control](https://doi.org/10.48550/arXiv.2411.06627)
7474
and [robot control for robotic surgery](https://doi.org/10.1016/j.ifacol.2023.10.015).
7575
```bibtex
76-
@misc{larby2024optimalvirtualmodelcontrol,
76+
@misc{Larby2024,
7777
title={Optimal Virtual Model Control for Robotics: Design and Tuning of Passivity-Based Controllers},
7878
author={Daniel Larby and Fulvio Forni},
7979
year={2024},
@@ -83,7 +83,7 @@ and [robot control for robotic surgery](https://doi.org/10.1016/j.ifacol.2023.10
8383
doi = {https://doi.org/10.48550/arXiv.2411.06627},
8484
url={https://arxiv.org/abs/2411.06627},
8585
}
86-
@article{LARBY20238548,
86+
@article{Larby2023,
8787
title = {A Generalized Approach to Impedance Control Design for Robotic Minimally Invasive Surgery},
8888
journal = {IFAC-PapersOnLine},
8989
year = {2023},
@@ -102,5 +102,5 @@ I was supported by my supervisor, [Fulvio Forni](https://sites.google.com/site/f
102102
the other students in the group.
103103

104104
My PhD was graciously supported by the Engineering and Physical Sciences Research Council;
105-
and by [CMR Surgical](https://us.cmrsurgical.com/).
105+
and by [CMR Surgical](https://cmrsurgical.com/).
106106

docs/src/tutorials/simulating.md

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
12
# Simulating with DifferentialEquations.jl
23

34
## Getting started
@@ -64,4 +65,6 @@ sol = solve(prob, Tsit5())
6465
sol.retcode
6566
```
6667

67-
## Using `f_setup` and `f_control`
68+
## Using `f_setup` and `f_control`
69+
70+
Two callbacks, `f_setup` and `f_control` can be provided when simulating. The first runs once before the simulation starts. The second runs once per step. The examples section demonstrates their use and signatures.

src/components/components.jl

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -388,14 +388,13 @@ struct Visual{G, FID} <: ComponentData{Float64}
388388
shininess::Float32
389389
function Visual(frame, geometry; color=RGBAf(1.0f0, 0.0f0, 1.0f0, 1.0f0), specular=0.2f0, shininess=32.0f0)
390390
if isa(geometry, GeometryBasics.GeometryPrimitive)
391-
_geom = hacky_normal_mesh(geometry)
391+
_mesh = GeometryBasics.normal_mesh(geometry)
392392
elseif isa(geometry, GeometryBasics.Mesh)
393-
_geom = geometry
393+
_mesh = geometry
394394
else
395395
error("Invalid geometry type: $(typeof(geometry))")
396396
end
397-
# _geom = standardize_geometrybasics_mesh(mesh)
398-
new{typeof(_geom), typeof(frame)}(frame, _geom, color, specular, shininess)
397+
new{typeof(_mesh), typeof(frame)}(frame, _mesh, color, specular, shininess)
399398
end
400399

401400
function Visual(name, color, geometry)

src/interface.jl

Lines changed: 35 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -706,40 +706,52 @@ See also [`control_step!`](@ref)
706706
"""
707707
function new_control_cache end
708708

709-
709+
# Compiled mechanisms cache bundles
710+
new_kinematics_cache(m::CompiledMechanism; initialize::Bool=true) = new_kinematics_cache(m, eltype(m); initialize)
711+
new_jacobians_cache(m::CompiledMechanism; initialize::Bool=true) = new_jacobians_cache(m, eltype(m); initialize)
712+
new_rbstates_cache(m::CompiledMechanism; initialize::Bool=true) = new_rbstates_cache(m, eltype(m); initialize)
713+
new_dynamics_cache(m::CompiledMechanism; initialize::Bool=true) = new_dynamics_cache(m, eltype(m); initialize)
714+
new_inverse_dynamics_cache(m::CompiledMechanism; initialize::Bool=true) = new_inverse_dynamics_cache(m, eltype(m); initialize)
710715

711716
function new_kinematics_cache(m::CompiledMechanism, ::Type{T}; initialize::Bool=true) where T
712717
cache = MechKinematicsCache{T}(m)
713718
bundle = MechanismCacheBundle(m, cache)
714-
if initialize
715-
# As the kinematics cache is used for plotting, it would be confusing if when we plot with
716-
# a fresh cache, things look broken because the cache is full of invalid data. Therefore
717-
# the default behaviour is to initialize the cache by calling `kinematics!` once.
718-
kinematics!(bundle, zero(T), zeros(ndof(m)))
719-
end
719+
# As the kinematics cache is used for plotting, it would be confusing if when we plot with
720+
# a fresh cache, things look broken because the cache is full of invalid data. Therefore
721+
# the default behaviour is to initialize the cache by calling `kinematics!` once.
722+
initialize && kinematics!(bundle, zero(T), zero_q(m))
720723
bundle
721724
end
722-
new_kinematics_cache(m::CompiledMechanism; initialize::Bool=true) = new_kinematics_cache(m, eltype(m); initialize)
723725

724-
new_jacobians_cache(m::CompiledMechanism, ::Type{T}) where T = MechanismCacheBundle(m, MechJacobiansCache{T}(m))
725-
new_jacobians_cache(m::CompiledMechanism) = new_jacobians_cache(m, eltype(m))
726-
727-
new_rbstates_cache(m::CompiledMechanism, ::Type{T}) where T = MechanismCacheBundle(m, MechRBStatesCache{T}(m))
728-
new_rbstates_cache(m::CompiledMechanism) = new_rbstates_cache(m, eltype(m))
729-
730-
new_dynamics_cache(m::CompiledMechanism, ::Type{T}) where T = MechanismCacheBundle(m, MechDynamicsCache{T}(m))
731-
new_dynamics_cache(m::CompiledMechanism) = new_dynamics_cache(m, eltype(m))
732-
733-
new_inverse_dynamics_cache(m::CompiledMechanism, ::Type{T}) where T = MechanismCacheBundle(m, MechRNECache{T}(m))
734-
new_inverse_dynamics_cache(m::CompiledMechanism) = new_inverse_dynamics_cache(m, eltype(m))
726+
function new_jacobians_cache(m::CompiledMechanism, ::Type{T}; initialize::Bool=true) where T
727+
cache = MechJacobiansCache{T}(m)
728+
bundle = MechanismCacheBundle(m, cache)
729+
initialize && jacobians!(bundle, zero(T), zero_q(m))
730+
bundle
731+
end
735732

736-
precompute!(m::CompiledMechanism, t::Real, q::SVector, q̇::SVector, gravity::SVector{3}) =
737-
error("Deprecated. Please use the new interface with a mechanism cache constructed using `new_dynamics_cache(m)`")
733+
function new_rbstates_cache(m::CompiledMechanism, ::Type{T}; initialize::Bool=true) where T
734+
cache = MechRBStatesCache{T}(m)
735+
bundle = MechanismCacheBundle(m, cache)
736+
initialize && velocity_kinematics!(bundle, zero(T), zero_q(m), zero_q̇(m))
737+
bundle
738+
end
738739

739-
precompute_transforms!(m::CompiledMechanism, t::Real, q::SVector) =
740-
error("Deprecated. Please use the new interface with a mechanism cache constructed using `new_kinematics_cache(m)`")
740+
function new_dynamics_cache(m::CompiledMechanism, ::Type{T}; initialize::Bool=true) where T
741+
cache = MechDynamicsCache{T}(m)
742+
bundle = MechanismCacheBundle(m, cache)
743+
initialize && dynamics!(bundle, zero(T), zero_q(m), zero_q̇(m), DEFAULT_GRAVITY, zero_u(m))
744+
bundle
745+
end
741746

747+
function new_inverse_dynamics_cache(m::CompiledMechanism, ::Type{T}; initialize::Bool=true) where T
748+
cache = MechRNECache{T}(m)
749+
bundle = MechanismCacheBundle(m, cache)
750+
initialize && inverse_dynamics!(bundle, zero(T), zero_q(m), zero_q̇(m), zero_q̈(m), DEFAULT_GRAVITY)
751+
bundle
752+
end
742753

754+
# VirtualMechanismSystem cache bundles
743755
function new_kinematics_cache(vms::CVMSystem, ::Type{T}; initialize::Bool=true) where T
744756
cache = VMSKinematicsCache{T}(vms)
745757
bundle = VirtualMechanismSystemCacheBundle(vms, cache)

src/mechanismcache.jl

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -490,6 +490,8 @@ signatures = [
490490
(:get_linear_acceleration, :cache, MechanismCacheBundle, (CompiledFrameID,)),
491491
(:get_linear_jacobian, :cache, MechanismCacheBundle, (CompiledFrameID,)),
492492
(:get_angular_jacobian, :cache, MechanismCacheBundle, (CompiledFrameID,)),
493+
(:get_frame_force, :cache, MechanismCacheBundle, (CompiledFrameID,)),
494+
(:get_frame_torque, :cache, MechanismCacheBundle, (CompiledFrameID,)),
493495
# Forwards to mechanism
494496
(:name, :mechanism, MechanismCacheBundle, ()),
495497
(:frames, :mechanism, MechanismCacheBundle, ()),
@@ -595,6 +597,10 @@ virtual_mechanism_ndof(bundle::VMSCacheBundle) = virtual_mechanism_ndof(bundle.v
595597
@inline _get_linear_acc(c::VirtualMechanismSystemCacheBundle, i::VMSFrameID) = _get_linear_acc(get_vms_subcache(c, i), i.idx)
596598
@inline get_linear_jacobian(c::VirtualMechanismSystemCacheBundle, i::VMSFrameID) = get_linear_jacobian(get_vms_subcache(c, i), i.idx)
597599
@inline get_angular_jacobian(c::VirtualMechanismSystemCacheBundle, i::VMSFrameID) = get_angular_jacobian(get_vms_subcache(c, i), i.idx)
600+
@inline get_frame_force(c::FrameRBStatesWrenchesCache, i::VMSFrameID) = error()
601+
@inline get_frame_torque(c::FrameRBStatesWrenchesCache, i::VMSFrameID) = error()
602+
603+
598604
@inline coordinate(c::VMSCacheBundle, id::VMSCoordID{C, S}) where {C, S} = coordinates(get_vms_subcache(c, id))[id.idx]
599605

600606
#===================================================================================================
@@ -633,6 +639,8 @@ get_angular_acceleration(c::ComputeCache, i::CompiledFrameID) = error("angular_a
633639
get_linear_acceleration(c::ComputeCache, i::CompiledFrameID) = error("linear_acceleration not available from type $(typeof(c))")
634640
get_linear_jacobian(c::ComputeCache, i::CompiledFrameID) = error("linear_jacobian not available from type $(typeof(c))")
635641
get_angular_jacobian(c::ComputeCache, i::CompiledFrameID) = error("angular_jacobian not available from type $(typeof(c))")
642+
get_frame_force(c::ComputeCache, i::CompiledFrameID) = error("frame_force not available from type $(typeof(c))")
643+
get_frame_torque(c::ComputeCache, i::CompiledFrameID) = error("frame_torque not available from type $(typeof(c))")
636644
get_frame_forces(c::ComputeCache) = error("frame_forces not available from type $(typeof(c))")
637645
get_frame_torques(c::ComputeCache) = error("frame_torques not available from type $(typeof(c))")
638646
get_inertance_matrix(c::ComputeCache) = error("inertance_matrix not available from type $(typeof(c))")
@@ -692,6 +700,8 @@ get_generalized_force_workspace(c::MechDynamicsCache) = c.generalized_force_work
692700
get_u(c::MechRNECache) = c.u
693701
get_frame_forces(c::MechRNECache) = c.frame_cache.forces
694702
get_frame_torques(c::MechRNECache) =c.frame_cache.torques
703+
get_frame_force(c::MechRNECache, i::CompiledFrameID) = c.frame_cache.forces[i]
704+
get_frame_torque(c::MechRNECache, i::CompiledFrameID) = c.frame_cache.torques[i]
695705

696706
# Methods for num frames to avoid ambiguity
697707
num_frames(c::MechanismCache) = num_frames(c.frame_cache)

src/mesh_utils.jl

Lines changed: 1 addition & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -19,38 +19,5 @@ function rescale_mesh(mesh, scale)
1919
end
2020

2121
function hacky_normal_mesh(primitive)
22-
pointtype=GeometryBasics.Point3f
23-
facetype=GeometryBasics.GLTriangleFace
24-
normaltype=GeometryBasics.Vec3f
25-
# This exists because GeometryBasics.normal_mesh does not result in correct normal vectors
26-
# for visualization in GLMakie (see [this](https://discourse.julialang.org/t/mesh-plotting-in-glmakie-with-geometrybasics-are-normals-broken/118227))
27-
28-
# This function is a hacky workaround to fix the normal vectors of a mesh
29-
# it works by duplicating vertices so that they we can associate different normal vectors
30-
# to the same point, resulting in inefficient meshes.
31-
32-
positions, faces = GeometryBasics.decompose_triangulate_fallback(primitive; pointtype=pointtype, facetype=facetype)
33-
34-
# We want to preserve any existing attributes!
35-
attrs = GeometryBasics.attributes(primitive)
36-
# Make sure this doesn't contain position, we'll add position explicitely via meta!
37-
delete!(attrs, :position)
38-
39-
40-
normals, normal_faces = let
41-
normals = Vector{normaltype}(undef, length(faces))
42-
normal_faces = Vector{facetype}(undef, length(faces))
43-
for (i, face) in enumerate(faces)
44-
@assert length(face) == 3
45-
v1, v2, v3 = GeometryBasics.metafree.(getindex.((positions,), (face[1], face[2], face[3])))
46-
# we can get away with two edges since faces are planar.
47-
n = normalize(GeometryBasics.orthogonal_vector(v1, v2, v3))
48-
normals[i] = n
49-
normal_face = facetype(length(normals), length(normals), length(normals))
50-
normal_faces[i] = normal_face
51-
end
52-
normals .= normalize.(normals)
53-
normals, normal_faces
54-
end
55-
DigitalAssetExchangeFormatIO.to_geometrybasics_mesh(positions, normals, faces, normal_faces)
22+
GeometryBasics.normal_mesh(primitive)
5623
end

src/rson/parsing.jl

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -508,12 +508,12 @@ function parseVisual!(mechanism, name::JSON_STR, data, cfg::RSONParserConfig)
508508
expect = (field, TYPE) -> expectField(data, field, TYPE, cfg)
509509
if type == "box"
510510
widths = parseVec(expect("size", Vector{Any}), Float64, Val{3}(), cfg)
511-
mesh = normal_mesh(Rect3{Float64}(-widths./2, widths))
511+
mesh = normal_mesh(Rect{3, Float64}(-widths./2, widths))
512512
elseif type == "cylinder"
513513
L = expect("length", Float64)
514514
origin = L * SVector(0.0, 0.0, -0.5)
515515
extremity = L * SVector(0.0, 0.0, 0.5)
516-
mesh = Cylinder3{Float64}(origin, extremity, expect("radius", Float64))
516+
mesh = Cylinder{Float64}(origin, extremity, expect("radius", Float64))
517517
elseif type == "sphere"
518518
origin = SVector(0.0, 0.0, 0.0)
519519
mesh = normal_mesh(Sphere{Float64}(origin, expect("radius", Float64)))

0 commit comments

Comments
 (0)