diff --git a/.github/workflows/ci.yml b/.github/workflows/CI.yml similarity index 72% rename from .github/workflows/ci.yml rename to .github/workflows/CI.yml index b1aa8b6..e12fba6 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/CI.yml @@ -4,6 +4,7 @@ on: branches: - master pull_request: + jobs: test: name: Julia ${{ matrix.version }} - ${{ matrix.os }} - ${{ matrix.arch }} - ${{ github.event_name }} @@ -12,7 +13,8 @@ jobs: fail-fast: false matrix: version: - - '1.6' + - '1.9' + - '1.10' - '1' os: - ubuntu-latest @@ -20,18 +22,22 @@ jobs: - windows-latest arch: - x64 + include: + - os: macOS-latest + arch: arm64 + version: 1 steps: - - uses: actions/checkout@v3 - - uses: julia-actions/setup-julia@v1 + - uses: actions/checkout@v4 + - uses: julia-actions/setup-julia@v2 with: version: ${{ matrix.version }} arch: ${{ matrix.arch }} - - uses: julia-actions/cache@v1 + - uses: julia-actions/cache@v2 - uses: julia-actions/julia-buildpkg@v1 - uses: julia-actions/julia-runtest@v1 with: prefix: ${{ matrix.prefix }} - uses: julia-actions/julia-processcoverage@v1 - - uses: codecov/codecov-action@v1 + - uses: codecov/codecov-action@v2 with: file: lcov.info diff --git a/.github/workflows/CompatHelper.yml b/.github/workflows/CompatHelper.yml index 7a9c79f..5f42779 100644 --- a/.github/workflows/CompatHelper.yml +++ b/.github/workflows/CompatHelper.yml @@ -15,7 +15,7 @@ jobs: run: which julia continue-on-error: true - name: Install Julia, but only if it is not already available in the PATH - uses: julia-actions/setup-julia@v1 + uses: julia-actions/setup-julia@v2 with: version: '1' arch: ${{ runner.arch }} diff --git a/Project.toml b/Project.toml index 6b9d121..c89ddf7 100644 --- a/Project.toml +++ b/Project.toml @@ -1,6 +1,6 @@ name = "MeshCatMechanisms" uuid = "6ad125db-dd91-5488-b820-c1df6aab299d" -version = "0.9.0" +version = "0.10.0" [deps] ColorTypes = "3da002f7-5984-5a60-b8a6-cbb66c0b333f" @@ -15,19 +15,18 @@ OrderedCollections = "bac558e1-5e72-5ebc-8fee-abe8a469f55d" RigidBodyDynamics = "366cf18f-59d5-5db9-a4de-86a9f6786172" [compat] -ColorTypes = "0.7, 0.8, 0.9, 0.10, 0.11" +ColorTypes = "0.7, 0.8, 0.9, 0.10, 0.11, 0.12" CoordinateTransformations = "0.5, 0.6" -GeometryBasics = "0.4" +GeometryBasics = "0.4, 0.5" InteractBase = "0.8, 0.9, 0.10" -Interpolations = "0.9, 0.10, 0.11, 0.12, 0.13, 0.14" +Interpolations = "0.9, 0.10, 0.11, 0.12, 0.13, 0.14, 0.15" LoopThrottle = "0.1" -MechanismGeometries = "0.7" -MeshCat = "0.13, 0.14, 0.15, 0.16" +MechanismGeometries = "0.7, 0.8" +MeshCat = "1" NBInclude = "1, 2" OrderedCollections = "1" RigidBodyDynamics = "2" -ValkyrieRobot = "0.2.1" -julia = "1.6" +julia = "1.9" [extras] NBInclude = "0db19996-df87-5ea3-a455-e3a50d440464" @@ -35,7 +34,6 @@ Pkg = "44cfe95a-1eb2-52ea-b672-e2afdf69b78f" Random = "9a3f8284-a2c9-5f02-9a11-845980a1fd5c" StaticArrays = "90137ffa-7385-5640-81b9-e52037218182" Test = "8dfed614-e22c-5e08-85e1-65c5234f0b40" -ValkyrieRobot = "c74b26e8-f247-5d24-b013-c11a2bbd97c6" [targets] -test = ["StaticArrays", "Pkg", "NBInclude", "Test", "ValkyrieRobot", "Random"] +test = ["StaticArrays", "Pkg", "NBInclude", "Test", "Random"] diff --git a/examples/demo.ipynb b/examples/demo.ipynb index 6ab79a2..dc57d20 100644 --- a/examples/demo.ipynb +++ b/examples/demo.ipynb @@ -16,9 +16,10 @@ "metadata": {}, "outputs": [], "source": [ + "using CoordinateTransformations: Translation\n", "using MeshCat\n", - "using RigidBodyDynamics\n", - "using MeshCatMechanisms" + "using MeshCatMechanisms\n", + "using RigidBodyDynamics" ] }, { @@ -141,20 +142,36 @@ "Try clicking \"Animation\" -> \"default\" -> \"play\" again in the MeshCat window. You should see the arm animation repeat, and the point and triad you've added will move as well. " ] }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Now let's try loading a more complex robot like NASA's Valkyrie (a humanoid robot)." + ] + }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ + "Pkg.activate(temp=true)\n", + "Pkg.add(\"ValkyrieRobot\")\n", "using ValkyrieRobot\n", "\n", "val = Valkyrie();\n", "delete!(vis)\n", - "mvis = MechanismVisualizer(\n", - " val.mechanism, \n", - " URDFVisuals(ValkyrieRobot.urdfpath(), package_path=[dirname(dirname(ValkyrieRobot.urdfpath()))]),\n", - " vis);" + "urdfvisuals = URDFVisuals(\n", + " ValkyrieRobot.urdfpath(),\n", + " package_path=[dirname(dirname(ValkyrieRobot.urdfpath()))])\n", + "mvis = MechanismVisualizer(val.mechanism, urdfvisuals, vis);" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Let's change the configuration from all zeros to a \"nominal\" configuration." ] }, { @@ -180,11 +197,40 @@ " set_configuration!(state, val.basejoint, [1; 0; 0; 0; 0; 0; 1.025])\n", " nothing\n", "end\n", + "\n", "state = MechanismState(val.mechanism)\n", "initialize!(state, val)\n", + "\n", "set_configuration!(mvis, configuration(state))" ] }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "We can also visualise the inertias of the robot's individual linkages as a set of ellipsoids.\n", + "\n", + "The snippet below adds this visual representation to the 3D viewer, side-by-side with the actual robot." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "mvis = MechanismVisualizer(val.mechanism, Skeleton(), vis[:val_inertia])\n", + "set_configuration!(mvis, configuration(state))\n", + "settransform!(vis[:val_inertia], Translation(0, 2, 0))" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "---" + ] + }, { "cell_type": "code", "execution_count": null, @@ -201,13 +247,6 @@ "set_configuration!(vis, [0.5]) \n", "render(vis)" ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [] } ], "metadata": { @@ -216,17 +255,17 @@ "lastKernelId": null }, "kernelspec": { - "display_name": "Julia 1.3.1", + "display_name": "Julia 1.11.2", "language": "julia", - "name": "julia-1.3" + "name": "julia-1.11" }, "language_info": { "file_extension": ".jl", "mimetype": "application/julia", "name": "julia", - "version": "1.3.1" + "version": "1.11.2" } }, "nbformat": 4, - "nbformat_minor": 2 + "nbformat_minor": 4 } diff --git a/examples/interactive_manipulation.ipynb b/examples/interactive_manipulation.ipynb index ac784b4..328e39b 100644 --- a/examples/interactive_manipulation.ipynb +++ b/examples/interactive_manipulation.ipynb @@ -138,13 +138,6 @@ " set_configuration!(mvis, configuration(x))\n", "end" ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [] } ], "metadata": { @@ -153,17 +146,17 @@ "lastKernelId": "7e34dd28-a64c-4428-9bea-63befbdea05d" }, "kernelspec": { - "display_name": "Julia 1.3.1", + "display_name": "Julia 1.11.2", "language": "julia", - "name": "julia-1.3" + "name": "julia-1.11" }, "language_info": { "file_extension": ".jl", "mimetype": "application/julia", "name": "julia", - "version": "1.3.1" + "version": "1.11.2" } }, "nbformat": 4, - "nbformat_minor": 2 + "nbformat_minor": 4 } diff --git a/src/animate.jl b/src/animate.jl index 36bc885..f5a9e21 100644 --- a/src/animate.jl +++ b/src/animate.jl @@ -1,5 +1,5 @@ """ - animate(vis::MechanismVisualizer, + animate(mvis::MechanismVisualizer, times::Vector{Float64}, configurations::Vector{Vector{Float64}}; fps::Float64=60, realtimerate::Float64=1.) @@ -7,14 +7,14 @@ Animate the given mechanism passing through a time-coded series of configurations by linearly interpolating the configuration vectors. """ -function animate(vis::MechanismVisualizer, +function animate(mvis::MechanismVisualizer, times::Vector{Float64}, configurations::AbstractVector{<:AbstractVector{Float64}}; - fps::Float64 = 60., realtimerate::Float64 = 1.) + fps::Float64=60.0, realtimerate::Float64=1.0) @assert fps > 0 @assert 0 < realtimerate < Inf - state = vis.state + state = mvis.state interpolated_configurations = interpolate((times,), configurations, Gridded(Linear())) t0, tf = first(times), last(times) framenum = 0 @@ -24,24 +24,24 @@ function animate(vis::MechanismVisualizer, q = interpolated_configurations(t) set_configuration!(state, q) rbd.normalize_configuration!(state) - _render_state!(vis) + _render_state!(mvis) framenum += 1 t == tf && break end max_rate = fps end function MeshCat.Animation(mvis::MechanismVisualizer, - times::AbstractVector{<:Real}, - configurations::AbstractVector{<:AbstractVector{<:Real}}; - fps::Integer=30) + times::AbstractVector{<:Real}, + configurations::AbstractVector{<:AbstractVector{<:Real}}; + fps::Integer=30) @assert axes(times) == axes(configurations) interpolated_configurations = interpolate((times,), configurations, Gridded(Linear())) - animation = Animation() + animation = Animation(mvis.visualizer) num_frames = floor(Int, (times[end] - first(times)) * fps) - for frame in 0 : num_frames + for frame in 0:num_frames time = first(times) + frame / fps - let mvis = mvis, interpolated_configurations = interpolated_configurations, time=time - atframe(animation, frame) do + let mvis = mvis, interpolated_configurations = interpolated_configurations, time = time + atframe(animation, frame) do set_configuration!(mvis, interpolated_configurations(time)) end end @@ -53,11 +53,11 @@ MeshCat.setanimation!(mvis::MechanismVisualizer, args...; kw...) = setanimation!(visualizer(mvis), args...; kw...) function MeshCat.setanimation!(mvis::MechanismVisualizer, - times::AbstractVector{<:Real}, - configurations::AbstractVector{<:AbstractVector{<:Real}}; - fps::Integer=30, - play::Bool=true, - repetitions::Integer=1) + times::AbstractVector{<:Real}, + configurations::AbstractVector{<:AbstractVector{<:Real}}; + fps::Integer=30, + play::Bool=true, + repetitions::Integer=1) Base.depwarn(""" `setanimation!(mvis, times, configurations; ..)` is deprecated. Instead, you can construct an `Animation` and then call `setanimation!` with the result. diff --git a/test/runtests.jl b/test/runtests.jl index eed172f..cc79fd1 100644 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -4,10 +4,16 @@ using MeshCatMechanisms using RigidBodyDynamics using RigidBodyDynamics.OdeIntegrators using CoordinateTransformations: Translation -using ValkyrieRobot using NBInclude using StaticArrays +import Pkg +Pkg.activate(temp=true) +# Can be replaced by simply `Pkg.add(ValkyrieRobot)` when this PR +# gets merged: https://github.com/tkoolen/ValkyrieRobot.jl/pull/13 +Pkg.add(url="https://github.com/ferrolho/ValkyrieRobot.jl", rev="hf/dev") +using ValkyrieRobot + vis = Visualizer() @testset "MeshCatMechanisms" begin