diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 58085d0b..c6d52936 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -18,7 +18,6 @@ jobs: os: - ubuntu-latest - windows-latest - - macos-latest arch: - x64 steps: diff --git a/Manifest.toml b/Manifest.toml index fd73b52c..34d9a694 100644 --- a/Manifest.toml +++ b/Manifest.toml @@ -20,9 +20,9 @@ version = "0.2.0" [[deps.ArrayInterface]] deps = ["Compat", "IfElse", "LinearAlgebra", "Requires", "SparseArrays", "Static"] -git-tree-sha1 = "1ee88c4c76caa995a885dc2f22a5d548dfbbc0ba" +git-tree-sha1 = "6e8fada11bb015ecf9263f64b156f98b546918c7" uuid = "4fba245c-0d91-5ea0-9b3e-6abc04ee57a9" -version = "3.2.2" +version = "5.0.5" [[deps.ArrayLayouts]] deps = ["FillArrays", "LinearAlgebra", "SparseArrays"] @@ -35,9 +35,9 @@ uuid = "56f22d72-fd6d-98f1-02f0-08ddc0907c33" [[deps.BandedMatrices]] deps = ["ArrayLayouts", "FillArrays", "LinearAlgebra", "Random", "SparseArrays"] -git-tree-sha1 = "ce68f8c2162062733f9b4c9e3700d5efc4a8ec47" +git-tree-sha1 = "019aa88766e2493c59cbd0a9955e1bac683ffbcd" uuid = "aae01518-5342-5314-be14-df237901396f" -version = "0.16.11" +version = "0.16.13" [[deps.Base64]] uuid = "2a0f44e3-6c83-55bd-87e4-b1978d98bd5f" @@ -61,9 +61,9 @@ version = "0.4.1" [[deps.CPUSummary]] deps = ["Hwloc", "IfElse", "Preferences", "Static"] -git-tree-sha1 = "2283583c451e880ec11c7fd693613434fb5ffa74" +git-tree-sha1 = "7f5830799ee4f40a143f40d6943d421ce985ed88" uuid = "2a0fbf3d-bb9c-48f3-b0a9-814d99fd7ab9" -version = "0.1.12" +version = "0.1.17" [[deps.Calculus]] deps = ["LinearAlgebra"] @@ -73,9 +73,9 @@ version = "0.5.1" [[deps.ChainRulesCore]] deps = ["Compat", "LinearAlgebra", "SparseArrays"] -git-tree-sha1 = "c9a6160317d1abe9c44b3beb367fd448117679ca" +git-tree-sha1 = "9950387274246d08af38f6eef8cb5480862a435f" uuid = "d360d2e6-b24c-11e9-a2a3-2a2ae2dbcce4" -version = "1.13.0" +version = "1.14.0" [[deps.ChangesOfVariables]] deps = ["ChainRulesCore", "LinearAlgebra", "Test"] @@ -114,9 +114,9 @@ version = "0.3.0" [[deps.Compat]] deps = ["Base64", "Dates", "DelimitedFiles", "Distributed", "InteractiveUtils", "LibGit2", "Libdl", "LinearAlgebra", "Markdown", "Mmap", "Pkg", "Printf", "REPL", "Random", "SHA", "Serialization", "SharedArrays", "Sockets", "SparseArrays", "Statistics", "Test", "UUIDs", "Unicode"] -git-tree-sha1 = "44c37b4636bc54afac5c574d2d02b625349d6582" +git-tree-sha1 = "96b0bc6c52df76506efc8a441c6cf1adcb1babc4" uuid = "34da2185-b29b-5c13-b0c7-acf172513d20" -version = "3.41.0" +version = "3.42.0" [[deps.CompilerSupportLibraries_jll]] deps = ["Artifacts", "Libdl"] @@ -167,9 +167,9 @@ uuid = "ade2ca70-3891-5945-98fb-dc099432e06a" [[deps.DelayDiffEq]] deps = ["ArrayInterface", "DataStructures", "DiffEqBase", "LinearAlgebra", "Logging", "NonlinearSolve", "OrdinaryDiffEq", "Printf", "RecursiveArrayTools", "Reexport", "UnPack"] -git-tree-sha1 = "9b50344853bd81a1a22bfe290781d538f4790244" +git-tree-sha1 = "52f54bd7f7bc1ce794add0ccf08f8fa21acfaed9" uuid = "bcd4f6db-9728-5f36-b5f7-82caef46ccdb" -version = "5.35.0" +version = "5.35.1" [[deps.DelimitedFiles]] deps = ["Mmap"] @@ -183,9 +183,9 @@ version = "0.4.0" [[deps.DiffEqBase]] deps = ["ArrayInterface", "ChainRulesCore", "DEDataArrays", "DataStructures", "Distributions", "DocStringExtensions", "FastBroadcast", "ForwardDiff", "FunctionWrappers", "IterativeSolvers", "LabelledArrays", "LinearAlgebra", "Logging", "MuladdMacro", "NonlinearSolve", "Parameters", "PreallocationTools", "Printf", "RecursiveArrayTools", "RecursiveFactorization", "Reexport", "Requires", "SciMLBase", "Setfield", "SparseArrays", "StaticArrays", "Statistics", "SuiteSparse", "ZygoteRules"] -git-tree-sha1 = "0dee26eff5f7a4ab0381f43281c9734354ddc93d" +git-tree-sha1 = "caada727813396d9402c26e5175a01def8fd89ce" uuid = "2b5f629d-d688-5b77-993f-72d75c75574e" -version = "6.82.0" +version = "6.82.2" [[deps.DiffEqCallbacks]] deps = ["DataStructures", "DiffEqBase", "ForwardDiff", "LinearAlgebra", "NLsolve", "OrdinaryDiffEq", "Parameters", "RecipesBase", "RecursiveArrayTools", "SciMLBase", "StaticArrays"] @@ -235,9 +235,9 @@ uuid = "8ba89e20-285c-5b6f-9357-94700520ee1b" [[deps.Distributions]] deps = ["ChainRulesCore", "DensityInterface", "FillArrays", "LinearAlgebra", "PDMats", "Printf", "QuadGK", "Random", "SparseArrays", "SpecialFunctions", "Statistics", "StatsBase", "StatsFuns", "Test"] -git-tree-sha1 = "9d3c0c762d4666db9187f363a76b47f7346e673b" +git-tree-sha1 = "c43e992f186abaf9965cc45e372f4693b7754b22" uuid = "31c24e10-a181-5473-b8eb-7969acd0382f" -version = "0.25.49" +version = "0.25.52" [[deps.DocStringExtensions]] deps = ["LibGit2"] @@ -257,9 +257,9 @@ uuid = "f43a241f-c20a-4ad4-852c-f6b1247861c6" [[deps.DualNumbers]] deps = ["Calculus", "NaNMath", "SpecialFunctions"] -git-tree-sha1 = "90b158083179a6ccbce2c7eb1446d5bf9d7ae571" +git-tree-sha1 = "5837a837389fccf076445fce071c8ddaea35a566" uuid = "fa6b7ba4-c1ee-5f82-b5fc-ecf0adba8f74" -version = "0.6.7" +version = "0.6.8" [[deps.EarCut_jll]] deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg"] @@ -366,9 +366,9 @@ version = "2.0.0" [[deps.Hwloc_jll]] deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg"] -git-tree-sha1 = "d8bccde6fc8300703673ef9e1383b11403ac1313" +git-tree-sha1 = "303d70c961317c4c20fafaf5dbe0e6d610c38542" uuid = "e33a78d0-f292-5ffc-b300-72abe9b543c8" -version = "2.7.0+0" +version = "2.7.1+0" [[deps.HypergeometricFunctions]] deps = ["DualNumbers", "LinearAlgebra", "SpecialFunctions", "Test"] @@ -392,9 +392,9 @@ uuid = "b77e0a4c-d291-57a0-90e8-8db25a27a240" [[deps.InverseFunctions]] deps = ["Test"] -git-tree-sha1 = "a7254c0acd8e62f1ac75ad24d5db43f5f19f3c65" +git-tree-sha1 = "91b5dcf362c5add98049e6c29ee756910b03051d" uuid = "3587e190-3f89-42d0-90ee-14403ec27112" -version = "0.1.2" +version = "0.1.3" [[deps.InvertedIndices]] git-tree-sha1 = "bee5f1ef5bf65df56bdd2e40447590b272a5471f" @@ -507,9 +507,9 @@ version = "1.13.0" [[deps.LogExpFunctions]] deps = ["ChainRulesCore", "ChangesOfVariables", "DocStringExtensions", "InverseFunctions", "IrrationalConstants", "LinearAlgebra"] -git-tree-sha1 = "e5718a00af0ab9756305a0392832c8952c7426c1" +git-tree-sha1 = "58f25e56b706f95125dcb796f39e1fb01d913a71" uuid = "2ab3a3ac-af41-5b50-aa03-7779005ae688" -version = "0.3.6" +version = "0.3.10" [[deps.Logging]] uuid = "56ddb016-857b-54e1-b83d-db4d58db5568" @@ -562,9 +562,9 @@ uuid = "a63ad114-7e13-5084-954f-fe012c677804" [[deps.Modia]] deps = ["DataFrames", "DifferentialEquations", "FiniteDiff", "ForwardDiff", "InteractiveUtils", "JSON", "LinearAlgebra", "Measurements", "ModiaBase", "ModiaResult", "MonteCarloMeasurements", "OrderedCollections", "Printf", "RecursiveFactorization", "Reexport", "StaticArrays", "Sundials", "Test", "TimerOutputs", "Unitful"] -git-tree-sha1 = "e318ef3be4b47e5352db1a3085705e06201adda2" +git-tree-sha1 = "28acd8404dcef5e884f987795093898df45e33a1" uuid = "cb905087-75eb-5f27-8515-1ce0ec8e839e" -version = "0.8.2" +version = "0.8.3" [[deps.ModiaBase]] deps = ["DataFrames", "DiffRules", "Measurements", "MonteCarloMeasurements", "OrderedCollections", "StaticArrays", "Unitful"] @@ -620,9 +620,9 @@ uuid = "ca575930-c2e3-43a9-ace4-1e988b2c1908" [[deps.NonlinearSolve]] deps = ["ArrayInterface", "FiniteDiff", "ForwardDiff", "IterativeSolvers", "LinearAlgebra", "RecursiveArrayTools", "RecursiveFactorization", "Reexport", "SciMLBase", "Setfield", "StaticArrays", "UnPack"] -git-tree-sha1 = "4e5ee038e5655c8aaa9ac179743c5227d1f0f0f3" +git-tree-sha1 = "aeebff6a2a23506e5029fd2248a26aca98e477b3" uuid = "8913a72c-1f9b-4ce2-8d82-65094dcecaec" -version = "0.3.15" +version = "0.3.16" [[deps.OffsetArrays]] deps = ["Adapt"] @@ -657,15 +657,15 @@ version = "1.4.1" [[deps.OrdinaryDiffEq]] deps = ["Adapt", "ArrayInterface", "DataStructures", "DiffEqBase", "DocStringExtensions", "ExponentialUtilities", "FastClosures", "FiniteDiff", "ForwardDiff", "LinearAlgebra", "LinearSolve", "Logging", "LoopVectorization", "MacroTools", "MuladdMacro", "NLsolve", "NonlinearSolve", "Polyester", "PreallocationTools", "RecursiveArrayTools", "Reexport", "SciMLBase", "SparseArrays", "SparseDiffTools", "StaticArrays", "UnPack"] -git-tree-sha1 = "d8f30cac5f1d2bf3b9c0012c2f078d850c804ef1" +git-tree-sha1 = "509aa6d3b2773e5109d4a4dd9a300259ac727961" uuid = "1dea7af3-3e70-54e6-95c3-0bf5283fa5ed" -version = "6.7.0" +version = "6.7.1" [[deps.PDMats]] deps = ["LinearAlgebra", "SparseArrays", "SuiteSparse"] -git-tree-sha1 = "7e2166042d1698b6072352c74cfd1fca2a968253" +git-tree-sha1 = "e8185b83b9fc56eb6456200e873ce598ebc7f262" uuid = "90014a1f-27ba-587c-ab20-58faa44d9150" -version = "0.11.6" +version = "0.11.7" [[deps.Parameters]] deps = ["OrderedCollections", "UnPack"] @@ -709,9 +709,9 @@ version = "3.0.0" [[deps.PooledArrays]] deps = ["DataAPI", "Future"] -git-tree-sha1 = "db3a23166af8aebf4db5ef87ac5b00d36eb771e2" +git-tree-sha1 = "28ef6c7ce353f0b35d0df0d5930e0d072c1f5b9b" uuid = "2dfb63ee-cc39-5dd5-95bd-886bf059d720" -version = "1.4.0" +version = "1.4.1" [[deps.PositiveFactorizations]] deps = ["LinearAlgebra"] @@ -727,9 +727,9 @@ version = "0.2.4" [[deps.Preferences]] deps = ["TOML"] -git-tree-sha1 = "de893592a221142f3db370f48290e3a2ef39998f" +git-tree-sha1 = "d3538e7f8a790dc8903519090857ef8e1283eecd" uuid = "21216c6a-2e73-6563-6e65-726566657250" -version = "1.2.4" +version = "1.2.5" [[deps.PrettyTables]] deps = ["Crayons", "Formatting", "Markdown", "Reexport", "Tables"] @@ -780,9 +780,9 @@ version = "1.2.1" [[deps.RecursiveArrayTools]] deps = ["Adapt", "ArrayInterface", "ChainRulesCore", "DocStringExtensions", "FillArrays", "LinearAlgebra", "RecipesBase", "Requires", "StaticArrays", "Statistics", "ZygoteRules"] -git-tree-sha1 = "b66df9b4f668b340a6b6b8a7e667a68f586c5561" +git-tree-sha1 = "f5dd036acee4462949cc10c55544cc2bee2545d6" uuid = "731186ca-8d62-57ce-b412-fbd966d074cd" -version = "2.25.0" +version = "2.25.1" [[deps.RecursiveFactorization]] deps = ["LinearAlgebra", "LoopVectorization", "Polyester", "StrideArraysCore", "TriangularSolve"] @@ -841,9 +841,9 @@ version = "0.6.31" [[deps.SciMLBase]] deps = ["ArrayInterface", "CommonSolve", "ConstructionBase", "Distributed", "DocStringExtensions", "IteratorInterfaceExtensions", "LinearAlgebra", "Logging", "RecipesBase", "RecursiveArrayTools", "StaticArrays", "Statistics", "Tables", "TreeViews"] -git-tree-sha1 = "c086056df381502621dc6b5f1d1a0a1c2d0185e7" +git-tree-sha1 = "61159e034c4cb36b76ad2926bb5bf8c28cc2fb12" uuid = "0bca4576-84f4-4d90-8ffe-ffa030f20462" -version = "1.28.0" +version = "1.29.0" [[deps.Serialization]] uuid = "9e88b42a-f829-5b0c-bbe9-9e923198166b" @@ -879,9 +879,9 @@ uuid = "2f01184e-e22b-5df5-ae63-d93ebab69eaf" [[deps.SparseDiffTools]] deps = ["Adapt", "ArrayInterface", "Compat", "DataStructures", "FiniteDiff", "ForwardDiff", "Graphs", "LinearAlgebra", "Requires", "SparseArrays", "StaticArrays", "VertexSafeGraphs"] -git-tree-sha1 = "87efd1676d87706f4079e8e717a7a5f02b6ea1ad" +git-tree-sha1 = "314a07e191ea4a5ea5a2f9d6b39f03833bde5e08" uuid = "47a9eef4-7e08-11e9-0b38-333d64bd3804" -version = "1.20.2" +version = "1.21.0" [[deps.SpecialFunctions]] deps = ["ChainRulesCore", "IrrationalConstants", "LogExpFunctions", "OpenLibm_jll", "OpenSpecFun_jll"] @@ -891,15 +891,15 @@ version = "2.1.4" [[deps.Static]] deps = ["IfElse"] -git-tree-sha1 = "7f5a513baec6f122401abfc8e9c074fdac54f6c1" +git-tree-sha1 = "87e9954dfa33fd145694e42337bdd3d5b07021a6" uuid = "aedffcd0-7271-4cad-89d0-dc628f76c6d3" -version = "0.4.1" +version = "0.6.0" [[deps.StaticArrays]] deps = ["LinearAlgebra", "Random", "Statistics"] -git-tree-sha1 = "74fb527333e72ada2dd9ef77d98e4991fb185f04" +git-tree-sha1 = "4f6ec5d99a28e1a749559ef7dd518663c5eca3d5" uuid = "90137ffa-7385-5640-81b9-e52037218182" -version = "1.4.1" +version = "1.4.3" [[deps.Statistics]] deps = ["LinearAlgebra", "SparseArrays"] @@ -937,9 +937,9 @@ version = "6.45.0" [[deps.StrideArraysCore]] deps = ["ArrayInterface", "CloseOpenIntervals", "IfElse", "LayoutPointers", "ManualMemory", "Requires", "SIMDTypes", "Static", "ThreadingUtilities"] -git-tree-sha1 = "49d616ef230fec080d02ada0ca5639e652cca06b" +git-tree-sha1 = "28debdcb4371020f89ffce06af4f7f68905a5fec" uuid = "7792a7ef-975c-4747-a70f-980b88e8d1da" -version = "0.2.13" +version = "0.2.15" [[deps.StructArrays]] deps = ["Adapt", "DataAPI", "StaticArrays", "Tables"] @@ -957,9 +957,9 @@ uuid = "bea87d4a-7f5b-5778-9afe-8cc45184846c" [[deps.Sundials]] deps = ["CEnum", "DataStructures", "DiffEqBase", "Libdl", "LinearAlgebra", "Logging", "Reexport", "SparseArrays", "Sundials_jll"] -git-tree-sha1 = "76d881c22a2f3f879ad74b5a9018c609969149ab" +git-tree-sha1 = "e0805213754f0d871f9333eacd77862a44acb46d" uuid = "c3572dad-4567-51f8-b174-8c6c989267f4" -version = "4.9.2" +version = "4.9.3" [[deps.Sundials_jll]] deps = ["Artifacts", "CompilerSupportLibraries_jll", "JLLWrappers", "Libdl", "OpenBLAS_jll", "Pkg", "SuiteSparse_jll"] @@ -999,9 +999,9 @@ version = "0.5.0" [[deps.TimerOutputs]] deps = ["ExprTools", "Printf"] -git-tree-sha1 = "97e999be94a7147d0609d0b9fc9feca4bf24d76b" +git-tree-sha1 = "d60b0c96a16aaa42138d5d38ad386df672cb8bd8" uuid = "a759f4b9-e2f1-59dc-863e-4aeb61b1ea8f" -version = "0.5.15" +version = "0.5.16" [[deps.TreeViews]] deps = ["Test"] diff --git a/Project.toml b/Project.toml index d3f4952c..dae7e720 100644 --- a/Project.toml +++ b/Project.toml @@ -1,7 +1,7 @@ authors = ["Andrea Neumayr ", "Martin Otter ", "Gerhard Hippmann "] name = "Modia3D" uuid = "07f2c1e0-90b0-56cf-bda7-b44b56e34eed" -version = "0.10.1" +version = "0.10.2" [compat] Colors = "0.12, 0.11, 0.10" diff --git a/docs/src/index.md b/docs/src/index.md index 339937b4..858613e7 100644 --- a/docs/src/index.md +++ b/docs/src/index.md @@ -21,33 +21,33 @@ julia> ]add Modia3D It is advised to also install Modia and at least one Modia plot package (for details see [Installation of Modia](https://modiasim.github.io/Modia.jl/stable/#Installation)). -Note, Modia3D reexports the following definitions +Note, Modia3D reexports the following definitions - `using Modia` - `using Unitful` - `using DifferentialEquations` - and exports functions `CVODE_BDF` and `IDA` of [Sundials.jl](https://github.com/SciML/Sundials.jl). -As a result, it is usually sufficient to have `using Modia3D` in a model to utilize the relevant +As a result, it is usually sufficient to have `using Modia3D` in a model to utilize the relevant functionalities of these packages. Modia3D has various *3D animation features*: - With `world = Object3D(feature=Scene(animationFile="filename.json"))` the animation produced during a simulation run is exported in [three.js JSON Object Scene format](https://github.com/mrdoob/three.js/wiki/JSON-Object-Scene-format-4). - The generated file can be imported into the open source web app [three.js editor](https://threejs.org/editor/) and - use all the features of three.js, for example to export in the widely used glb format (the binary version of the [glTF](https://www.khronos.org/gltf/) format) + The generated file can be imported into the open source web app [three.js editor](https://threejs.org/editor/) and + use all the features of three.js, for example to export in the widely used glb format (the binary version of the [glTF](https://www.khronos.org/gltf/) format) and use any glb viewer (for example 3D-Viewer of Windows). -- With the default option `world = Object3D(feature=Scene(enableVisualization=true))` the +- With the default option `world = Object3D(feature=Scene(enableVisualization=true))` the [DLR Visualization Library](https://www.systemcontrolinnovationlab.de/the-dlr-visualization-library/) - (see the many examples from various research and industrial projects) is used, if installed, for + (see the many examples from various research and industrial projects) is used, if installed, for online animation (during simulation), replays (after simulation), and the generation of mpg4-videos. This library is available as *(free) Community Edition* and as *(commercial) Professional Edition* ([Web page to request download of DLR Visualization Library](https://visualization.ltx.de/)). After download, make the library available in the following way: - - Set Julia environment variable `ENV["DLR_VISUALIZATION"] = "/Visualization/Extras/SimVis"` - or add it to the [Julia startup.jl file](https://github.com/ModiaSim/Modia3D.jl/wiki/Template-for-startup.jl). + - Set Julia environment variable `ENV["DLR_VISUALIZATION"] = "/Visualization/Extras/SimVis"` + or add it to the [Julia startup.jl file](https://github.com/ModiaSim/Modia3D.jl/wiki/Template-for-startup.jl). *Make sure that the SimVis executable under this directory has execution rights.* For example in Linux with command: `chmod ug+x /Visualization/Extras/SimVis/linux/SimVis` @@ -69,6 +69,33 @@ Modia3D has various *3D animation features*: ## Release Notes +### Version 0.10.2 + +- Model3D(..) with no degrees of freedom is now supported (previously, an error was triggered). + +- Massless solid is now supported (previously, an error was triggered if Solid(..) had zero mass). + +- SolidMaterial, MassProperties, VisualMaterial in Solid(..) and VisualMaterial in Visual(..) improved to handle corner cases: + - SolidMaterial=="" is treated as SolidMaterial = nothing + - VisualMaterial=="" is treated as Shapes.VisualMaterial(), that is the default VisualMaterial. + - massProperties==nothing && solidMaterial==nothing is treated as MassProperties(), that is as massless solid. + +- Error message improved, if closed kinematic loop is detected. Especially, the names of all Object3Ds in the kinematic loop are printed. + +- Error message improved, if no Scene is defined. + +- solid(..., contactSphereRadius::Union{Nothing,FloatType}=xxx) improved: + - changed to contactSphereRadius::Union{Nothing,Number} (e.g. Int is also allowed). + - contactSphereRadius <= 0 is the same as contactSphereRadius = nothing. + +- Removed keyword "path" from the docu of Prismatic, Revolute, FreeMotion, since not to be set by the user (path is set when calling Model3D(..) to store the absolute path name in the joint). + +- New function `loadPalettes!`. Example: + `Modia3D.loadPalettes!(solidMaterialPalette = "file1.json", contactPairMaterialPalette = "file2.json", + visualMaterialPalette = "file3.json", log=true)` + to use the palettes from the provided files instead of the default palettes from `Modia3D/palettes/*.json`. + + ### Version 0.10.1 - Reduce memory allocations, especially in case of collisions and FreeMotion joints. @@ -91,7 +118,7 @@ The effect on Modia3D is: - Modia3D is removed from Modia (so when a model is using Modia3D, the package must be explicitly imported and is no longer automatically imported from Modia). - + - In user models, all references to ModiaBase and to ModiaLang should be replaced by Modia (otherwise, it is highly likely that the model does not longer compile and/or simulate). @@ -107,10 +134,10 @@ The effect on Modia3D is: **Non-backwards compatible changes**: - Operator `buildModia3D(..)` is removed. Instead, the new constructor `Model3D(..)` must be used at the top level of a - Modia3D definition. It is now possible to define several, independent multibody systems + Modia3D definition. It is now possible to define several, independent multibody systems (currently, only one of them can have animation and animation export). - If init/start vectors are defined (e.g. initial state of a FreeMotion joint), they must be defined as SVector{3,Float64}(..). - Otherwise, errors occur during compilation. + Otherwise, errors occur during compilation. Other changes diff --git a/src/Basics/_module.jl b/src/Basics/_module.jl index f75afd1d..01bb9a2e 100644 --- a/src/Basics/_module.jl +++ b/src/Basics/_module.jl @@ -14,6 +14,7 @@ Andrea Neumayr and Martin Otter, [DLR - Institute of System Dynamics and Control module Basics import Modia3D +import Modia3D.Modia.OrderedCollections export trailingPartOfName diff --git a/src/Basics/constantsAndFunctions.jl b/src/Basics/constantsAndFunctions.jl index 75483ea1..98f14e08 100644 --- a/src/Basics/constantsAndFunctions.jl +++ b/src/Basics/constantsAndFunctions.jl @@ -93,7 +93,7 @@ Read a JSON file from `fileName` and return a `Dict{String, StructType}` diction """ function readDictOfStructsFromJSON(fileName, StructType) dict1 = JSON.parsefile(fileName) - palette = Dict{String, StructType}() + palette = OrderedCollections.OrderedDict{String, StructType}() for (key1,value1) in dict1 obj = StructType() for (key2,value2) in value1 diff --git a/src/Composition/_module.jl b/src/Composition/_module.jl index 3b21033c..4a3b999f 100644 --- a/src/Composition/_module.jl +++ b/src/Composition/_module.jl @@ -92,6 +92,7 @@ import Printf import Modia import TimerOutputs import MonteCarloMeasurements +import Modia3D.Modia.OrderedCollections include(joinpath("joints", "object3DMotion.jl")) include("object3D.jl") diff --git a/src/Composition/dynamics.jl b/src/Composition/dynamics.jl index 7bcc1a81..bfecefb4 100644 --- a/src/Composition/dynamics.jl +++ b/src/Composition/dynamics.jl @@ -12,10 +12,10 @@ function getJointsAndForceElementsAndObject3DsWithoutParents!(evaluatedParameter if typeof(value.feature) <: Scene push!(object3DWithoutParents, value) else - error("\n", value.path, " is an Object3D that has no parent, but no feature=Scene(..)!\n") + error("\n", value.path, " is an Object3D that has no parent, but no feature=Scene(..)!\nThis means no Scene is defined (exactly one Object3D must have feature=Scene(..))!") end elseif typeof(value.feature) <: Scene - error("\n", value.path, " is an Object3D that has feature=Scene(..) and has a parent (= ", value.parent.path, ")!\n") + error("\n", value.path, " is an Object3D that has feature=Scene(..) and has a parent (= ", value.parent.path, ")!\nThe Object3D with feature=Scene(..) is not allowed to have a parent!") end elseif typeof(value) <: Modia3D.Composition.Revolute diff --git a/src/Composition/joints/Fix.jl b/src/Composition/joints/Fix.jl index a4456e0c..0e8240ec 100644 --- a/src/Composition/joints/Fix.jl +++ b/src/Composition/joints/Fix.jl @@ -34,11 +34,7 @@ struct Fix{F <: Modia3D.VarFloatType} translation::AbstractVector = Modia3D.ZeroVector3D(F), rotation::AbstractVector = Modia3D.ZeroVector3D(F)) where F <: Modia3D.VarFloatType - (parent, child, cutJoint) = attach(obj1, obj2) - if cutJoint - error("\nError from Fix joint connecting ", Modia3D.fullName(obj1), " with ", Modia3D.fullName(obj2), ":", - "\nThis joint is a cut-joint which is not allowed.") - end + (parent, child, cutJoint) = attach(obj1, obj2, name = "Fix joint") # an error is triggered if cutJoint=true r_rel = Modia3D.convertAndStripUnit(SVector{3,F}, u"m", translation) rot = Modia3D.convertAndStripUnit(SVector{3,F}, u"rad", rotation) diff --git a/src/Composition/joints/Prismatic.jl b/src/Composition/joints/Prismatic.jl index 3413e130..e19de9d8 100644 --- a/src/Composition/joints/Prismatic.jl +++ b/src/Composition/joints/Prismatic.jl @@ -16,7 +16,7 @@ get_eAxis(::Type{F}, axis::Int) where F <: Modia3D.VarFloatType = axis== 1 ? SV error("Modia3D.Composition.Prismatic: axis = ", axis, " but must be 1, 2, 3, -1, -2, or -3.") """ - joint = Prismatic(; obj1, obj2, path="", axis=1, s=0, v=0, canCollide=true) + joint = Prismatic(; obj1, obj2, axis=1, s=0, v=0, canCollide=true) Return a `joint` that translates `obj2::`[`Object3D`](@ref) with respect to `obj1::`[`Object3D`](@ref) along coordinate axis `axis` (`axis = 1,2,3,-1,-2,-3`) @@ -52,11 +52,7 @@ mutable struct Prismatic{F <: Modia3D.VarFloatType} <: Modia3D.AbstractJoint v::Real = F(0.0), canCollide::Bool = true) where F <: Modia3D.VarFloatType - (parent,obj,cutJoint) = attach(obj1, obj2) - if cutJoint - error("\nError from Prismatic joint connecting ", Modia3D.fullName(obj1), " with ", Modia3D.fullName(obj2), ":\n", - " This joint is a cut-joint which is currently not supported.!") - end + (parent,obj,cutJoint) = attach(obj1, obj2, name = "Prismatic joint") # an error is triggered if cutJoint=true if !(1 <= abs(axis) <= 3) error("\nError from Prismatic joint connecting ", Modia3D.fullName(obj1), " with ", Modia3D.fullName(obj2), ":\n", diff --git a/src/Composition/joints/Revolute.jl b/src/Composition/joints/Revolute.jl index c3fab78d..a4e142e0 100644 --- a/src/Composition/joints/Revolute.jl +++ b/src/Composition/joints/Revolute.jl @@ -8,7 +8,7 @@ import Modia3D.Frames """ - joint = Revolute(;obj1, obj2, path="", axis=3, phi=0, w=0, canCollide=false) + joint = Revolute(;obj1, obj2, axis=3, phi=0, w=0, canCollide=false) Return a Revolute `joint` that rotates `obj1::`[`Object3D`](@ref) into `obj2::`[`Object3D`](@ref) along the axis `axis` of `obj1` (`axis = 1,2,3,-1,-2,-3`). @@ -43,11 +43,7 @@ mutable struct Revolute{F <: Modia3D.VarFloatType} <: Modia3D.AbstractJoint w::Real = F(0.0), canCollide::Bool = false) where F <: Modia3D.VarFloatType - (parent,obj,cutJoint) = attach(obj1, obj2) - if cutJoint - error("\nError from Revolute joint connecting ", Modia3D.fullName(obj1), " with ", Modia3D.fullName(obj2), ":\n", - " This joint is a cut-joint which is currently not supported.!") - end + (parent,obj,cutJoint) = attach(obj1, obj2, name = "Revolute joint") # an error is triggered if cutJoint=true if !(1 <= abs(axis) <= 3) error("\nError from Revolute joint connecting ", Modia3D.fullName(obj1), " with ", Modia3D.fullName(obj2), ":\n", diff --git a/src/Composition/joints/joints.jl b/src/Composition/joints/joints.jl index a9f39a8c..0e87dc9a 100644 --- a/src/Composition/joints/joints.jl +++ b/src/Composition/joints/joints.jl @@ -120,6 +120,8 @@ function attachAndReverseParents(newParent::Object3D{F}, obj::Object3D{F})::Noth end +getParents(obj,rootPath) = "\"" * Modia3D.fullName(obj) * "\" has " * (length(rootPath) == 0 ? "no parents" : "parents: $rootPath") + """ (obj1, obj2, cutJoint) = attach(frame_a, frame_b) @@ -128,7 +130,7 @@ and cutJoint = false is returned. If they have the same root, the tree is not modified and cutJoint=true is returned. """ -function attach(obj1::Object3D, obj2::Object3D) +function attach(obj1::Object3D, obj2::Object3D; name = "") root1 = rootObject3D(obj1) root2 = rootObject3D(obj2) #println("attach: obj1 = ", Modia3D.fullName(obj1), ", root = ", Modia3D.fullName(root1)) @@ -137,6 +139,16 @@ function attach(obj1::Object3D, obj2::Object3D) if root1 ≡ root2 # Compute absolute positions # updatePosition!(root1) + + if name != "" + # Collect all objects that form a loop + rootPath1 = rootObject3DPath(obj1) + rootPath2 = rootObject3DPath(obj2) + error("\nError from $name connecting \"", Modia3D.fullName(obj1), "\" with \"", Modia3D.fullName(obj2), "\":\n", + " ", getParents(obj1,rootPath1), "\n", + " ", getParents(obj2,rootPath2), "\n", + " Therefore, a closed kinematic loop is defined, which is currently not supported.") + end return (obj1,obj2,true) end diff --git a/src/Composition/joints/object3DMotion.jl b/src/Composition/joints/object3DMotion.jl index 75d10a6c..7ae8095d 100644 --- a/src/Composition/joints/object3DMotion.jl +++ b/src/Composition/joints/object3DMotion.jl @@ -14,7 +14,7 @@ end """ - joint = FreeMotion(; obj1, obj2, path="", r, rot, v, w) + joint = FreeMotion(; obj1, obj2, r, rot, v, w) Return a `joint` that describes the free movement of `obj2::`[`Object3D`](@ref) with respect to `obj1::`[`Object3D`](@ref). The initial position is `r` diff --git a/src/Composition/massPropertiesComputation.jl b/src/Composition/massPropertiesComputation.jl index 3a8bb407..d678ad83 100644 --- a/src/Composition/massPropertiesComputation.jl +++ b/src/Composition/massPropertiesComputation.jl @@ -104,7 +104,7 @@ function addOrSubtractMassPropertiesOfChildToRoot!(obj_root::Object3D{F}, obj_ch m = m_root + m_child # common center of mass (parent + child) - @assert(m > 0.0) + @assert(m >= 0.0) rCM = (m_root * rCM_root + m_child * rCM_child_new)/m # I: substract new common mass multiplied with skew matrices of diff --git a/src/Composition/object3D.jl b/src/Composition/object3D.jl index 8af5c5c2..d664d86a 100644 --- a/src/Composition/object3D.jl +++ b/src/Composition/object3D.jl @@ -36,8 +36,8 @@ end """ Object3D(; parent = nothing, - translation = Modia3D.ZeroVector3D(F), - rotation = Modia3D.ZeroVector3D(F), + translation = [0.0, 0.0, 0.0], + rotation = [0.0, 0.0, 0.0], feature = nothing) Generate a new Object3D object, that is a coordinate system (= frame, object3D) with associated feature that is described relatively to its (optional) parent Object3D. @@ -46,7 +46,7 @@ Generate a new Object3D object, that is a coordinate system (= frame, object3D) All arguments have default values. Thus, not all arguments must be defined. -- `parent`: Parent Object3D. If `parent` is present, the Object3D is defined relatively to the parent. If `parent` is not present, the Object3D is either a reference object (such as the world-Object3D), or the object is connected later with a joint to another Object3D. +- `parent`: Parent Object3D. If `parent` is present, the Object3D is defined relatively to the parent. If `parent` is not present, the Object3D is either the world-Object3D, or the object is connected later with a joint to another Object3D. - `translation`: Vector from the origin of the parent to the origin of the Object3D, resolved in the parent coordinate system in [m]. - Example: `translation = [0.0, 0.5, 0.0]` is a relative translation of 0.5 m in y-direction of the parent. If nothing is defined, the default value (= no translation) is taken. @@ -55,7 +55,7 @@ All arguments have default values. Thus, not all arguments must be defined. - Example: `rotation = [0.0, pi/2, 0.0]` or `rotation = [0.0, 90u"°", 0.0]` defines that a rotation around the y-axis of the parent coordinate system with 90 degrees arrives at the Object3D. If nothing is defined, the default value (= no rotation) is taken. - `feature`: Defines the (optional) property associated with the Object3D by a constructor call. Supported constructors: - - `Scene`: A [Scene](@ref) feature marks the root (world, origin) Object3D. It has no parent Object3D and allows to define global properties, such as the gravity field. + - `Scene`: A [Scene](@ref) feature marks the root Object3D (world, origin, inertial system). It has no parent Object3D and allows to define global properties, such as the gravity field. - `Visual`: A [Visual](@ref) feature defines a shape used for visualization. - `Solid`: A [Solid](@ref) feature defines the solid properties of an Object3D, like mass, inertia tensor, collision behavior. - `nothing`: No feature is associated with the Object3D. This might be useful for helper Object3Ds, for example to mark a point on a shape and connecting it later via a revolute joint. @@ -63,7 +63,9 @@ All arguments have default values. Thus, not all arguments must be defined. # Example ```julia -model = Model( +using Modia3D + +model = Model3D( world = Object3D(feature = Scene()), worldFrame = Object3D(parent = :world, feature = Visual(shape=CoordinateSystem())), @@ -551,6 +553,18 @@ function rootObject3D(obj::Object3D{F}) where F <: Modia3D.VarFloatType end +""" path = rootObject3DPath(obj) - returns a vector of Object3D names of all objects from obj to root""" +function rootObject3DPath(obj::Object3D{F}) where F <: Modia3D.VarFloatType + path = String[] + obj1 = obj + while hasParent(obj1) + obj1 = obj1.parent + push!(path, obj1.path) + end + return path +end + + """ removeChild!(obj, child) - Remove child from obj.children""" function removeChild!(obj::Object3D{F}, child::Object3D{F})::Nothing where F <: Modia3D.VarFloatType children = obj.children diff --git a/src/Composition/responseCalculation/elasticCollisionResponse.jl b/src/Composition/responseCalculation/elasticCollisionResponse.jl index 498c8f77..26d8e63c 100644 --- a/src/Composition/responseCalculation/elasticCollisionResponse.jl +++ b/src/Composition/responseCalculation/elasticCollisionResponse.jl @@ -75,8 +75,11 @@ function contactStart(matPair::Shapes.ElasticContactPairMaterial, # Compute spring constant name1 = obj1.feature.contactMaterial name2 = obj2.feature.contactMaterial - mat1 = Shapes.solidMaterialPalette[name1] - mat2 = Shapes.solidMaterialPalette[name2] + + solidMaterialPalette::OrderedCollections.OrderedDict{String,Shapes.SolidMaterial} = Shapes.solidMaterialPalette[1] + mat1 = solidMaterialPalette[name1] + mat2 = solidMaterialPalette[name2] + E1 = mat1.YoungsModulus E2 = mat2.YoungsModulus nu1 = mat1.PoissonsRatio diff --git a/src/Composition/scene.jl b/src/Composition/scene.jl index 47a68708..f89f5933 100644 --- a/src/Composition/scene.jl +++ b/src/Composition/scene.jl @@ -30,21 +30,23 @@ gravityAcceleration(grav::NoGravityField, r_abs::SVector{3,F}) where F <: Modia3 """ - UniformGravityField(;g=9.81, n=[0,-1,0]) + UniformGravityField(; g = 9.81, + n = [0,-1,0]) Generate an instance of type `UniformGravityField` that defines a uniform gravity field with gravitational acceleration `g` in -direction `n`. +direction `n`. The default value is a gravity of 9.81 m/s^2 in negative +direction of the y-axis of the root (world) Object3D. # Arguments -- `g::Float64`: Gravitational acceleration +- `g::Float64`: Gravitational acceleration in m/s^2. - `n::AbstractVector`: Direction of gravitational acceleration # Example ```julia -import Modia3D +using Modia3D -grav = Modia3D.Composition.UniformGravityField() +grav = UniformGravityField() r = Modia3D.EarthRadius g = gravityAcceleration(grav,r) # g is independent of r ``` @@ -66,7 +68,7 @@ const EarthRadius = 6.3781e6 # [m] Radius of earth (https://en.wik """ - PointGravityField([mass|;mue=G*EarthMass]) + PointGravityField([mass|; mue = G*EarthMass]) Generate an instance of type `PointGravityField` that defines a point gravity field of `mass` or gravity field constant `mue`. @@ -76,11 +78,11 @@ from world. # Example ```julia -import Modia3D +using Modia3D -grav = Modia3D.PointGravityField() # Gravity field of earth +grav = PointGravityField() # Gravity field of earth r = Modia3D.EarthRadius - g = gravityAcceleration(grav,r) # g is singular at r=0 + g = gravityAcceleration(grav,r) # g is a function of r. ``` """ struct PointGravityField <: Modia3D.AbstractGravityField @@ -306,18 +308,17 @@ end """ Scene(; kwargs...) -Defines global properties of the system, such as the gravity field. Exactly one [Object3D](@ref) must have a `Scene` feature defined. This Object3D is used as inertial system (world, root) and is not allowed to have a parent Object3D. +Defines global properties of the system, such as the gravity field. Exactly one [Object3D](@ref) must have a `Scene` feature defined. This Object3D is used as root Object3D (world, origin, inertial system) and is not allowed to have a parent Object3D. | Keyword arguments | defaults | |:--------------------------------|:----------------------------------------| -| `gravityField` | [`UniformGravityField`](@ref)`()` | -| `useOptimizedStructure` | true | +| `gravityField` | UniformGravity(g=9.81, n=[0,-1,0]) | +| `enableVisualization` | true | +| `animationFile` | nothing (e.g. animationFile = "animation.json") | | `enableContactDetection` | true | -| `mprTolerance` | 1.0e-20 | -| `elasticContactReductionFactor` | 1.0 (<= 1.0 required) | +| `elasticContactReductionFactor` | 1.0 (> 0.0, <= 1.0) | | `maximumContactDamping` | 2000.0 | -| `enableVisualization` | true | -| `animationFile` | nothing | +| `mprTolerance` | 1.0e-20 | | `visualizeFrames` | false | | `visualizeBoundingBox` | false | | `visualizeContactPoints` | false | @@ -332,6 +333,7 @@ Defines global properties of the system, such as the gravity field. Exactly one | `lightDistance` | 10.0*`nominalLength` | | `lightLongitude` | 60/180*pi | | `lightLatitude` | 45/180*pi | +| `useOptimizedStructure` | true | # Arguments @@ -340,20 +342,23 @@ Defines global properties of the system, such as the gravity field. Exactly one - [`UniformGravityField`](@ref), - [`PointGravityField`](@ref) -- `useOptimizedStructure::Bool`: = true, if pre-processing the whole system. For example, computing the common mass, common center of mass and common inertia tensor of all rigidly connected Object3Ds that have mass properties. - -- `enableContactDetection::Bool`: = true, if contact detection is enable, see [Collision Handling](@ref). +- `enableVisualization::Bool`: = true, to enable online animation with DLR SimVis. If SimVis is not installed, this flag has no effect. -- `mprTolerance::1.0e-20`: Local tolerance used for terminating the mpr algorithm. Changing this value might improve speed. +- `animationFile::String`: After termination of the simulation, store animation in json-file that can be imported into + the open source 3D editor [threejs.org](https://threejs.org/). + Example: `animationFile = "animation.json"`. -- `elasticContactReductionFactor::Float64`: (> 0.0) - - ``usedContactCompliance = contactCompliance * elasticContactReductionFactor`` +- `enableContactDetection::Bool`: = true, if contact detection is enabled, see [Collision Handling](@ref). -- `maximumContactDamping`: Maximum damping factor for elastic contacts +- `elasticContactReductionFactor::Float64` (> 0.0, <= 1.0): + `usedContactCompliance = contactCompliance * elasticContactReductionFactor`. + For more details, see [Material constants](@ref). -- `enableVisualization::Bool`: = true, to enable online animation with DLR SimVis. If SimVis is not installed, this flag has no effect. +- `maximumContactDamping` (> 0.0): Maximum damping factor for elastic contacts. + For more details, see [Damping coefficient](@ref). -- `animationFile::String`: only if a valid path and name of the animation file is set (it must be a .json file) a json file is exported +- `mprTolerance::1.0e-20`: Local tolerance used for terminating the mpr algorithm (that computes the distances between shapes). Changing this value might improve speed. + For integrators with step-size control, a value is needed that is much smaller as the relative tolerance used for the integration. - `visualizeFrames::Bool`: = true, to visualize the coordinate system of every [Object3D](@ref) that is not explicitly switched off. @@ -382,6 +387,8 @@ Defines global properties of the system, such as the gravity field. Exactly one - `lightLongitude::Float64`: longitude angle of light position (0 = -y/-z/-x direction) - `lightLatitude::Float64`: latitude angle of light position (0 = horizontal) + +- `useOptimizedStructure::Bool`: = true, if pre-processing the whole system. For example, computing the common mass, common center of mass and common inertia tensor of all rigidly connected Object3Ds that have mass properties. """ mutable struct Scene{F <: Modia3D.VarFloatType} <: Modia3D.AbstractScene name::String # model name diff --git a/src/Modia3D.jl b/src/Modia3D.jl index cc6be606..cd47add2 100644 --- a/src/Modia3D.jl +++ b/src/Modia3D.jl @@ -4,8 +4,8 @@ module Modia3D const path = dirname(dirname(@__FILE__)) # Absolute path of package directory -const Version = "0.10.1" -const Date = "2022-03-08" +const Version = "0.10.2" +const Date = "2022-03-26" println("\nImporting Modia3D Version $Version ($Date)") diff --git a/src/ModiaInterface/buildModia3D.jl b/src/ModiaInterface/buildModia3D.jl index 539348f4..9370b7d2 100644 --- a/src/ModiaInterface/buildModia3D.jl +++ b/src/ModiaInterface/buildModia3D.jl @@ -97,6 +97,8 @@ function buildModia3D!(model::AbstractDict, FloatType::Type, TimeType::Type, jointStatesFreeMotion_isrot123 = Expr[] freeMotionIndices = OrderedCollections.OrderedDict{String,Int}() + println("modelPath = $modelPath") + modelPathAsString = isnothing(modelPath) ? "" : string(modelPath) i=1 @@ -243,6 +245,9 @@ function buildModia3D!(model::AbstractDict, FloatType::Type, TimeType::Type, else @error "Error should not occur (buildOption = $buildOption)" end + else + # ndofTotal == 0 + mbsCode = mbs_variables | Model(equations = :[$(mbs_equations...)]) end # Store info in buildDict diff --git a/src/Shapes/_module.jl b/src/Shapes/_module.jl index 4fda01d5..e8b09568 100644 --- a/src/Shapes/_module.jl +++ b/src/Shapes/_module.jl @@ -32,6 +32,7 @@ import JSON import Modia3D import Modia3D.Basics import Modia3D.Frames +import Modia3D.Modia.OrderedCollections # Colors and material export rgb, defaultColor, colorPalette, visualMaterialPalette @@ -53,7 +54,7 @@ export SolidMaterial export solidMaterial, solidMaterialPalette # Collision -export rereadContactPairMaterialFromJSON +export loadPalettes!, showPalettes export contactPairMaterialPalette, ElasticContactPairMaterial, TwoNamesKey export NoContactPairMaterial, ObserverContactPairMaterial, ImpulseContactPairMaterial, WheelRailContactPairMaterial export regularize, resultantCoefficientOfRestitution, resultantDampingCoefficient @@ -86,5 +87,6 @@ include("massProperties.jl") include("contactPairMaterials.jl") include("setCollisionSmoothingRadius.jl") include("solid.jl") +include("palettes.jl") end diff --git a/src/Shapes/contactPairMaterials.jl b/src/Shapes/contactPairMaterials.jl index 30a3e291..9db02b96 100644 --- a/src/Shapes/contactPairMaterials.jl +++ b/src/Shapes/contactPairMaterials.jl @@ -109,7 +109,7 @@ return a `Dict{String, ContactPairMaterial}` dictionary. """ function readContactPairMaterialFromJSON(filename::AbstractString) dataJSON = JSON.parsefile(filename) - palette = Dict{TwoNamesKey, Modia3D.AbstractContactPairMaterial}() + palette = OrderedCollections.OrderedDict{TwoNamesKey, Modia3D.AbstractContactPairMaterial}() for (namesPair,dataPair) in dataJSON # Split a key "name1,name2" in two parts i = findfirst(",", namesPair) @@ -132,14 +132,17 @@ end """ - contactPairMaterialPalette + const contactPairMaterialPalette Dictionary of contact pair material data, see [`ElasticContactPairMaterial`](@ref) """ -contactPairMaterialPalette = readContactPairMaterialFromJSON( joinpath(Modia3D.path, "palettes", "contactPairMaterials.json") ) +const contactPairMaterialPalette = [readContactPairMaterialFromJSON( joinpath(Modia3D.path, "palettes", "contactPairMaterials.json") )] -function rereadContactPairMaterialFromJSON() - global contactPairMaterialPalette = readContactPairMaterialFromJSON( joinpath(Modia3D.path, "palettes", "contactPairMaterials.json") ) +function rereadContactPairMaterialFromJSON(; file="") + if file == "" + file = joinpath(Modia3D.path, "palettes", "contactPairMaterials.json") + end + global contactPairMaterialPalette[1] = readContactPairMaterialFromJSON(file) return nothing end @@ -154,11 +157,11 @@ function getContactPairMaterial(obj1, obj2)::Modia3D.AbstractContactPairMaterial name1 = obj1.feature.contactMaterial name2 = obj2.feature.contactMaterial - value = get(contactPairMaterialPalette, TwoNamesKey(name1,name2), NoContactPairMaterial()) + value = get(contactPairMaterialPalette[1], TwoNamesKey(name1,name2), NoContactPairMaterial()) if typeof(value) == NoContactPairMaterial # Combination name1,name2 is not present - value1 = get(contactPairMaterialPalette, TwoNamesKey(name1,name1), NoContactPairMaterial()) - value2 = get(contactPairMaterialPalette, TwoNamesKey(name2,name2), NoContactPairMaterial()) + value1 = get(contactPairMaterialPalette[1], TwoNamesKey(name1,name1), NoContactPairMaterial()) + value2 = get(contactPairMaterialPalette[1], TwoNamesKey(name2,name2), NoContactPairMaterial()) if typeof(value1) != NoContactPairMaterial && typeof(value2) != NoContactPairMaterial return combineContactPairMaterials(value1, value2) else @@ -179,11 +182,11 @@ function checkContactPairMaterialInit(obj1, obj2)::Nothing name1 = obj1.feature.contactMaterial name2 = obj2.feature.contactMaterial - value = get(contactPairMaterialPalette, TwoNamesKey(name1,name2), NoContactPairMaterial()) + value = get(contactPairMaterialPalette[1], TwoNamesKey(name1,name2), NoContactPairMaterial()) if typeof(value) == NoContactPairMaterial # Combination name1,name2 is not present - value1 = get(contactPairMaterialPalette, TwoNamesKey(name1,name1), NoContactPairMaterial()) - value2 = get(contactPairMaterialPalette, TwoNamesKey(name2,name2), NoContactPairMaterial()) + value1 = get(contactPairMaterialPalette[1], TwoNamesKey(name1,name1), NoContactPairMaterial()) + value2 = get(contactPairMaterialPalette[1], TwoNamesKey(name2,name2), NoContactPairMaterial()) if typeof(value1) != NoContactPairMaterial && typeof(value2) != NoContactPairMaterial return nothing else diff --git a/src/Shapes/massProperties.jl b/src/Shapes/massProperties.jl index 48ea7a4c..e6ebd00a 100644 --- a/src/Shapes/massProperties.jl +++ b/src/Shapes/massProperties.jl @@ -15,7 +15,7 @@ struct MassProperties{F <: Modia3D.VarFloatType} <: Modia3D.AbstractMassProperti #---------------- different constructors for MassProperties ----------------- # Constructor 0: takes mass, centerOfMass and inertiaMatrix as input values function MassProperties{F}(mass::Number, centerOfMass::AbstractVector, inertiaMatrix::AbstractMatrix) where F <: Modia3D.VarFloatType - @assert(mass > 0.0) + @assert(mass >= 0.0) new(mass, centerOfMass, inertiaMatrix) end end @@ -68,7 +68,7 @@ MassProperties{F}(shape::Modia3D.AbstractGeometry, material::SolidMaterial) wher # Constructor d: shape and materialName is given, material must be defined in # solidMaterialPalette --> constructor c is called MassProperties{F}(shape::Modia3D.AbstractGeometry, materialName::AbstractString) where F <: Modia3D.VarFloatType = - MassProperties{F}(shape, solidMaterialPalette[materialName]) + MassProperties{F}(shape, solidMaterialPalette[1][materialName]) createMassProperties(::Type{F}, massProperties::MassProperties, shape, solidMaterial) where F <: Modia3D.VarFloatType = massProperties diff --git a/src/Shapes/palettes.jl b/src/Shapes/palettes.jl new file mode 100644 index 00000000..69840a1e --- /dev/null +++ b/src/Shapes/palettes.jl @@ -0,0 +1,70 @@ +# License for this file: MIT (expat) +# Copyright 2022, DLR Institute of System Dynamics and Control +# +# This file is part of module +# Modia3D.Shapes (Modia3D/src/Shapes/_module.jl) +# + +""" + loadPalettes!(; solidMaterialPalette = nothing, + contactPairMaterialPalette = nothing, + visualMaterialPalette = nothing, + log = true +Read the palettes for which a file name is given and store them as global palettes in Modia3D. +If `log=true`, log the reading of the files. + +When Modia3D is used the first time, it reads the palettes automatically from +`"Modia3D/palettes/*.json"`. The `loadPalettes` function overwrites this default setting. + +# Examples + +``` +file1 = "$(Modia3D.path)/palettes/solidMaterials.json" +file2 = "$(Modia3D.path)/palettes/contactPairMaterials.json" +file3 = "$(Modia3D.path)/palettes/visualMaterials.json" + +Modia3D.loadPalettes!(solidMaterialPalette = file1, + contactPairMaterialPalette = file2, + visualMaterialPalette = file3) +``` +""" +function loadPalettes!(; solidMaterialPalette = nothing, + contactPairMaterialPalette = nothing, + visualMaterialPalette = nothing, + log = true)::Nothing + if !isnothing(solidMaterialPalette) + if log + println(" Reading solidMaterialPalette from JSON file \"$solidMaterialPalette\".") + end + rereadSolidMaterialFromJSON(file = solidMaterialPalette) + end + + if !isnothing(contactPairMaterialPalette) + if log + println(" Reading contactPairMaterialPalette from JSON file \"$contactPairMaterialPalette\".") + end + rereadContactPairMaterialFromJSON(file = contactPairMaterialPalette) + end + + if !isnothing(visualMaterialPalette) + if log + println(" Reading visualMaterialPalette from JSON file \"$visualMaterialPalette\".") + end + rereadVisualMaterialFromJSON(file = visualMaterialPalette) + end + + return nothing +end + + +""" + showPalettes() + +Show loaded palettes +""" +function showPalettes()::Nothing + println("\nsolidMaterialPalette = ", Modia3D.solidMaterialPalette[1]) + println("\ncontactPairMaterialPalette = ", Modia3D.contactPairMaterialPalette[1]) + println("\nvisualMaterialPalette = ", Modia3D.visualMaterialPalette) + return nothing +end diff --git a/src/Shapes/shape.jl b/src/Shapes/shape.jl index 1b161361..1b69c267 100644 --- a/src/Shapes/shape.jl +++ b/src/Shapes/shape.jl @@ -129,7 +129,9 @@ end """ ModelicaShape(; type=1, lengthX=1.0, lengthY=1.0, lengthZ=1.0, extra=[0.0, 0.0, 0.0]) -Generate a new visual shape according to the [Modelica](https://modelica.org) [Visualization Library](https://www.systemcontrolinnovationlab.de/the-dlr-visualization-library/). +Generate a new visual shape according to the +[Modelica.Mechanicis.MultiBody.Visualizers.Advanced.Shape](https://doc.modelica.org/Modelica%204.0.0/Resources/helpDymola/Modelica_Mechanics_MultiBody_Visualizers_Advanced.html#Modelica.Mechanics.MultiBody.Visualizers.Advanced.Shape) +model of the [Modelica Standard Library](https://github.com/modelica/ModelicaStandardLibrary). # Arguments - `type` defines the type of the shape: 1=box; 2=sphere; 3=cylinder; 4=cone; 5=capsule; 6=coordinate system; @@ -141,7 +143,7 @@ Generate a new visual shape according to the [Modelica](https://modelica.org) [V # Notes - ModelicaShape is intended for import of Modelica models and not for Modia3D models. -- ModelicaShape is [not supported by animation export](https://github.com/ModiaSim/PrivateModia3D.jl/issues/77). +- ModelicaShape is [not yet supported by animation export](https://github.com/ModiaSim/PrivateModia3D.jl/issues/77). """ mutable struct ModelicaShape <: Modia3D.AbstractShape type::Int diff --git a/src/Shapes/solid.jl b/src/Shapes/solid.jl index e5ee271d..e84a940e 100644 --- a/src/Shapes/solid.jl +++ b/src/Shapes/solid.jl @@ -1,12 +1,12 @@ """ - Solid(; shape = nothing, - solidMaterial = nothing, - massProperties = nothing, - collision = false, + Solid(; shape = nothing, + solidMaterial = nothing, + massProperties = nothing, + visualMaterial = VisualMaterial(), + collision = false, contactMaterial = "", collisionSmoothingRadius = 0.001, - contactSphereRadius = nothing, - visualMaterial = VisualMaterial()) + contactSphereRadius = nothing) Generate a [Solid](@ref) with physical behavior of a rigid body with mass, visualization and collision properties. `Solid` is used as `feature` of an [Object3D](@ref). @@ -19,25 +19,32 @@ Generate a [Solid](@ref) with physical behavior of a rigid body with mass, visua - `solidMaterial`: Defines the material of the solid used for mass properties computation and (if `contactMaterial` is undefined) contact force calculation. A pre-defined [Solid material](@ref) from palettes/solidMaterials.json (e.g. `"Steel"`) or a user-defined [Solid material](@ref) (e.g. `SolidMaterial(density=7850)`) can be used. + `solidMaterial = ""` is treated as `solidMaterial = nothing`. -- `massProperties`: Defines the mass properties of the solid. If `massProperties` is undefined, the mass properties are - computed from `shape` and `solidMaterial`. It is also possible to define only the mass of the solid and compute the - center of mass and inertia tensor from `shape` (e.g. `MassPropertiesFromShapeAndMass(mass=4.5)`) or explicitly - define all mass properties (e.g. `MassProperties(mass=4.5, centerOfMass=[1.0,2.0,3.0], Ixx=4.0, Iyy=5.0, Izz=6.0, - Ixy=4.5, Ixz=4.6, Iyz=5.5)`). +- `massProperties`: Defines the mass properties of the solid. + - `massProperties = nothing`: The mass properties are computed from `shape` and `solidMaterial`. + If additionally `solidMaterial = nothing`, the solid is treated as massless. + - `massProperties = MassProperties(; mass=0.0, centerOfMass=[0.0,0.0,0.0], Ixx=0.0, Iyy=0.0, Izz=0.0) + Ixy=4.5, Ixz=4.6, Iyz=5.5)`: Defines all mass properties explicitly + `MassProperties()` defines a massless solid. + - `massProperties = MassPropertiesFromShapeAndMass(; mass=0.0)`: + The center of mass and the inertia tensor is computed from `shape` and from `mass`. + +- `visualMaterial`: Defines the material of the solid used for visualization. A pre-defined [Visual material](@ref) + from palettes/visualMaterials.json (e.g. `visualMaterial = "RedTransparent"`) or a user-defined [Visual material](@ref) (e.g. + `VisualMaterial(color="DeepSkyBlue4", transparency=0.75)`) can be used. + Note, `VisualMaterial = ""` is treated as `visualMaterial = VisualMaterial()`, so using the default visual material. - `collision`: Defines if the solid is considered in [Collision Handling](@ref). `collision=true` requires definition - of `shape`, mass properties (defined by `solidMaterial` or `massProperties`) and contact material (defined by - `solidMaterial` or `contactMaterial`). + of `shape` and of contact material (defined by `solidMaterial` or `contactMaterial`). -- `contactMaterial`: Defines the contact material for force computation with [Contact Force Law](@ref) (e.g. `"Steel"`). +- `contactMaterial`: Defines the contact material in case of collision. For details, see [Contact Force Law](@ref) (e.g. `"Steel"`). If undefined `solidMaterial` is used as contact material. Only contact material combinations defined in palettes/contactPairMaterials.json can be used. -- `collisionSmoothingRadius`: Defines a collision smoothing radius for surface edges, its default value is `0.001`. It takes the minimum value of your collision smoothing radius and 10% of the smallest shape length, like `min(collisionSmoothingRadius, 0.1 min(shape dimensions))`. If it is set to `0.0` no `collisionSmoothingRadius` is used. A `collisionSmoothingRadius` is used for `Box`, `Cylinder`, `Cone`, and `Beam`. - -- `contactSphereRadius`: for each shape a `contactSphereRadius` is defined. So that Herz' pressure is used in [Response calculation](@ref) not only for spheres. You can define your own `contactSphereRadius`, otherwise it is computed from shape geometry (sketched in the following table). +- `collisionSmoothingRadius`: Defines a collision smoothing radius for surface edges, its default value is `0.001` [m]. This improves the robustness of the integration, if contact is on or close to a surface edge. It takes the minimum value of the provided collision smoothing radius and 10% of the smallest shape length, like `min(collisionSmoothingRadius, 0.1 min(shape dimensions))`. If it is set to `0.0` no `collisionSmoothingRadius` is used. A `collisionSmoothingRadius` is used for `Box`, `Cylinder`, `Cone`, and `Beam`. +- `contactSphereRadius`: For each shape a `contactSphereRadius` is defined, so that a rough approximiation of Hertz' pressure is used in [Response calculation](@ref) not only for spheres. You can define your own `contactSphereRadius`, otherwise it is computed from shape geometry (sketched in the following table). | Shape | `contactSphereRadius` from shape | |:--------------------------|:---------------------------------| @@ -50,15 +57,11 @@ Generate a [Solid](@ref) with physical behavior of a rigid body with mass, visua | [Beam](@ref) | `min(length, width, thickness)/2` | | [FileMesh](@ref) | `shortestEdge/2` | -For flat shapes, [Box](@ref) and [Beam](@ref), no `contactSphereRadius` is taken. For Herz' pressure it is needed only if two flat shapes are colliding. - -- `visualMaterial`: Defines the material of the solid used for visualization. A pre-defined [Visual material](@ref) - from palettes/visualMaterials.json (e.g. `"RedTransparent"`) or a user-defined [Visual material](@ref) (e.g. - `VisualMaterial(color="DeepSkyBlue4", transparency=0.75)`) can be used. +For flat shapes, [Box](@ref) and [Beam](@ref), no `contactSphereRadius` is taken. For Herz' pressure it is needed only if two flat shapes are colliding. Note, `contactSphereRadius <= 0` is treated as `contactSphereRadius = nothing`, so is computed from the table above. # Example ```julia -import Modia3D +using Modia3D Solid(; shape = Sphere(diameter=0.5), solidMaterial = "DryWood", @@ -88,7 +91,7 @@ struct Solid{F <: Modia3D.VarFloatType} <: Modia3D.AbstractObject3DFeature collisionSmoothingRadius=F(0.001), visualMaterial::Union{Shapes.VisualMaterial,AbstractString,Nothing} = Shapes.VisualMaterial(), visualMaterialConvexDecomposition::Union{Shapes.VisualMaterial,AbstractString,Nothing} = Shapes.VisualMaterial(), - contactSphereRadius::Union{Nothing, F} = nothing) where F <: Modia3D.VarFloatType + contactSphereRadius::Union{Nothing, Number} = nothing) where F <: Modia3D.VarFloatType if collision && isnothing(shape) error("For collision/gripping simulations, a shape must be defined.") @@ -105,12 +108,16 @@ struct Solid{F <: Modia3D.VarFloatType} <: Modia3D.AbstractObject3DFeature contactMaterial = "" end + if typeof(solidMaterial) == String && solidMaterial == "" + solidMaterial = nothing + end + if typeof(solidMaterial) == String - solidMaterial = solidMaterialPalette[solidMaterial] + solidMaterial = solidMaterialPalette[1][solidMaterial] end if typeof(visualMaterial) == String - visualMaterial = Shapes.visualMaterialPalette[visualMaterial] + visualMaterial = visualMaterial == "" ? Shapes.VisualMaterial() : Shapes.visualMaterialPalette[visualMaterial] end if typeof(shape) == FileMesh @@ -118,7 +125,9 @@ struct Solid{F <: Modia3D.VarFloatType} <: Modia3D.AbstractObject3DFeature (shape.volume, shape.centroidAlgo, shape.inertia) = computeMassProperties(shape.objPoints, shape.facesIndizes; bodyCoords=false) end - massProperties = createMassProperties(F, massProperties, shape, solidMaterial) + massProperties = isnothing(massProperties) && isnothing(solidMaterial) ? MassProperties{F}() : createMassProperties(F, massProperties, shape, solidMaterial) + + contactSphereRadius::Union{Nothing,F} = isnothing(contactSphereRadius) || F(contactSphereRadius) <= F(0) ? nothing : F(contactSphereRadius) (isFlat, contactSphereRadius) = setContactSphereRadius(shape, contactSphereRadius, F) new(shape, solidMaterial, massProperties, collision, contactMaterial, setCollisionSmoothingRadius(shape, F(collisionSmoothingRadius)), visualMaterial, isFlat, contactSphereRadius) end diff --git a/src/Shapes/solidMaterial.jl b/src/Shapes/solidMaterial.jl index 0fa3da74..95757c75 100644 --- a/src/Shapes/solidMaterial.jl +++ b/src/Shapes/solidMaterial.jl @@ -1,13 +1,19 @@ """ - SolidMaterial(density=3000.0, YoungsModulus=2e11) + SolidMaterial(; density = NaN, + YoungsModulus = NaN, + PoissonsRatio = NaN, + meltingPoint = NaN, + specificHeatCapacity = NaN, + thermalConductivity = NaN, + linearThermalExpansionCoefficient = NaN) -Generates a SolidMaterial object by providing the material properties of a [Solid] with keyword arguments. +Generates a SolidMaterial object by providing the material properties of a [Solid](@ref) with keyword arguments. # Arguments Arguments that are not provided have value `NaN`. - `density` in [kg/m^3]: Density, see [Wikipedia](https://en.wikipedia.org/wiki/Density). -- `YoungsModulus` in [Pa]: Youngs's modulus, see [Wikipedia](https://en.wikipedia.org/wiki/Young%27s_modulus). -- `PoissonsRatio`: Poisson's ratio, see [Wikipedia](https://en.wikipedia.org/wiki/Poisson%27s_ratio). +- `YoungsModulus` in [Pa]: Youngs' modulus, see [Wikipedia](https://en.wikipedia.org/wiki/Young%27s_modulus). +- `PoissonsRatio`: Poissons' ratio, see [Wikipedia](https://en.wikipedia.org/wiki/Poisson%27s_ratio). - `meltingPoint` in [K]: Melting point, see [Wikipedia](https://en.wikipedia.org/wiki/Melting_point). If the material is destroyed before its melting point (e.g. wood that is burning) then `meltingPoint` is the temperature when destruction of the solid starts. @@ -16,6 +22,12 @@ Arguments that are not provided have value `NaN`. [List of thermal conductivities](https://en.wikipedia.org/wiki/List_of_thermal_conductivities) - `linearThermalExpansionCoefficient::Float64` in [1/K]: Linear thermal expansion coefficient, see [Wikipedia](https://en.wikipedia.org/wiki/Thermal_expansion). +# Examples +```julia +using Modia3D + +solidMaterial = SolidMaterial(density=3000.0, YoungsModulus=2e11) +``` """ mutable struct SolidMaterial density::Float64 # [kg/m^3], https://en.wikipedia.org/wiki/Density @@ -31,12 +43,12 @@ mutable struct SolidMaterial linearThermalExpansionCoefficient::Float64 # [1/K], https://en.wikipedia.org/wiki/Thermal_expansion end SolidMaterial(; density=NaN, - YoungsModulus=NaN, - PoissonsRatio=NaN, - meltingPoint=NaN, - specificHeatCapacity=NaN, - thermalConductivity=NaN, - linearThermalExpansionCoefficient=NaN) = + YoungsModulus=NaN, + PoissonsRatio=NaN, + meltingPoint=NaN, + specificHeatCapacity=NaN, + thermalConductivity=NaN, + linearThermalExpansionCoefficient=NaN) = SolidMaterial(density, YoungsModulus, PoissonsRatio, meltingPoint, specificHeatCapacity, thermalConductivity, linearThermalExpansionCoefficient) @@ -57,4 +69,13 @@ readSolidMaterialFromJSON(fileName::AbstractString) = Dictionary of solid material data, see [`SolidMaterial`](@ref) """ const solidMaterialPalette = - readSolidMaterialFromJSON( joinpath(Modia3D.path, "palettes", "solidMaterials.json") ) + [readSolidMaterialFromJSON( joinpath(Modia3D.path, "palettes", "solidMaterials.json") )] + +function rereadSolidMaterialFromJSON(; file="") + if file == "" + file = joinpath(Modia3D.path, "palettes", "solidMaterials.json") + end + + global solidMaterialPalette[1] = readSolidMaterialFromJSON(file) + return nothing +end diff --git a/src/Shapes/visual.jl b/src/Shapes/visual.jl index d2c59a99..3f38bb0f 100644 --- a/src/Shapes/visual.jl +++ b/src/Shapes/visual.jl @@ -1,17 +1,31 @@ convertStringToVisualMaterial(visualMaterial::Shapes.VisualMaterial) = visualMaterial -convertStringToVisualMaterial(visualMaterial::AbstractString) = Shapes.visualMaterialPalette[visualMaterial] +convertStringToVisualMaterial(visualMaterial::AbstractString) = visualMaterial == "" ? Shapes.VisualMaterial() : Shapes.visualMaterialPalette[visualMaterial] + """ - Visual(; - shape = Sphere(diameter = 0.5), - visualMaterial = VisualMaterial(color = "Green")) + Visual(; shape = nothing, + visualMaterial = VisualMaterial()) -Generate a new visual shape with a visual material. It is only for visualizing, without physical behavior. In this case it is a greenish sphere. +Generate a new visual shape with a visual material. It is only for visualizing, without physical behavior. +The default is no shape and a default visual material. # Arguments -- `shape`: it is possible to use all [Shapes](@ref) from both sets visual and solid, e.g. [`Sphere`](@ref), [`Box`](@ref), [`CoordinateSystem`](@ref). The default value is `nothing`, this means it will not be visualized. -- `visualMaterial`: use a predefined [Visual material](@ref) defined in palettes/visualMaterials.json, or define it with `VisualMaterial(color = "Blue")`. The default value is `VisualMaterial()`. +- `shape`: It is possible to use all [Shapes](@ref) from both sets visual and solid, e.g. [`Sphere`](@ref), [`Box`](@ref), [`CoordinateSystem`](@ref). The default value is `nothing`, this means it will not be visualized. +- `visualMaterial`: Defines the material of the shape used for visualization. A pre-defined [Visual material](@ref) + from palettes/visualMaterials.json (e.g. `visualMaterial = "RedTransparent"`) or a user-defined [Visual material](@ref) (e.g. + `VisualMaterial(color="DeepSkyBlue4", transparency=0.75)`) can be used. + Note, `VisualMaterial = ""` is treated as `visualMaterial = VisualMaterial()`, so using the default visual material. + +# Examples +```julia +using Modia3D + +shape1 = Visual(shape = Sphere(diameter = 0.5), + visualMaterial = VisualMaterial(color = "Green")); +shape2 = Visual(shape = Sphere(diameter = 0.5), + visualMaterial = "GreenTransparent"); +``` """ struct Visual <: Modia3D.AbstractObject3DFeature shape::Union{Modia3D.AbstractShape,Nothing} diff --git a/src/Shapes/visualMaterial.jl b/src/Shapes/visualMaterial.jl index dd9989a2..2ce1f4fc 100644 --- a/src/Shapes/visualMaterial.jl +++ b/src/Shapes/visualMaterial.jl @@ -13,27 +13,44 @@ import JSON # Material for visual elements """ - VisualMaterial(; color="Green", - wireframe=false, transparency=0.5, - reflectslight=true, shininess=0.7, - shadowMask=CastsAndReceivesShadows)) + VisualMaterial(; color = defaultColor(), + wireframe = false, + transparency = 0.0, + reflectslight = true, + shininess = 0.7, + shadowMask = CastsAndReceivesShadows) Return a material object that defines attributes for the visualization of an Object3D that has visual or solid properties. # Arguments -- `color` defines the material color as a String or RGB values. In case of Strings the color - is constructed using [Colors.jl](https://github.com/JuliaGraphics/Colors.jl). So - [named colors](https://juliagraphics.github.io/Colors.jl/stable/namedcolors/) and - many other kinds of [color specifications](https://juliagraphics.github.io/Colors.jl/stable/constructionandconversion/#Color-Parsing) - are available. In addition, colors can be directly defined by a vector of RGB values. - E.g. `color="MediumVioletRed"` or `color=[255, 0, 0]`. +- `color` defines the material color + - `color::Vector{Int}`: The color is defined by a vector of RGB values where every value can be in the + range 0..255. Example: `color = [255, 0, 0]`. + - `color::String`: The color is constructed by using `color` as key of + [named colors](https://juliagraphics.github.io/Colors.jl/stable/namedcolors/). + Example: `color = "lightsteelblue1"` or `color = "LightSteelBlue1"`. + Note, color names are case insensitive. + - Otherwise: Any other of the [color specifications](https://juliagraphics.github.io/Colors.jl/stable/constructionandconversion/#Color-Parsing) + can be used. - `wireframe`: = false, if solid, otherwise wireframe representation. - `transparency`: = 0.0 (opaque) ... 1.0 (fully transparent). - `reflectslight`: = true if it reflects light and false, if it does not reflect light. - `shininess`: = 0.0 (matte surface) ... 1.0 (very shiny surface). - `shadowMask`: defines whether or not an object casts or receives shadows. Possible values: NoShadows, CastsShadows, ReceivesShadows, CastsAndReceivesShadows. + +# Examples +```julia +using Modia3D + +material = VisualMaterial(color = "Green", + wireframe = false, + transparency = 0.5, + reflectslight = true, + shininess = 0.5, + shadowMask = NoShadows)) +``` """ mutable struct VisualMaterial color::MVector{3,Cint} # RGB color @@ -85,12 +102,20 @@ end Read a JSON file consisting of a dictionary of VisualMaterial instances from `fileName` and return a `Dict{String, VisualMaterial}` dictionary. """ -readDictOfStructsFromJSONVisualMaterial(fileName::AbstractString) = readDictOfStructsFromJSONVisualMaterial(fileName, VisualMaterial) +readVisualMaterialFromJSON(fileName::AbstractString) = readDictOfStructsFromJSONVisualMaterial(fileName, VisualMaterial) """ - const visualMaterialPalette + visualMaterialPalette Dictionary of visual material data, see [`Modia3D.Shapes.VisualMaterial`](@ref) """ -const visualMaterialPalette = readDictOfStructsFromJSONVisualMaterial( joinpath(Modia3D.path, "palettes", "visualMaterials.json") ) +visualMaterialPalette = readVisualMaterialFromJSON( joinpath(Modia3D.path, "palettes", "visualMaterials.json") ) + +function rereadVisualMaterialFromJSON(; file="") + if file == "" + file = joinpath(Modia3D.path, "palettes", "visualMaterials.json") + end + global visualMaterialPalette = readVisualMaterialFromJSON( file ) + return nothing +end diff --git a/test/includeTests.jl b/test/includeTests.jl index 665caa9f..4f4215e6 100644 --- a/test/includeTests.jl +++ b/test/includeTests.jl @@ -1,5 +1,9 @@ import Test +Modia3D.loadPalettes!(solidMaterialPalette = "$(Modia3D.path)/palettes/solidMaterials.json", + contactPairMaterialPalette = "$(Modia3D.path)/palettes/contactPairMaterials.json", + visualMaterialPalette = "$(Modia3D.path)/palettes/visualMaterials.json") + Test.@testset "Basic" begin include(joinpath("Basic", "AllShapes.jl")) include(joinpath("Basic", "PendulumWithBar1.jl"))