Initial open sourcing of MuJoCo.

PiperOrigin-RevId: 450374687
Change-Id: Ie3225a46ce095fc28ae8e63c326a640261f562bb
This commit is contained in:
Saran Tunyasuvunakool
2022-05-23 01:08:10 -07:00
committed by Copybara-Service
parent 0e5d062302
commit 1913a02b40
275 changed files with 99607 additions and 935 deletions
+25
View File
@@ -0,0 +1,25 @@
---
name: Bug report
about: Create a report to help us improve
title: ''
labels: bug
assignees: ''
---
**How to submit a good bug report**
- Are you sure this is a bug? If not, consider using the "Ask for help" or "Feature request" templates.
- Use a clear and descriptive title.
- Make it easy to reproduce the problem.
- Include a ***minimal*** model that demonstrates the problem. If the model is small, include it as inline XML. If it requires binary assets, attach it as a zip file.
- Include a screenshot or video, if relevant.
- Include the following context:
- Operating system.
- MuJoCo version (and if the bug is new, the version where it used to work).
- For Python issues, what bindings are you using (i.e `mujoco`, `dm_control`, `mujoco-py`)?
+20
View File
@@ -0,0 +1,20 @@
---
name: Feature request
about: Suggest an idea for MuJoCo
title: ''
labels: enhancement
assignees: ''
---
**Is your feature request related to a problem? Please describe.**
A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]
**Describe the solution you'd like**
A clear and concise description of what you want to happen.
**Describe alternatives you've considered**
A clear and concise description of any alternative solutions or features you've considered.
**Additional context**
Add any other context or screenshots about the feature request here.
+16
View File
@@ -0,0 +1,16 @@
---
name: Help
about: Ask for help with MuJoCo
title: ''
labels: question
assignees: ''
---
**How to ask for help**
- Take a step back and tell us what you're trying to accomplish, and in what context. The more information you give, the better the answers you will get.
- If relevant, include a ***minimal*** model that demonstrates the problem. If the model is small, include it as inline XML. If it requires binary assets, attach it as a zip file.
- Include a screenshot or video, if relevant.
+228
View File
@@ -0,0 +1,228 @@
# Copyright 2021 DeepMind Technologies Limited
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# https://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
cmake_minimum_required(VERSION 3.18)
# Make CMAKE_C_VISIBILITY_PRESET work properly.
set(CMAKE_POLICY_DEFAULT_CMP0063 NEW)
# INTERPROCEDURAL_OPTIMIZATION is enforced when enabled.
set(CMAKE_POLICY_DEFAULT_CMP0069 NEW)
# Default to GLVND if available.
set(CMAKE_POLICY_DEFAULT_CMP0072 NEW)
# Avoid BUILD_SHARED_LIBS getting overridden by an option() in ccd.
set(CMAKE_POLICY_DEFAULT_CMP0077 NEW)
# This line has to appear before 'PROJECT' in order to be able to disable incremental linking
set(MSVC_INCREMENTAL_DEFAULT ON)
project(
mujoco
VERSION 2.2.0
DESCRIPTION "MuJoCo Physics Simulator"
HOMEPAGE_URL "https://mujoco.org"
)
enable_language(C)
enable_language(CXX)
list(APPEND CMAKE_MODULE_PATH "${PROJECT_SOURCE_DIR}/cmake")
option(MUJOCO_BUILD_EXAMPLES "Build samples for MuJoCo" ON)
option(MUJOCO_BUILD_TESTS "Build tests for MuJoCo" ON)
option(MUJOCO_TEST_PYTHON_UTIL "Build and test utility libraries for Python bindings" ON)
if(APPLE AND MUJOCO_BUILD_EXAMPLES)
enable_language(OBJC)
enable_language(OBJCXX)
endif()
include(MujocoOptions)
include(MujocoMacOS)
include(MujocoDependencies)
set(MUJOCO_HEADERS
include/mujoco/mjdata.h
include/mujoco/mjexport.h
include/mujoco/mjmodel.h
include/mujoco/mjrender.h
include/mujoco/mjtnum.h
include/mujoco/mjui.h
include/mujoco/mjvisualize.h
include/mujoco/mjxmacro.h
include/mujoco/mujoco.h
)
add_library(mujoco SHARED)
target_include_directories(
mujoco
PUBLIC $<BUILD_INTERFACE:${CMAKE_SOURCE_DIR}/include>
$<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}/>
PRIVATE src
)
add_subdirectory(src/engine)
add_subdirectory(src/user)
add_subdirectory(src/xml)
add_subdirectory(src/render)
add_subdirectory(src/ui)
target_compile_definitions(mujoco PRIVATE _GNU_SOURCE CCD_STATIC_DEFINE MUJOCO_DLL_EXPORTS)
if(MUJOCO_ENABLE_AVX_INTRINSICS)
target_compile_definitions(mujoco PUBLIC mjUSEPLATFORMSIMD)
endif()
target_compile_options(
mujoco
PRIVATE ${AVX_COMPILE_OPTIONS}
${MUJOCO_MACOS_COMPILE_OPTIONS}
${EXTRA_COMPILE_OPTIONS}
${MUJOCO_CXX_FLAGS}
)
target_link_options(
mujoco
PRIVATE
${MUJOCO_MACOS_LINK_OPTIONS}
${EXTRA_LINK_OPTIONS}
)
target_link_libraries(
mujoco
PRIVATE ccd
lodepng
qhullstatic_r
tinyobjloader
tinyxml2
)
set_target_properties(
mujoco PROPERTIES VERSION "${mujoco_VERSION}" PUBLIC_HEADER "${MUJOCO_HEADERS}"
)
# CMake's built-in FRAMEWORK option doesn't give us control over the dylib name inside the
# Framework. We instead make our own Framework here.
if(APPLE AND MUJOCO_BUILD_MACOS_FRAMEWORKS)
include(DuplicateTarget)
duplicate_target(
TARGET
mujoco
NEW_TARGET_NAME
mujoco_framework
)
# Do not add mujoco::mujoco to the ALL target. We do this to speed up the
# build assuming the user is interested in the Frameworks.
set_target_properties(mujoco PROPERTIES EXCLUDE_FROM_ALL TRUE)
set(TAPI
"/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/tapi"
)
configure_file(
${CMAKE_CURRENT_SOURCE_DIR}/dist/Info.plist.framework.in
${CMAKE_CURRENT_SOURCE_DIR}/dist/Info.framework.plist
)
set_target_properties(
mujoco_framework
PROPERTIES LIBRARY_OUTPUT_DIRECTORY
"${CMAKE_LIBRARY_OUTPUT_DIRECTORY}/mujoco.framework/Versions/A"
BUILD_WITH_INSTALL_NAME_DIR TRUE
INSTALL_NAME_DIR "@rpath/mujoco.framework/Versions/A"
OUTPUT_NAME "mujoco"
)
add_custom_command(
TARGET mujoco_framework
POST_BUILD
COMMAND mkdir -p $<TARGET_FILE_DIR:mujoco_framework>/Headers
COMMAND cd ${CMAKE_CURRENT_SOURCE_DIR} && cp ${MUJOCO_HEADERS}
$<TARGET_FILE_DIR:mujoco_framework>/Headers
COMMAND mkdir -p $<TARGET_FILE_DIR:mujoco_framework>/Modules
COMMAND cp ${CMAKE_CURRENT_SOURCE_DIR}/dist/module.modulemap
$<TARGET_FILE_DIR:mujoco_framework>/Modules
COMMAND mkdir -p $<TARGET_FILE_DIR:mujoco_framework>/Resources
COMMAND mv ${CMAKE_CURRENT_SOURCE_DIR}/dist/Info.framework.plist
$<TARGET_FILE_DIR:mujoco_framework>/Resources/Info.plist
COMMAND ln -fhs A $<TARGET_FILE_DIR:mujoco_framework>/../Current
COMMAND ${TAPI} stubify $<TARGET_FILE:mujoco_framework> -o
$<TARGET_FILE_DIR:mujoco_framework>/../../mujoco.tbd
COMMAND ln -fhs Versions/Current/Headers $<TARGET_FILE_DIR:mujoco_framework>/../../Headers
COMMAND ln -fhs Versions/Current/Modules $<TARGET_FILE_DIR:mujoco_framework>/../../Modules
COMMAND ln -fhs Versions/Current/Resources $<TARGET_FILE_DIR:mujoco_framework>/../../Resources
COMMAND_EXPAND_LISTS
)
endif()
# Add a namespace alias to mujoco to be used by the examples.
# This simulates the install interface when building with sources.
add_library(mujoco::mujoco ALIAS mujoco)
add_subdirectory(model)
if(MUJOCO_BUILD_EXAMPLES)
add_subdirectory(sample)
endif()
if(BUILD_TESTING AND MUJOCO_BUILD_TESTS)
enable_testing()
add_subdirectory(test)
endif()
if(BUILD_TESTING AND MUJOCO_TEST_PYTHON_UTIL)
enable_testing()
add_subdirectory(python/mujoco/util)
endif()
# Install the libraries.
install(
TARGETS mujoco
EXPORT ${PROJECT_NAME}
RUNTIME DESTINATION "${CMAKE_INSTALL_BINDIR}" COMPONENT runtime
LIBRARY DESTINATION "${CMAKE_INSTALL_LIBDIR}" COMPONENT runtime
ARCHIVE DESTINATION "${CMAKE_INSTALL_LIBDIR}" COMPONENT dev
PUBLIC_HEADER DESTINATION ${CMAKE_INSTALL_INCLUDEDIR} COMPONENT dev
)
set(CONFIG_PACKAGE_LOCATION "${CMAKE_INSTALL_LIBDIR}/cmake/${PROJECT_NAME}")
# Generate and install the mujocoTargets.cmake file. This defines the targets as
# IMPORTED libraries for downstream users.
install(
EXPORT ${PROJECT_NAME}
DESTINATION ${CONFIG_PACKAGE_LOCATION}
NAMESPACE mujoco::
FILE "${PROJECT_NAME}Targets.cmake"
)
include(CMakePackageConfigHelpers)
write_basic_package_version_file(
"${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}ConfigVersion.cmake"
VERSION ${mujoco_VERSION}
COMPATIBILITY AnyNewerVersion
)
configure_package_config_file(
cmake/${PROJECT_NAME}Config.cmake.in "${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}Config.cmake"
INSTALL_DESTINATION ${CONFIG_PACKAGE_LOCATION}
)
install(FILES "${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}Config.cmake"
"${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}ConfigVersion.cmake"
DESTINATION ${CONFIG_PACKAGE_LOCATION}
)
# Install also models into share folder.
install(
DIRECTORY model
DESTINATION "${CMAKE_INSTALL_DATADIR}/mujoco"
PATTERN "CMakeLists.txt" EXCLUDE
)
+104 -13
View File
@@ -1,25 +1,116 @@
# How to Contribute
# Contributing to MuJoCo
We are still in the process of preparing the MuJoCo codebase for open-sourcing,
however the full source code for the Python bindings and the Unity plugin are
already released. You are welcome to send us pull requests to improve any part
of this repository.
We intend for MuJoCo to be a true community-driven project and look forward to
accepting your contributions!
## Contributor License Agreement
## Before you contribute
### Documentation, forums
Please read MuJoCo's [documentation](https://mujoco.readthedocs.io) and look
through current topics on our GitHub
[issues](https://github.com/deepmind/mujoco/issues) and
[discussions](https://github.com/deepmind/mujoco/discussions) pages.
### Contributor License Agreement
Contributions to this project must be accompanied by a Contributor License
Agreement. You (or your employer) retain the copyright to your contribution,
this simply gives us permission to use and redistribute your contributions as
part of the project. Head over to <https://cla.developers.google.com/> to see
your current agreements on file or to sign a new one.
Agreement (CLA). You (or your employer) retain the copyright to your
contribution; this simply gives us permission to use and redistribute your
contributions as part of the project. Head over to
<https://cla.developers.google.com/> to see your current agreements on file or
to sign a new one.
You generally only need to submit a CLA once, so if you've already submitted one
(even if it was for a different project), you probably don't need to do it
again.
## Code reviews
## Contributing
All submissions require review. Please use GitHub pull requests for this
purpose. Consult
### Reporting bugs
How to submit a good bug report:
- Use a clear and descriptive title.
- Make it easy to reproduce the problem. If this requires a model, attach it as
a zip file to the bug report. The model and steps required to reproduce the
proplem should be *minimal*, in the sense that irrelevant parts are
removed.
- Clearly state what is the expected behavior.
- Include an illustrative screenshot, if relevant.
Try to provide context:
- If the problem is new, see if you can reproduce it in an older version.
What's the most recent version in which the problem doesn't happen?
- Can you reproduce the problem on multiple platforms?
### Suggesting enhancements
Before submitting an enhancement suggestion:
- Check if you're using the [latest
version](https://github.com/deepmind/mujoco/releases/latest) of MuJoCo.
- Perform a quick [search](https://github.com/deepmind/mujoco/issues) to see if
the enhancement has already been suggested. If it has, add a comment to the
existing issue instead of opening a new one.
How to submit a good enhacement suggestion:
- Use a clear and descriptive title.
- Describe the current behaviour and the behavior which you hope to see instead.
- Explain why this enhancement would be useful.
- Specify the version of MuJoCo and platform/OS you are using.
### Contributing code
- Except for small and straightforward bugfixes, please get in touch with us
before you start working on a contribution so that we can help and possibly
guide you. Coordinating up front makes it much easier to avoid frustration later
on.
- All submissions require review. Please use GitHub pull requests for this
purpose. Please consult
[GitHub Help](https://help.github.com/articles/about-pull-requests/) for more
information on pull requests.
- Write tests. MuJoCo uses [googletest](https://github.com/google/googletest)
for C++ tests, [absltest](https://abseil.io/docs/python/guides/testing) for
Python binding code and [nunit](https://nunit.org/) for C# code in the Unity
plugin. In most cases, a pull request will only be accepted if it includes
tests. MuJoCo's internal codebase is currently lacking in test coverage. If you
want to modify a function that isn't covered by tests, you'll be expected to
contribute tests for the existing functionality, not just your modification. In
fact, writing a test for existing code is a great way to get started with
contributions.
- Resolve compiler warnings.
- All existing tests must pass.
- Follow the [Style Guide](./STYLEGUIDE.md). In particular, adequately comment
your code.
- Make small pull requests. We will likely ask you to split up a large pull
request into self-contained, smaller ones, especially if the PR is trying to
achieve multiple things.
- Respond to reviewers. Please be responsive to any questions and comments.
Once you have met all the requirements, your code will be merged.
Thanks for improving MuJoCo!
### Community guidelines
This project follows Google's
[Open Source Community Guidelines](https://opensource.google/conduct/).
+53 -72
View File
@@ -6,77 +6,50 @@ in robotics, biomechanics, graphics and animation, machine learning, and other
areas which demand fast and accurate simulation of articulated structures
interacting with their environment.
DeepMind has acquired MuJoCo, and we are currently making preparations to open
source the codebase. In the meantime, MuJoCo is available for download as a free
and unrestricted precompiled binary under the Apache 2.0 license from
the [GitHub Releases page](https://github.com/deepmind/mujoco/releases).
MuJoCo's source code will be released through this GitHub repository once it is
ready. In the meantime, the repository hosts MuJoCo's documentation, C header
files for its public API, sample program code, along with the full source code
for the Python bindings and Unity plugin. If you wish to report bugs or make
feature requests, please file them as [GitHub Issues]. You are also welcome to
send us pull requests to improve anything that has been released into this
repository.
## Overview
MuJoCo is a compiled library with a C API, intended for researchers and
developers. The runtime simulation module is tuned to maximize performance and
operates on low-level data structures which are preallocated by the built-in XML
parser and compiler. The user defines models in the native MJCF scene
description language -- an XML file format designed to be as human readable and
editable as possible. URDF model files can also be loaded. The library includes
interactive visualization with a native GUI, rendered in OpenGL. MuJoCo further
exposes a large number of utility functions for computing physics-related
quantities, not necessarily in a simulation loop. Features include
- Simulation in generalized coordinates, avoiding joint violations.
- Inverse dynamics that are well-defined even in the presence of contacts.
- Unified continuous-time formulation of constraints via convex optimization.
- Constraints include soft contacts, limits, dry friction, equality
constraints.
- Simulation of particle systems, cloth, rope and soft objects.
- Actuators including motors, cylinders, muscles, tendons, slider-cranks.
- Choice of Newton, Conjugate Gradient, or Projected Gauss-Seidel solvers.
- Choice of pyramidal or elliptic friction cones, dense or sparse Jacobians.
- Choice of Euler or Runge-Kutta numerical integrators.
- Multi-threaded sampling and finite-difference approximations.
- Intuitive XML model format (called MJCF) and built-in model compiler.
- Cross-platform GUI with interactive 3D visualization in OpenGL.
- Run-time module written in ANSI C and hand-tuned for performance.
[Python bindings](https://github.com/deepmind/mujoco/tree/main/python) and a
[plugin for the Unity game engine](https://github.com/deepmind/mujoco/tree/main/unity)
are also provided and are actively supported by the MuJoCo development team.
## Requirements
MuJoCo binaries are currently built for Linux (x86-64 and AArch64),
Windows (x86-64 only), and macOS. If you require a build for a different
platform, please let us know via [GitHub Issues] or
[Discussions](https://github.com/deepmind/mujoco/discussions).
This repository is maintained by DeepMind, please see our [acquisition] and
[open sourcing] announcements.
MuJoCo has a C API and is intended for researchers and developers. The runtime
simulation module is tuned to maximize performance and operates on low-level
data structures that are preallocated by the built-in XML compiler. The library
includes interactive visualization with a native GUI, rendered in OpenGL. MuJoCo
further exposes a large number of utility functions for computing physics-
related quantities. We also provide Python bindings and a plug-in for the Unity
game engine.
## Documentation
MuJoco's current documentation is available at [mujoco.org/book], which is
serving Sphinx-based webpages derived from the ReStructuredText
[documentation source files].
MuJoCo's documentation is available at [mujoco.readthedocs.io], which serves
webpages derived from the [documentation source files].
## Releases
Versioned releases are available as precompiled binaries from the GitHub
[releases page], built for Linux (x86-64 and AArch64), Windows (x86-64 only),
and macOS (universal). This is the recommended way to use the software.
Users who wish to build MuJoCo from source, please consult the [build from
source] section of the documentation. However, please note that the commit at
the tip of the `main` branch branch may be unstable.
## Getting Started
There are two easy ways to get started with MuJoCo:
1. **Run `simulate` on your machine.**
[This video](https://www.youtube.com/watch?v=0ORsj_E17B0) shows a screen capture
of `simulate`, MuJoCo's native interactive viewer. Follow the steps described in
the [Getting Started] section of the documentation to get `simulate` running on
your machine.
2. **Explore our online IPython notebooks.**
If you are a Python user, you might want to start with our tutorial notebooks,
running on Google Colab:
- The first tutorial focuses on the basic MuJoco Python bindings: [![Open In Colab](https://colab.research.google.com/assets/colab-badge.svg)](https://colab.research.google.com/github/deepmind/dm_control/blob/main/dm_control/mujoco/tutorial.ipynb).
- The second tutorial includes more examples of `dm_control`-specific functionality: [![Open In Colab](https://colab.research.google.com/assets/colab-badge.svg)](https://colab.research.google.com/github/deepmind/dm_control/blob/main/tutorial.ipynb).
## Citation
@@ -85,19 +58,23 @@ If you use MuJoCo for published research, please cite:
```
@inproceedings{todorov2012mujoco,
title={Mujoco: A physics engine for model-based control},
title={MuJoCo: A physics engine for model-based control},
author={Todorov, Emanuel and Erez, Tom and Tassa, Yuval},
booktitle={2012 IEEE/RSJ International Conference on Intelligent Robots and Systems},
pages={5026--5033},
year={2012},
organization={IEEE}
organization={IEEE},
doi={10.1109/IROS.2012.6386109}
}
```
## License and Disclaimer
Copyright 2021 DeepMind Technologies Limited
Copyright 2021 DeepMind Technologies Limited.
Box collision code ([`engine_collision_box.c`](https://github.com/deepmind/mujoco/tree/main/src/engine/engine_collision_box.c))
is Copyright 2016 Svetoslav Kolev.
ReStructuredText documents, images, and videos in the `doc` directory are made
available under the terms of the Creative Commons Attribution 4.0 (CC BY 4.0)
@@ -109,7 +86,11 @@ copy of the License at https://www.apache.org/licenses/LICENSE-2.0.
This is not an officially supported Google product.
[build from source]: https://mujoco.readthedocs.io/en/latest/programming.html#building-mujoco-from-source
[Getting Started]: https://mujoco.readthedocs.io/en/latest/programming.html#getting-started
[acquisition]: https://www.deepmind.com/blog/opening-up-a-physics-simulator-for-robotics
[open sourcing]: https://www.deepmind.com/blog/open-sourcing-mujoco
[releases page]: https://github.com/deepmind/mujoco/releases
[GitHub Issues]: https://github.com/deepmind/mujoco/issues
[documentation source files]: https://github.com/deepmind/mujoco/tree/main/doc
[mujoco.org/book]: https://mujoco.org/book
[mujoco.readthedocs.io]: https://mujoco.readthedocs.io
+159
View File
@@ -0,0 +1,159 @@
# MuJoCo Style Guide
The MuJoCo codebase follows an internally consistent style that values
compactness and readability. Please try to follow the style guide as closely as
possible in your code contributions.
### Scope of this guide
MuJoCo has three main code categories:
1. **C code:** MuJoCo's core codebase. It consists of public headers under
`include/` and C source files and internal headers under `src/`. This style
guide primarily concerns itself with this category.
2. **Legacy C++:** Files under `src/user/` and `src/xml/`. These do not
necessarily follow best C++ practices. We intend to gradually replace these with
new code that follows the [Google C++
style](https://google.github.io/styleguide/cppguide.html) over time.
3. **New code:** This includes C++ files under `test/` and `python/` and C#
files under `unity/`. Added by DeepMind engineers, this code adheres to the
[Google style](https://google.github.io/styleguide/).
### General principles
Where any aspect of coding style is not explicitly spelled out in this guide,
the following principle is followed:
| Maximise consistency with the rest of the code. |
| --- |
If there is a contradiction between this guide and existing code, the guide
takes precedence. Additional principles include:
- Follow the [naming conventions](https://mujoco.readthedocs.io/en/latest/programming.html#naming-convention).
- Be sparing with horizontal space: Try to keep lines short, avoid line-breaks
where possble.
- Be generous with vertical space: Empty lines between code blocks are good.
- Keep names short.
- Inline comments are part of the code, treat them as such.
- Use American English in comments and documentation.
### Specific rules for C code
Over time, this style guide will be expanded to cover most aspects of C
programming in the MuJoCo codebase. In the meantime, it is usually enough to
inspect existing code and try to follow its example.
If there are any consistent coding patterns that are specific to the MuJoCo
codebase but aren't mentioned in the guide, the guide should be expanded. If you
spot such a pattern, feel free to send a PR to update the guide.
#### Indentation
2-space indents, using space characters rather than tabs.
#### Line length
Line length is 100 characters. In rare situations, like the collision table at
the top of
[engine_collision_driver.c](https://github.com/deepmind/mujoco/search?q=repo%3Ad
eepmind%2Fmujoco+filename%3Aengine_collision_driver.c), longer lines are alowed
for readability.
#### Comments
MuJoCo makes generous use of short, one-line comments describing the code block
just below them. They are considered an essential part of the code. Comments
should be:
- As succinct as possible, while maintaining clarity.
- Preceded by an empty line, unless at the top of a block.
- Uncapitalized and not terminated by a full-stop.
A helpful heuristic regarding in-code comments is that the reader should be able
to get a sense of what is happening in a function just by reading the comments.
An exception to the third bullet point above are function declaration comments
in public header files which are considered to be docstrings rather than code
and are therefore capitalized and terminated by a full stop. These docstrings
are required.
#### Braces
- MuJoCo uses
[attached K&R braces](https://en.wikipedia.org/wiki/Indentation_style#Variant:_mandatory_braces),
including for one-line blocks:
```C
// transpose matrix
void mju_transpose(mjtNum* res, const mjtNum* mat, int nr, int nc) {
for (int i=0; i<nr; i++) {
for (int j=0; j<nc; j++) {
res[j*nr+i] = mat[i*nc+j];
}
}
}
```
- Brace-less single line statements are allowed outside of `engine/` code, for
similar, repeated blocks, that do not contain flow control statements (`return`,
`continue`, etc.). For an example of this exception, inspect the [`mjCModel`
destructor](https://github.com/deepmind/mujoco/search?q=repo%3Adeepmind%2Fmujoco+filename%3Auser_model.cc).
- Unattached braces are allowed in `if/else` blocks, when inserting a comment
before the `else`:
```C
// rotate vector by quaternion
void mju_rotVecQuat(mjtNum res[3], const mjtNum vec[3], const mjtNum quat[4]) {
// null quat: copy vec
if (quat[0]==1 && quat[1]==0 && quat[2]==0 && quat[3]==0) {
mju_copy3(res, vec);
}
// regular processing
else {
mjtNum mat[9];
mju_quat2Mat(mat, quat);
mju_rotVecMat(res, vec, mat);
}
}
```
#### Spacing
- MuJoCo encourages judicious use of spacing around operators to promote
readability. For example below, note the lack of spaces around the
multiplication operator, and the aligning spaces in the second and fourth
assignments:
```C
// time-derivative of quaternion, given 3D rotational velocity
void mju_derivQuat(mjtNum res[4], const mjtNum quat[4], const mjtNum vel[3]) {
res[0] = 0.5*(-vel[0]*quat[1] - vel[1]*quat[2] - vel[2]*quat[3]);
res[1] = 0.5*( vel[0]*quat[0] + vel[1]*quat[3] - vel[2]*quat[2]);
res[2] = 0.5*(-vel[0]*quat[3] + vel[1]*quat[0] + vel[2]*quat[1]);
res[3] = 0.5*( vel[0]*quat[2] - vel[1]*quat[1] + vel[2]*quat[0]);
}
```
- Spaces are not allowed around comparison operators in `for` statements and
inside array subscripts `[]`. For an example, inspect the `mju_transpose`
implementation above.
- Three empty lines between function declarations.
#### Variable declarations
Historically the MuJoCo C codebase used exclusively C89-style variable
declarations, with all stack variables pre-declared at the top of the function.
We are in the process of migrating the code to the C99 convention of declaring
variables at the narrowest possible scope. For example iterator variables in
for-loops are mostly declared in the narrow scope, as in the `mju_transpose`
example above.
New code should use the C99 convention. When editing an existing function,
please move existing variable declarations into local scope. Pull requests
helping us to complete the migration are very welcome.
+177
View File
@@ -0,0 +1,177 @@
# Copyright 2022 DeepMind Technologies Limited
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# https://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
#.rst:
# duplicate_target
# ----------------------
#
# Duplicates the specified target.
#
# duplicate_target(TARGET target NEW_TARGET_NAME new_target_name)
#
# Duplicates the specified target by creating a new target with the name
# specified by ``NEW_TARGET_NAME`` and copying all properties defined by
# ``TARGET``.
# The command has the following parameters:
#
# Arguments:
# - ``TARGET`` Target to be duplicated.
# - ``NEW_TARGET_NAME`` name of the new target.
#
if(COMMAND duplicate_target)
return()
endif()
macro(duplicate_target)
# Parse arguments.
set(options)
set(one_value_args TARGET NEW_TARGET_NAME)
set(multi_value_args)
cmake_parse_arguments(
_ARGS
"${options}"
"${one_value_args}"
"${multi_value_args}"
${ARGN}
)
# Check required variables are defined.
if(NOT _ARGS_TARGET)
message(FATAL_ERROR "duplicate_target: TARGET must be specified.")
endif()
if(NOT _ARGS_NEW_TARGET_NAME)
message(FATAL_ERROR "duplicate_target: NEW_TARGET_NAME must be specified.")
endif()
# Check for the target to exist.
if(NOT TARGET ${_ARGS_TARGET})
message(FATAL_ERROR "duplicate_target: TARGET ${_ARGS_TARGET} not found.")
endif()
# Non-exausitve list.
set(PROPERTIES_TO_SKIP)
get_target_property(TARGET_TYPE ${_ARGS_TARGET} TYPE)
if(${TARGET_TYPE} STREQUAL "STATIC_LIBRARY")
add_library(${_ARGS_NEW_TARGET_NAME} STATIC)
list(APPEND PROPERTIES_TO_SKIP "IMPORTED_GLOBAL")
elseif(${TARGET_TYPE} STREQUAL "SHARED_LIBRARY")
add_library(${_ARGS_NEW_TARGET_NAME} SHARED)
list(APPEND PROPERTIES_TO_SKIP "IMPORTED_GLOBAL")
elseif(${TARGET_TYPE} STREQUAL "OBJECT_LIBRARY")
add_library(${_ARGS_NEW_TARGET_NAME} OBJECT)
list(APPEND PROPERTIES_TO_SKIP "IMPORTED_GLOBAL")
elseif(${TARGET_TYPE} STREQUAL "INTERFACE_LIBRARY")
add_library(${_ARGS_NEW_TARGET_NAME} INTERFACE)
elseif(${TARGET_TYPE} STREQUAL "EXECUTABLE")
add_executable(${_ARGS_NEW_TARGET_NAME})
list(APPEND PROPERTIES_TO_SKIP "IMPORTED_GLOBAL")
endif()
set(IGNORED_PROPERTIES "HEADER_SETS;INTERFACE_HEADER_SETS;NAME;TYPE")
# Get all CMake target properties.
if(NOT CMAKE_ALL_PROPERTY_LIST)
execute_process(COMMAND cmake --help-property-list OUTPUT_VARIABLE ALL_PROPERTIES)
# Convert command output into a CMake list
string(
REGEX
REPLACE ";"
"\\\\;"
ALL_PROPERTIES
"${ALL_PROPERTIES}"
)
string(
REGEX
REPLACE "\n"
";"
ALL_PROPERTIES
"${ALL_PROPERTIES}"
)
# Post process the properties. We:
# - Remove all properties listed in ``IGNORED_PROPERTIES``.
# - Remove LOCATION as it should not be accessed, See https://stackoverflow.com/questions/32197663/how-can-i-remove-the-the-location-property-may-not-be-read-from-target-error-i
# - Substitute <CONFIG> with all the possible build types. This is needed for multi-config generators as they can change the type of build without invoking again CMake.
set(CMAKE_ALL_PROPERTY_LIST "")
foreach(PROPERTY ${ALL_PROPERTIES})
# Skip reading the LOCAION property as they should not be read.
# See https://stackoverflow.com/questions/32197663/how-can-i-remove-the-the-location-property-may-not-be-read-from-target-error-i
if(PROPERTY STREQUAL "LOCATION"
OR PROPERTY MATCHES "^LOCATION_"
OR PROPERTY MATCHES "_LOCATION$"
)
continue()
endif()
set(_ignore OFF)
foreach(_pro ${IGNORED_PROPERTIES})
if(PROPERTY STREQUAL ${_pro})
set(_ignore ON)
break()
endif()
endforeach()
if(_ignore)
continue()
endif()
string(FIND ${PROPERTY} "<CONFIG>" FOUND)
if(${FOUND} EQUAL -1)
# Simply append the property.
list(APPEND CMAKE_ALL_PROPERTY_LIST ${PROPERTY})
else()
# Iterate on the build types to add the correct property.
foreach(BUILD_TYPE ${BUILD_TYPES})
string(
REPLACE "<CONFIG>"
"${BUILD_TYPE}"
CONFIG_PROPERTY
${PROPERTY}
)
list(APPEND CMAKE_ALL_PROPERTY_LIST ${CONFIG_PROPERTY})
endforeach()
endif()
endforeach()
endif()
foreach(PROPERTY ${CMAKE_ALL_PROPERTY_LIST})
# Search if we should skip this property.
list(
FIND
PROPERTIES_TO_SKIP
${PROPERTY}
SHOULD_SKIP
)
if(${SHOULD_SKIP} GREATER_EQUAL 0)
continue()
endif()
# First check if the property was set on the target
get_property(
PROPERTY_FOUND
TARGET ${_ARGS_TARGET}
PROPERTY ${PROPERTY}
SET
)
if(PROPERTY_FOUND)
get_target_property(PROPERTY_VALUE ${_ARGS_TARGET} ${PROPERTY})
set_target_properties(${_ARGS_NEW_TARGET_NAME} PROPERTIES ${PROPERTY} "${PROPERTY_VALUE}")
endif()
endforeach()
endmacro()
+25 -14
View File
@@ -31,8 +31,9 @@
#
# Arguments:
# - ``USE_SYSTEM_PACKAGE`` one-value argument on whether to search for the
# package in the system (ON) or whether to fetch the library from a git
# repository (OFF).
# package in the system (ON) or whether to fetch the library using
# FetchContent from the specified Git repository (OFF). Note that
# FetchContent variables will override this behaviour.
# - ``PACKAGE_NAME`` name of the system-package. Ignored if
# ``USE_SYSTEM_PACKAGE`` is ``OFF``.
# - ``LIBRARY_NAME`` name of the library. Ignored if
@@ -41,9 +42,19 @@
# ``USE_SYSTEM_PACKAGE`` is ``ON``.
# - ``GIT_TAG`` tag reference when fetching the library from the git
# repository. Ignored if ``USE_SYSTEM_PACKAGE`` is ``ON``.
# - ``PATCH_COMMAND`` Specifies a custom command to patch the sources after an
# update. See https://cmake.org/cmake/help/latest/module/ExternalProject.html#command:externalproject_add
# for details on the parameter.
# - ``TARGETS`` list of targets to be satisfied. If any of these targets are
# not currently defined, this macro will attempt to either find or fetch the
# package.
# - ``EXCLUDE_FROM_ALL`` if specified, the targets are not added to the ``all``
# metatarget.
#
# Note: if ``USE_SYSTEM_PACKAGE`` is ``OFF``, FetchContent will be used to
# retrieve the specified targets. It is possible to specify any variable in
# https://cmake.org/cmake/help/latest/module/FetchContent.html#variables to
# override this macro behaviour.
if(COMMAND FindOrFetch)
return()
@@ -76,10 +87,14 @@ macro(FindOrFetch)
if(NOT _ARGS_TARGETS)
message(FATAL_ERROR "mujoco::FindOrFetch: TARGETS must be specified.")
endif()
set(targets_found TRUE)
message(CHECK_START
"mujoco::FindOrFetch: checking for targets in package `${_ARGS_PACKAGE_NAME}`"
)
foreach(target ${_ARGS_TARGETS})
if(NOT TARGET ${target})
message(STATUS "mujoco::FindOrFetch: target `${target}` not defined.")
message(CHECK_FAIL "target `${target}` not defined.")
set(targets_found FALSE)
break()
endif()
@@ -88,16 +103,14 @@ macro(FindOrFetch)
# If targets are not found, use `find_package` or `FetchContent...` to get it.
if(NOT targets_found)
if(${_ARGS_USE_SYSTEM_PACKAGE})
message(
STATUS
"mujoco::FindOrFetch: Attempting to find `${_ARGS_PACKAGE_NAME}` in system packages..."
message(CHECK_START
"mujoco::FindOrFetch: finding `${_ARGS_PACKAGE_NAME}` in system packages..."
)
find_package(${_ARGS_PACKAGE_NAME} REQUIRED)
message(STATUS "mujoco::FindOrFetch: Found `${_ARGS_PACKAGE_NAME}` in system packages.")
message(CHECK_PASS "found")
else()
message(
STATUS
"mujoco::FindOrFetch: Attempting to fetch `${_ARGS_LIBRARY_NAME}` from `${_ARGS_GIT_REPO}`..."
message(CHECK_START
"mujoco::FindOrFetch: Using FetchContent to retrieve `${_ARGS_LIBRARY_NAME}`"
)
FetchContent_Declare(
${_ARGS_LIBRARY_NAME}
@@ -118,11 +131,9 @@ macro(FindOrFetch)
else()
FetchContent_MakeAvailable(${_ARGS_LIBRARY_NAME})
endif()
message(
STATUS "mujoco::FindOrFetch: Fetched `${_ARGS_LIBRARY_NAME}` from `${_ARGS_GIT_REPO}`."
)
message(CHECK_PASS "Done")
endif()
else()
message(STATUS "mujoco::FindOrFetch: `${_ARGS_PACKAGE_NAME}` targets found.")
message(CHECK_PASS "found")
endif()
endmacro()
+327
View File
@@ -0,0 +1,327 @@
# Copyright 2021 DeepMind Technologies Limited
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# https://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
# Build configuration for third party libraries used in MuJoCo.
# Override the BUILD_SHARED_LIBS setting, just for building third party libs (since we always want
# static libraries). The ccd CMakeLists.txt doesn't expose an option to build a static ccd library,
# unless BUILD_SHARED_LIBS is set.
set(MUJOCO_DEP_VERSION_lodepng
48e5364ef48ec2408f44c727657ac1b6703185f8
CACHE STRING "Version of `lodepng` to be fetched."
)
set(MUJOCO_DEP_VERSION_tinyxml2
1dee28e51f9175a31955b9791c74c430fe13dc82 # 9.0.0
CACHE STRING "Version of `tinyxml2` to be fetched."
)
set(MUJOCO_DEP_VERSION_tinyobjloader
1421a10d6ed9742f5b2c1766d22faa6cfbc56248
CACHE STRING "Version of `tinyobjloader` to be fetched."
)
set(MUJOCO_DEP_VERSION_ccd
7931e764a19ef6b21b443376c699bbc9c6d4fba8 # v2.1
CACHE STRING "Version of `ccd` to be fetched."
)
set(MUJOCO_DEP_VERSION_qhull
3df027b91202cf179f3fba3c46eebe65bbac3790
CACHE STRING "Version of `qhull` to be fetched."
)
set(MUJOCO_DEP_VERSION_Eigen3
b02c384ef4e8eba7b8bdef16f9dc6f8f4d6a6b2b
CACHE STRING "Version of `Eigen3` to be fetched."
)
set(MUJOCO_DEP_VERSION_abseil
78f9680225b9792c26dfdd99d0bd26c96de53dd4 # Fixes universal builds for macOS
CACHE STRING "Version of `abseil` to be fetched."
)
set(MUJOCO_DEP_VERSION_gtest
e2239ee6043f73722e7aa812a459f54a28552929 # release-1.11.0
CACHE STRING "Version of `gtest` to be fetched."
)
set(MUJOCO_DEP_VERSION_benchmark
0d98dba29d66e93259db7daa53a9327df767a415 # v1.6.1
CACHE STRING "Version of `benchmark` to be fetched."
)
mark_as_advanced(MUJOCO_DEP_VERSION_lodepng)
mark_as_advanced(MUJOCO_DEP_VERSION_tinyxml2)
mark_as_advanced(MUJOCO_DEP_VERSION_tinyobjloader)
mark_as_advanced(MUJOCO_DEP_VERSION_ccd)
mark_as_advanced(MUJOCO_DEP_VERSION_qhull)
mark_as_advanced(MUJOCO_DEP_VERSION_Eigen3)
mark_as_advanced(MUJOCO_DEP_VERSION_abseil)
mark_as_advanced(MUJOCO_DEP_VERSION_gtest)
mark_as_advanced(MUJOCO_DEP_VERSION_benchmark)
include(FetchContent)
include(FindOrFetch)
# We force all the dependencies to be compiled as static libraries.
# TODO(fraromano) Revisit this choice when adding support for install.
set(BUILD_SHARED_LIBS_OLD ${BUILD_SHARED_LIBS})
set(BUILD_SHARED_LIBS
OFF
CACHE INTERNAL "Build SHARED libraries"
)
if(NOT TARGET lodepng)
FetchContent_Declare(
lodepng
GIT_REPOSITORY https://github.com/lvandeve/lodepng.git
GIT_TAG ${MUJOCO_DEP_VERSION_lodepng}
)
FetchContent_GetProperties(lodepng)
if(NOT lodepng_POPULATED)
FetchContent_Populate(lodepng)
# This is not a CMake project.
set(LODEPNG_SRCS ${lodepng_SOURCE_DIR}/lodepng.cpp)
set(LODEPNG_HEADERS ${lodepng_SOURCE_DIR}/lodepng.h)
add_library(lodepng STATIC ${LODEPNG_HEADERS} ${LODEPNG_SRCS})
target_compile_options(lodepng PRIVATE ${MUJOCO_MACOS_COMPILE_OPTIONS})
target_link_options(lodepng PRIVATE ${MUJOCO_MACOS_LINK_OPTIONS})
target_include_directories(lodepng PUBLIC ${lodepng_SOURCE_DIR})
endif()
endif()
# TODO(fraromano) We fetch qhull before the other libraries as it needs to go before until https://github.com/qhull/qhull/pull/111 is merged.
set(QHULL_ENABLE_TESTING OFF)
# We need Git to apply the patch using git apply.
find_package(Git REQUIRED)
findorfetch(
USE_SYSTEM_PACKAGE
OFF
PACKAGE_NAME
qhull
LIBRARY_NAME
qhull
GIT_REPO
https://github.com/qhull/qhull.git
GIT_TAG
${MUJOCO_DEP_VERSION_qhull}
TARGETS
qhull
# TODO(fraromano) Remove when https://github.com/qhull/qhull/pull/112 is merged.
# Do not fail if patch fails. This will happen the second time we run CMake as the sources will be already patched.
PATCH_COMMAND
"${GIT_EXECUTABLE}"
"apply"
"-q"
"${PROJECT_SOURCE_DIR}/cmake/qhull_fix_testing.patch"
"||"
"${CMAKE_COMMAND}"
"-E"
"true"
EXCLUDE_FROM_ALL
)
# MuJoCo includes a file from libqhull_r which is not exported by the qhull include directories.
# Add it to the target.
target_include_directories(
qhullstatic_r INTERFACE $<BUILD_INTERFACE:${qhull_SOURCE_DIR}/src/libqhull_r>
)
target_compile_options(qhullstatic_r PRIVATE ${MUJOCO_MACOS_COMPILE_OPTIONS})
target_link_options(qhullstatic_r PRIVATE ${MUJOCO_MACOS_LINK_OPTIONS})
set(tinyxml2_BUILD_TESTING OFF)
findorfetch(
USE_SYSTEM_PACKAGE
OFF
PACKAGE_NAME
tinyxml2
LIBRARY_NAME
tinyxml2
GIT_REPO
https://github.com/leethomason/tinyxml2.git
GIT_TAG
${MUJOCO_DEP_VERSION_tinyxml2}
TARGETS
tinyxml2
EXCLUDE_FROM_ALL
)
target_compile_options(tinyxml2 PRIVATE ${MUJOCO_MACOS_COMPILE_OPTIONS})
target_link_options(tinyxml2 PRIVATE ${MUJOCO_MACOS_LINK_OPTIONS})
findorfetch(
USE_SYSTEM_PACKAGE
OFF
PACKAGE_NAME
tinyobjloader
LIBRARY_NAME
tinyobjloader
GIT_REPO
https://github.com/tinyobjloader/tinyobjloader.git
GIT_TAG
${MUJOCO_DEP_VERSION_tinyobjloader}
TARGETS
tinyobjloader
EXCLUDE_FROM_ALL
)
set(ENABLE_DOUBLE_PRECISION ON)
set(CCD_HIDE_ALL_SYMBOLS ON)
findorfetch(
USE_SYSTEM_PACKAGE
OFF
PACKAGE_NAME
ccd
LIBRARY_NAME
ccd
GIT_REPO
https://github.com/danfis/libccd.git
GIT_TAG
${MUJOCO_DEP_VERSION_ccd}
TARGETS
ccd
EXCLUDE_FROM_ALL
)
target_compile_options(ccd PRIVATE ${MUJOCO_MACOS_COMPILE_OPTIONS})
target_link_options(ccd PRIVATE ${MUJOCO_MACOS_LINK_OPTIONS})
# libCCD has an unconditional `#define _CRT_SECURE_NO_WARNINGS` on Windows.
# TODO(stunya): Remove this after https://github.com/danfis/libccd/pull/77 is merged.
if(WIN32)
if(MSVC)
# C4005 is the MSVC equivalent of -Wmacro-redefined.
target_compile_options(ccd PRIVATE /wd4005)
else()
target_compile_options(ccd PRIVATE -Wno-macro-redefined)
endif()
endif()
if(MUJOCO_BUILD_TESTS)
set(ABSL_PROPAGATE_CXX_STD ON)
# This specific version of Abseil does not have the following variable. We need to work with BUILD_TESTING
set(BUILD_TESTING_OLD ${BUILD_TESTING})
set(BUILD_TESTING
OFF
CACHE INTERNAL "Build tests."
)
set(ABSL_BUILD_TESTING OFF)
findorfetch(
USE_SYSTEM_PACKAGE
OFF
PACKAGE_NAME
absl
LIBRARY_NAME
abseil-cpp
GIT_REPO
https://github.com/abseil/abseil-cpp.git
GIT_TAG
${MUJOCO_DEP_VERSION_abseil}
TARGETS
absl::core_headers
EXCLUDE_FROM_ALL
)
set(BUILD_TESTING
${BUILD_TESTING_OLD}
CACHE BOOL "Build tests." FORCE
)
# Avoid linking errors on Windows by dynamically linking to the C runtime.
set(gtest_force_shared_crt
ON
CACHE BOOL "" FORCE
)
findorfetch(
USE_SYSTEM_PACKAGE
OFF
PACKAGE_NAME
GTest
LIBRARY_NAME
googletest
GIT_REPO
https://github.com/google/googletest.git
GIT_TAG
${MUJOCO_DEP_VERSION_gtest}
TARGETS
gtest
gmock
gtest_main
EXCLUDE_FROM_ALL
)
set(BENCHMARK_EXTRA_FETCH_ARGS "")
if(WIN32 AND NOT MSVC)
set(BENCHMARK_EXTRA_FETCH_ARGS
PATCH_COMMAND
"sed"
"-i"
"-e"
"s/-std=c++11/-std=c++14/g"
"-e"
"s/HAVE_CXX_FLAG_STD_CXX11/HAVE_CXX_FLAG_STD_CXX14/g"
"${CMAKE_BINARY_DIR}/_deps/benchmark-src/CMakeLists.txt"
)
endif()
set(BENCHMARK_ENABLE_TESTING OFF)
findorfetch(
USE_SYSTEM_PACKAGE
OFF
PACKAGE_NAME
benchmark
LIBRARY_NAME
benchmark
GIT_REPO
https://github.com/google/benchmark.git
GIT_TAG
${MUJOCO_DEP_VERSION_benchmark}
TARGETS
benchmark::benchmark
benchmark::benchmark_main
${BENCHMARK_EXTRA_FETCH_ARGS}
EXCLUDE_FROM_ALL
)
endif()
if(MUJOCO_TEST_PYTHON_UTIL)
add_compile_definitions(EIGEN_MPL2_ONLY)
if(NOT TARGET eigen)
# Support new IN_LIST if() operator.
set(CMAKE_POLICY_DEFAULT_CMP0057 NEW)
FetchContent_Declare(
Eigen3
GIT_REPOSITORY https://gitlab.com/libeigen/eigen.git
GIT_TAG ${MUJOCO_DEP_VERSION_Eigen3}
)
FetchContent_GetProperties(Eigen3)
if(NOT Eigen3_POPULATED)
FetchContent_Populate(Eigen3)
# Mark the library as IMPORTED as a workaround for https://gitlab.kitware.com/cmake/cmake/-/issues/15415
add_library(Eigen3::Eigen INTERFACE IMPORTED)
set_target_properties(
Eigen3::Eigen PROPERTIES INTERFACE_INCLUDE_DIRECTORIES "${eigen3_SOURCE_DIR}"
)
endif()
endif()
endif()
# Reset BUILD_SHARED_LIBS to its previous value
set(BUILD_SHARED_LIBS
${BUILD_SHARED_LIBS_OLD}
CACHE BOOL "Build MuJoCo as a shared library" FORCE
)
+35
View File
@@ -0,0 +1,35 @@
# Copyright 2022 DeepMind Technologies Limited
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# https://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
option(MUJOCO_HARDEN "Enable build hardening for MuJoCo." OFF)
if(MUJOCO_HARDEN
AND NOT
CMAKE_CXX_COMPILER_ID
MATCHES
".*Clang.*"
)
message(FATAL_ERROR "MUJOCO_HARDEN is only supported when building with Clang")
endif()
if(MUJOCO_HARDEN)
set(MUJOCO_HARDEN_COMPILE_OPTIONS -D_FORTIFY_SOURCE=2 -fstack-protector)
if(${CMAKE_SYSTEM_NAME} MATCHES "Darwin")
set(MUJOCO_HARDEN_LINK_OPTIONS -Wl,-bind_at_load)
elseif(${CMAKE_SYSTEM_NAME} MATCHES "Linux")
set(MUJOCO_HARDEN_LINK_OPTIONS -Wl,-z,relro -Wl,-z,now)
endif()
else()
set(MUJOCO_HARDEN_COMPILE_OPTIONS "")
set(MUJOCO_HARDEN_LINK_OPTIONS "")
endif()
+38
View File
@@ -0,0 +1,38 @@
# Copyright 2022 DeepMind Technologies Limited
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# https://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
if(APPLE)
# 10.12 is the oldest version of macOS that supports C++17, launched 2016.
set(MUJOCO_MACOSX_VERSION_MIN 10.12)
# We are setting the -mmacosx-version-min compiler flag directly rather than using the
# CMAKE_OSX_DEPLOYMENT_TARGET variable since we do not want to affect choice of SDK,
# and also we only want to apply the version restriction locally.
set(MUJOCO_MACOS_COMPILE_OPTIONS -mmacosx-version-min=${MUJOCO_MACOSX_VERSION_MIN}
-Werror=partial-availability -Werror=unguarded-availability
)
set(MUJOCO_MACOS_LINK_OPTIONS -mmacosx-version-min=${MUJOCO_MACOSX_VERSION_MIN}
-Wl,-no_weak_imports
)
else()
set(MUJOCO_MACOS_COMPILE_OPTIONS "")
set(MUJOCO_MACOS_LINK_OPTIONS "")
endif()
function(enforce_mujoco_macosx_min_version)
if(APPLE)
add_compile_options(${MUJOCO_MACOS_COMPILE_OPTIONS})
add_link_options(${MUJOCO_MACOS_LINK_OPTIONS})
endif()
endfunction()
+106
View File
@@ -0,0 +1,106 @@
# Copyright 2021 DeepMind Technologies Limited
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# https://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
# Global compilation settings
set(CMAKE_C_STANDARD 11)
set(CMAKE_C_STANDARD_REQUIRED ON)
set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(CMAKE_CXX_EXTENSIONS OFF)
set(CMAKE_C_EXTENSIONS OFF)
set(CMAKE_EXPORT_COMPILE_COMMANDS ON) # For LLVM tooling
if(NOT CMAKE_CONFIGURATION_TYPES)
if(NOT CMAKE_BUILD_TYPE)
message(STATUS "Setting build type to 'Release' as none was specified.")
set(CMAKE_BUILD_TYPE
"Release"
CACHE STRING "Choose the type of build, recommanded options are: Debug or Release" FORCE
)
endif()
set(BUILD_TYPES
"Debug"
"Release"
"MinSizeRel"
"RelWithDebInfo"
)
set_property(CACHE CMAKE_BUILD_TYPE PROPERTY STRINGS ${BUILD_TYPES})
endif()
include(GNUInstallDirs)
# Change the default output directory in the build structure. This is not stricly needed, but helps
# running in Windows, such that all built executables have DLLs in the same folder as the .exe
# files.
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/${CMAKE_INSTALL_BINDIR}")
set(CMAKE_LIBRARY_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/${CMAKE_INSTALL_LIBDIR}")
set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/${CMAKE_INSTALL_LIBDIR}")
set(OpenGL_GL_PREFERENCE GLVND)
set(CMAKE_POSITION_INDEPENDENT_CODE ON)
set(CMAKE_C_VISIBILITY_PRESET hidden)
set(CMAKE_CXX_VISIBILITY_PRESET hidden)
set(CMAKE_VISIBILITY_INLINES_HIDDEN ON)
if(MSVC)
add_compile_options(/Gy /Gw /Oi)
elseif(CMAKE_CXX_COMPILER_ID STREQUAL "GNU" OR CMAKE_CXX_COMPILER_ID MATCHES "Clang")
add_compile_options(-fdata-sections -ffunction-sections)
endif()
# We default to shared library.
set(BUILD_SHARED_LIBS
ON
CACHE BOOL "Build Mujoco as shared library."
)
option(MUJOCO_ENABLE_AVX "Build binaries that require AVX instructions, if possible." ON)
option(MUJOCO_ENABLE_AVX_INTRINSICS "Make use of hand-written AVX intrinsics, if possible." ON)
option(MUJOCO_ENABLE_RPATH "Enable RPath support when installing Mujoco." ON)
mark_as_advanced(MUJOCO_ENABLE_RPATH)
if(MUJOCO_ENABLE_AVX)
include(CheckAvxSupport)
get_avx_compile_options(AVX_COMPILE_OPTIONS)
else()
set(AVX_COMPILE_OPTIONS)
endif()
option(MUJOCO_BUILD_MACOS_FRAMEWORKS "Build libraries as macOS Frameworks" OFF)
# Get some extra link options.
include(MujocoLinkOptions)
get_mujoco_extra_link_options(EXTRA_LINK_OPTIONS)
if(CMAKE_CXX_COMPILER_ID STREQUAL "GNU" OR (CMAKE_CXX_COMPILER_ID MATCHES "Clang" AND NOT MSVC))
set(EXTRA_COMPILE_OPTIONS -Wall -Werror)
if(CMAKE_CXX_COMPILER_ID STREQUAL "GNU")
set(EXTRA_COMPILE_OPTIONS
-Wno-int-in-bool-context
-Wno-maybe-uninitialized
-Wno-sign-compare
-Wno-stringop-overflow
-Wno-stringop-truncation
)
endif()
endif()
if(WIN32)
add_compile_definitions(_CRT_SECURE_NO_WARNINGS)
endif()
include(MujocoHarden)
set(EXTRA_COMPILE_OPTIONS ${EXTRA_COMPILE_OPTIONS} ${MUJOCO_HARDEN_COMPILE_OPTIONS})
set(EXTRA_LINK_OPTIONS ${EXTRA_LINK_OPTIONS} ${MUJOCO_HARDEN_LINK_OPTIONS})
+188
View File
@@ -0,0 +1,188 @@
# Copyright 2022 DeepMind Technologies Limited
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# https://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
#[=======================================================================[.rst:
TargetAddRpath
----------------------
Add support to RPATH for the specified targets
.. command:: target_add_rpath
Add support to RPATH for the specified targets::
.. code-block:: cmake
target_add_rpath(target1 target2 ...
INSTALL_DIRECTORY install_directory
LIB_DIRS dir1 dir2 ...
[INSTALL_NAME_DIR [dir]]
[DEPENDS condition [condition]]
[USE_LINK_PATH])
This function setups the RPATH paths for the specified targets. The use of
RPATH allows to avoid using the (dangerous) environment variable
``LD_LIBRARY_PATH`` (or equivalent on macOS) when installing without absolute
paths.
By using RPATH the installation can be relocated as the linker will look for
(some of) the dependencies at run time.
The function has the following parameters:
Options:
- ``USE_LINK_PATH``: if defined, the function will set
``INSTALL_RPATH_USE_LINK_PATH`` on all the specified targets, i.e. CMake
will automatically adds to the RPATH the path to all the dependent
libraries defined outside this project.
Arguments:
- ``INSTALL_DIRECTORY`` The directory where the specified targets will be
installed.
- ``LIB_DIRS`` list of directories to be added a search path to the RPATH.
Note that the relative path between ``INSTALL_DIRECTORY`` and these
directories will be added to the RPATH.
- ``INSTALL_NAME_DIR`` directory where the libraries will be installed.
This variable will be used only if ``CMAKE_SKIP_RPATH`` or
``CMAKE_SKIP_INSTALL_RPATH`` is set to ``TRUE`` as it will set the
``INSTALL_NAME_DIR`` on all targets.
- ``DEPENDS`` list of conditions that should be ``TRUE`` to enable
RPATH, for example ``FOO; NOT BAR``.
Note: see https://gitlab.kitware.com/cmake/community/-/wikis/doc/cmake/RPATH-handling
and https://gitlab.kitware.com/cmake/cmake/issues/16589 for further details.
#]=======================================================================]
if(COMMAND target_add_rpath)
return()
endif()
function(_get_system_dirs _output_var)
set(${_output_var}
${CMAKE_PLATFORM_IMPLICIT_LINK_DIRECTORIES}
PARENT_SCOPE
)
endfunction()
function(
_get_rpath_relative_path
_output_var
_bin_dir
_lib_dir
)
file(
RELATIVE_PATH
_rel_path
${_bin_dir}
${_lib_dir}
)
if(${CMAKE_SYSTEM_NAME} MATCHES "Darwin")
set(${_output_var}
"@loader_path/${_rel_path}"
PARENT_SCOPE
)
else()
set(${_output_var}
"\$ORIGIN/${_rel_path}"
PARENT_SCOPE
)
endif()
endfunction()
function(target_add_rpath)
set(_options USE_LINK_PATH)
set(_oneValueArgs INSTALL_NAME_DIR INSTALL_DIRECTORY)
set(_multiValueArgs TARGETS LIB_DIRS DEPENDS)
cmake_parse_arguments(
_ARGS
"${_options}"
"${_oneValueArgs}"
"${_multiValueArgs}"
"${ARGN}"
)
# Handle Apple-specific installation directory. Note that this disable proper RPATH.
if(CMAKE_SKIP_RPATH OR CMAKE_SKIP_INSTALL_RPATH)
if(DEFINED _ARGS_INSTALL_NAME_DIR)
set_target_properties(${_ARGS_TARGETS} PROPERTIES INSTALL_NAME_DIR ${_ARGS_INSTALL_NAME_DIR})
endif()
endif()
# If RPATH is disabled, do nothing and return.
if(CMAKE_SKIP_RPATH OR (CMAKE_SKIP_INSTALL_RPATH AND CMAKE_SKIP_BUILD_RPATH))
return()
endif()
# Check if the user requested RPATH for the specified targets.
set(_enable_rpath ON)
if(DEFINED _ARGS_DEPENDS)
foreach(_cond ${_ARGS_DEPENDS})
string(
REGEX
REPLACE " +"
";"
_cond
"${_cond}"
)
if(NOT (${_cond}))
set(_enable_rpath OFF)
endif()
endforeach()
endif()
if(NOT _enable_rpath)
return()
endif()
# Now enable RPATH for the specified targets.
_get_system_dirs(_system_dirs)
# We do this per target to preserve the original rpath setting.
foreach(_target ${_ARGS_TARGETS})
get_target_property(_install_rpath ${_target} INSTALL_RPATH)
foreach(_lib_dir ${_ARGS_LIB_DIRS})
# Check if the specified library path is a system directory. These are always searched so we do
# not need to include them in the RPATH.
list(
FIND
_system_dirs
"${_lib_dir}"
is_system_dir
)
if("${is_system_dir}" STREQUAL "-1")
_get_rpath_relative_path(_bin_lib_rel_path ${_ARGS_INSTALL_DIRECTORY} ${_lib_dir})
list(APPEND _install_rpath ${_bin_lib_rel_path})
endif()
endforeach()
if(NOT
"${_install_rpath}"
STREQUAL
""
)
list(REMOVE_DUPLICATES _install_rpath)
endif()
set_target_properties(
${_target}
PROPERTIES INSTALL_RPATH ${_install_rpath}
INSTALL_RPATH_USE_LINK_PATH ${_ARGS_USE_LINK_PATH}
MACOSX_RPATH ON # This is ON by default.
)
endforeach()
endfunction()
+21
View File
@@ -0,0 +1,21 @@
#!/bin/bash
# Copyright 2021 DeepMind Technologies Limited
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
if [ -z "$1" ]; then
echo "Expecting an output directory. Got none." 1>&2
exit 1
fi
rm -rf "$1"
+24
View File
@@ -0,0 +1,24 @@
# Copyright 2021 DeepMind Technologies Limited
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# https://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
@PACKAGE_INIT@
include(CMakeFindDependencyMacro)
find_dependency(OpenGL)
if(NOT TARGET mujoco AND NOT @PROJECT_NAME@_BINARY_DIR)
include("${CMAKE_CURRENT_LIST_DIR}/mujocoTargets.cmake")
endif()
check_required_components(mujoco)
+92
View File
@@ -0,0 +1,92 @@
From 2bf2d1f5151d0d36cd17dea03129bd9a825384c5 Mon Sep 17 00:00:00 2001
From: Francesco Romano <francesco.romano.1987@gmail.com>
Date: Fri, 6 May 2022 11:30:44 +0100
Subject: [PATCH] Add option to disable testing
---
CMakeLists.txt | 55 ++++++++++++++++++++++++++------------------------
1 file changed, 29 insertions(+), 26 deletions(-)
diff --git a/CMakeLists.txt b/CMakeLists.txt
index cd95ad0..6ff1c98 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -113,6 +113,7 @@ cmake_dependent_option(LINK_APPS_SHARED "Use shared library for linking applicat
"BUILD_SHARED_LIBS;BUILD_STATIC_LIBS"
${BUILD_SHARED_LIBS}
)
+option(QHULL_ENABLE_TESTING "Build and run tests" ON)
if(INCLUDE_INSTALL_DIR)
else()
@@ -147,6 +148,7 @@ message(STATUS "Build Type (CMAKE_BUILD_TYPE): ${CMAKE_BUILD_TYPE}")
message(STATUS "Build static libraries: ${BUILD_STATIC_LIBS}")
message(STATUS "Build shared library: ${BUILD_SHARED_LIBS}")
message(STATUS "Use shared library for linking apps: ${LINK_APPS_SHARED}")
+message(STATUS "Build tests: ${QHULL_ENABLE_TESTING}")
message(STATUS "To override these options, add -D{OPTION_NAME}=... to the cmake command")
message(STATUS " Build the debug targets -DCMAKE_BUILD_TYPE=Debug")
message(STATUS)
@@ -636,32 +638,33 @@ set_target_properties(user_egp PROPERTIES
# ---------------------------------------
# Define test
# ---------------------------------------
-
-enable_testing()
-add_test(NAME testqset
- COMMAND ./testqset 10000)
-add_test(NAME testqset_r
- COMMAND ./testqset_r 10000)
-add_test(NAME smoketest
- COMMAND sh -c "./rbox D4 | ./qhull Tv")
-add_test(NAME rbox-10-qhull
- COMMAND sh -c "./rbox 10 | ./qhull Tv")
-add_test(NAME rbox-10-qconvex
- COMMAND sh -c "./rbox 10 | ./qconvex Tv")
-add_test(NAME rbox-10-qdelaunay
- COMMAND sh -c "./rbox 10 | ./qdelaunay Tv")
-add_test(NAME rbox-10-qhalf
- COMMAND sh -c "./rbox 10 | ./qconvex FQ FV n Tv | ./qhalf Tv")
-add_test(NAME rbox-10-qvoronoi
- COMMAND sh -c "./rbox 10 | ./qvoronoi Tv")
-add_test(NAME user_eg
- COMMAND sh -c "./user_eg")
-add_test(NAME user_eg2
- COMMAND sh -c "./user_eg2")
-
-if(${BUILD_STATIC_LIBS})
- add_test(NAME user_eg3
- COMMAND sh -c "./user_eg3 rbox '10 D2' '2 D2' qhull 's p' facets")
+if (QHULL_ENABLE_TESTING)
+ enable_testing()
+ add_test(NAME testqset
+ COMMAND ./testqset 10000)
+ add_test(NAME testqset_r
+ COMMAND ./testqset_r 10000)
+ add_test(NAME smoketest
+ COMMAND sh -c "./rbox D4 | ./qhull Tv")
+ add_test(NAME rbox-10-qhull
+ COMMAND sh -c "./rbox 10 | ./qhull Tv")
+ add_test(NAME rbox-10-qconvex
+ COMMAND sh -c "./rbox 10 | ./qconvex Tv")
+ add_test(NAME rbox-10-qdelaunay
+ COMMAND sh -c "./rbox 10 | ./qdelaunay Tv")
+ add_test(NAME rbox-10-qhalf
+ COMMAND sh -c "./rbox 10 | ./qconvex FQ FV n Tv | ./qhalf Tv")
+ add_test(NAME rbox-10-qvoronoi
+ COMMAND sh -c "./rbox 10 | ./qvoronoi Tv")
+ add_test(NAME user_eg
+ COMMAND sh -c "./user_eg")
+ add_test(NAME user_eg2
+ COMMAND sh -c "./user_eg2")
+
+ if(${BUILD_STATIC_LIBS})
+ add_test(NAME user_eg3
+ COMMAND sh -c "./user_eg3 rbox '10 D2' '2 D2' qhull 's p' facets")
+ endif()
endif()
# ---------------------------------------
--
2.36.0.512.ge40c2bad7a-goog
+22
View File
@@ -0,0 +1,22 @@
#!/bin/bash
# Copyright 2021 DeepMind Technologies Limited
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
if [ -z "$1" ]; then
echo "Expecting an output directory. Got none." 1>&2
exit 1
fi
mkdir -p "$1"
rm -rf "$1/*"
+30
View File
@@ -0,0 +1,30 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>CFBundleName</key>
<string>MuJoCo</string>
<key>CFBundleIdentifier</key>
<string>org.mujoco.mujoco</string>
<key>CFBundleVersion</key>
<string>${PROJECT_VERSION}</string>
<key>CFBundleGetInfoString</key>
<string>${PROJECT_VERSION}</string>
<key>CFBundleExecutable</key>
<string>libmujoco.dylib</string>
<key>CFBundlePackageType</key>
<string>FMWK</string>
<key>NSHumanReadableCopyright</key>
<string>Copyright 2021 DeepMind Technologies Limited.</string>
<key>MDItemKeywords</key>
<string>MuJoCo, physics engine, physics simulator, physics, MJ</string>
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>CFBundleDevelopmentRegion</key>
<string>en</string>
<key>CFBundleSupportedPlatforms</key>
<array>
<string>MacOSX</string>
</array>
</dict>
</plist>
+36
View File
@@ -0,0 +1,36 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>CFBundleName</key>
<string>${MACOSX_BUNDLE_BUNDLE_NAME}</string>
<key>CFBundleIdentifier</key>
<string>${MACOSX_BUNDLE_GUI_IDENTIFIER}</string>
<key>CFBundleVersion</key>
<string>${MACOSX_BUNDLE_BUNDLE_VERSION}</string>
<key>CFBundleGetInfoString</key>
<string>${MACOSX_BUNDLE_INFO_STRING}</string>
<key>CFBundleLongVersionString</key>
<string>${MACOSX_BUNDLE_LONG_VERSION_STRING}</string>
<key>CFBundleShortVersionString</key>
<string>${MACOSX_BUNDLE_SHORT_VERSION_STRING}</string>
<key>CFBundleExecutable</key>
<string>simulate</string>
<key>CFBundleIconFile</key>
<string>${MACOSX_BUNDLE_ICON_FILE}</string>
<key>CFBundlePackageType</key>
<string>APPL</string>
<key>NSHumanReadableCopyright</key>
<string>${MACOSX_BUNDLE_COPYRIGHT}</string>
<key>MDItemKeywords</key>
<string>MuJoCo, physics engine, physics simulator, physics, simulate, MJ, mujoco simulate, mj simulate</string>
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>CFBundleDevelopmentRegion</key>
<string>en</string>
<key>CFBundleSupportedPlatforms</key>
<array>
<string>MacOSX</string>
</array>
</dict>
</plist>
+1
View File
@@ -0,0 +1 @@
IDI_ICON1 ICON DISCARDABLE "mujoco.ico"
+6
View File
@@ -0,0 +1,6 @@
framework module mujoco {
umbrella header "mujoco.h"
export *
module * { export * }
}
BIN
View File
Binary file not shown.
BIN
View File
Binary file not shown.

After

Width:  |  Height:  |  Size: 27 KiB

+81 -81
View File
@@ -38,7 +38,7 @@ mjtNum
typedef float mjtNum;
#endif
| Defined in `mjtnum.h <https://github.com/deepmind/mujoco/blob/main/include/mjtnum.h>`_
| Defined in `mjtnum.h <https://github.com/deepmind/mujoco/blob/main/include/mujoco/mjtnum.h>`_
| This is the floating-point type used throughout the simulator. If the symbol ``mjUSEDOUBLE`` is defined in
``mjmodel.h``, this type is defined as ``double``, otherwise it is defined as ``float``. Currently only the
@@ -61,7 +61,7 @@ mjtByte
typedef unsigned char mjtByte;
| Defined in `mjmodel.h <https://github.com/deepmind/mujoco/blob/main/include/mjmodel.h>`_
| Defined in `mjmodel.h <https://github.com/deepmind/mujoco/blob/main/include/mujoco/mjmodel.h>`_
| Byte type used to represent boolean variables.
@@ -90,7 +90,7 @@ mjtDisableBit
mjNDISABLE = 12 // number of disable flags
} mjtDisableBit;
| Defined in `mjmodel.h <https://github.com/deepmind/mujoco/blob/main/include/mjmodel.h>`_
| Defined in `mjmodel.h <https://github.com/deepmind/mujoco/blob/main/include/mujoco/mjmodel.h>`_
| Constants which are powers of 2. They are used as bitmasks for the field ``disableflags`` of :ref:`mjOption`.
At runtime this field is ``m->opt.disableflags``. The number of these constants is given by ``mjNDISABLE`` which is
@@ -117,7 +117,7 @@ mjtEnableBit
mjNENABLE = 5 // number of enable flags
} mjtEnableBit;
| Defined in `mjmodel.h <https://github.com/deepmind/mujoco/blob/main/include/mjmodel.h>`_
| Defined in `mjmodel.h <https://github.com/deepmind/mujoco/blob/main/include/mujoco/mjmodel.h>`_
| Constants which are powers of 2. They are used as bitmasks for the field ``enableflags`` of :ref:`mjOption`.
At runtime this field is ``m->opt.enableflags``. The number of these constants is given by ``mjNENABLE`` which is also
@@ -138,7 +138,7 @@ mjtJoint
mjJNT_HINGE // rotation angle (rad) around body-fixed axis (1)
} mjtJoint;
| Defined in `mjmodel.h <https://github.com/deepmind/mujoco/blob/main/include/mjmodel.h>`_
| Defined in `mjmodel.h <https://github.com/deepmind/mujoco/blob/main/include/mujoco/mjmodel.h>`_
| Primitive joint types. These values are used in ``m->jnt_type``. The numbers in the comments indicate how many
positional coordinates each joint type has. Note that ball joints and rotational components of free joints are
@@ -176,7 +176,7 @@ mjtGeom
mjGEOM_NONE = 1001 // missing geom type
} mjtGeom;
| Defined in `mjmodel.h <https://github.com/deepmind/mujoco/blob/main/include/mjmodel.h>`_
| Defined in `mjmodel.h <https://github.com/deepmind/mujoco/blob/main/include/mujoco/mjmodel.h>`_
| Geometric types supported by MuJoCo. The first group are "official" geom types that can be used in the model. The
second group are geom types that cannot be used in the model but are used by the visualizer to add decorative
@@ -198,7 +198,7 @@ mjtCamLight
mjCAMLIGHT_TARGETBODYCOM // pos fixed in body, rot tracks target subtree com
} mjtCamLight;
| Defined in `mjmodel.h <https://github.com/deepmind/mujoco/blob/main/include/mjmodel.h>`_
| Defined in `mjmodel.h <https://github.com/deepmind/mujoco/blob/main/include/mujoco/mjmodel.h>`_
| Dynamic modes for cameras and lights, specifying how the camera/light position and orientation are computed. These
values are used in ``m->cam_mode`` and ``m->light_mode``.
@@ -217,7 +217,7 @@ mjtTexture
mjTEXTURE_SKYBOX // cube texture used as skybox
} mjtTexture;
| Defined in `mjmodel.h <https://github.com/deepmind/mujoco/blob/main/include/mjmodel.h>`_
| Defined in `mjmodel.h <https://github.com/deepmind/mujoco/blob/main/include/mujoco/mjmodel.h>`_
| Texture types, specifying how the texture will be mapped. These values are used in ``m->tex_type``.
@@ -234,7 +234,7 @@ mjtIntegrator
mjINT_RK4 // 4th-order Runge Kutta
} mjtIntegrator;
| Defined in `mjmodel.h <https://github.com/deepmind/mujoco/blob/main/include/mjmodel.h>`_
| Defined in `mjmodel.h <https://github.com/deepmind/mujoco/blob/main/include/mujoco/mjmodel.h>`_
| Numerical integrator types. These values are used in ``m->opt.integrator``.
@@ -252,7 +252,7 @@ mjtCollision
mjCOL_DYNAMIC // test dynamic pairs only
} mjtCollision;
| Defined in `mjmodel.h <https://github.com/deepmind/mujoco/blob/main/include/mjmodel.h>`_
| Defined in `mjmodel.h <https://github.com/deepmind/mujoco/blob/main/include/mujoco/mjmodel.h>`_
| Collision modes specifying how candidate geom pairs are generated for near-phase collision checking. These values are
used in ``m->opt.collision``.
@@ -270,7 +270,7 @@ mjtCone
mjCONE_ELLIPTIC // elliptic
} mjtCone;
| Defined in `mjmodel.h <https://github.com/deepmind/mujoco/blob/main/include/mjmodel.h>`_
| Defined in `mjmodel.h <https://github.com/deepmind/mujoco/blob/main/include/mujoco/mjmodel.h>`_
| Available friction cone types. These values are used in ``m->opt.cone``.
@@ -288,7 +288,7 @@ mjtJacobian
mjJAC_AUTO // dense if nv<=60, sparse otherwise
} mjtJacobian;
| Defined in `mjmodel.h <https://github.com/deepmind/mujoco/blob/main/include/mjmodel.h>`_
| Defined in `mjmodel.h <https://github.com/deepmind/mujoco/blob/main/include/mujoco/mjmodel.h>`_
| Available Jacobian types. These values are used in ``m->opt.jacobian``.
@@ -306,7 +306,7 @@ mjtSolver
mjSOL_NEWTON // Newton (primal)
} mjtSolver;
| Defined in `mjmodel.h <https://github.com/deepmind/mujoco/blob/main/include/mjmodel.h>`_
| Defined in `mjmodel.h <https://github.com/deepmind/mujoco/blob/main/include/mujoco/mjmodel.h>`_
| Available constraint solver algorithms. These values are used in ``m->opt.solver``.
@@ -326,7 +326,7 @@ mjtEq
mjEQ_DISTANCE // fix the contact distance betweent two geoms
} mjtEq;
| Defined in `mjmodel.h <https://github.com/deepmind/mujoco/blob/main/include/mjmodel.h>`_
| Defined in `mjmodel.h <https://github.com/deepmind/mujoco/blob/main/include/mujoco/mjmodel.h>`_
| Equality constraint types. These values are used in ``m->eq_type``.
@@ -347,7 +347,7 @@ mjtWrap
mjWRAP_CYLINDER // wrap around (infinite) cylinder
} mjtWrap;
| Defined in `mjmodel.h <https://github.com/deepmind/mujoco/blob/main/include/mjmodel.h>`_
| Defined in `mjmodel.h <https://github.com/deepmind/mujoco/blob/main/include/mujoco/mjmodel.h>`_
| Tendon wrapping object types. These values are used in ``m->wrap_type``.
@@ -369,7 +369,7 @@ mjtTrn
mjTRN_UNDEFINED = 1000 // undefined transmission type
} mjtTrn;
| Defined in `mjmodel.h <https://github.com/deepmind/mujoco/blob/main/include/mjmodel.h>`_
| Defined in `mjmodel.h <https://github.com/deepmind/mujoco/blob/main/include/mujoco/mjmodel.h>`_
| Actuator transmission types. These values are used in ``m->actuator_trntype``.
@@ -389,7 +389,7 @@ mjtDyn
mjDYN_USER // user-defined dynamics type
} mjtDyn;
| Defined in `mjmodel.h <https://github.com/deepmind/mujoco/blob/main/include/mjmodel.h>`_
| Defined in `mjmodel.h <https://github.com/deepmind/mujoco/blob/main/include/mujoco/mjmodel.h>`_
| Actuator dynamics types. These values are used in ``m->actuator_dyntype``.
@@ -407,7 +407,7 @@ mjtGain
mjGAIN_USER // user-defined gain type
} mjtGain;
| Defined in `mjmodel.h <https://github.com/deepmind/mujoco/blob/main/include/mjmodel.h>`_
| Defined in `mjmodel.h <https://github.com/deepmind/mujoco/blob/main/include/mujoco/mjmodel.h>`_
| Actuator gain types. These values are used in ``m->actuator_gaintype``.
@@ -426,7 +426,7 @@ mjtBias
mjBIAS_USER // user-defined bias type
} mjtBias;
| Defined in `mjmodel.h <https://github.com/deepmind/mujoco/blob/main/include/mjmodel.h>`_
| Defined in `mjmodel.h <https://github.com/deepmind/mujoco/blob/main/include/mujoco/mjmodel.h>`_
| Actuator bias types. These values are used in ``m->actuator_biastype``.
@@ -465,7 +465,7 @@ mjtObj
mjOBJ_KEY // keyframe
} mjtObj;
| Defined in `mjmodel.h <https://github.com/deepmind/mujoco/blob/main/include/mjmodel.h>`_
| Defined in `mjmodel.h <https://github.com/deepmind/mujoco/blob/main/include/mujoco/mjmodel.h>`_
| MuJoCo object types. These values are used in the support functions :ref:`mj_name2id` and
:ref:`mj_id2name` to convert between object names and integer ids.
@@ -489,7 +489,7 @@ mjtConstraint
mjCNSTR_CONTACT_ELLIPTIC // frictional contact, elliptic friction cone
} mjtConstraint;
| Defined in `mjmodel.h <https://github.com/deepmind/mujoco/blob/main/include/mjmodel.h>`_
| Defined in `mjmodel.h <https://github.com/deepmind/mujoco/blob/main/include/mujoco/mjmodel.h>`_
| Constraint types. These values are not used in mjModel, but are used in the mjData field ``d->efc_type`` when the list
of active constraints is constructed at each simulation time step.
@@ -510,7 +510,7 @@ mjtConstraintState
mjCNSTRSTATE_CONE // squared distance to cone cost (elliptic contact)
} mjtConstraintState;
| Defined in `mjmodel.h <https://github.com/deepmind/mujoco/blob/main/include/mjmodel.h>`_
| Defined in `mjmodel.h <https://github.com/deepmind/mujoco/blob/main/include/mujoco/mjmodel.h>`_
| These values are used by the solver internally to keep track of the constraint states.
@@ -574,7 +574,7 @@ mjtSensor
mjSENS_USER // sensor data provided by mjcb_sensor callback
} mjtSensor;
| Defined in `mjmodel.h <https://github.com/deepmind/mujoco/blob/main/include/mjmodel.h>`_
| Defined in `mjmodel.h <https://github.com/deepmind/mujoco/blob/main/include/mujoco/mjmodel.h>`_
| Sensor types. These values are used in ``m->sensor_type``.
@@ -593,7 +593,7 @@ mjtStage
mjSTAGE_ACC // acceleration/force-dependent computations
} mjtStage;
| Defined in `mjmodel.h <https://github.com/deepmind/mujoco/blob/main/include/mjmodel.h>`_
| Defined in `mjmodel.h <https://github.com/deepmind/mujoco/blob/main/include/mujoco/mjmodel.h>`_
| These are the compute stages for the skipstage parameters of :ref:`mj_forwardSkip` and
:ref:`mj_inverseSkip`.
@@ -613,7 +613,7 @@ mjtDataType
mjDATATYPE_QUATERNION // unit quaternion
} mjtDataType;
| Defined in `mjmodel.h <https://github.com/deepmind/mujoco/blob/main/include/mjmodel.h>`_
| Defined in `mjmodel.h <https://github.com/deepmind/mujoco/blob/main/include/mujoco/mjmodel.h>`_
| These are the possible sensor data types, used in ``mjData.sensor_datatype``.
@@ -638,7 +638,7 @@ mjtWarning
mjNWARNING // number of warnings
} mjtWarning;
| Defined in `mjdata.h <https://github.com/deepmind/mujoco/blob/main/include/mjdata.h>`_
| Defined in `mjdata.h <https://github.com/deepmind/mujoco/blob/main/include/mujoco/mjdata.h>`_
| Warning types. The number of warning types is given by ``mjNWARNING`` which is also the length of the array
``mjData.warning``.
@@ -674,7 +674,7 @@ mjtTimer
mjNTIMER // number of timers
} mjtTimer;
| Defined in `mjdata.h <https://github.com/deepmind/mujoco/blob/main/include/mjdata.h>`_
| Defined in `mjdata.h <https://github.com/deepmind/mujoco/blob/main/include/mujoco/mjdata.h>`_
| Timer types. The number of timer types is given by ``mjNTIMER`` which is also the length of the array
``mjData.timer``, as well as the length of the string array :ref:`mjTIMERSTRING` with timer names.
@@ -694,7 +694,7 @@ mjtCatBit
mjCAT_ALL = 7 // select all categories
} mjtCatBit;
| Defined in `mjvisualize.h <https://github.com/deepmind/mujoco/blob/main/include/mjvisualize.h>`_
| Defined in `mjvisualize.h <https://github.com/deepmind/mujoco/blob/main/include/mujoco/mjvisualize.h>`_
| These are the available categories of geoms in the abstract visualizer. The bitmask can be used in the function
:ref:`mjr_render` to specify which categories should be rendered.
@@ -717,7 +717,7 @@ mjtMouse
mjMOUSE_SELECT // selection
} mjtMouse;
| Defined in `mjvisualize.h <https://github.com/deepmind/mujoco/blob/main/include/mjvisualize.h>`_
| Defined in `mjvisualize.h <https://github.com/deepmind/mujoco/blob/main/include/mujoco/mjvisualize.h>`_
| These are the mouse actions that the abstract visualizer recognizes. It is up to the user to intercept mouse events
and translate them into these actions, as illustrated in ``simulate.cc``.
@@ -735,7 +735,7 @@ mjtPertBit
mjPERT_ROTATE = 2 // rotation
} mjtPertBit;
| Defined in `mjvisualize.h <https://github.com/deepmind/mujoco/blob/main/include/mjvisualize.h>`_
| Defined in `mjvisualize.h <https://github.com/deepmind/mujoco/blob/main/include/mujoco/mjvisualize.h>`_
| These bitmasks enable the translational and rotational components of the mouse perturbation. For the regular mouse,
only one can be enabled at a time. For the 3D mouse (SpaceNavigator) both can be enabled simultaneously. They are used
@@ -756,7 +756,7 @@ mjtCamera
mjCAMERA_USER // user is responsible for setting OpenGL camera
} mjtCamera;
| Defined in `mjvisualize.h <https://github.com/deepmind/mujoco/blob/main/include/mjvisualize.h>`_
| Defined in `mjvisualize.h <https://github.com/deepmind/mujoco/blob/main/include/mujoco/mjvisualize.h>`_
| These are the possible camera types, used in ``mjvCamera.type``.
@@ -787,7 +787,7 @@ mjtLabel
mjNLABEL // number of label types
} mjtLabel;
| Defined in `mjvisualize.h <https://github.com/deepmind/mujoco/blob/main/include/mjvisualize.h>`_
| Defined in `mjvisualize.h <https://github.com/deepmind/mujoco/blob/main/include/mujoco/mjvisualize.h>`_
| These are the abstract visualization elements that can have text labels. Used in ``mjvOption.label``.
@@ -811,7 +811,7 @@ mjtFrame
mjNFRAME // number of visualization frames
} mjtFrame;
| Defined in `mjvisualize.h <https://github.com/deepmind/mujoco/blob/main/include/mjvisualize.h>`_
| Defined in `mjvisualize.h <https://github.com/deepmind/mujoco/blob/main/include/mujoco/mjvisualize.h>`_
| These are the MuJoCo objects whose spatial frames can be rendered. Used in ``mjvOption.frame``.
@@ -850,7 +850,7 @@ mjtVisFlag
mjNVISFLAG // number of visualization flags
} mjtVisFlag;
| Defined in `mjvisualize.h <https://github.com/deepmind/mujoco/blob/main/include/mjvisualize.h>`_
| Defined in `mjvisualize.h <https://github.com/deepmind/mujoco/blob/main/include/mujoco/mjvisualize.h>`_
| These are indices in the array ``mjvOption.flags``, whose elements enable/disable the visualization of the
corresponding model or decoration element.
@@ -877,7 +877,7 @@ mjtRndFlag
mjNRNDFLAG // number of rendering flags
} mjtRndFlag;
| Defined in `mjvisualize.h <https://github.com/deepmind/mujoco/blob/main/include/mjvisualize.h>`_
| Defined in `mjvisualize.h <https://github.com/deepmind/mujoco/blob/main/include/mujoco/mjvisualize.h>`_
| These are indices in the array ``mjvScene.flags``, whose elements enable/disable OpenGL rendering effects.
@@ -895,7 +895,7 @@ mjtStereo
mjSTEREO_SIDEBYSIDE // side-by-side
} mjtStereo;
| Defined in `mjvisualize.h <https://github.com/deepmind/mujoco/blob/main/include/mjvisualize.h>`_
| Defined in `mjvisualize.h <https://github.com/deepmind/mujoco/blob/main/include/mujoco/mjvisualize.h>`_
| These are the possible stereo rendering types. They are used in ``mjvScene.stereo``.
@@ -914,7 +914,7 @@ mjtGridPos
mjGRID_BOTTOMRIGHT // bottom right
} mjtGridPos;
| Defined in `mjrender.h <https://github.com/deepmind/mujoco/blob/main/include/mjrender.h>`_
| Defined in `mjrender.h <https://github.com/deepmind/mujoco/blob/main/include/mujoco/mjrender.h>`_
| These are the possible grid positions for text overlays. They are used as an argument to the function
:ref:`mjr_overlay`.
@@ -932,7 +932,7 @@ mjtFramebuffer
mjFB_OFFSCREEN // offscreen buffer
} mjtFramebuffer;
| Defined in `mjrender.h <https://github.com/deepmind/mujoco/blob/main/include/mjrender.h>`_
| Defined in `mjrender.h <https://github.com/deepmind/mujoco/blob/main/include/mujoco/mjrender.h>`_
| These are the possible framebuffers. They are used as an argument to the function :ref:`mjr_setBuffer`.
@@ -953,7 +953,7 @@ mjtFontScale
mjFONTSCALE_300 = 300 // 300% scale
} mjtFontScale;
| Defined in `mjrender.h <https://github.com/deepmind/mujoco/blob/main/include/mjrender.h>`_
| Defined in `mjrender.h <https://github.com/deepmind/mujoco/blob/main/include/mujoco/mjrender.h>`_
| These are the possible font sizes. The fonts are predefined bitmaps stored in the dynamic library at three different
sizes.
@@ -972,7 +972,7 @@ mjtFont
mjFONT_BIG // big font (for user alerts)
} mjtFont;
| Defined in `mjrender.h <https://github.com/deepmind/mujoco/blob/main/include/mjrender.h>`_
| Defined in `mjrender.h <https://github.com/deepmind/mujoco/blob/main/include/mujoco/mjrender.h>`_
| These are the possible font types.
@@ -991,7 +991,7 @@ mjtButton
mjBUTTON_MIDDLE // middle button
} mjtButton;
| Defined in `mjui.h <https://github.com/deepmind/mujoco/blob/main/include/mjui.h>`_
| Defined in `mjui.h <https://github.com/deepmind/mujoco/blob/main/include/mujoco/mjui.h>`_
| Mouse button IDs used in the UI framework.
@@ -1013,7 +1013,7 @@ mjtEvent
mjEVENT_RESIZE // resize
} mjtEvent;
| Defined in `mjui.h <https://github.com/deepmind/mujoco/blob/main/include/mjui.h>`_
| Defined in `mjui.h <https://github.com/deepmind/mujoco/blob/main/include/mujoco/mjui.h>`_
| Event types used in the UI framework.
@@ -1046,7 +1046,7 @@ mjtItem
mjNITEM // number of item types
} mjtItem;
| Defined in `mjui.h <https://github.com/deepmind/mujoco/blob/main/include/mjui.h>`_
| Defined in `mjui.h <https://github.com/deepmind/mujoco/blob/main/include/mujoco/mjui.h>`_
| Item types used in the UI framework.
@@ -1055,8 +1055,8 @@ mjtItem
Function types
^^^^^^^^^^^^^^
MuJoCo callbacks have corresponding function types. They are defined in `mjdata.h <https://github.com/deepmind/mujoco/blob/main/include/mjdata.h>`_ and in
`mjui.h <https://github.com/deepmind/mujoco/blob/main/include/mjui.h>`_. The actual callback functions are documented later.
MuJoCo callbacks have corresponding function types. They are defined in `mjdata.h <https://github.com/deepmind/mujoco/blob/main/include/mujoco/mjdata.h>`_ and in
`mjui.h <https://github.com/deepmind/mujoco/blob/main/include/mujoco/mjui.h>`_. The actual callback functions are documented later.
.. _mjfGeneric:
@@ -1163,7 +1163,7 @@ mjVFS
};
typedef struct _mjVFS mjVFS;
| Defined in `mjmodel.h <https://github.com/deepmind/mujoco/blob/main/include/mjmodel.h>`_
| Defined in `mjmodel.h <https://github.com/deepmind/mujoco/blob/main/include/mujoco/mjmodel.h>`_
| This is the data structure with the virtual file system. It can only be constructed programmatically, and does not
have an analog in MJCF.
@@ -1213,7 +1213,7 @@ mjOption
};
typedef struct _mjOption mjOption;
| Defined in `mjmodel.h <https://github.com/deepmind/mujoco/blob/main/include/mjmodel.h>`_
| Defined in `mjmodel.h <https://github.com/deepmind/mujoco/blob/main/include/mujoco/mjmodel.h>`_
| This is the data structure with simulation options. It corresponds to the MJCF element
:ref:`option <option>`. One instance of it is embedded in mjModel.
@@ -1319,7 +1319,7 @@ mjVisual
};
typedef struct _mjVisual mjVisual;
| Defined in `mjmodel.h <https://github.com/deepmind/mujoco/blob/main/include/mjmodel.h>`_
| Defined in `mjmodel.h <https://github.com/deepmind/mujoco/blob/main/include/mujoco/mjmodel.h>`_
| This is the data structure with abstract visualization options. It corresponds to the MJCF element
:ref:`visual <visual>`. One instance of it is embedded in mjModel.
@@ -1341,7 +1341,7 @@ mjStatistic
};
typedef struct _mjStatistic mjStatistic;
| Defined in `mjmodel.h <https://github.com/deepmind/mujoco/blob/main/include/mjmodel.h>`_
| Defined in `mjmodel.h <https://github.com/deepmind/mujoco/blob/main/include/mujoco/mjmodel.h>`_
| This is the data structure with model statistics precomputed by the compiler or set by the user. It corresponds to the
MJCF element :ref:`statistic <statistic>`. One instance of it is embedded in mjModel.
@@ -1751,7 +1751,7 @@ mjModel
};
typedef struct _mjModel mjModel;
| Defined in `mjmodel.h <https://github.com/deepmind/mujoco/blob/main/include/mjmodel.h>`_
| Defined in `mjmodel.h <https://github.com/deepmind/mujoco/blob/main/include/mujoco/mjmodel.h>`_
| This is the main data structure holding the MuJoCo model. It is treated as constant by the simulator.
@@ -1792,7 +1792,7 @@ mjContact
};
typedef struct _mjContact mjContact;
| Defined in `mjdata.h <https://github.com/deepmind/mujoco/blob/main/include/mjdata.h>`_
| Defined in `mjdata.h <https://github.com/deepmind/mujoco/blob/main/include/mujoco/mjdata.h>`_
| This is the data structure holding information about one contact. ``mjData.contact`` is a preallocated array of
mjContact data structures, populated at runtime with the contacts found by the collision detector. Additional contact
@@ -1812,7 +1812,7 @@ mjWarningStat
};
typedef struct _mjWarningStat mjWarningStat;
| Defined in `mjdata.h <https://github.com/deepmind/mujoco/blob/main/include/mjdata.h>`_
| Defined in `mjdata.h <https://github.com/deepmind/mujoco/blob/main/include/mujoco/mjdata.h>`_
| This is the data structure holding information about one warning type. ``mjData.warning`` is a preallocated array of
mjWarningStat data structures, one for each warning type.
@@ -1831,7 +1831,7 @@ mjTimerStat
};
typedef struct _mjTimerStat mjTimerStat;
| Defined in `mjdata.h <https://github.com/deepmind/mujoco/blob/main/include/mjdata.h>`_
| Defined in `mjdata.h <https://github.com/deepmind/mujoco/blob/main/include/mujoco/mjdata.h>`_
| This is the data structure holding information about one timer. ``mjData.timer`` is a preallocated array of
mjTimerStat data structures, one for each timer type.
@@ -1855,7 +1855,7 @@ mjSolverStat
};
typedef struct _mjSolverStat mjSolverStat;
| Defined in `mjdata.h <https://github.com/deepmind/mujoco/blob/main/include/mjdata.h>`_
| Defined in `mjdata.h <https://github.com/deepmind/mujoco/blob/main/include/mujoco/mjdata.h>`_
| This is the data structure holding information about one solver iteration. ``mjData.solver`` is a preallocated array
of mjSolverStat data structures, one for each iteration of the solver, up to a maximum of mjNSOLVER. The actual number
@@ -2042,11 +2042,11 @@ mjData
mjtNum* qfrc_actuator; // actuator force (nv x 1)
// computed by mj_fwdAcceleration
mjtNum* qfrc_unc; // net unconstrained force (nv x 1)
mjtNum* qacc_unc; // unconstrained acceleration (nv x 1)
mjtNum* qfrc_smooth; // net unconstrained force (nv x 1)
mjtNum* qacc_smooth; // unconstrained acceleration (nv x 1)
// computed by mj_fwdConstraint/mj_inverse
mjtNum* efc_b; // linear cost term: J*qacc_unc - aref (njmax x 1)
mjtNum* efc_b; // linear cost term: J*qacc_smooth - aref (njmax x 1)
mjtNum* efc_force; // constraint force in constraint space (njmax x 1)
int* efc_state; // constraint state (mjtConstraintState) (njmax x 1)
mjtNum* qfrc_constraint; // constraint force (nv x 1)
@@ -2062,7 +2062,7 @@ mjData
};
typedef struct _mjData mjData;
| Defined in `mjdata.h <https://github.com/deepmind/mujoco/blob/main/include/mjdata.h>`_
| Defined in `mjdata.h <https://github.com/deepmind/mujoco/blob/main/include/mujoco/mjdata.h>`_
| This is the main data structure holding the simulation state. It is the workspace where all functions read their
modifiable inputs and write their outputs.
@@ -2086,7 +2086,7 @@ mjvPerturb
};
typedef struct _mjvPerturb mjvPerturb;
| Defined in `mjvisualize.h <https://github.com/deepmind/mujoco/blob/main/include/mjvisualize.h>`_
| Defined in `mjvisualize.h <https://github.com/deepmind/mujoco/blob/main/include/mujoco/mjvisualize.h>`_
| This is the data structure holding information about mouse perturbations.
@@ -2112,7 +2112,7 @@ mjvCamera
};
typedef struct _mjvCamera mjvCamera;
| Defined in `mjvisualize.h <https://github.com/deepmind/mujoco/blob/main/include/mjvisualize.h>`_
| Defined in `mjvisualize.h <https://github.com/deepmind/mujoco/blob/main/include/mujoco/mjvisualize.h>`_
| This is the data structure describing one abstract camera.
@@ -2139,7 +2139,7 @@ mjvGLCamera
};
typedef struct _mjvGLCamera mjvGLCamera;
| Defined in `mjvisualize.h <https://github.com/deepmind/mujoco/blob/main/include/mjvisualize.h>`_
| Defined in `mjvisualize.h <https://github.com/deepmind/mujoco/blob/main/include/mujoco/mjvisualize.h>`_
| This is the data structure describing one OpenGL camera.
@@ -2182,7 +2182,7 @@ mjvGeom
};
typedef struct _mjvGeom mjvGeom;
| Defined in `mjvisualize.h <https://github.com/deepmind/mujoco/blob/main/include/mjvisualize.h>`_
| Defined in `mjvisualize.h <https://github.com/deepmind/mujoco/blob/main/include/mujoco/mjvisualize.h>`_
| This is the data structure describing one abstract visualization geom - which could correspond to a model geom or to a
decoration element constructed by the visualizer.
@@ -2210,7 +2210,7 @@ mjvLight
};
typedef struct _mjvLight mjvLight;
| Defined in `mjvisualize.h <https://github.com/deepmind/mujoco/blob/main/include/mjvisualize.h>`_
| Defined in `mjvisualize.h <https://github.com/deepmind/mujoco/blob/main/include/mujoco/mjvisualize.h>`_
| This is the data structure describing one OpenGL light.
@@ -2234,7 +2234,7 @@ mjvOption
};
typedef struct _mjvOption mjvOption;
| Defined in `mjvisualize.h <https://github.com/deepmind/mujoco/blob/main/include/mjvisualize.h>`_
| Defined in `mjvisualize.h <https://github.com/deepmind/mujoco/blob/main/include/mujoco/mjvisualize.h>`_
| This structure contains options that enable and disable the visualization of various elements.
@@ -2280,7 +2280,7 @@ mjvScene
};
typedef struct _mjvScene mjvScene;
| Defined in `mjvisualize.h <https://github.com/deepmind/mujoco/blob/main/include/mjvisualize.h>`_
| Defined in `mjvisualize.h <https://github.com/deepmind/mujoco/blob/main/include/mujoco/mjvisualize.h>`_
| This structure contains everything needed to render the 3D scene in OpenGL.
@@ -2334,7 +2334,7 @@ mjvFigure
};
typedef struct _mjvFigure mjvFigure;
| Defined in `mjvisualize.h <https://github.com/deepmind/mujoco/blob/main/include/mjvisualize.h>`_
| Defined in `mjvisualize.h <https://github.com/deepmind/mujoco/blob/main/include/mujoco/mjvisualize.h>`_
| This structure contains everything needed to render a 2D plot in OpenGL. The buffers for line points etc. are
preallocated, and the user has to populate them before calling the function :ref:`mjr_figure` with this
@@ -2356,7 +2356,7 @@ mjrRect
};
typedef struct _mjrRect mjrRect;
| Defined in `mjrender.h (57) <https://github.com/deepmind/mujoco/blob/main/include/mjrender.h#L57>`_
| Defined in `mjrender.h (57) <https://github.com/deepmind/mujoco/blob/main/include/mujoco/mjrender.h#L57>`_
| This structure specifies a rectangle.
@@ -2451,7 +2451,7 @@ mjrContext
};
typedef struct _mjrContext mjrContext;
| Defined in `mjrender.h (67) <https://github.com/deepmind/mujoco/blob/main/include/mjrender.h#L67>`_
| Defined in `mjrender.h (67) <https://github.com/deepmind/mujoco/blob/main/include/mujoco/mjrender.h#L67>`_
| This structure contains the custom OpenGL rendering context, with the ids of all OpenGL resources uploaded to the GPU.
@@ -2502,7 +2502,7 @@ mjuiState
};
typedef struct _mjuiState mjuiState;
| Defined in `mjui.h <https://github.com/deepmind/mujoco/blob/main/include/mjui.h>`_
| Defined in `mjui.h <https://github.com/deepmind/mujoco/blob/main/include/mujoco/mjui.h>`_
| This structure contains the keyboard and mouse state used by the UI framework.
@@ -2529,7 +2529,7 @@ mjuiThemeSpacing
};
typedef struct _mjuiThemeSpacing mjuiThemeSpacing;
| Defined in `mjui.h <https://github.com/deepmind/mujoco/blob/main/include/mjui.h>`_
| Defined in `mjui.h <https://github.com/deepmind/mujoco/blob/main/include/mujoco/mjui.h>`_
| This structure defines the spacing of UI items in the theme.
@@ -2566,7 +2566,7 @@ mjuiThemeColor
};
typedef struct _mjuiThemeColor mjuiThemeColor;
| Defined in `mjui.h <https://github.com/deepmind/mujoco/blob/main/include/mjui.h>`_
| Defined in `mjui.h <https://github.com/deepmind/mujoco/blob/main/include/mujoco/mjui.h>`_
| This structure defines the colors of UI items in the theme.
@@ -2624,7 +2624,7 @@ mjuiItem
};
typedef struct _mjuiItem mjuiItem;
| Defined in `mjui.h <https://github.com/deepmind/mujoco/blob/main/include/mjui.h>`_
| Defined in `mjui.h <https://github.com/deepmind/mujoco/blob/main/include/mujoco/mjui.h>`_
| This structure defines one UI item.
@@ -2651,7 +2651,7 @@ mjuiSection
};
typedef struct _mjuiSection mjuiSection;
| Defined in `mjui.h <https://github.com/deepmind/mujoco/blob/main/include/mjui.h>`_
| Defined in `mjui.h <https://github.com/deepmind/mujoco/blob/main/include/mujoco/mjui.h>`_
| This structure defines one section of the UI.
@@ -2698,7 +2698,7 @@ mjUI
};
typedef struct _mjUI mjUI;
| Defined in `mjui.h <https://github.com/deepmind/mujoco/blob/main/include/mjui.h>`_
| Defined in `mjui.h <https://github.com/deepmind/mujoco/blob/main/include/mujoco/mjui.h>`_
| This structure defines the entire UI.
@@ -2719,7 +2719,7 @@ mjuiDef
};
typedef struct _mjuiDef mjuiDef;
| Defined in `mjui.h <https://github.com/deepmind/mujoco/blob/main/include/mjui.h>`_
| Defined in `mjui.h <https://github.com/deepmind/mujoco/blob/main/include/mujoco/mjui.h>`_
| This structure defines one entry in the definition table used for simplified UI construction.
@@ -2730,7 +2730,7 @@ X Macros
The X Macros are not needed in most user projects. They are used internally to allocate the model, and are also
available for users who know how to use this programming technique. See the header file
`mjxmacro.h <https://github.com/deepmind/mujoco/blob/main/include/mjxmacro.h>`_ for the actual definitions. They are particularly useful in writing MuJoCo wrappers
`mjxmacro.h <https://github.com/deepmind/mujoco/blob/main/include/mujoco/mjxmacro.h>`_ for the actual definitions. They are particularly useful in writing MuJoCo wrappers
for scripting languages, where dynamic structures matching the MuJoCo data structures need to be constructed
programmatically.
@@ -3231,7 +3231,7 @@ Numeric constants
API functions
-------------
The main header `mujoco.h <https://github.com/deepmind/mujoco/blob/main/include/mujoco.h>`_ exposes a very large number
The main header `mujoco.h <https://github.com/deepmind/mujoco/blob/main/include/mujoco/mujoco.h>`_ exposes a very large number
of functions. However the functions that most users are likely to need are a small fraction. For example,
``simulate.cc`` which is as elaborate as a MuJoCo application is likely to get, calls around 40 of these functions,
while ``basic.cc`` calls around 20. The rest are explosed just in case someone has a use for them. This includes us as
@@ -3852,7 +3852,7 @@ mj_fwdActuation
void mj_fwdActuation(const mjModel* m, mjData* d);
Compute actuator force qfrc_actuation.
Compute actuator force qfrc_actuator.
.. _mj_fwdAcceleration:
@@ -3863,7 +3863,7 @@ mj_fwdAcceleration
void mj_fwdAcceleration(const mjModel* m, mjData* d);
Add up all non-constraint forces, compute qacc_unc.
Add up all non-constraint forces, compute qacc_smooth.
.. _mj_fwdConstraint:
@@ -6118,7 +6118,7 @@ mju_mulQuat
void mju_mulQuat(mjtNum res[4], const mjtNum quat1[4], const mjtNum quat2[4]);
Muiltiply quaternions.
Multiply quaternions.
.. _mju_mulQuatAxis:
@@ -6129,7 +6129,7 @@ mju_mulQuatAxis
void mju_mulQuatAxis(mjtNum res[4], const mjtNum quat[4], const mjtNum axis[3]);
Muiltiply quaternion and axis.
Multiply quaternion and axis.
.. _mju_axisAngle2Quat:
+130 -116
View File
@@ -12,10 +12,10 @@ This chapter is the reference manual for the MJCF modeling language used in MuJo
XML schema
~~~~~~~~~~
| The table below summarizes the XML elements and their attributes in MJCF. It is generated automatically with the
function :ref:`mj_printSchema` which prints out the custom schema used by the parser to validate the model file.
Note that all information in MJCF is entered through elements and attributes. Text content in elements is not used;
if present, the parser ignores it. The symbols in the second column of the table have the following meaning:
The table below summarizes the XML elements and their attributes in MJCF. It is generated automatically with the
function :ref:`mj_printSchema` which prints out the custom schema used by the parser to validate the model file.
Note that all information in MJCF is entered through elements and attributes. Text content in elements is not used;
if present, the parser ignores it. The symbols in the second column of the table have the following meaning:
====== ===================================================
**!** required element, can appear only once
@@ -24,8 +24,6 @@ XML schema
**R** optional element, can appear many times recursively
====== ===================================================
|
+--------------------------+----+------------------------------------------------------------------------------------+
| :el:`mujoco` | ! | .. table:: |
| | | :class: mjcf-attributes |
@@ -355,15 +353,17 @@ XML schema
| | | :class: mjcf-attributes |
| | | |
| | | +-------------------------+-------------------------+-------------------------+ |
| | | | :at:`ctrllimited` | :at:`forcelimited` | :at:`ctrlrange` | |
| | | | :at:`ctrllimited` | :at:`forcelimited` | :at:`actlimited` | |
| | | +-------------------------+-------------------------+-------------------------+ |
| | | | :at:`forcerange` | :at:`gear` | :at:`cranklength` | |
| | | | :at:`ctrlrange` | :at:`forcerange` | :at:`actrange` | |
| | | +-------------------------+-------------------------+-------------------------+ |
| | | | :at:`user` | :at:`group` | :at:`dyntype` | |
| | | | :at:`gear` | :at:`cranklength` | | |
| | | +-------------------------+-------------------------+-------------------------+ |
| | | | :at:`gaintype` | :at:`biastype` | :at:`dynprm` | |
| | | | :at:`user` | :at:`group` | | |
| | | +-------------------------+-------------------------+-------------------------+ |
| | | | :at:`gainprm` | :at:`biasprm` | | |
| | | | :at:`dyntype` | :at:`gaintype` | :at:`biastype` | |
| | | +-------------------------+-------------------------+-------------------------+ |
| | | | :at:`dynprm` | :at:`gainprm` | :at:`biasprm` | |
| | | +-------------------------+-------------------------+-------------------------+ |
+--------------------------+----+------------------------------------------------------------------------------------+
| |_2|:el:`motor` | ? | .. table:: |
@@ -891,19 +891,21 @@ XML schema
| | | +-------------------------+-------------------------+-------------------------+ |
| | | | :at:`name` | :at:`class` | :at:`group` | |
| | | +-------------------------+-------------------------+-------------------------+ |
| | | | :at:`ctrllimited` | :at:`forcelimited` | :at:`ctrlrange` | |
| | | | :at:`ctrllimited` | :at:`forcelimited` | :at:`actlimited` | |
| | | +-------------------------+-------------------------+-------------------------+ |
| | | | :at:`forcerange` | :at:`lengthrange` | :at:`gear` | |
| | | | :at:`ctrlrange` | :at:`forcerange` | :at:`actrange` | |
| | | +-------------------------+-------------------------+-------------------------+ |
| | | | :at:`cranklength` | :at:`user` | :at:`joint` | |
| | | | :at:`joint` | :at:`tendon` | :at:`site` | |
| | | +-------------------------+-------------------------+-------------------------+ |
| | | | :at:`jointinparent` | :at:`tendon` | :at:`slidersite` | |
| | | | :at:`lengthrange` | :at:`gear` | :at:`jointinparent` | |
| | | +-------------------------+-------------------------+-------------------------+ |
| | | | :at:`cranksite` | :at:`site` | :at:`dyntype` | |
| | | | :at:`cranklength` | :at:`cranksite` | :at:`slidersite` | |
| | | +-------------------------+-------------------------+-------------------------+ |
| | | | :at:`gaintype` | :at:`biastype` | :at:`dynprm` | |
| | | | :at:`user` | | | |
| | | +-------------------------+-------------------------+-------------------------+ |
| | | | :at:`gainprm` | :at:`biasprm` | | |
| | | | :at:`dyntype` | :at:`gaintype` | :at:`biastype` | |
| | | +-------------------------+-------------------------+-------------------------+ |
| | | | :at:`dynprm` | :at:`gainprm` | :at:`biasprm` | |
| | | +-------------------------+-------------------------+-------------------------+ |
+--------------------------+----+------------------------------------------------------------------------------------+
| |_2|:el:`motor` | \* | .. table:: |
@@ -1913,7 +1915,7 @@ possibly slower speed. Note that `simulate.cc <https://github.com/deepmind/mujoc
displays the frames per second (FPS). The target FPS is 60 Hz; if the number shown in the visualizer is substantially
lower, this means that the GPU is over-loaded and the visualization should somehow be simplified.
:at:`shadowsize`: :at-val:`int, "1024"`
:at:`shadowsize`: :at-val:`int, "4096"`
This attribute specifies the size of the square texture used for shadow mapping. Higher values result is smoother
shadows. The size of the area over which a :ref:`light <light>` can cast shadows also affects smoothness, so these
settings should be adjusted jointly. The default here is somewhat conservative. Most modern GPUs are able to handle
@@ -2743,39 +2745,42 @@ practice this is rarely needed.
:el-prefix:`asset/` **skin** (*)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
| Skinned meshes (or skins) were added in MuJoCo 2.0. These are deformable meshes whose vertex positions and normals are
computed each time the model is rendered. MuJoCo skins are only used for visualization and do not affect the physics
in any way. In particular, collisions involve the geoms of the bodies to which the skin is attached, and not the skin
itself. Unlike regular meshes which are referenced from geoms and participate in collisions, the skin is not
referenced from anywhere else in the model. It is a stand-alone asset that is used by renderer and not by the
simulator.
| The skin has vertex positions and normals updated at runtime, and triangle faces and optional texture coordinates
which are predefined. It also has "bones" used for updating. Bones are regular MuJoCo bodies referenced with the
:el:`bone` subelement. Each bone has a list of vertex indices and corresponding real-valued weights which specify how
much the bone position and orientation influence the corresponding vertex. The vertex has local coordinates with
respect to every bone that influences it. The local coordinates are computed by the model compiler, given global
vertex coordinates and global bind poses for each body. The bind poses do not have to correspond to the model
reference configuration qpos0. Note that the vertex positions and bone bind poses provided in the skin definition are
always global, even if the model itself is defined in local coordinates.
| At runtime the local coordinates of each vertex with respect to each bone that influences it are converted to global
coordinates, and averaged in proportion to the corresponding weights to obtain a single set of 3D coordinates for each
vertex. Normals then are computed automatically given the resulting global vertex positions and face information.
Finally, the skin can be inflated by applying an offset to each vertex position along its (computed) normal.
| Skins are one-sided for rendering purposes; this is because back-face culling is needed to avoid shading and aliasing
artifacts. When the skin is a closed 3D shape this does not matter because the back sides cannot be seen. But if the
skin is a 2D object, we have to specify both sides and offset them slightly to avoid artifacts. Note that the
composite objects introduced in MuJoCo 2.0 generate skins automatically. So one can save an XML model with a composite
object, and obtain an elaborate example of how a skin is specified in the XML.
| Similar to meshes, skins can be specified directly in the XML via attributes documented later, or loaded from a binary
SKN file which is in a custom format. The specification of skins is more complex than meshes because of the bone
subelements. The file format starts with a header of 4 integers: nvertex, ntexcoord, nface, nbone. The first three are
the same as in meshes, and specify the total number of vertices, texture coordinate pairs, and triangle faces in the
skin. ntexcoord can be zero or equal to nvertex. nbone specifies the number of MuJoCo bodies that will be used as
bones in the skin. The header is followed by the vertex, texcoord and face data, followed by a specification for each
bone. The bone specification contains the name of the corresponding model body, 3D bind position, 4D bind quaterion,
number of vertices influenced by the bone, and the vertex index array and weight array. Body names are represented as
fixed-length character arrays and are expected to be 0-terminated. Characters after the first 0 are ignored. The
contents of the SKN file are:
Skinned meshes (or skins) were added in MuJoCo 2.0. These are deformable meshes whose vertex positions and normals are
computed each time the model is rendered. MuJoCo skins are only used for visualization and do not affect the physics
in any way. In particular, collisions involve the geoms of the bodies to which the skin is attached, and not the skin
itself. Unlike regular meshes which are referenced from geoms and participate in collisions, the skin is not
referenced from anywhere else in the model. It is a stand-alone asset that is used by renderer and not by the
simulator.
The skin has vertex positions and normals updated at runtime, and triangle faces and optional texture coordinates
which are predefined. It also has "bones" used for updating. Bones are regular MuJoCo bodies referenced with the
:el:`bone` subelement. Each bone has a list of vertex indices and corresponding real-valued weights which specify how
much the bone position and orientation influence the corresponding vertex. The vertex has local coordinates with
respect to every bone that influences it. The local coordinates are computed by the model compiler, given global
vertex coordinates and global bind poses for each body. The bind poses do not have to correspond to the model
reference configuration qpos0. Note that the vertex positions and bone bind poses provided in the skin definition are
always global, even if the model itself is defined in local coordinates.
At runtime the local coordinates of each vertex with respect to each bone that influences it are converted to global
coordinates, and averaged in proportion to the corresponding weights to obtain a single set of 3D coordinates for each
vertex. Normals then are computed automatically given the resulting global vertex positions and face information.
Finally, the skin can be inflated by applying an offset to each vertex position along its (computed) normal.
Skins are one-sided for rendering purposes; this is because back-face culling is needed to avoid shading and aliasing
artifacts. When the skin is a closed 3D shape this does not matter because the back sides cannot be seen. But if the
skin is a 2D object, we have to specify both sides and offset them slightly to avoid artifacts. Note that the
composite objects introduced in MuJoCo 2.0 generate skins automatically. So one can save an XML model with a composite
object, and obtain an elaborate example of how a skin is specified in the XML.
Similar to meshes, skins can be specified directly in the XML via attributes documented later, or loaded from a binary
SKN file which is in a custom format. The specification of skins is more complex than meshes because of the bone
subelements. The file format starts with a header of 4 integers: nvertex, ntexcoord, nface, nbone. The first three are
the same as in meshes, and specify the total number of vertices, texture coordinate pairs, and triangle faces in the
skin. ntexcoord can be zero or equal to nvertex. nbone specifies the number of MuJoCo bodies that will be used as
bones in the skin. The header is followed by the vertex, texcoord and face data, followed by a specification for each
bone. The bone specification contains the name of the corresponding model body, 3D bind position, 4D bind quaterion,
number of vertices influenced by the bone, and the vertex index array and weight array. Body names are represented as
fixed-length character arrays and are expected to be 0-terminated. Characters after the first 0 are ignored. The
contents of the SKN file are:
.. code:: Text
@@ -3030,7 +3035,7 @@ unit quaternions.
The **hinge** type creates a hinge joint with one rotational degree of freedom. The rotation takes place around a
specified axis through a specified position. This is the most common type of joint and is therefore the default. Most
models contact only hinge and free joints.
models contain only hinge and free joints.
:at:`group`: :at-val:`int, "0"`
Integer group to which the joint belongs. This attribute can be used for custom tags. It is also used by the
visualizer to enable and disable the rendering of entire groups of joints.
@@ -3121,18 +3126,19 @@ mjModel. If the XML model is saved, it will appear as a regular joint of type "f
:el-prefix:`body/` **geom** (*)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
| This element creates a geom, and attaches it rigidly to the body within which the geom is defined. Multiple geoms can
be attached to the same body. At runtime they determine the appearance and collision properties of the body. At
compile time they can also determine the inertial properties of the body, depending on the presence of the
:ref:`inertial <inertial>` element and the setting of the inertiafromgeom attribute of :ref:`compiler <compiler>`.
This is done by summing the masses and inertias of all geoms attached to the body with geom group in the range
specified by the inertiagrouprange attribute of :ref:`compiler <compiler>`. The geom masses and inertias are computed
using the geom shape, a specified density or a geom mass which implies a density, and the assumption of uniform
density.
| Geoms are not strictly required for physics simulation. One can create and simulate a model that only has bodies and
joints. Such a model can even be visualized, using equivalent inertia boxes to represent bodies. Only contact forces
would be missing from such a simulation. We do not recommend using such models, but knowing that this is possible
helps clarify the role of bodies and geoms in MuJoCo.
This element creates a geom, and attaches it rigidly to the body within which the geom is defined. Multiple geoms can
be attached to the same body. At runtime they determine the appearance and collision properties of the body. At
compile time they can also determine the inertial properties of the body, depending on the presence of the
:ref:`inertial <inertial>` element and the setting of the inertiafromgeom attribute of :ref:`compiler <compiler>`.
This is done by summing the masses and inertias of all geoms attached to the body with geom group in the range
specified by the inertiagrouprange attribute of :ref:`compiler <compiler>`. The geom masses and inertias are computed
using the geom shape, a specified density or a geom mass which implies a density, and the assumption of uniform
density.
Geoms are not strictly required for physics simulation. One can create and simulate a model that only has bodies and
joints. Such a model can even be visualized, using equivalent inertia boxes to represent bodies. Only contact forces
would be missing from such a simulation. We do not recommend using such models, but knowing that this is possible
helps clarify the role of bodies and geoms in MuJoCo.
:at:`name`: :at-val:`string, optional`
Name of the geom.
@@ -3978,19 +3984,19 @@ can also represent different forms of mechanical coupling.
:width: 400px
:align: right
| This element creates a spatial tendon, which is a minimum-length path passing through specified via-points and
wrapping around specified obstacle geoms. The objects along the path are defined with the sub-elements
:ref:`site <spatial-site>` and :ref:`geom <spatial-geom>` below. One can also define :ref:`pulleys <spatial-pulley>`
which split the path in multiple branches. Each branch of the tendon path must start and end with a site, and if it
has multiple obstacle geoms they must be separated by sites - so as to avoid the need for an iterative solver at the
tendon level. This example illustrates a multi-branch tendon acting as a finger extensor, with a counter-weight
instead of an actuator.
This element creates a spatial tendon, which is a minimum-length path passing through specified via-points and
wrapping around specified obstacle geoms. The objects along the path are defined with the sub-elements
:ref:`site <spatial-site>` and :ref:`geom <spatial-geom>` below. One can also define :ref:`pulleys <spatial-pulley>`
which split the path in multiple branches. Each branch of the tendon path must start and end with a site, and if it
has multiple obstacle geoms they must be separated by sites - so as to avoid the need for an iterative solver at the
tendon level. This example illustrates a multi-branch tendon acting as a finger extensor, with a counter-weight
instead of an actuator.
| MuJoCo 2.0 introduced a second form of wrapping, where the tendon is constrained to pass through a geom rather than
wrap around it. This is enabled automatically when a sidesite is specified and its position is inside the volume of
the obstacle geom.
MuJoCo 2.0 introduced a second form of wrapping, where the tendon is constrained to pass through a geom rather than
wrap around it. This is enabled automatically when a sidesite is specified and its position is inside the volume of
the obstacle geom.
| `tendon.xml <_static/tendon.xml>`__
`tendon.xml <_static/tendon.xml>`__
:at:`name`: :at-val:`string, optional`
Name of the tendon.
@@ -4147,16 +4153,23 @@ specify them independently.
Integer group to which the actuator belongs. This attribute can be used for custom tags. It is also used by the
visualizer to enable and disable the rendering of entire groups of actuators.
:at:`ctrllimited`: :at-val:`[false, true], "false"`
If true, the control input to this actuator is automatically clamped to ctrlrange at runtime. If false, control input
clamping is disabled. Note that control input clamping can also be globally disabled with the clampctrl attribute of
option/ :ref:`flag <option-flag>`.
If true, the control input to this actuator is automatically clamped to :at:`ctrlrange` at runtime. If false, control
input clamping is disabled. Note that control input clamping can also be globally disabled with the :at:`clampctrl`
attribute of :ref:`option/flag <option-flag>`.
:at:`forcelimited`: :at-val:`[false, true], "false"`
If true, the force output of this actuator is automatically clamped to forcerange at runtime. If false, force output
If true, the force output of this actuator is automatically clamped to :at:`forcerange` at runtime. If false, force
clamping is disabled.
:at:`actlimited`: :at-val:`[false, true], "false"`
If true, the internal state (activation) associated with this actuator is automatically clamped to :at:`actrange` at
runtime. If false, activation clamping is disabled. See the :ref:`Activation clamping <CActRange>` section for more
details.
:at:`ctrlrange`: :at-val:`real(2), "0 0"`
Range for clamping the control input. The compiler expects the first value to be smaller than the second value.
:at:`forcerange`: :at-val:`real(2), "0 0"`
Range for clamping the force output. The compiler expects the first value to be no greater than the second value.
:at:`actrange`: :at-val:`real(2), "0 0"`
Range for clamping the activation state. The compiler expects the first value to be no greater than the second value.
See the :ref:`Activation clamping <CActRange>` section for more details.
:at:`lengthrange`: :at-val:`real(2), "0 0"`
Range of feasible lengths of the actuator's transmission. See :ref:`Length Range <CLengthRange>`.
:at:`gear`: :at-val:`real(6), "1 0 0 0 0 0"`
@@ -4262,12 +4275,13 @@ specify them independently.
:el-prefix:`actuator/` **motor** (*)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
| This and the next three elements are the :ref:`Actuator shortcuts <CActuator>` discussed earlier. When a
such shortcut is encountered, the parser creates a :el:`general` actuator and sets its dynprm, gainprm and biasprm
attributes to the internal defaults shown above, regardless of any default settings. It then adjusts dyntype, gaintype
and biastype depending on the shortcut, parses any custom attributes (beyond the common ones), and translates them
into regular attributes (i.e., attributes of the :el:`general` actuator type) as explained here.
| This element creates a direct-drive actuator. The underlying :el:`general` attributes are set as follows:
This and the next three elements are the :ref:`Actuator shortcuts <CActuator>` discussed earlier. When a
such shortcut is encountered, the parser creates a :el:`general` actuator and sets its dynprm, gainprm and biasprm
attributes to the internal defaults shown above, regardless of any default settings. It then adjusts dyntype, gaintype
and biastype depending on the shortcut, parses any custom attributes (beyond the common ones), and translates them
into regular attributes (i.e., attributes of the :el:`general` actuator type) as explained here.
This element creates a direct-drive actuator. The underlying :el:`general` attributes are set as follows:
========= ======= ========= =======
Attribute Setting Attribute Setting
@@ -4277,8 +4291,8 @@ gaintype fixed gainprm 1 0 0
biastype none biasprm 0 0 0
========= ======= ========= =======
|
| This element does not have custom attributes. It only has common attributes, which are:
This element does not have custom attributes. It only has common attributes, which are:
.. |actuator/motor attrib list| replace::
@@ -4294,7 +4308,7 @@ biastype none biasprm 0 0 0
:el-prefix:`actuator/` **position** (*)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
| This element creates a position servo. The underlying :el:`general` attributes are set as follows:
This element creates a position servo. The underlying :el:`general` attributes are set as follows:
========= ======= ========= =======
Attribute Setting Attribute Setting
@@ -4304,8 +4318,8 @@ gaintype fixed gainprm kp 0 0
biastype affine biasprm 0 -kp 0
========= ======= ========= =======
|
| This element has one custom attribute in addition to the common attributes:
This element has one custom attribute in addition to the common attributes:
.. |actuator/position attrib list| replace::
:at:`name`, :at:`class`, :at:`group`, :at:`ctrllimited`, :at:`forcelimited`, :at:`ctrlrange`, :at:`forcerange`,
@@ -4322,9 +4336,9 @@ biastype affine biasprm 0 -kp 0
:el-prefix:`actuator/` **velocity** (*)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
| This element creates a velocity servo. Note that in order create a PD controller, one has to define two actuators: a
position servo and a velocity servo. This is because MuJoCo actuators are SISO while a PD controller takes two control
inputs (reference position and reference velocity). The underlying :el:`general` attributes are set as follows:
This element creates a velocity servo. Note that in order create a PD controller, one has to define two actuators: a
position servo and a velocity servo. This is because MuJoCo actuators are SISO while a PD controller takes two control
inputs (reference position and reference velocity). The underlying :el:`general` attributes are set as follows:
========= ======= ========= =======
Attribute Setting Attribute Setting
@@ -4334,8 +4348,8 @@ gaintype fixed gainprm kv 0 0
biastype affine biasprm 0 0 -kv
========= ======= ========= =======
|
| This element has one custom attribute in addition to the common attributes:
This element has one custom attribute in addition to the common attributes:
.. |actuator/velocity attrib list| replace::
:at:`name`, :at:`class`, :at:`group`, :at:`ctrllimited`, :at:`forcelimited`, :at:`ctrlrange`, :at:`forcerange`,
@@ -4352,8 +4366,8 @@ biastype affine biasprm 0 0 -kv
:el-prefix:`actuator/` **cylinder** (*)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
| This element is suitable for modeling pneumatic or hidraulic cylinders. The underlying :el:`general` attributes are
set as follows:
This element is suitable for modeling pneumatic or hidraulic cylinders. The underlying :el:`general` attributes are
set as follows:
========= ======= ========= =============
Attribute Setting Attribute Setting
@@ -4363,8 +4377,8 @@ gaintype fixed gainprm area 0 0
biastype affine biasprm bias(3)
========= ======= ========= =============
|
| This element has four custom attributes in addition to the common attributes:
This element has four custom attributes in addition to the common attributes:
.. |actuator/cylinder attrib list| replace::
:at:`name`, :at:`class`, :at:`group`, :at:`ctrllimited`, :at:`forcelimited`, :at:`ctrlrange`, :at:`forcerange`,
@@ -4387,8 +4401,8 @@ biastype affine biasprm bias(3)
:el-prefix:`actuator/` **muscle** (*)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
| This element is used to model a muscle actuator, as described in the :ref:`Muscles actuators <CMuscle>`
section. The underlying :el:`general` attributes are set as follows:
This element is used to model a muscle actuator, as described in the :ref:`Muscles actuators <CMuscle>`
section. The underlying :el:`general` attributes are set as follows:
========= ======= ========= ======================================================
Attribute Setting Attribute Setting
@@ -4398,8 +4412,8 @@ gaintype muscle gainprm range(2), force, scale, lmin, lmax, vmax, fpmax, fvm
biastype muscle biasprm same as gainprm
========= ======= ========= ======================================================
|
| This element has nine custom attributes in addition to the common attributes:
This element has nine custom attributes in addition to the common attributes:
.. |actuator/muscle attrib list| replace::
:at:`name`, :at:`class`, :at:`group`, :at:`ctrllimited`, :at:`forcelimited`, :at:`ctrlrange`, :at:`forcerange`,
@@ -4436,14 +4450,15 @@ biastype muscle biasprm same as gainprm
**sensor** (*)
~~~~~~~~~~~~~~~~~~~~~~~~~~~
| This is a grouping element for sensor definitions. It does not have attributes. The outputs of all sensors are
concatenated in the field mjData.sensordata which has size mjModel.nsensordata. This data is not used in any internal
computations.
| In addition to the sensors created with the elements below, the top-level function
:ref:`mj_step` computes the quantities mjData.cacc, mjData.cfrc_int and mjData.crfc_ext
corresponding to body accelerations and interaction forces. Some of these quantities are used to compute the output of
certain sensors (force, acceleration etc.) but even if no such sensors are defined in the model, these quantities
themselves are "features" that could be of interest to the user.
This is a grouping element for sensor definitions. It does not have attributes. The outputs of all sensors are
concatenated in the field mjData.sensordata which has size mjModel.nsensordata. This data is not used in any internal
computations.
In addition to the sensors created with the elements below, the top-level function
:ref:`mj_step` computes the quantities mjData.cacc, mjData.cfrc_int and mjData.crfc_ext
corresponding to body accelerations and interaction forces. Some of these quantities are used to compute the output of
certain sensors (force, acceleration etc.) but even if no such sensors are defined in the model, these quantities
themselves are "features" that could be of interest to the user.
.. _sensor-touch:
@@ -4511,10 +4526,9 @@ simulate an inertial measurement unit (IMU).
This element creates a 3-axis force sensor. The sensor outputs three numbers, which are the interaction force between a
child and a parent body, expressed in the site frame defining the sensor. The convention is that the site is attached to
the child body, and the force points from the child towards the parent. To change the sign of the sensor reading, use
the scale attribute. The computation here takes into account all forces acting on the system, including contacts as well
as external perturbations. Using this sensor often requires creating a dummy body welded to its parent (i.e., having no
joint elements).
the child body, and the force points from the child towards the parent. The computation here takes into account all
forces acting on the system, including contacts as well as external perturbations. Using this sensor often requires
creating a dummy body welded to its parent (i.e., having no joint elements).
:at:`name`, :at:`noise`, :at:`cutoff`, :at:`user`
See :ref:`CSensor`.
+58 -1
View File
@@ -2,6 +2,63 @@
Changelog
=========
Version 2.2.0 (May 23, 2022)
-----------------------------
Open Sourcing
^^^^^^^^^^^^^
1. MuJoCo is now fully open-source software. Newly available top level directories are:
a. ``src/``: All source files. Subrirectories correspond to the modules described in the Programming chapter
:ref:`introduction<inIntro>`:
- ``src/engine/``: Core engine.
- ``src/xml/``: XML parser.
- ``src/user/``: Model compiler.
- ``src/visualize/``: Abstract visualizer.
- ``src/ui/``: UI framework.
b. ``test/``: Tests and corresponding asset files.
c. ``dist/``: Files related to packaging and binary distribution.
#. Added `contributor's guide <https://github.com/deepmind/mujoco/blob/main/CONTRIBUTING.md>`_ and
`style guide <https://github.com/deepmind/mujoco/blob/main/STYLEGUIDE.md>`_.
General
^^^^^^^
3. Added :at:`actlimited` and :at:`actrange` attributes to :ref:`general actuators<general>`, for clamping actuator
internal states (activations). This clamping is useful for integrated-velocity actuators, see the :ref:`Activation
clamping <CActRange>` section for details.
#. ``mjData`` fields ``qfrc_unc`` (unconstrained forces) and ``qacc_unc`` (unconstrained accelerations) were renamed
``qfrc_smooth`` and ``qacc_smooth``, respectively. While "unconstrained" is precise, "smooth" is more intelligible
than "unc".
#. Public headers have been moved from ``/include`` to ``/include/mujoco/``, in line with the directory layout common in
other open source projects. Developers are encouraged to include MuJoCo public headers in their own codebase via
``#include <mujoco/filename.h>``.
#. The default shadow resolution specified by the :ref:`shadowsize<quality>` attribute was increased from 1024 to 4096.
#. Saved XMLs now use 2-space indents.
Bug fixes
^^^^^^^^^
8. Antialiasing was disabled for segmentation rendering. Before this change, if the :ref:`offsamples<quality>`
attribute was greater than 0 (the default value is 4), pixels that overlapped with multiple geoms would receive
averaged segmentation IDs, leading to incorrect or non-existant IDs. After this change :at:`offsamples` is ignored
during segmentation rendering.
#. The value of the enable flag for the experimental multiCCD feature was made sequential with other enable flags.
Sequentiality is assumed in the ``simulate`` UI and elsewhere.
#. Fix issue of duplicated meshes when saving models with OBJ meshes using mj_saveLastXML.
Version 2.1.5 (Apr. 13, 2022)
-----------------------------
@@ -106,7 +163,7 @@ API changes
^^^^^^^^^^^
4. Moved definition of ``mjtNum`` floating point type into a new header
`mjtnum.h <https://github.com/deepmind/mujoco/blob/main/include/mjtnum.h>`_.
`mjtnum.h <https://github.com/deepmind/mujoco/blob/3577e2cf8bf841475b489aefff52276a39f24d51/include/mjtnum.h>`_.
#. Renamed header `mujoco_export.h` to :ref:`mjexport.h<inHeader>`.
#. Added ``mj_printFormattedData``, which accepts a format string for floating point numbers, for example to increase
precision.
+1 -1
View File
@@ -314,7 +314,7 @@ Putting all this together, the net force in generalized coordinates contributed
.. math::
\sum_i \nabla l_i(q) \; p_i \left(u_i, w_i, l_i(q), \dot{l}_i(q, v) \right)
This quantity is stored in ``mjData.qfrc_actuation``. It is added to the applied force vector :math:`\tau`, together
This quantity is stored in ``mjData.qfrc_actuator``. It is added to the applied force vector :math:`\tau`, together
with any user-defined forces in joint or Cartesian coordinates (which are stored in ``mjData.qfrc_applied`` and
``mjData.xfrc_applied`` respectively).
+2
View File
@@ -26,6 +26,7 @@ sys.path.insert(0, os.path.abspath('../'))
sys.path.append(os.path.abspath('ext'))
import sphinxcontrib.katex as katex # pylint: disable=g-import-not-at-top
import sphinxcontrib.youtube as youtube # pylint: disable=g-import-not-at-top
# -- Project information -----------------------------------------------------
@@ -42,6 +43,7 @@ master_doc = 'index'
# ones.
extensions = [
'sphinxcontrib.katex',
'sphinxcontrib.youtube',
'sphinx_reredirects',
]
+290 -216
View File
@@ -243,13 +243,13 @@ coordinates, but that effort is rarely justified.
Frame orientations
~~~~~~~~~~~~~~~~~~
Several model elements have right-handed spatial frames associated with them. These are all the elements defined in
the kinematic tree except for joints. A spatial frame is defined by its position and orientation. Specifying 3D
positions is straightforward, but specifying 3D orientations can be challenging. This is why MJCF provides several
alternative mechanisms. No matter which mechanism the user chooses, the frame orientation is always represented as a
unit quaternion after compilation. Recall that a 3D rotation by angle *a* around axis given by the unit vector (*x, y,
z*) corresponds to the quaternion (cos(*a*/2), sin(*a*/2) \* (*x, y, z*)). Also recall that every 3D orientation can
be uniquely specified by a single 3D rotation by some angle around some axis.
Several model elements have right-handed spatial frames associated with them. These are all the elements defined in the
kinematic tree except for joints. A spatial frame is defined by its position and orientation. Specifying 3D positions is
straightforward, but specifying 3D orientations can be challenging. This is why MJCF provides several alternative
mechanisms. No matter which mechanism the user chooses, the frame orientation is always represented as a unit quaternion
after compilation. Recall that a 3D rotation by angle :math:`a` around axis given by the unit vector :math:`(x, y, z)`
corresponds to the quaternion :math:`(\cos(a/2), \: \sin(a/2) \cdot (x, y, z))`. Also recall that every 3D orientation
can be uniquely specified by a single 3D rotation by some angle around some axis.
All MJCF elements that have spatial frames allow the five attributes listed below. The frame orientation is specified
using at most one of these attributes. The :at:`quat` attribute has a default value corresponding to the null
@@ -261,12 +261,12 @@ specified by the user, the frame is not rotated.
conversions. Instead it is normalized to unit length and copied into mjModel during compilation. When a model is
saved as MJCF, all frame orientations are expressed as quaternions using this attribute.
:at:`axisangle`: :at-val:`real(4), optional`
These are the quantities (*x, y, z, a*) mentioned above. The last number is the angle of rotation, in degrees or
radians as specified by the :at:`angle` attribute of :ref:`compiler <compiler>`. The first three
numbers determine a 3D vector which is the rotation axis. This vector is normalized to unit length during
compilation, so the user can specify a vector of any non-zero length. Keep in mind that the rotation is right-handed;
if the direction of the vector (*x, y, z*) is reversed this will result in the opposite rotation. Changing the sign
of *a* can also be used to specify the opposite rotation.
These are the quantities :math:`(x, y, z, a)` mentioned above. The last number is the angle of rotation, in degrees
or radians as specified by the :at:`angle` attribute of :ref:`compiler <compiler>`. The first three numbers determine
a 3D vector which is the rotation axis. This vector is normalized to unit length during compilation, so the user can
specify a vector of any non-zero length. Keep in mind that the rotation is right-handed; if the direction of the
vector :math:`(x, y, z)` is reversed this will result in the opposite rotation. Changing the sign of :math:`a` can
also be used to specify the opposite rotation.
:at:`euler`: :at-val:`real(3), optional`
Rotation angles around three coordinate axes. The sequence of axes around which these rotations are applied is
determined by the :at:`eulerseq` attribute of :ref:`compiler <compiler>` and is the same for the
@@ -275,96 +275,110 @@ specified by the user, the frame is not rotated.
The first 3 numbers are the X axis of the frame. The next 3 numbers are the Y axis of the frame, which is
automatically made orthogonal to the X axis. The Z axis is then defined as the cross-product of the X and Y axes.
:at:`zaxis`: :at-val:`real(3), optional`
The Z axis of the frame. The compiler finds the minimal rotation that maps the vector (0,0,1) into the vector
specified here. This determines the X and Y axes of the frame implicitly. This is useful for geoms with rotational
symmetry around the Z axis, as well as lights - which are oriented along the Z axis of their frame.
The Z axis of the frame. The compiler finds the minimal rotation that maps the vector :math:`(0, 0, 1)` into the
vector specified here. This determines the X and Y axes of the frame implicitly. This is useful for geoms with
rotational symmetry around the Z axis, as well as lights - which are oriented along the Z axis of their frame.
.. _CSolver:
Solver parameters
~~~~~~~~~~~~~~~~~
The solver :ref:`Parameters <soParameters>` section of the Computation chapter explained the
mathematical and algorithmic meaning of the quantities d, b, k which determine the behavior of the constraints in
MuJoCo. Here we explain how to set them. Setting is done indirectly, through the attributes :at:`solref` and
:at:`solimp` which are available in all MJCF elements involving constraints. These parameters can be adjusted per
constraint, or per defaults class, or left undefined - in which case MuJoCo uses the internal defaults shown below.
Note also the override mechanism available in :ref:`option <option>`; it can be used to change all
contact-related solver parameters at runtime, so as to experiment interactively with parameter settings or implement
continuation methods for numerical optimization.
The solver :ref:`Parameters <soParameters>` section of the Computation chapter explained the mathematical and
algorithmic meaning of the quantities :math:`d, b, k` which determine the behavior of the constraints in MuJoCo. Here we
explain how to set them. Setting is done indirectly, through the attributes :at:`solref` and :at:`solimp` which are
available in all MJCF elements involving constraints. These parameters can be adjusted per constraint, or per defaults
class, or left undefined - in which case MuJoCo uses the internal defaults shown below. Note also the override mechanism
available in :ref:`option <option>`; it can be used to change all contact-related solver parameters at runtime, so as to
experiment interactively with parameter settings or implement continuation methods for numerical optimization.
Here we focus on a single scalar constraint. Using slightly different notation from the Computation chapter, let a1
denote the acceleration, v the velocity, r the position or residual (defined as 0 in friction dimensions), k and b the
stiffness and damping of the virtual spring used to define the reference acceleration aref = -b*v - k*r. Let d be the
constraint impedance, and a0 the acceleration in the absence of constraint force. Our earlier analysis revealed that
the dynamics in constraint space are approximately
Here we focus on a single scalar constraint. Using slightly different notation from the Computation chapter, let
:math:`a_1` denote the acceleration, :math:`v` the velocity, :math:`r` the position or residual (defined as 0 in
friction dimensions), :math:`k` and :math:`b` the stiffness and damping of the virtual spring used to define the
reference acceleration :math:`a_{\rm ref} = -b v - k r`. Let :math:`d` be the constraint impedance, and :math:`a_0` the
acceleration in the absence of constraint force. Our earlier analysis revealed that the dynamics in constraint space are
approximately
a1 + d \* (b v + k r) = (1 - d) \* a0
.. math::
a_1 + d \cdot (b v + k r) = (1 - d)\cdot a_0
Again, the parameters that are under the user's control are d, b, k. The remaining quantities are functions of the
Again, the parameters that are under the user's control are :math:`d, b, k`. The remaining quantities are functions of the
system state and are computed automatically at each time step.
First we explain the setting of the impedance d. Recall that d must lie between 0 and 1; internally MuJoCo clamps it
to the range [:ref:`mjMINIMP mjMAXIMP <glNumeric>`] which is currently set to [0.0001 0.9999]. It
causes the solver to interpolate between the unforced acceleration a0 and reference acceleration aref. Small values of
d correspond to soft/weak constraints while large values of d correspond to strong/hard constraints. The user can set
d to a constant, or take advantage of its interpolating property and make it position-dependent, i.e., a function of r.
Position-dependent impedance can be used to model soft contact layers around objects, or define equality constraints
that become stronger with larger violation (so as to approximate backlash for example). The shape of the function d(r)
is determined by the element-specific parameter vector :at:`solimp`.
First we explain the setting of the impedance :math:`d`. Recall that :math:`d` must lie between 0 and 1; internally
MuJoCo clamps it to the range [:ref:`mjMINIMP mjMAXIMP <glNumeric>`] which is currently set to [0.0001 0.9999]. It
causes the solver to interpolate between the unforced acceleration :math:`a_0` and reference acceleration
:math:`a_{\rm ref}`. Small values of :math:`d` correspond to soft/weak constraints while large values of :math:`d`
correspond to strong/hard constraints. The user can set :math:`d` to a constant, or take advantage of its interpolating
property and make it position-dependent, i.e., a function of :math:`r`. Position-dependent impedance can be used to
model soft contact layers around objects, or define equality constraints that become stronger with larger violation (so
as to approximate backlash for example). The shape of the function :math:`d(r)` is determined by the element-specific
parameter vector :at:`solimp`.
**solimp :** real(5), "0.9 0.95 0.001 0.5 2"
The five numbers are (dmin, dmax, width, midpoint, power). They parameterize the function d(r). Prior to MuJoCo 2.0
this attribute had three parameters, plus a global option specifying the shape of the function. In MuJoCo 2.0 we
expanded the family of impedance functions while keeping it backward-compatible as follows. The user is allowed to
set only the first three parameters, whose defaults are the same as in prior releases. The defaults for the last two
parameters then generate the same function which was the default in prior releases (a sigmoid). The new
The five numbers are (dmin, dmax, width, midpoint, power). They parameterize the function :math:`d(r)`. Prior to
MuJoCo 2.0 this attribute had three parameters, plus a global option specifying the shape of the function. In MuJoCo
2.0 we expanded the family of impedance functions while keeping it backward-compatible as follows. The user is
allowed to set only the first three parameters, whose defaults are the same as in prior releases. The defaults for
the last two parameters then generate the same function which was the default in prior releases (a sigmoid). The new
parameterization further allows the sigmoid to become shifted and skewed, as shown in the plots below for different
values of the additional parameters. The plots actually show two reflected sigmoids, because the impedance function
d(r) depends on the absolute value of r. This flexibility was added to allow better control of remote contact forces,
and can also be used for other constraints. The power (of the polynomial spline used to generate the function) must
be 1 or greater. The midpoint (specifying the inflection point) must be between 0 and 1, and is expressed in units of
width. Note that when the power is 1, the function is linear regardless of the midpoint.
:math:`d(r)` depends on the absolute value of :math:`r`. This flexibility was added to allow better control of remote
contact forces, and can also be used for other constraints. The power (of the polynomial spline used to generate the
function) must be 1 or greater. The midpoint (specifying the inflection point) must be between 0 and 1, and is
expressed in units of width. Note that when the power is 1, the function is linear regardless of the midpoint.
|image0|
These plots show the impedance d(r) on the vertical axis, as a function of the constraint violation r on the
horizontal axis. The quantity r is computed as follows. For equality constraints, r equals the constraint violation
which can be either positive or negative. For friction loss or friction dimensions of elliptic cones, r is always 0.
For limits, normal directions of elliptic cones and all directions of pyramidal cones, r is the (limit or contact)
distance minus the margin at which the constraint becomes active; for contacts this margin is actually margin-gap.
Therefore limit and contact constraints are active when the corresponding r is negative.
These plots show the impedance :math:`d(r)` on the vertical axis, as a function of the constraint violation :math:`r`
on the horizontal axis. The quantity :math:`r` is computed as follows. For equality constraints, :math:`r` equals the
constraint violation which can be either positive or negative. For friction loss or friction dimensions of elliptic
cones, :math:`r` is always 0. For limits, normal directions of elliptic cones and all directions of pyramidal cones,
:math:`r` is the (limit or contact) distance minus the margin at which the constraint becomes active; for contacts
this margin is actually margin-gap. Therefore limit and contact constraints are active when the corresponding
:math:`r` is negative.
Next we explain the setting of the stiffness k and damping b. The idea here is to re-parameterize the model in terms of
the time constant and damping ratio of the above mass-spring-damper system. By "time constant" we mean the inverse of
the natural frequency times the damping ratio. Constraints whose residual is identically 0 have first-order dynamics and
the mass-spring-damper analysis does not apply. In that case the time constant is the rate of exponential decay of the
constraint velocity, and the damping ratio is ignored. In addition to this format, MuJoCo 2.0 allows a second format
where stiffness and damping are specified more directly.
Next we explain the setting of the stiffness :math:`k` and damping :math:`b`. The idea here is to re-parameterize the
model in terms of the time constant and damping ratio of the above mass-spring-damper system. By "time constant" we mean
the inverse of the natural frequency times the damping ratio. Constraints whose residual is identically 0 have first-
order dynamics and the mass-spring-damper analysis does not apply. In that case the time constant is the rate of
exponential decay of the constraint velocity, and the damping ratio is ignored. In addition to this format, MuJoCo 2.0
allows a second format where stiffness and damping are specified more directly.
**solref :** real(2), "0.02 1"
There are two formats for this attribute, determined by the sign of the numbers. If both numbers are positive the
specification is considered to be in the (timeconst, dampratio) format which has been available in MuJoCo all along.
Otherwise the specification is considered to be in the new (-stiffness, -damping) format introduced in MuJoCo 2.0.
We first describe the original format where the two numbers are (timeconst, dampratio). In this case we use a
mass-spring-damper model to compute k, b after suitable scaling. Note that the effective stiffness d(r)*k and damping
d(r)*b are scaled by the impedance d(r) which is a function of the distance r. Thus we cannot always achieve the
specified mass-spring-damper properties, unless we completely undo the scaling by d. But the latter is undesirable
because it would ruin the interpolating property, in particular the limit d = 0 would no longer disable the
constraint. Instead we scale the stiffness and damping so that the damping ratio remains constant, while the time
constant increases when d(r) gets smaller. The scaling formulas are
b = 2 / (dmax \* timeconst)
k = d(r) / (dmax \* dmax \* timeconst \* timeconst \* dampratio \* dampratio)
specification is considered to be in the :math:`(\text{timeconst}, \text{dampratio})` format which has been available
in MuJoCo all along. Otherwise the specification is considered to be in the new :math:`(-\text{stiffness}, -
\text{damping})`, format introduced in MuJoCo 2.0. We first describe the original format where the two numbers are
:math:`(\text{timeconst}, \text{dampratio})`. In this case we use a mass-spring-damper model to compute :math:`k, b`
after suitable scaling. Note that the effective stiffness :math:`d(r) \cdot k` and damping :math:`d(r) \cdot b` are
scaled by the impedance :math:`d(r)` which is a function of the distance :math:`r`. Thus we cannot always achieve the
specified mass-spring-damper properties, unless we completely undo the scaling by :math:`d`. But the latter is
undesirable because it would ruin the interpolating property, in particular the limit :math:`d=0` would no longer
disable the constraint. Instead we scale the stiffness and damping so that the damping ratio remains constant, while
the time constant increases when :math:`d(r)` gets smaller. The scaling formulas are
.. math::
\begin{aligned}
b &= 2 / (d_\text{max}\cdot \text{timeconst}) \\
k &= d(r) / (d_\text{max}^2 \cdot \text{timeconst}^2 \cdot \text{dampratio}^2) \\
\end{aligned}
The timeconst parameter should be at least two times larger than the simulation time step, otherwise the system can
become too stiff relative to the numerical integrator (especially when Euler integration is used) and the simulation
can go unstable. This is enforced internally, unless the :at:`refsafe` attribute of
:ref:`flag <option-flag>` is set to false. The dampratio parameter would normally be set to 1,
corresponding to critical damping. Smaller values result in under-damped or bouncy constraints, while larger values
result in over-damped constraints.
Next we describe the new format where the two numbers are (-stiffness, -damping). This allows more direct control
over restitution in particular. We still apply some scaling so that the same numbers can be used with different
impedances, but the scaling no longer depends on r and the two numbers no longer interact. The scaling formulas are
b = damping / dmax
k = stiffness / (dmax \* dmax)
can go unstable. This is enforced internally, unless the :at:`refsafe` attribute of :ref:`flag <option-flag>` is set
to false. The :math:`\text{dampratio}` parameter would normally be set to 1, corresponding to critical damping.
Smaller values result in under-damped or bouncy constraints, while larger values result in over-damped constraints.
Next we describe the new format where the two numbers are :math:`(-\text{stiffness}, -\text{damping})`. This allows
more direct control over restitution in particular. We still apply some scaling so that the same numbers can be used
with different impedances, but the scaling no longer depends on :math:`r` and the two numbers no longer interact. The
scaling formulas are
.. math::
\begin{aligned}
b &= \text{damping} / d_\text{max} \\
k &= \text{stiffness} / d_\text{max}^2 \\
\end{aligned}
.. _CContact:
@@ -530,20 +544,18 @@ well as solver statistics per iteration. We can offer the following general guid
Actuator shortcuts
~~~~~~~~~~~~~~~~~~
As explained in the :ref:`Actuation model <geActuation>` section of the Computation chapter, MuJoCo
offers a flexible actuator model with transmission, activation dynamics and force generation components that can be
specified independently. The full functionality can be accessed via the XML element
:ref:`general <general>` which allows the user to create a variety of custom actuators. In addition,
MJCF provides shortcuts for configuring common actuators. This is done via the XML elements
:ref:`motor <motor>`, :ref:`position <position>`,
:ref:`velocity <velocity>`, :ref:`cylinder <cylinder>`,
:ref:`muscle <muscle>`. These are *not* separate model elements. Internally MuJoCo supports only one
As explained in the :ref:`Actuation model <geActuation>` section of the Computation chapter, MuJoCo offers a flexible
actuator model with transmission, activation dynamics and force generation components that can be specified
independently. The full functionality can be accessed via the XML element :ref:`general <general>` which allows the user
to create a variety of custom actuators. In addition, MJCF provides shortcuts for configuring common actuators. This is
done via the XML elements :ref:`motor <motor>`, :ref:`position <position>`, :ref:`velocity <velocity>`, :ref:`cylinder
<cylinder>`, :ref:`muscle <muscle>`. These are *not* separate model elements. Internally MuJoCo supports only one
actuator type - which is why when an MJCF model is saved all actuators are written as :el:`general`. Shortcuts create
general actuators implicitly, set their attributes to suitable values, and expose a subset of attributes with possibly
different names. For example, :el:`position` creates a position servo with attribute :at:`kp` which is the servo
gain. However :el:`general` does not have an attribute :at:`kp`. Instead the parser adjusts the gain and bias
parameters of the general actuator in a coordinated way so as to mimic a position servo. The same effect could have
been achieved by using :el:`general` directly, and setting its attributes to certain values as described below.
different names. For example, :el:`position` creates a position servo with attribute :at:`kp` which is the servo gain.
However :el:`general` does not have an attribute :at:`kp`. Instead the parser adjusts the gain and bias parameters of
the general actuator in a coordinated way so as to mimic a position servo. The same effect could have been achieved by
using :el:`general` directly, and setting its attributes to certain values as described below.
Actuator shortcuts also interact with defaults. Recall that the :ref:`default setting <CDefault>` mechanism involves
classes, each of which has a complete collection of dummy elements (one of each element type) used to initialize the
@@ -561,6 +573,53 @@ defaults class and in the creation of actual model elements. If a given model re
create multiple defaults classes, or avoid using defaults for actuators and instead specify all their attributes
explicitly.
.. _CActRange:
Activation clamping
~~~~~~~~~~~~~~~~~~~
As described in the :ref:`Actuation model <geActuation>` section of the Computation chapter, MuJoCo supports actuators
with internal dynamics whose states are called "activations". One useful application of these stateful actuators is the
"integrated-velocity" actuator. Different from the :ref:`pure velocity<velocity>` actuators, which implement direct
feedback on transmission target's velocity, *integrated-velocity* actuators couple an *integrator* with a *position-
feedback* actuator. In this case the semantics of the activation state are "the target of the position actuator", and
the semantics of the control signal are "the velocity of the target of the position actuator". Note that in real robotic
systems this integrated-velocity actuator is the most common implementation of actuators with velocity semantics, rather
than pure feedback on velocity which is often quite unstable (both in real life and in simulation).
In the case of integrated-velocity actuators, it is often desirable to *clamp* the activation state, since otherwise the
position target would keep integrating beyond the joint limits, leading to loss of controllabillity. To see the effect
of activation clamping, load the example model below:
.. code-block:: xml
<mujoco>
<default>
<joint axis="0 0 1" limited="true" range="-90 90" damping="0.3"/>
<geom size=".1 .1 .1" type="box"/>
<general gainprm="1" biastype="affine" biasprm="0 -1" dyntype="integrator"/>
</default>
<worldbody>
<body>
<joint name="joint 1"/>
<geom/>
</body>
<body pos=".3 0 0">
<joint name="joint 2"/>
<geom/>
</body>
</worldbody>
<actuator>
<general name="unclamped" joint="joint 1"/>
<general name="clamped" actlimited="true" actrange="-1.57 1.57"/>
</actuator>
</mujoco>
Note that the :at:`actrange` attribute is always specified in native units (radians), even though the joint range
can be either in degrees (the default) or radians, depending on the :ref:`compiler/angle <compiler>` attribute.
.. _CLengthRange:
Actuator length range
@@ -637,103 +696,120 @@ the shortcut :ref:`muscle <muscle>` is more convenient. As with all other actuat
production mechanism and the transmission are defined independently. Nevertheless, muscles only make (bio)physical
sense when attached to tendon or joint transmissions. For concreteness we will assume a tendon transmission here.
First we discuss length and length scaling. The range of feasible lengths of the transmission (i.e., MuJoCo tendon)
will play an important role; see :ref:`Length range <CLengthRange>` section above. In biomechanics, a muscle and a
tendon are attached in series and form a muscle-tendon actuator. Our convention is somewhat different: in MuJoCo the
entity that has spatial properties (in particular length and velocity) is the tendon, while the muscle is an abstract
force-generating mechanism that pulls on the tendon. Thus the tendon length in MuJoCo corresponds to the muscle+tendon
length in biomechanics. We assume that the biological tendon is inelastic, with constant length LT, while the
biological muscle length LM varies over time. The MuJoCo tendon length is the sum of the biological muscle and tendon
lengths:
First we discuss length and length scaling. The range of feasible lengths of the transmission (i.e., MuJoCo tendon) will
play an important role; see :ref:`Length range <CLengthRange>` section above. In biomechanics, a muscle and a tendon are
attached in series and form a muscle-tendon actuator. Our convention is somewhat different: in MuJoCo the entity that
has spatial properties (in particular length and velocity) is the tendon, while the muscle is an abstract force-
generating mechanism that pulls on the tendon. Thus the tendon length in MuJoCo corresponds to the muscle+tendon length
in biomechanics. We assume that the biological tendon is inelastic, with constant length :math:`L_T`, while the
biological muscle length :math:`L_M` varies over time. The MuJoCo tendon length is the sum of the biological muscle and
tendon lengths:
actuator_length = LT + LM
.. math::
\texttt{actuator\_length} = L_T + L_M
Another important constant is the optimal resting length of the muscle, denoted L0. It equals the length LM at which
the muscle generates maximum active force at zero velocity. We do not ask the user to specify L0 and LT directly,
because it is difficult to know their numeric values given the spatial complexity of the tendon routing and wrapping.
Instead we compute L0 and LT automatically as follows. The length range computation described above already provided
the operating range for LT + LM. In addition, we ask the user to specify the operating range for the muscle length LM
scaled by the (still unknown) constant L0. This is done with the attribute range; the default scaled range is (0.75,
1.05). Now we can compute the two constants, using the fact that the actual and scaled ranges have to map to each
other:
Another important constant is the optimal resting length of the muscle, denoted :math:`L_0`. It equals the length
:math:`L_M` at which the muscle generates maximum active force at zero velocity. We do not ask the user to specify
:math:`L_0` and :math:`L_T` directly, because it is difficult to know their numeric values given the spatial complexity
of the tendon routing and wrapping. Instead we compute :math:`L_0` and :math:`L_T` automatically as follows. The length
range computation described above already provided the operating range for :math:`L_T+L_M`. In addition, we ask the user
to specify the operating range for the muscle length :math:`L_M` scaled by the (still unknown) constant :math:`L_0`.
This is done with the attribute range; the default scaled range is :math:`(0.75, 1.05)`. Now we can compute the two
constants, using the fact that the actual and scaled ranges have to map to each other:
(actuator_lengthrange[0] - LT) / L0 = range[0]
(actuator_lengthrange[1] - LT) / L0 = range[1]
.. math::
\begin{aligned}
(\texttt{actuator\_lengthrange[0]} - L_T) / L_0 &= \texttt{range[0]} \\
(\texttt{actuator\_lengthrange[1]} - L_T) / L_0 &= \texttt{range[1]} \\
\end{aligned}
At runtime, we compute the scaled muscle length and velocity as:
L = (actuator_length - LT) / L0
V = actuator_velocity / L0
.. math::
\begin{aligned}
L &= (\texttt{actuator\_length} - L_T) / L_0 \\
V &= \texttt{actuator\_velocity} / L_0 \\
\end{aligned}
The advantage of the scaled quantities is that all muscles behave similarly in that representation. The behavior is
captured by the Force-Length-Velocity (FLV) function measured in many experimental papers. We approximate this
function as follows:
captured by the Force-Length-Velocity (:math:`\text{\small FLV}`) function measured in many experimental papers. We
approximate this function as follows:
|image1|
The function is in the form:
FLV(L, V, act) = FL(L)*FV(V)*act + FP(L)
.. math::
\text{\small FLV}(L, V, \texttt{act}) = F_L(L)\cdot F_V(V)\cdot \texttt{act} + F_P(L)
Comparing to the general form of a MuJoCo actuator, we see that FL*FV is the actuator gain and FP is the actuator
bias. FL is the active force as a function of length, while FV is the active force as a function of velocity. They are
multiplied to obtain the overall active force (note the scaling by act which is the actuator activation). FP is the
passive force which is always present regardless of activation. The output of the FLV function is the scaled muscle
force. We multiply the scaled force by a muscle-specific constant F0 to obtain the actual force:
Comparing to the general form of a MuJoCo actuator, we see that :math:`F_L\cdot F_V` is the actuator gain and
:math:`F_P` is the actuator bias. :math:`F_L` is the active force as a function of length, while :math:`F_V` is the
active force as a function of velocity. They are multiplied to obtain the overall active force (note the scaling by act
which is the actuator activation). :math:`F_P` is the passive force which is always present regardless of activation.
The output of the :math:`\text{\small FLV}` function is the scaled muscle force. We multiply the scaled force by a
muscle-specific constant :math:`F_0` to obtain the actual force:
actuator_force = - FLV(L, V, act) \* F0
.. math::
\texttt{actuator\_force} = -\text{\small FLV}(L, V, \texttt{act}) \cdot F_0
The negative sign is because positive muscle activation generates pulling force. The constant F0 is the peak active
force at zero velocity. It is related to the muscle thickness (i.e., physiological cross-sectional area or PCSA). If
known, it can be set with the attribute force of element :ref:`muscle <muscle>`. If it is not known, we
set it to -1 which is the default. In that case we rely on the fact that larger muscles tend to act on joints that
move more weight. The attribute scale defines this relationship as:
The negative sign is because positive muscle activation generates pulling force. The constant :math:`F_0` is the peak
active force at zero velocity. It is related to the muscle thickness (i.e., physiological cross-sectional area or PCSA).
If known, it can be set with the attribute force of element :ref:`muscle <muscle>`. If it is not known, we set it to
:math:`-1` which is the default. In that case we rely on the fact that larger muscles tend to act on joints that move
more weight. The attribute scale defines this relationship as:
F0 = scale / actuator_acc0
.. math::
F_0 = \text{scale} / \texttt{actuator\_acc0}
The quantity actuator_acc0 is precomputed by the model compiler. It is the norm of the joint acceleration caused by
unit force acting on the actuator transmission. Intuitively, scale determines how strong the muscle is "on average"
while its actual strength depends on the geometric and inertial properties of the entire model.
The quantity :math:`\texttt{actuator\_acc0}` is precomputed by the model compiler. It is the norm of the joint
acceleration caused by unit force acting on the actuator transmission. Intuitively, :math:`\text{scale}` determines how
strong the muscle is "on average" while its actual strength depends on the geometric and inertial properties of the
entire model.
Thus far we encountered three constants that define the properties of an individual muscle: LT, L0, F0. In addition,
the function FLV itself has several parameters illustrated in the above figure: lmin, lmax, vmax, fpmax, fvmax. These
are supposed to be the same for all muscles, however different experimental papers suggest different shapes of the FLV
function, thus users familiar with that literature may want to adjust them. We provide the MATLAB function
`FLV.m <_static/FLV.m>`__ which was used to generate the above figure and shows how we compute the FLV function.
Thus far we encountered three constants that define the properties of an individual muscle: :math:`L_T, L_0, F_0`. In
addition, the function :math:`\text{\small FLV}` itself has several parameters illustrated in the above figure:
:math:`l_\text{min}, l_\text{max}, v_\text{max}, f_\text{pmax}, f_\text{vmax}`. These are supposed to be the same for
all muscles, however different experimental papers suggest different shapes of the FLV function, thus users familiar
with that literature may want to adjust them. We provide the MATLAB function `FLV.m <_static/FLV.m>`__ which was used to
generate the above figure and shows how we compute the :math:`\text{\small FLV}` function.
Before embarking on a mission to design more accurate FLV functions, consider the fact that the operating range of the
muscle has a bigger effect than the shape of the FLV function, and in many cases this parameter is unknown. Below is a
graphical illustration:
Before embarking on a mission to design more accurate :math:`\text{\small FLV}` functions, consider the fact that the
operating range of the muscle has a bigger effect than the shape of the :math:`\text{\small FLV}` function, and in many
cases this parameter is unknown. Below is a graphical illustration:
|image2|
This figure format is common in the biomechanics literature, showing the operating range of each muscle superimposed
on the normalized FL curve (ignore the vertical displacement). Our default range is shown in black. The blue curves
are experimental data for two arm muscles. One can find muscles with small range, large range, range spanning the
ascending portion of the FL curve, or the descending portion, or some of both. Now suppose you have a model with 50
muscles. Do you believe that someone did careful experiments and measured the operating range for every muscle in your
model, taking into account all the joints that the muscle spans? If not, then it is better to think of
This figure format is common in the biomechanics literature, showing the operating range of each muscle superimposed on
the normalized :math:`\text{FL}` curve (ignore the vertical displacement). Our default range is shown in black. The blue
curves are experimental data for two arm muscles. One can find muscles with small range, large range, range spanning the
ascending portion of the :math:`\text{FL}` curve, or the descending portion, or some of both. Now suppose you have a
model with 50 muscles. Do you believe that someone did careful experiments and measured the operating range for every
muscle in your model, taking into account all the joints that the muscle spans? If not, then it is better to think of
musculo-skeletal models as having the same general behavior as the biological system, while being different in various
details - including details that are of great interest to some research community. For most muscle properties which
modelers consider constant and known, there is an experimental paper showing that they vary under some conditions.
This is not to discourage people from building accurate models, but rather to discourage people from believing too
strongly in their models. Modeling in biology is quite different from modeling in physics and engineering... which is
why we find it ironic when people in Robotics complain that building accurate robot models is hard.
modelers consider constant and known, there is an experimental paper showing that they vary under some conditions. This
is not to discourage people from building accurate models, but rather to discourage people from believing too strongly
in their models. Modeling in biology is quite different from modeling in physics and engineering... which is why we find
it ironic when people in Robotics complain that building accurate robot models is hard.
Coming back to our muscle model, there is the muscle activation act. This is the state of a first-order nonlinear
filter whose input is the control signal. The filter dynamics are:
d act / dt = (ctrl - act) / tau(ctrl, act)
.. math::
\frac{\partial}{\partial t}\texttt{act} = \frac{\texttt{ctrl} - \texttt{act}}{\tau(\texttt{ctrl}, \texttt{act})}
Internally the control signal is clamped to [0, 1] even if the actuator does not have a control range specified. There
are two time constants specified with the attribute timeconst, namely timeconst = (tau_act, tau_deact) with defaults
(0.01, 0.04). The effective time constant tau is then computed at runtime as:
are two time constants specified with the attribute timeconst, namely :math:`\text{timeconst} = (\tau_\text{act},
\tau_\text{deact})` with defaults :math:`(0.01, 0.04)`. Following `Millard et al. (2013)
<https://doi.org/10.1115/1.4023390>`__, the effective time constant :math:`\tau` is then computed at runtime as:
tau(ctrl, act) = tau_act \* (0.5 + 1.5*act), if ctrl > act
tau(ctrl, act) = tau_deact / (0.5 + 1.5*act), if ctrl <= act
.. math::
\tau(\texttt{ctrl}, \texttt{act}) =
\begin{cases}
\tau_\text{act} \cdot (0.5 + 1.5\cdot\texttt{act}) & \texttt{ctrl} \gt \texttt{act} \\
\tau_\text{deact} / (0.5 + 1.5\cdot\texttt{act}) & \texttt{ctrl} \leq \texttt{act}
\end{cases}
Now we summarize the attributes of element :ref:`muscle <muscle>` which users may want to adjust,
depending on their familiarity with the biomechanics literature and availability of detailed measurements with regard
@@ -747,8 +823,8 @@ scale
This can be adjusted separately for each muscle, but it makes more sense to set it once in the
:ref:`default <default>` element.
force
If you know the peak active force F0 of the individual muscles, enter it here. Many experimental papers contain this
data.
If you know the peak active force :math:`F_0` of the individual muscles, enter it here. Many experimental papers
contain this data.
range
The operating range of the muscle in scaled lengths is also available in some papers. It is not clear how reliable
such measurements are (given that muscles act on many joints) but they do exist. Note that the range differs
@@ -756,11 +832,11 @@ range
timeconst
Muscles are composed of slow-twitch and fast-twitch fibers. The typical muscle is mixed, but some muscles have a
higher proportion of one or the other fiber type, making them faster or slower. This can be modeled by adjusting the
time constants. The vmax parameter of the FLV function should also be adjusted accordingly.
time constants. The vmax parameter of the :math:`\text{\small FLV}` function should also be adjusted accordingly.
lmin, lmax, vmax, fpmax, fvmax
These are the parameters controlling the shape of the FLV function. Advanced users can experiment with them; see
MATLAB function `FLV.m <_static/FLV.m>`__. Similar to the scale setting, if you want to change the FLV
parameters for all muscles, do so in the :ref:`default <default>` element.
These are the parameters controlling the shape of the :math:`\text{\small FLV}` function. Advanced users can
experiment with them; see MATLAB function `FLV.m <_static/FLV.m>`__. Similar to the scale setting, if you want to
change the :math:`\text{\small FLV}` parameters for all muscles, do so in the :ref:`default <default>` element.
Custom model
Instead of adjusting the parameters of our muscle model, users can implement a different model, by setting gaintype,
biastype and dyntype of a :ref:`general <general>` actuator to "user" and providing callbacks at
@@ -777,17 +853,15 @@ simulations. To help MuJoCo users convert OpenSim models, here we summarize the
The activation dynamics model is identical to OpenSim, including the default time constants.
The FLV function is not exactly the same, but both MuJoCo and OpenSim approximate the same experimental data, so they
are very close. For a description of the OpenSim model and summary of relevant experimental data, see:
Millard et al, "Flexing computational muscle: modeling and simulation of musculotendon dynamics", J Biomech Eng. 2013
Feb;135(2)
The :math:`\text{\small FLV}` function is not exactly the same, but both MuJoCo and OpenSim approximate the same
experimental data, so they are very close. For a description of the OpenSim model and summary of relevant experimental
data, see `Millard et al. (2013) <https://doi.org/10.1115/1.4023390>`__.
We assume inelastic tendons while OpenSim can model tendon elasticity. We decided not to do that here, because tendon
elasticity requires fast-equilibrium assumptions which in turn require various tweaks and are prone to simulation
instability. In practice tendons are quite stiff, and their effect can be captured approximately by stretching the FL
curve corresponding to the inelastic case (Zajac 89). This can be done in MuJoCo by shortening the muscle operating
range.
instability. In practice tendons are quite stiff, and their effect can be captured approximately by stretching the
:math:`\text{FL}` curve corresponding to the inelastic case (`Zajac (1989)
<https://pubmed.ncbi.nlm.nih.gov/2676342/>`__). This can be done in MuJoCo by shortening the muscle operating range.
Pennation angle (i.e., the angle between the muscle and the line of force) is not modeled in MuJoCo and is assumed to
be 0. This effect can be approximated by scaling down the muscle force and also adjusting the operating range.
@@ -885,9 +959,9 @@ see the XML model files in the distribution for the complete examples.
.. code-block:: xml
<worldbody>
<composite type="particle" count="10 10 10" spacing="0.07" offset="0 0 1">
<geom size=".02" rgba=".8 .2 .1 1"/>
</composite>
<composite type="particle" count="10 10 10" spacing="0.07" offset="0 0 1">
<geom size=".02" rgba=".8 .2 .1 1"/>
</composite>
</worldbody>
The above XML is all it takes to create a system with 1000 particles with initial positions on a 10-10-10 grid, and
@@ -908,11 +982,11 @@ simulation at much larger timesteps (this model is stable at 30 ms timestep and
.. code-block:: xml
<composite type="grid" count="20 1 1" spacing="0.045" offset="0 0 1">
<joint kind="main" damping="0.001"/>
<tendon kind="main" width="0.01"/>
<geom size=".02" rgba=".8 .2 .1 1"/>
<pin coord="1"/>
<pin coord="13"/>
<joint kind="main" damping="0.001"/>
<tendon kind="main" width="0.01"/>
<geom size=".02" rgba=".8 .2 .1 1"/>
<pin coord="1"/>
<pin coord="13"/>
</composite>
The grid type can create 1D or 2D grids, depending on the :at:`count` attribute. Here we illustrate 1D grids. These
@@ -930,10 +1004,10 @@ example; in that case the parent body would be moving, and the first element bod
.. code-block:: xml
<composite type="grid" count="9 9 1" spacing="0.05" offset="0 0 1">
<skin material="matcarpet" inflate="0.001" subgrid="3" texcoord="true"/>
<geom size=".02"/>
<pin coord="0 0"/>
<pin coord="8 0"/>
<skin material="matcarpet" inflate="0.001" subgrid="3" texcoord="true"/>
<geom size=".02"/>
<pin coord="0 0"/>
<pin coord="8 0"/>
</composite>
A 2D grid can be used to simulate cloth. What it really simulates is a 2D grid of spheres connected with
@@ -950,11 +1024,11 @@ absence of textures. When textures are present (left) the benefits of subdivisio
.. code-block:: xml
<body name="B10" pos="0 0 1">
<freejoint/>
<composite type="rope" count="21 1 1" spacing="0.04" offset="0 0 2">
<joint kind="main" damping="0.005"/>
<geom type="capsule" size=".01 .015" rgba=".8 .2 .1 1"/>
</composite>
<freejoint/>
<composite type="rope" count="21 1 1" spacing="0.04" offset="0 0 2">
<joint kind="main" damping="0.005"/>
<geom type="capsule" size=".01 .015" rgba=".8 .2 .1 1"/>
</composite>
</body>
The remaining composite object types create kinematic trees of element bodies, and the parent body becomes the root of
@@ -978,12 +1052,12 @@ The loop is similar to a rope but the first and last element bodies are connecte
.. code-block:: xml
<body name="B3_5" pos="0 0 1">
<freejoint/>
<composite type="cloth" count="9 9 1" spacing="0.05" flatinertia="0.01">
<joint kind="main" damping="0.001"/>
<skin material="matcarpet" texcoord="true" inflate="0.005" subgrid="2"/>
<geom type="capsule" size="0.015 0.01" rgba=".8 .2 .1 1"/>
</composite>
<freejoint/>
<composite type="cloth" count="9 9 1" spacing="0.05" flatinertia="0.01">
<joint kind="main" damping="0.001"/>
<skin material="matcarpet" texcoord="true" inflate="0.005" subgrid="2"/>
<geom type="capsule" size="0.015 0.01" rgba=".8 .2 .1 1"/>
</composite>
</body>
The cloth type is an alternative to a 2D grid, and has somewhat different properties. Similar to rope vs. 1D grid, the
@@ -1004,11 +1078,11 @@ some damping for stable integration. The parameters can be found in the XML mode
.. code-block:: xml
<body pos="0 0 1">
<freejoint/>
<composite type="box" count="7 7 7" spacing="0.04">
<skin texcoord="true" material="matsponge" rgba=".7 .7 .7 1"/>
<geom type="capsule" size=".015 0.05" rgba=".8 .2 .1 1"/>
</composite>
<freejoint/>
<composite type="box" count="7 7 7" spacing="0.04">
<skin texcoord="true" material="matsponge" rgba=".7 .7 .7 1"/>
<geom type="capsule" size=".015 0.05" rgba=".8 .2 .1 1"/>
</composite>
</body>
The box type, as well as the cylinder and ellipsoid types below, are used to model soft 3D objects. The element bodies
@@ -1036,11 +1110,11 @@ points to the outside, thus creating a thicker shell which is harder to penetrat
.. code-block:: xml
<body pos="0 0 1">
<freejoint/>
<composite type="ellipsoid" count="5 7 9" spacing="0.05">
<skin texcoord="true" material="matsponge" rgba=".7 .7 .7 1"/>
<geom type="capsule" size=".015 0.05" rgba=".8 .2 .1 1"/>
</composite>
<freejoint/>
<composite type="ellipsoid" count="5 7 9" spacing="0.05">
<skin texcoord="true" material="matsponge" rgba=".7 .7 .7 1"/>
<geom type="capsule" size=".015 0.05" rgba=".8 .2 .1 1"/>
</composite>
</body>
Cylinders and ellipsoids are created in the same way as boxes. The only difference is that the reference positions of
@@ -1141,11 +1215,11 @@ Here is an example extension section of a URDF model:
.. code-block:: xml
<robot name="darwin">
<mujoco>
<compiler meshdir="../mesh/darwin/" balanceinertia="true"/>
</mujoco>
<link name="MP_BODY">
...
<mujoco>
<compiler meshdir="../mesh/darwin/" balanceinertia="true"/>
</mujoco>
<link name="MP_BODY">
...
</robot>
The above extensions make URDF more usable but still limited. If the user wants to build models taking full advantage of
@@ -1179,8 +1253,8 @@ orientation:
.. code-block:: xml
<body>
<joint name="J1" type="hinge" pos="0 0 0" axis="0 0 1" armature="0.01"/>
<joint name="J2" type="hinge" pos="0 0 0" axis="0 0 1" limited="true" range="-1 1"/>
<joint name="J1" type="hinge" pos="0 0 0" axis="0 0 1" armature="0.01"/>
<joint name="J2" type="hinge" pos="0 0 0" axis="0 0 1" limited="true" range="-1 1"/>
</body>
Thus the overall rotation of the body relative to its parent is J1+J2. Now define an actuator acting only on J1. The
@@ -1249,12 +1323,12 @@ in a visible way, and the energy fluctuates around the initial value instead of
.. code-block:: xml
<worldbody>
<geom type="plane" size="1 1 .1"/>
<geom type="plane" size="1 1 .1"/>
<body pos="0 0 1">
<freejoint/>
<geom type="sphere" size="0.1" solref="-1000 0"/>
</body>
<body pos="0 0 1">
<freejoint/>
<geom type="sphere" size="0.1" solref="-1000 0"/>
</body>
</worldbody>
.. _CSize:
+29 -3
View File
@@ -640,6 +640,32 @@ interpreted as MKS, then forces and torques are in Newton and Newton-Meter, resp
are using MKS, angular velocities reported by :ref:`gyroscopes<sensor-gyro>` would be in rad/s while stiffness of hinge
joints would be in Nm/rad.
.. _SurprisingCollisions:
Surprising Collisions
~~~~~~~~~~~~~~~~~~~~~
MuJoCo by default excludes collisions between geoms that belong to body pairs which have a direct parent-child
relationship. For example, consider the arm model in the :ref:`Examples` section above: there is no collision at the
"elbow" even though the capsule geoms are penetrating, because the forearm is an immediate child of the upper arm.
However, this exclusion is **not applied if the parent is a static body** i.e., the world body, or a body without any
degrees of freedom relative to the world body. This behavior, documented in the :ref:`Collision detection<Collision>`
section, prevents objects from falling through the floor or moving through walls. However, this behavior often leads to
the following situation:
The user comments out the root joint of a floating-base model, perhaps in order to prevent it from falling; now that the
base body is counted as static, new collisions appear that were not there before and the user is confused. There are two
easy ways to avoid this problem:
1. Don't remove the root joint. Perhaps it is enough to :ref:`disable gravity<option-flag>` and possibly add some
:ref:`fluid viscosity<option>` in order to prevent your model from moving around too much.
2. Use :ref:`collision filtering<Collision>` to explicitly disable the unwanted collisions, either by setting the
relevant :at:`contype` and :at:`conaffinity` attributes, or by using a contact :ref:`exclude <exclude>` directive.
.. _NotObject:
Not object-oriented
@@ -707,7 +733,7 @@ first, followed by the limits of the second joint etc. This ordering reflects th
row-major format.
The available element types are defined in
`mjmodel.h <https://github.com/deepmind/mujoco/blob/main/include/mjmodel.h#L243>`_, in the enum type :ref:`mjtObj`.
`mjmodel.h <https://github.com/deepmind/mujoco/blob/main/include/mujoco/mjmodel.h#L243>`_, in the enum type :ref:`mjtObj`.
These enums are mostly used internally. One exception are the functions :ref:`mj_name2id` and :ref:`mj_id2name` in the
MuJoCo API, which map element names to integer ids and vice versa. These functions take an element type as input.
@@ -761,8 +787,8 @@ properties.
Sites are light geoms. They have the same appearance properties but cannot participate in collisions and cannot be used
to infer body masses. On the other hand sites can do things that geoms cannot do: they can specify the volumes of touch
sensors, the attachment of IMU sensors, the routing of spatial tendons, the end-points of slider-crank actuators. These
are all spatial quantities, and yet they do not correspond to entities that should have mass or collide other entities -
which is why the site element was created. Sites can also be used to specify points (or rather frames) of interest to
are all spatial quantities, and yet they do not correspond to entities that should have mass or collide other entities
-- which is why the site element was created. Sites can also be used to specify points (or rather frames) of interest to
the user.
The following example illustrates the point that multiple sites and geoms can be attached to the same body: two sites
+183 -160
View File
@@ -2,6 +2,8 @@
Programming
===========
.. _inIntro:
Introduction
------------
@@ -10,32 +12,16 @@ is a dynamic library compatible with Windows, Linux and macOS, which requires a
library exposes the full functionality of the simulator through a compiler-independent shared-memory C API. It can also
be used in C++ programs.
MuJoCo is a free product currently distributed as a pre-built dynamic library and will soon be made available as an
open-source project. The software distribution contains a compiled version of GLFW which is used in the code samples to
create an OpenGL window and direct user input to it. The distribution for each platform contains the following dynamic
library:
.. code-block:: Text
Windows: mujoco.dll (stub library: mujoco.lib)
Linux: mujoco.so.2.1.5
macOS: mujoco.2.1.5.dylib
Even though MuJoCo is a single dynamic library with unified C API, it contains several modules, some of which are
implemented in C++. We have taken advantage of the convenience of C++ for functionality that is used before the
simulation starts (namely the parser and compiler), and have gone to the trouble of writing carefully-tuned C code for
all runtime functionality. The modules are:
The MuJoCo codebase is organized into subdirectories corresponding to different major areas of functionality:
Engine
The simulator (or physics engine) is written in C. It is responsible for all runtime computations.
Parser
The XML parser is written in C++. It can parse MJCF models and URDF models, converting them into an internal mjCModel
C++ object which is not directly exposed to the user.
Compiler
The compiler is written in C++. It takes an mjCModel C++ object constructed by the parser, and converts it into an
mjModel C structure used at runtime.
Simulator
The simulator (or physics engine) is written in C. It is responsible for all runtime computations.
Abstract visualizer
The abstract visualizer is written in C. It generates a list of abstract geometric entities representing the
simulation state, with all information needed for actual rendering. It also provides abstract mouse hooks for camera
@@ -54,43 +40,83 @@ UI framework
Getting started
~~~~~~~~~~~~~~~
The software distribution is a single .zip (Windows) or .tar.gz (Mac and Linux) archive whose name contains the platform
and software version, e.g. mujoco210_windows.zip. There is no installer. Simply unzip this archive in a directory of
your choice (where you have write access). You may need to use chmod to set execute permissions or otherwise give
permissions to run the libraries. From the bin subdirectory, you can now run the precompiled code samples, for example:
MuJoCo is an open source project. Pre-built dynamic libraries are available for x86_64 and arm64 machines running
Windows, Linux, and macOS. These can be downloaded from the `GitHub Releases page <https://github.com/deepmind/mujoco/releases>`_.
Users who do not intend to develop or modify core MuJoCo code are encouraged to use our pre-built libraries, as these
come bundled with the same versions of dependencies those that we regularly test against, and benefit from build flags
that have been tuned for performance. Our pre-built libraries are almost entirely self-contained and do not require
other any library to be present, other than the standard C runtime. We also hide all symbols corresponding apart from
those that form MuJoCo's public API, thus ensuring that it can coexist with any other libraries that may be loaded into
the process (including other versions of libraries that MuJoCo depends on).
The pre-built distribution is a single .zip on Windows, .dmg on macOS, and .tar.gz on Linux. There is no installer.
On Windows and Linux, simply extract the archive in a directory of your choice. From the ``bin`` subdirectory, you can
now run the precompiled code samples, for example:
.. code-block:: Text
Windows: simulate ..\model\humanoid.xml
Linux and macOS: ./simulate ../model/humanoid.xml
Prior to MuJoCo 2.0, running the code samples needed LD_LIBRARY_PATH on Linux. As of MuJoCo 2.0, they are compiled with
"rpath $ORIGIN" so the library is found in the executable directory (if it is not in the path).
The directory structure is shown below. Users can re-organize it if needed, as well as install the dynamic libraries in
other directories and set the path accordingly. The only file created automatically is MUJOCO_LOG.TXT in the executable
directory; it contains error and warning messages, and can be deleted at any time.
.. code-block:: Text
mujoco210
bin - dynamic libraries, executables, MUJOCO_LOG.TXT
doc - README.txt and REFERENCE.txt
include - header files needed to develop with MuJoCo
model - model collection (extra models available on the Forum)
sample - code samples and makefile need to build them
bin - dynamic libraries, executables, MUJOCO_LOG.TXT
doc - README.txt and REFERENCE.txt
include - header files needed to develop with MuJoCo
model - model collection
sample - code samples and makefile need to build them
After verifying that the simulator works, the next step is to re-compile the code samples so as to ensure that the
development environment is properly installed. The distribution includes a platform-specific makefile in the sample
subdirectory, which assumes Visual Studio on Windows, GCC on Linux and Clang on macOS. On Windows, remember to open a
Visual Studio command prompt with native x64 tools. Assuming the compilation succeeded and the resulting executables in
the bin subdirectory work, you are ready to start developing with MuJoCo.
After verifying that the simulator works, you may also want to re-compile the code samples to ensure that you have a
working development environment. We provide Makefiles for `Windows <https://github.com/deepmind/mujoco/blob/main/sample/Makefile.windows>`_,
`macOS <https://github.com/deepmind/mujoco/blob/main/sample/Makefile.macos>`_, and
`Linux <https://github.com/deepmind/mujoco/blob/main/sample/Makefile>`_, and also a cross-platform
`CMake <https://github.com/deepmind/mujoco/blob/main/sample/CMakeLists.txt>`_ setup that can be used to build sample
applications independently of the MuJoCo library itself. If you are using the vanilla Makefile, we assume that you are
using Visual Studio on Windows and LLVM/Clang on Linux. On Windows, you also need to either open a Visual Studio command
prompt with native x64 tools or call the ``vcvarsall.bat`` script that comes with your MSVC installation to set up the
appropriate environment variables.
As already mentioned, MuJoCo is a compiler-independent library. In theory the user should be able to switch to any
compiler of their choice. In practice we are using C++11 features as well as std:: functionality internally, and despite
our efforts to statically link all necessary runtime libraries, this is not always possible - especially on Linux where
licensing restrictions prevent static linking. If MuJoCo fails to start because of missing or incompatible dynamic
libraries, please install the necessary libraries.
On macOS, the DMG disk image contains ``MuJoCo.app``, which you can double-click to launch the ``simulate`` GUI.
You can also drag ``MuJoCo.app`` into the ``/Application`` on your system, as you would to install any other app.
While ``MuJoCo.app`` may look like a file, it is in fact an `Application Bundle <https://developer.apple.com/go/?id=bundle-structure>`_,
which is a directory that contains executable binaries for all of MuJoCo's sample applications, along with an embedded
`framework <https://developer.apple.com/library/archive/documentation/MacOSX/Conceptual/BPFrameworks/Concepts/WhatAreFrameworks.html>`_,
which is a subdirectory containing the MuJoCo dynamic library and all of its public headers. In other words,
``MuJoCo.app`` contains all the same files that are shipped in the archive on Windows and Linux. To see this, right
click (or control-click) on ``MuJoCo.app`` and click "Show Package Contents".
As mentioned above, ``mujoco.framework`` contains the library and headers that are necessary to build any application
that depends on MuJoCo. If you are using Xcode, you can import it as a framework dependency on your project. (This also
works for Swift projects without any modification). If you are building manually, you can use ``-F`` and
``-framework mujoco`` to specify the header search path and the library search path respectively. The macOS Makefile
provides an example for this.
.. _inBuild:
Building MuJoCo from source
~~~~~~~~~~~~~~~~~~~~~~~~~~~
To build MuJoCo from source, you will need CMake and a working C++17 compiler installed. The steps are:
#. Clone the ``mujoco`` repository from GitHub.
#. Create a new build directory somewhere, and ``cd`` into it.
#. Run ``cmake $PATH_TO_CLONED_REPO`` to configure the build.
#. Run ``cmake --build .`` to build.
MuJoCo's build system automatically fetches dependencies from upstream repositories over the Internet using CMake's
`FetchContent <https://cmake.org/cmake/help/latest/module/FetchContent.html>`_ module.
The main CMake setup will build the MuJoCo library itself along with all sample applications, but the Python
bindings are not built. Those come with their own build instructions, which can be found in the :doc:`python`
section of the documentation.
Additionally, the CMake setup also implements an installation phase which will copy and organize the output files to a
target directory. Specify the directory using ``cmake $PATH_TO_CLONED_REPO -DCMAKE_INSTALL_PREFIX=<my_install_dir>``.
After successfully building MuJoCo following the instructions above, you can install it using ``cmake --install .``.
.. _inHeader:
@@ -100,29 +126,29 @@ Header files
The distribution contains several header files which are identical on all platforms. They are also available from the
links below, to make this documentation self-contained.
mujoco.h   `(source) <https://github.com/deepmind/mujoco/blob/main/include/mujoco.h>`__
mujoco.h   `(source) <https://github.com/deepmind/mujoco/blob/main/include/mujoco/mujoco.h>`__
This is the main header file and must be included in all programs using MuJoCo. It defines all API functions and
global variables, and includes the next 5 files which provide the necessary type definitions.
mjmodel.h   `(source) <https://github.com/deepmind/mujoco/blob/main/include/mjmodel.h>`__
mjmodel.h   `(source) <https://github.com/deepmind/mujoco/blob/main/include/mujoco/mjmodel.h>`__
This file defines the C structure :ref:`mjModel` which is the runtime representation of the
model being simulated. It also defines a number of primitive types and other structures needed to define mjModel.
mjdata.h   `(source) <https://github.com/deepmind/mujoco/blob/main/include/mjdata.h>`__
mjdata.h   `(source) <https://github.com/deepmind/mujoco/blob/main/include/mujoco/mjdata.h>`__
This file defines the C structure :ref:`mjData` which is the workspace where all computations
read their inputs and write their outputs. It also defines primitive types and other structures needed to define
mjData.
mjvisualize.h   `(source) <https://github.com/deepmind/mujoco/blob/main/include/mjvisualize.h>`__
mjvisualize.h   `(source) <https://github.com/deepmind/mujoco/blob/main/include/mujoco/mjvisualize.h>`__
This file defines the primitive types and structures needed by the abstract visualizer.
mjrender.h   `(source) <https://github.com/deepmind/mujoco/blob/main/include/mjrender.h>`__
mjrender.h   `(source) <https://github.com/deepmind/mujoco/blob/main/include/mujoco/mjrender.h>`__
This file defines the primitive types and structures needed by the OpenGL renderer.
mjui.h   `(source) <https://github.com/deepmind/mujoco/blob/main/include/mjui.h>`__
mjui.h   `(source) <https://github.com/deepmind/mujoco/blob/main/include/mujoco/mjui.h>`__
This file defines the primitive types and structures needed by the UI framework.
mjtnum.h   `(source) <https://github.com/deepmind/mujoco/blob/main/include/mjtnum.h>`__
mjtnum.h   `(source) <https://github.com/deepmind/mujoco/blob/main/include/mujoco/mjtnum.h>`__
Defines MuJoCo's ``mjtNum`` floating-point type to be either ``double`` or ``float``. See :ref:`mjtNum`.
mjxmacro.h   `(source) <https://github.com/deepmind/mujoco/blob/main/include/mjxmacro.h>`__
mjxmacro.h   `(source) <https://github.com/deepmind/mujoco/blob/main/include/mujoco/mjxmacro.h>`__
This file is optional and is not included by mujoco.h. It defines :ref:`X Macros <tyXMacro>` that can
automate the mapping of mjModel and mjData into scripting languages, as well as other operations that require
accessing all fields of mjModel and mjData. See code sample :ref:`testxml.cc <saTestXML>`.
mjexport.h   `(source) <https://github.com/deepmind/mujoco/blob/main/include/mjexport.h>`__
mjexport.h   `(source) <https://github.com/deepmind/mujoco/blob/main/include/mujoco/mjexport.h>`__
Macros used for exporting public symbols from the MuJoCo library. This header should not be used directly by client
code.
glfw3.h
@@ -152,7 +178,7 @@ the symbol :ref:`mjVERSION_HEADER <glNumeric>` and the library provides the func
// recommended version check
if( mjVERSION_HEADER!=mj_version() )
complain();
complain();
Note that only the main header defines this symbol. We assume that the collection of headers released with each software
version will stay together and will not be mixed between versions. To avoid complications with floating-point
@@ -309,7 +335,10 @@ This code sample is a full-featured interactive simulator. It opens an OpenGL wi
GLFW library, and renders the simulation state in it. There is built-in help, simulation statistics, profiler, sensor
data plots. The model file can be specified as a command-line argument, or loaded at runtime using drag-and-drop
functionality. As of MuJoCo 2.0, this code sample uses the native UI to render various controls, and provides an
illustration of how the new UI framework is intended to be used.
illustration of how the new UI framework is intended to be used. Below is a screen-capture of ``simulate`` in action:
.. youtube:: 0ORsj_E17B0
:align: center
Interaction is done with the mouse; see the built-in help for summary of available commands. Briefly, an object is
selected by left-double-click. The user can then apply forces and torques on the selected object by holding Ctrl and
@@ -556,7 +585,7 @@ function :ref:`mj_step` in a loop such as
// simulate until t = 10 seconds
while( d->time<10 )
mj_step(m, d);
mj_step(m, d);
This by itself will simulate the passive dynamics, because we have not provided any control signals or applied forces.
The default (and recommended) way to control the system is to implement a control callback, for example
@@ -566,8 +595,8 @@ The default (and recommended) way to control the system is to implement a contro
// simple controller applying damping to each dof
void mycontroller(const mjModel* m, mjData* d)
{
if( m->nu==m->nv )
mju_scl(d->ctrl, d->qvel, -0.1, m->nv);
if( m->nu==m->nv )
mju_scl(d->ctrl, d->qvel, -0.1, m->nv);
}
This illustrates two concepts. First, we are checking if the number of controls ``mjModel.nu`` equals the number of
@@ -595,10 +624,9 @@ control callback) would become
.. code-block:: C
while( d->time<10 )
{
// set d->ctrl or d->qfrc_applied or d->xfrc_applied
mj_step(m, d);
while( d->time<10 ) {
// set d->ctrl or d->qfrc_applied or d->xfrc_applied
mj_step(m, d);
}
Why would we not be able to compute the controls before ``mj_step`` is called? After all, isn't this what causality means?
@@ -619,11 +647,10 @@ before the control is needed, and after the control is needed. The simulation lo
.. code-block:: C
while( d->time<10 )
{
mj_step1(m, d);
// set d->ctrl or d->qfrc_applied or d->xfrc_applied
mj_step2(m, d);
while( d->time<10 ) {
mj_step1(m, d);
// set d->ctrl or d->qfrc_applied or d->xfrc_applied
mj_step2(m, d);
}
There is one complication however: this only works with Euler integration. The Runge-Kutta integrator (as well as other
@@ -637,23 +664,22 @@ omitting some code that computes timing diagnostics. The main simulation functio
.. code-block:: C
void mj_step(const mjModel* m, mjData* d)
{
// common to all integrators
mj_checkPos(m, d);
mj_checkVel(m, d);
mj_forward(m, d);
mj_checkAcc(m, d);
void mj_step(const mjModel* m, mjData* d) {
// common to all integrators
mj_checkPos(m, d);
mj_checkVel(m, d);
mj_forward(m, d);
mj_checkAcc(m, d);
// compare forward and inverse solutions if enabled
if( mjENABLED(mjENBL_FWDINV) )
mj_compareFwdInv(m, d);
// compare forward and inverse solutions if enabled
if( mjENABLED(mjENBL_FWDINV) )
mj_compareFwdInv(m, d);
// use selected integrator
if( m->opt.integrator==mjINT_RK4 )
mj_RungeKutta(m, d, 4);
else
mj_Euler(m, d);
// use selected integrator
if( m->opt.integrator==mjINT_RK4 )
mj_RungeKutta(m, d, 4);
else
mj_Euler(m, d);
}
The checking functions reset the simulation automatically if any numerical values have become invalid or too large.
@@ -668,34 +694,34 @@ mj_step2 regardless of the setting of ``mjModel.opt.integrator``.
void mj_step1(const mjModel* m, mjData* d)
{
mj_checkPos(m, d);
mj_checkVel(m, d);
mj_fwdPosition(m, d);
mj_sensorPos(m, d);
mj_energyPos(m, d);
mj_fwdVelocity(m, d);
mj_sensorVel(m, d);
mj_energyVel(m, d);
mj_checkPos(m, d);
mj_checkVel(m, d);
mj_fwdPosition(m, d);
mj_sensorPos(m, d);
mj_energyPos(m, d);
mj_fwdVelocity(m, d);
mj_sensorVel(m, d);
mj_energyVel(m, d);
// if we had a callback we would be using mj_step, but call it anyway
if( mjcb_control )
mjcb_control(m, d);
// if we had a callback we would be using mj_step, but call it anyway
if( mjcb_control )
mjcb_control(m, d);
}
void mj_step2(const mjModel* m, mjData* d)
{
mj_fwdActuation(m, d);
mj_fwdAcceleration(m, d);
mj_fwdConstraint(m, d);
mj_sensorAcc(m, d);
mj_checkAcc(m, d);
mj_fwdActuation(m, d);
mj_fwdAcceleration(m, d);
mj_fwdConstraint(m, d);
mj_sensorAcc(m, d);
mj_checkAcc(m, d);
// compare forward and inverse solutions if enabled
if( mjENABLED(mjENBL_FWDINV) )
mj_compareFwdInv(m, d);
// compare forward and inverse solutions if enabled
if( mjENABLED(mjENBL_FWDINV) )
mj_compareFwdInv(m, d);
// integrate with Euler; ignore integrator option
mj_Euler(m, d);
// integrate with Euler; ignore integrator option
mj_Euler(m, d);
}
.. _siStateControl:
@@ -830,37 +856,35 @@ skip arguments (mjSTAGE_NONE, 0), where the latter function is implemented as
.. code-block:: C
void mj_forwardSkip(const mjModel* m, mjData* d,
int skipstage, int skipsensor)
{
// position-dependent
if( skipstage<mjSTAGE_POS )
{
mj_fwdPosition(m, d);
if( !skipsensor )
mj_sensorPos(m, d);
if( mjENABLED(mjENBL_ENERGY) )
mj_energyPos(m, d);
}
// velocity-dependent
if( skipstage<mjSTAGE_VEL )
{
mj_fwdVelocity(m, d);
if( !skipsensor )
mj_sensorVel(m, d);
if( mjENABLED(mjENBL_ENERGY) )
mj_energyVel(m, d);
}
// acceleration-dependent
if( mjcb_control )
mjcb_control(m, d);
mj_fwdActuation(m, d);
mj_fwdAcceleration(m, d);
mj_fwdConstraint(m, d);
void mj_forwardSkip(const mjModel* m, mjData* d, int skipstage, int skipsensor) {
// position-dependent
if( skipstage<mjSTAGE_POS )
{
mj_fwdPosition(m, d);
if( !skipsensor )
mj_sensorAcc(m, d);
mj_sensorPos(m, d);
if( mjENABLED(mjENBL_ENERGY) )
mj_energyPos(m, d);
}
// velocity-dependent
if( skipstage<mjSTAGE_VEL )
{
mj_fwdVelocity(m, d);
if( !skipsensor )
mj_sensorVel(m, d);
if( mjENABLED(mjENBL_ENERGY) )
mj_energyVel(m, d);
}
// acceleration-dependent
if( mjcb_control )
mjcb_control(m, d);
mj_fwdActuation(m, d);
mj_fwdAcceleration(m, d);
mj_fwdConstraint(m, d);
if( !skipsensor )
mj_sensorAcc(m, d);
}
Note that this is the same sequence of calls as in mj_step1 and mj_step2 above, except that checking of real values
@@ -985,17 +1009,17 @@ management.
// parallel section
#pragma omp parallel
{
int n = omp_get_thread_num(); // thread-private variable with thread id (0 to nthread-1)
int n = omp_get_thread_num(); // thread-private variable with thread id (0 to nthread-1)
// ... initialize d[n] from results in serial code
// ... initialize d[n] from results in serial code
// thread function
worker(m, d[n]); // shared mjModel (read-only), per-thread mjData (read-write)
// thread function
worker(m, d[n]); // shared mjModel (read-only), per-thread mjData (read-write)
}
// delete per-thread mjData
for( int n=0; n<nthread; n++ )
mj_deleteData(d[n]);
mj_deleteData(d[n]);
Since all top-level API functions threat mjModel as ``const``, this multi-threading scheme is safe. Each thread only
writes to its own mjData. Therefore no further synchronization among threads is needed.
@@ -1310,11 +1334,11 @@ the total energy indicate inaccuracies in numerical integration. For such system
better performance than the default semi-implicit Euler integrator.
Finally, the user can implement additional diagnostics as needed. Two examples were provided in the code samples
``testxml.cc`` and ``derivative.cc``, where we computed model mismatches after save and load, and assessed the accuracy of the
numerical derivatives respectively. Key to such diagnostics is to implement two different algorithms or simulation
paths that compute the same quantity, and compare the results numerically. This type of sanity check is essential when
dealing with complex dynamical systems where we do not really know what the numerical output should be; if we knew
that, we would not be using a simulator in the first place.
``testxml.cc`` and ``derivative.cc``, where we computed model mismatches after save and load, and assessed the accuracy
of the numerical derivatives respectively. Key to such diagnostics is to implement two different algorithms or
simulation paths that compute the same quantity, and compare the results numerically. This type of sanity check is
essential when dealing with complex dynamical systems where we do not really know what the numerical output should be;
if we knew that, we would not be using a simulator in the first place.
.. _siJacobian:
@@ -1529,29 +1553,28 @@ one of its derivatives.
// ... install GLFW keyboard and mouse callbacks
// run main loop, target real-time simulation and 60 fps rendering
while( !glfwWindowShouldClose(window) )
{
// advance interactive simulation for 1/60 sec
// Assuming MuJoCo can simulate faster than real-time, which it usually can,
// this loop will finish on time for the next frame to be rendered at 60 fps.
// Otherwise add a cpu timer and exit this loop when it is time to render.
mjtNum simstart = d->time;
while( d->time - simstart < 1.0/60.0 )
mj_step(m, d);
while( !glfwWindowShouldClose(window) ) {
// advance interactive simulation for 1/60 sec
// Assuming MuJoCo can simulate faster than real-time, which it usually can,
// this loop will finish on time for the next frame to be rendered at 60 fps.
// Otherwise add a cpu timer and exit this loop when it is time to render.
mjtNum simstart = d->time;
while( d->time - simstart < 1.0/60.0 )
mj_step(m, d);
// get framebuffer viewport
mjrRect viewport = {0, 0, 0, 0};
glfwGetFramebufferSize(window, &viewport.width, &viewport.height);
// get framebuffer viewport
mjrRect viewport = {0, 0, 0, 0};
glfwGetFramebufferSize(window, &viewport.width, &viewport.height);
// update scene and render
mjv_updateScene(m, d, &opt, NULL, &cam, mjCAT_ALL, &scn);
mjr_render(viewport, &scn, &con);
// update scene and render
mjv_updateScene(m, d, &opt, NULL, &cam, mjCAT_ALL, &scn);
mjr_render(viewport, &scn, &con);
// swap OpenGL buffers (blocking call due to v-sync)
glfwSwapBuffers(window);
// swap OpenGL buffers (blocking call due to v-sync)
glfwSwapBuffers(window);
// process pending GUI events, call GLFW callbacks
glfwPollEvents();
// process pending GUI events, call GLFW callbacks
glfwPollEvents();
}
// close GLFW, free visualization storage
-3
View File
@@ -2,9 +2,6 @@
Python Bindings
===============
Introduction
------------
Starting with version 2.1.2, MuJoCo comes with native Python bindings that are developed in C++ using
`pybind11 <https://pybind11.readthedocs.io/>`__. Unlike previous Python bindings, these are officially supported by the
MuJoCo development team and will be kept up-to-date with the latest developments in MuJoCo itself.
+1
View File
@@ -1,6 +1,7 @@
sphinx==3.5.4
sphinx_rtd_theme==0.5.2
sphinxcontrib-katex==0.8.6
sphinxcontrib-youtube==1.1.0
sphinx-reredirects==0.0.1
nbsphinx==0.8.0
pandoc==1.0.2
+2 -2
View File
@@ -29,14 +29,14 @@ _____
The MuJoCo app needs to be run at least once before the native library can be used, in order to register the library as
a trusted binary. Then, copy the dynamic library file from
``/Applications/MuJoCo.app/Contents/Frameworks/MuJoCo.framework/Versions/Current/libmujoco.2.1.5.dylib`` (it can be
``/Applications/MuJoCo.app/Contents/Frameworks/mujoco.framework/Versions/Current/libmujoco.2.2.0.dylib`` (it can be
found by browsing the contents of ``MuJoCo.app``) and rename it as ``mujoco.dylib``.
Linux
_____
Expand the ``tar.gz`` archive to ``~/.mujoco``. Then copy the dynamic library from
``~/.mujoco/mujoco-2.1.5/lib/libmujoco.so.2.1.5`` and rename it as ``libmujoco.so``.
``~/.mujoco/mujoco-2.2.0/lib/libmujoco.so.2.2.0`` and rename it as ``libmujoco.so``.
Windows
_______
+5 -5
View File
@@ -15,8 +15,8 @@
#ifndef MUJOCO_MJDATA_H_
#define MUJOCO_MJDATA_H_
#include <mjtnum.h>
#include <mjmodel.h>
#include <mujoco/mjtnum.h>
#include <mujoco/mjmodel.h>
//---------------------------------- primitive types (mjt) -----------------------------------------
@@ -293,11 +293,11 @@ struct mjData_ {
mjtNum* qfrc_actuator; // actuator force (nv x 1)
// computed by mj_fwdAcceleration
mjtNum* qfrc_unc; // net unconstrained force (nv x 1)
mjtNum* qacc_unc; // unconstrained acceleration (nv x 1)
mjtNum* qfrc_smooth; // net unconstrained force (nv x 1)
mjtNum* qacc_smooth; // unconstrained acceleration (nv x 1)
// computed by mj_fwdConstraint/mj_inverse
mjtNum* efc_b; // linear cost term: J*qacc_unc - aref (njmax x 1)
mjtNum* efc_b; // linear cost term: J*qacc_smooth - aref (njmax x 1)
mjtNum* efc_force; // constraint force in constraint space (njmax x 1)
int* efc_state; // constraint state (mjtConstraintState) (njmax x 1)
mjtNum* qfrc_constraint; // constraint force (nv x 1)
@@ -15,7 +15,7 @@
#ifndef MUJOCO_MJMODEL_H_
#define MUJOCO_MJMODEL_H_
#include <mjtnum.h>
#include <mujoco/mjtnum.h>
// global constants
#define mjPI 3.14159265358979323846
@@ -68,9 +68,8 @@ typedef enum mjtEnableBit_ { // enable optional feature bitflags
mjENBL_ENERGY = 1<<1, // energy computation
mjENBL_FWDINV = 1<<2, // record solver statistics
mjENBL_SENSORNOISE = 1<<3, // add noise to sensor data
// experimental features:
mjENBL_MULTICCD = 1<<30, // multi-point convex collision detection
mjENBL_MULTICCD = 1<<4, // multi-point convex collision detection
mjNENABLE = 5 // number of enable flags
} mjtEnableBit;
@@ -833,11 +832,13 @@ struct mjModel_ {
int* actuator_group; // group for visibility (nu x 1)
mjtByte* actuator_ctrllimited; // is control limited (nu x 1)
mjtByte* actuator_forcelimited;// is force limited (nu x 1)
mjtByte* actuator_actlimited; // is activation limited (nu x 1)
mjtNum* actuator_dynprm; // dynamics parameters (nu x mjNDYN)
mjtNum* actuator_gainprm; // gain parameters (nu x mjNGAIN)
mjtNum* actuator_biasprm; // bias parameters (nu x mjNBIAS)
mjtNum* actuator_ctrlrange; // range of controls (nu x 2)
mjtNum* actuator_forcerange; // range of forces (nu x 2)
mjtNum* actuator_actrange; // range of activations (nu x 2)
mjtNum* actuator_gear; // scale length and transmitted force (nu x 6)
mjtNum* actuator_cranklength; // crank length for slider-crank (nu x 1)
mjtNum* actuator_acc0; // acceleration from unit force in qpos0 (nu x 1)
@@ -15,7 +15,7 @@
#ifndef MUJOCO_MJRENDER_H_
#define MUJOCO_MJRENDER_H_
#include <mjmodel.h>
#include <mujoco/mjmodel.h>
#if defined(__cplusplus)
extern "C" {
+1 -1
View File
@@ -15,7 +15,7 @@
#ifndef MUJOCO_MJUI_H_
#define MUJOCO_MJUI_H_
#include <mjrender.h>
#include <mujoco/mjrender.h>
#define mjMAXUISECT 10 // maximum number of sections
#define mjMAXUIITEM 80 // maximum number of items per section
@@ -15,8 +15,8 @@
#ifndef MUJOCO_MJVISUALIZE_H_
#define MUJOCO_MJVISUALIZE_H_
#include <mjtnum.h>
#include <mjmodel.h>
#include <mujoco/mjtnum.h>
#include <mujoco/mjmodel.h>
#define mjNGROUP 6 // number of geom, site, joint groups with visflags
#define mjMAXLIGHT 100 // maximum number of lights in a scene
@@ -20,28 +20,28 @@
// scalar fields of mjOption
#define MJOPTION_FLOATS \
X( mjtNum, timestep ) \
X( mjtNum, apirate ) \
X( mjtNum, impratio ) \
X( mjtNum, tolerance ) \
X( mjtNum, timestep ) \
X( mjtNum, apirate ) \
X( mjtNum, impratio ) \
X( mjtNum, tolerance ) \
X( mjtNum, noslip_tolerance ) \
X( mjtNum, mpr_tolerance ) \
X( mjtNum, density ) \
X( mjtNum, viscosity ) \
X( mjtNum, o_margin ) \
X( mjtNum, mpr_tolerance ) \
X( mjtNum, density ) \
X( mjtNum, viscosity ) \
X( mjtNum, o_margin ) \
#define MJOPTION_INTS \
X( int, integrator ) \
X( int, collision ) \
X( int, cone ) \
X( int, jacobian ) \
X( int, solver ) \
X( int, iterations ) \
X( int, integrator ) \
X( int, collision ) \
X( int, cone ) \
X( int, jacobian ) \
X( int, solver ) \
X( int, iterations ) \
X( int, noslip_iterations ) \
X( int, mpr_iterations ) \
X( int, disableflags ) \
X( int, enableflags )
X( int, mpr_iterations ) \
X( int, disableflags ) \
X( int, enableflags )
#define MJOPTION_SCALARS \
@@ -351,11 +351,13 @@
X( int, actuator_group, nu, 1 ) \
X( mjtByte, actuator_ctrllimited, nu, 1 ) \
X( mjtByte, actuator_forcelimited, nu, 1 ) \
X( mjtByte, actuator_actlimited, nu, 1 ) \
X( mjtNum, actuator_dynprm, nu, mjNDYN ) \
X( mjtNum, actuator_gainprm, nu, mjNGAIN ) \
X( mjtNum, actuator_biasprm, nu, mjNBIAS ) \
X( mjtNum, actuator_ctrlrange, nu, 2 ) \
X( mjtNum, actuator_forcerange, nu, 2 ) \
X( mjtNum, actuator_actrange, nu, 2 ) \
X( mjtNum, actuator_gear, nu, 6 ) \
X( mjtNum, actuator_cranklength, nu, 1 ) \
X( mjtNum, actuator_acc0, nu, 1 ) \
@@ -508,8 +510,8 @@
X( mjtNum, subtree_angmom, nbody, 3 ) \
X( mjtNum, actuator_force, nu, 1 ) \
X( mjtNum, qfrc_actuator, nv, 1 ) \
X( mjtNum, qfrc_unc, nv, 1 ) \
X( mjtNum, qacc_unc, nv, 1 ) \
X( mjtNum, qfrc_smooth, nv, 1 ) \
X( mjtNum, qacc_smooth, nv, 1 ) \
X( mjtNum, efc_b, njmax, 1 ) \
X( mjtNum, efc_force, njmax, 1 ) \
X( int, efc_state, njmax, 1 ) \
+32 -50
View File
@@ -15,7 +15,7 @@
#ifndef MUJOCO_MUJOCO_H_
#define MUJOCO_MUJOCO_H_
#include <mjexport.h>
#include <mujoco/mjexport.h>
// this is a C-API
@@ -24,7 +24,7 @@ extern "C" {
#endif
// header version; should match the library version as returned by mj_version()
#define mjVERSION_HEADER 215
#define mjVERSION_HEADER 220
// needed to define size_t, fabs and log10
#include "stdlib.h"
@@ -32,12 +32,12 @@ extern "C" {
// type definitions
#include <mjdata.h>
#include <mjmodel.h>
#include <mjrender.h>
#include <mjtnum.h>
#include <mjui.h>
#include <mjvisualize.h>
#include <mujoco/mjdata.h>
#include <mujoco/mjmodel.h>
#include <mujoco/mjrender.h>
#include <mujoco/mjtnum.h>
#include <mujoco/mjui.h>
#include <mujoco/mjvisualize.h>
// macros
@@ -139,12 +139,10 @@ MJAPI void mj_forward(const mjModel* m, mjData* d);
MJAPI void mj_inverse(const mjModel* m, mjData* d);
// Forward dynamics with skip; skipstage is mjtStage.
MJAPI void mj_forwardSkip(const mjModel* m, mjData* d,
int skipstage, int skipsensor);
MJAPI void mj_forwardSkip(const mjModel* m, mjData* d, int skipstage, int skipsensor);
// Inverse dynamics with skip; skipstage is mjtStage.
MJAPI void mj_inverseSkip(const mjModel* m, mjData* d,
int skipstage, int skipsensor);
MJAPI void mj_inverseSkip(const mjModel* m, mjData* d, int skipstage, int skipsensor);
//---------------------------------- Initialization ------------------------------------------------
@@ -215,8 +213,7 @@ MJAPI int mj_setLengthRange(mjModel* m, mjData* d, int index,
// Print mjModel to text file, specifying format.
// float_format must be a valid printf-style format string for a single float value.
MJAPI void mj_printFormattedModel(const mjModel* m, const char* filename,
const char* float_format);
MJAPI void mj_printFormattedModel(const mjModel* m, const char* filename, const char* float_format);
// Print model to text file.
MJAPI void mj_printModel(const mjModel* m, const char* filename);
@@ -234,8 +231,7 @@ MJAPI void mju_printMat(const mjtNum* mat, int nr, int nc);
// Print sparse matrix to screen.
MJAPI void mju_printMatSparse(const mjtNum* mat, int nr,
const int* rownnz, const int* rowadr,
const int* colind);
const int* rownnz, const int* rowadr, const int* colind);
//---------------------------------- Components ----------------------------------------------------
@@ -246,7 +242,7 @@ MJAPI void mj_fwdPosition(const mjModel* m, mjData* d);
// Run velocity-dependent computations.
MJAPI void mj_fwdVelocity(const mjModel* m, mjData* d);
// Compute actuator force qfrc_actuation.
// Compute actuator force qfrc_actuator.
MJAPI void mj_fwdActuation(const mjModel* m, mjData* d);
// Add up all non-constraint forces, compute qacc_unc.
@@ -375,35 +371,29 @@ MJAPI int mj_isSparse(const mjModel* m);
MJAPI int mj_isDual(const mjModel* m);
// Multiply dense or sparse constraint Jacobian by vector.
MJAPI void mj_mulJacVec(const mjModel* m, mjData* d,
mjtNum* res, const mjtNum* vec);
MJAPI void mj_mulJacVec(const mjModel* m, mjData* d, mjtNum* res, const mjtNum* vec);
// Multiply dense or sparse constraint Jacobian transpose by vector.
MJAPI void mj_mulJacTVec(const mjModel* m, mjData* d, mjtNum* res, const mjtNum* vec);
// Compute 3/6-by-nv end-effector Jacobian of global point attached to given body.
MJAPI void mj_jac(const mjModel* m, const mjData* d,
mjtNum* jacp, mjtNum* jacr, const mjtNum point[3], int body);
MJAPI void mj_jac(const mjModel* m, const mjData* d, mjtNum* jacp, mjtNum* jacr,
const mjtNum point[3], int body);
// Compute body frame end-effector Jacobian.
MJAPI void mj_jacBody(const mjModel* m, const mjData* d,
mjtNum* jacp, mjtNum* jacr, int body);
MJAPI void mj_jacBody(const mjModel* m, const mjData* d, mjtNum* jacp, mjtNum* jacr, int body);
// Compute body center-of-mass end-effector Jacobian.
MJAPI void mj_jacBodyCom(const mjModel* m, const mjData* d,
mjtNum* jacp, mjtNum* jacr, int body);
MJAPI void mj_jacBodyCom(const mjModel* m, const mjData* d, mjtNum* jacp, mjtNum* jacr, int body);
// Compute geom end-effector Jacobian.
MJAPI void mj_jacGeom(const mjModel* m, const mjData* d,
mjtNum* jacp, mjtNum* jacr, int geom);
MJAPI void mj_jacGeom(const mjModel* m, const mjData* d, mjtNum* jacp, mjtNum* jacr, int geom);
// Compute site end-effector Jacobian.
MJAPI void mj_jacSite(const mjModel* m, const mjData* d,
mjtNum* jacp, mjtNum* jacr, int site);
MJAPI void mj_jacSite(const mjModel* m, const mjData* d, mjtNum* jacp, mjtNum* jacr, int site);
// Compute translation end-effector Jacobian of point, and rotation Jacobian of axis.
MJAPI void mj_jacPointAxis(const mjModel* m, mjData* d,
mjtNum* jacPoint, mjtNum* jacAxis,
MJAPI void mj_jacPointAxis(const mjModel* m, mjData* d, mjtNum* jacPoint, mjtNum* jacAxis,
const mjtNum point[3], const mjtNum axis[3], int body);
// Get id of object with specified name, return -1 if not found; type is mjtObj.
@@ -423,12 +413,10 @@ MJAPI void mj_mulM2(const mjModel* m, const mjData* d, mjtNum* res, const mjtNum
// Add inertia matrix to destination matrix.
// Destination can be sparse uncompressed, or dense when all int* are NULL
MJAPI void mj_addM(const mjModel* m, mjData* d, mjtNum* dst,
int* rownnz, int* rowadr, int* colind);
MJAPI void mj_addM(const mjModel* m, mjData* d, mjtNum* dst, int* rownnz, int* rowadr, int* colind);
// Apply cartesian force and torque (outside xfrc_applied mechanism).
MJAPI void mj_applyFT(const mjModel* m, mjData* d,
const mjtNum force[3], const mjtNum torque[3],
MJAPI void mj_applyFT(const mjModel* m, mjData* d, const mjtNum force[3], const mjtNum torque[3],
const mjtNum point[3], int body, mjtNum* qfrc_target);
// Compute object 6D velocity in object-centered frame, world/local orientation.
@@ -453,9 +441,8 @@ MJAPI void mj_integratePos(const mjModel* m, mjtNum* qpos, const mjtNum* qvel, m
MJAPI void mj_normalizeQuat(const mjModel* m, mjtNum* qpos);
// Map from body local to global Cartesian coordinates.
MJAPI void mj_local2Global(mjData* d, mjtNum xpos[3], mjtNum xmat[9],
const mjtNum pos[3], const mjtNum quat[4],
int body, mjtByte sameframe);
MJAPI void mj_local2Global(mjData* d, mjtNum xpos[3], mjtNum xmat[9], const mjtNum pos[3],
const mjtNum quat[4], int body, mjtByte sameframe);
// Sum all body masses.
MJAPI mjtNum mj_getTotalmass(const mjModel* m);
@@ -657,8 +644,7 @@ MJAPI void mjr_blitBuffer(mjrRect src, mjrRect dst,
MJAPI void mjr_setAux(int index, const mjrContext* con);
// Blit from Aux buffer to con->currentBuffer.
MJAPI void mjr_blitAux(int index, mjrRect src, int left, int bottom,
const mjrContext* con);
MJAPI void mjr_blitAux(int index, mjrRect src, int left, int bottom, const mjrContext* con);
// Draw text at (x,y) in relative coordinates; font is mjtFont.
MJAPI void mjr_text(int font, const char* txt, const mjrContext* con,
@@ -914,12 +900,10 @@ MJAPI mjtNum mju_norm(const mjtNum* res, int n);
MJAPI mjtNum mju_dot(const mjtNum* vec1, const mjtNum* vec2, const int n);
// Multiply matrix and vector: res = mat * vec.
MJAPI void mju_mulMatVec(mjtNum* res, const mjtNum* mat, const mjtNum* vec,
int nr, int nc);
MJAPI void mju_mulMatVec(mjtNum* res, const mjtNum* mat, const mjtNum* vec, int nr, int nc);
// Multiply transposed matrix and vector: res = mat' * vec.
MJAPI void mju_mulMatTVec(mjtNum* res, const mjtNum* mat, const mjtNum* vec,
int nr, int nc);
MJAPI void mju_mulMatTVec(mjtNum* res, const mjtNum* mat, const mjtNum* vec, int nr, int nc);
// Transpose matrix: res = mat'.
MJAPI void mju_transpose(mjtNum* res, const mjtNum* mat, int nr, int nc);
@@ -954,10 +938,10 @@ MJAPI void mju_rotVecQuat(mjtNum res[3], const mjtNum vec[3], const mjtNum quat[
// Conjugate quaternion, corresponding to opposite rotation.
MJAPI void mju_negQuat(mjtNum res[4], const mjtNum quat[4]);
// Muiltiply quaternions.
// Multiply quaternions.
MJAPI void mju_mulQuat(mjtNum res[4], const mjtNum quat1[4], const mjtNum quat2[4]);
// Muiltiply quaternion and axis.
// Multiply quaternion and axis.
MJAPI void mju_mulQuatAxis(mjtNum res[4], const mjtNum quat[4], const mjtNum axis[3]);
// Convert axisAngle to quaternion.
@@ -1030,12 +1014,10 @@ MJAPI mjtNum mju_muscleBias(mjtNum len, const mjtNum lengthrange[2],
MJAPI mjtNum mju_muscleDynamics(mjtNum ctrl, mjtNum act, const mjtNum prm[2]);
// Convert contact force to pyramid representation.
MJAPI void mju_encodePyramid(mjtNum* pyramid, const mjtNum* force,
const mjtNum* mu, int dim);
MJAPI void mju_encodePyramid(mjtNum* pyramid, const mjtNum* force, const mjtNum* mu, int dim);
// Convert pyramid representation to contact force.
MJAPI void mju_decodePyramid(mjtNum* force, const mjtNum* pyramid,
const mjtNum* mu, int dim);
MJAPI void mju_decodePyramid(mjtNum* force, const mjtNum* pyramid, const mjtNum* mu, int dim);
// Integrate spring-damper analytically, return pos(dt).
MJAPI mjtNum mju_springDamper(mjtNum pos0, mjtNum vel0, mjtNum Kp, mjtNum Kv, mjtNum dt);
+1 -1
View File
@@ -51,7 +51,7 @@ ENUMS: Mapping[str, EnumDecl] = dict([
('mjENBL_ENERGY', 2),
('mjENBL_FWDINV', 4),
('mjENBL_SENSORNOISE', 8),
('mjENBL_MULTICCD', 1073741824),
('mjENBL_MULTICCD', 16),
('mjNENABLE', 5),
]),
)),
+1 -1
View File
@@ -42,7 +42,7 @@ class EnumsTest(absltest.TestCase):
('mjENBL_ENERGY', 1<<1),
('mjENBL_FWDINV', 1<<2),
('mjENBL_SENSORNOISE', 1<<3),
('mjENBL_MULTICCD', 1<<30),
('mjENBL_MULTICCD', 1<<4),
('mjNENABLE', 5)))
# values mostly increment by one with occasional overrides
+3 -3
View File
@@ -998,7 +998,7 @@ FUNCTIONS: Mapping[str, FunctionDecl] = dict([
),
),
),
doc='Compute actuator force qfrc_actuation.',
doc='Compute actuator force qfrc_actuator.',
)),
('mj_fwdAcceleration',
FunctionDecl(
@@ -5895,7 +5895,7 @@ FUNCTIONS: Mapping[str, FunctionDecl] = dict([
),
),
),
doc='Muiltiply quaternions.',
doc='Multiply quaternions.',
)),
('mju_mulQuatAxis',
FunctionDecl(
@@ -5924,7 +5924,7 @@ FUNCTIONS: Mapping[str, FunctionDecl] = dict([
),
),
),
doc='Muiltiply quaternion and axis.',
doc='Multiply quaternion and axis.',
)),
('mju_axisAngle2Quat',
FunctionDecl(
+24
View File
@@ -0,0 +1,24 @@
# Copyright 2021 DeepMind Technologies Limited
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# https://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
# Copy the model files to the binary directory to make them available to tests and benchmarks
file(
GLOB_RECURSE
MUJOCO_MODELS
CONFIGURE_DEPENDS
"*.xml"
"*.png"
)
file(COPY ${MUJOCO_MODELS} DESTINATION ${CMAKE_CURRENT_BINARY_DIR})
+45 -26
View File
@@ -31,44 +31,63 @@ need to be downloaded or installed separately.
### Source
**Note.** Building from source is only necessary if you are modifying the Python bindings (or are trying to run on exceptionally old Linux systems). If that's not the case, then we recommend installing the prebuilt binaries from PyPI.
**IMPORTANT:** Building from source is only necessary if you are modifying the
Python bindings (or are trying to run on exceptionally old Linux systems).
If that's not the case, then we recommend installing the prebuilt binaries from
PyPI.
Before proceeding, make sure you have CMake and a C++17 compiler installed.
1. Make sure you have CMake and a C++17 compiler installed.
1. Download the latest release of the [binary archives](https://github.com/deepmind/mujoco/releases) from GitHub. On macOS, the download corresponds to a DMG file from which you can drag the `MuJoCo` app into your Applications folder.
1. Download the [latest binary release](https://github.com/deepmind/mujoco/releases)
from GitHub. On macOS, the download corresponds to a DMG file from which you
can drag `MuJoCo.app` into your `/Applications` folder.
2. Clone the entire `mujoco` repository from GitHub and `cd` into the python directory.
1. Clone the entire `mujoco` repository from GitHub and `cd` into the python
directory.
```bash
git clone https://github.com/deepmind/mujoco.git
cd mujoco/python
```
```bash
git clone https://github.com/deepmind/mujoco.git
cd mujoco/python
```
3. Create a virtual environment:
1. Create a virtual environment:
```bash
python3 -m venv /tmp/mujoco
source /tmp/mujoco/bin/activate
```
```bash
python3 -m venv /tmp/mujoco
source /tmp/mujoco/bin/activate
```
4. Generate a [source distribution](https://packaging.python.org/en/latest/glossary/#term-Source-Distribution-or-sdist)
tarball with the `make_sdist.sh` script.
1. Generate a [source distribution](https://packaging.python.org/en/latest/glossary/#term-Source-Distribution-or-sdist)
tarball with the `make_sdist.sh` script.
```bash
cd python
bash make_sdist.sh
```
```bash
cd python
bash make_sdist.sh
```
The `make_sdist.sh` script generates additional C++ header files that are needed to build the bindings, and also pulls in required files from elsewhere in the repository outside the `python` directory into the sdist. Upon completion, the script will create a `dist` directory with a `mujoco-2.1.X.tar.gz` file (where X is the version number of the release).
The `make_sdist.sh` script generates additional C++ header files that are
needed to build the bindings, and also pulls in required files from elsewhere
in the repository outside the `python` directory into the sdist. Upon
completion, the script will create a `dist` directory with a
`mujoco-x.y.z.tar.gz` file (where `x.y.z` is the version number).
5. Install the generated tarball. You'll need to specify the path to the MuJoCo library you downloaded earlier. For example, on macOS, this will be `/Applications/MuJoCo.app/Contents/Frameworks/MuJoCo.framework` if you dragged it to your Applications folder.
1. Use the generated source distribution to build and install the bindings.
You'll need to specify the path to the MuJoCo library you downloaded earlier
in the `MUJOCO_PATH` environment variable.
```bash
cd dist
MUJOCO_PATH=/PATH/TO/MUJOCO pip install mujoco-2.1.X.tar.gz
```
**Note**: For macOS, this can be the path to a directory that contains the
`mujoco.framework`. In particular, you can set
`MUJOCO_PATH=/Applications/MuJoCo.app` if you installed MuJoCo as suggested
in step 1.
The Python bindings should now be installed! To check that they've been successfully installed, `cd` outside of the `mujoco` directory and run `python -c "import mujoco"`.
```bash
cd dist
MUJOCO_PATH=/PATH/TO/MUJOCO pip install mujoco-x.y.z.tar.gz
```
The Python bindings should now be installed! To check that they've been
successfully installed, `cd` outside of the `mujoco` directory and run
`python -c "import mujoco"`.
## Usage
+84 -45
View File
@@ -40,32 +40,60 @@ set(CMAKE_VISIBILITY_INLINES_HIDDEN ON)
separate_arguments(CMDLINE_LINK_OPTIONS UNIX_COMMAND ${CMAKE_SHARED_LINKER_FLAGS})
add_link_options(${CMDLINE_LINK_OPTIONS})
if(MSVC)
add_compile_options(/Gy /Gw /Oi)
elseif(CMAKE_CXX_COMPILER_ID STREQUAL "GNU" OR CMAKE_CXX_COMPILER_ID MATCHES "Clang")
add_compile_options(-fdata-sections -ffunction-sections)
endif()
include(MujocoLinkOptions)
get_mujoco_extra_link_options(EXTRA_LINK_OPTIONS)
add_link_options(${EXTRA_LINK_OPTIONS})
if(APPLE)
add_compile_options(-Werror=partial-availability -Werror=unguarded-availability)
add_link_options(-Wl,-no_weak_imports)
include(MujocoMacOS)
enforce_mujoco_macosx_min_version()
if(WIN32)
add_compile_definitions(_CRT_SECURE_NO_WARNINGS)
endif()
include(MujocoHarden)
add_compile_options("${MUJOCO_HARDEN_COMPILE_OPTIONS}")
add_link_options("${MUJOCO_HARDEN_LINK_OPTIONS}")
find_package(Python3 COMPONENTS Interpreter Development)
include(FindOrFetch)
# ==================== MUJOCO LIBRARY ==========================================
if(NOT TARGET mujoco)
find_library(MUJOCO_LIBRARY mujoco mujoco.2.1.5 HINTS ${MUJOCO_LIBRARY_DIR} REQUIRED)
find_path(MUJOCO_INCLUDE mujoco.h HINTS ${MUJOCO_INCLUDE_DIR} REQUIRED)
message("MuJoCo is at ${MUJOCO_LIBRARY}")
message("MuJoCo headers are at ${MUJOCO_INCLUDE}")
add_library(mujoco SHARED IMPORTED)
if(APPLE)
# On macOS, check if we are using mujoco.framework first.
# Framework headers are searched differently from normal headers.
# We need to use -F instead of the usual target_include_directories.
find_path(MUJOCO_FRAMEWORK mujoco.Framework HINTS ${MUJOCO_FRAMEWORK_DIR})
if(MUJOCO_FRAMEWORK)
message("MuJoCo framework is at ${MUJOCO_FRAMEWORK}/mujoco.framework")
set(MUJOCO_LIBRARY ${MUJOCO_FRAMEWORK}/mujoco.framework/Versions/A/libmujoco.2.2.0.dylib)
target_compile_options(mujoco INTERFACE -F${MUJOCO_FRAMEWORK})
endif()
endif()
if(NOT MUJOCO_FRAMEWORK)
find_library(MUJOCO_LIBRARY mujoco mujoco.2.2.0 HINTS ${MUJOCO_LIBRARY_DIR} REQUIRED)
find_path(MUJOCO_INCLUDE mujoco/mujoco.h HINTS ${MUJOCO_INCLUDE_DIR} REQUIRED)
message("MuJoCo is at ${MUJOCO_LIBRARY}")
message("MuJoCo headers are at ${MUJOCO_INCLUDE}")
target_include_directories(mujoco INTERFACE "${MUJOCO_INCLUDE}")
endif()
if(WIN32)
set_target_properties(mujoco PROPERTIES IMPORTED_IMPLIB "${MUJOCO_LIBRARY}")
else()
set_target_properties(mujoco PROPERTIES IMPORTED_LOCATION "${MUJOCO_LIBRARY}")
endif()
target_include_directories(mujoco INTERFACE "${MUJOCO_INCLUDE}")
if(APPLE)
execute_process(
COMMAND otool -XD ${MUJOCO_LIBRARY}
@@ -88,18 +116,7 @@ if(NOT TARGET mujoco)
endif()
# ==================== ABSEIL ==================================================
if(APPLE)
set(ABSL_EXTRA_FETCH_ARGS
PATCH_COMMAND
"sed"
"-i"
" "
"s/-march=armv8-a+crypto/-mcpu=apple-m1+crypto/g"
"${CMAKE_BINARY_DIR}/_deps/abseil-cpp-src/absl/copts/GENERATED_AbseilCopts.cmake"
)
else()
set(ABSL_EXTRA_FETCH_ARGS "")
endif()
set(MUJOCO_PYTHON_ABSL_TARGETS absl::core_headers absl::flat_hash_map absl::span)
findorfetch(
USE_SYSTEM_PACKAGE
OFF
@@ -110,14 +127,26 @@ findorfetch(
GIT_REPO
https://github.com/abseil/abseil-cpp
GIT_TAG
215105818dfde3174fe799600bb0f3cae233d0bf # 20211102.0
78f9680225b9792c26dfdd99d0bd26c96de53dd4 # # Fixes universal builds for macOS
TARGETS
absl::core_headers
absl::flat_hash_map
absl::span
${ABSL_EXTRA_FETCH_ARGS}
${MUJOCO_PYTHON_ABSL_TARGETS}
EXCLUDE_FROM_ALL
)
foreach(absl_target IN ITEMS ${MUJOCO_PYTHON_ABSL_TARGETS})
get_target_property(absl_target_aliased ${absl_target} ALIASED_TARGET)
if(absl_target_aliased)
set(absl_target ${absl_target_aliased})
endif()
get_target_property(absl_target_type ${absl_target} TYPE)
if(NOT
${absl_target_type}
STREQUAL
"INTERFACE_LIBRARY"
)
target_compile_options(${absl_target} PRIVATE ${MUJOCO_MACOS_COMPILE_OPTIONS})
target_link_options(${absl_target} PRIVATE ${MUJOCO_MACOS_LINK_OPTIONS})
endif()
endforeach()
# ==================== EIGEN ===================================================
add_compile_definitions(EIGEN_MPL2_ONLY)
@@ -138,26 +167,21 @@ findorfetch(
)
# ==================== PYBIND11 ================================================
if(MUJOCO_PYBIND11_DIR)
FetchContent_Declare(pybind11 SOURCE_DIR ${MUJOCO_PYBIND11_DIR} EXCLUDE_FROM_ALL)
FetchContent_MakeAvailable(pybind11)
else()
findorfetch(
USE_SYSTEM_PACKAGE
OFF
PACKAGE_NAME
pybind11
LIBRARY_NAME
pybind11
GIT_REPO
https://github.com/pybind/pybind11
GIT_TAG
a8f1a5567608f346bdba293b3d062a288ee16cd4
TARGETS
pybind11::pybind11_headers
EXCLUDE_FROM_ALL
)
endif()
findorfetch(
USE_SYSTEM_PACKAGE
OFF
PACKAGE_NAME
pybind11
LIBRARY_NAME
pybind11
GIT_REPO
https://github.com/pybind/pybind11
GIT_TAG
a8f1a5567608f346bdba293b3d062a288ee16cd4
TARGETS
pybind11::pybind11_headers
EXCLUDE_FROM_ALL
)
# ==================== MUJOCO PYTHON BINDINGS ==================================
@@ -222,6 +246,7 @@ target_link_libraries(
structs_header
INTERFACE absl::flat_hash_map
absl::span
crossplatform
mujoco
raw
)
@@ -246,6 +271,19 @@ get_avx_compile_options(AVX_COMPILE_OPTIONS)
macro(mujoco_pybind11_module name)
pybind11_add_module(${name} ${ARGN})
target_compile_options(${name} PRIVATE ${AVX_COMPILE_OPTIONS})
if(NOT MSVC)
target_compile_options(${name} PRIVATE -Wall -Werror)
if(CMAKE_C_COMPILER_ID STREQUAL GNU)
target_compile_options(
${name}
PRIVATE -Wno-int-in-bool-context
-Wno-maybe-uninitialized
-Wno-sign-compare
-Wno-stringop-overflow
-Wno-stringop-truncation
)
endif()
endif()
set_target_properties(${name} PROPERTIES LIBRARY_OUTPUT_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR})
if(APPLE)
add_custom_command(
@@ -323,6 +361,7 @@ mujoco_pybind11_module(
target_link_libraries(
_structs
PRIVATE absl::flat_hash_map
crossplatform
mujoco
raw
errors_header
+1 -1
View File
@@ -53,6 +53,6 @@ if _MUJOCO_GL not in ('disable', 'disabled', 'off', 'false', '0'):
else:
from mujoco.glfw import GLContext
HEADERS_DIR = os.path.join(os.path.dirname(__file__), 'include')
HEADERS_DIR = os.path.join(os.path.dirname(__file__), 'include/mujoco')
__version__ = mj_versionString() # pylint: disable=undefined-variable
+1 -1
View File
@@ -19,7 +19,7 @@
#include <sstream>
#include <type_traits>
#include <mujoco.h>
#include <mujoco/mujoco.h>
#include "errors.h"
#include "structs.h"
#include "raw.h"
@@ -71,7 +71,7 @@ struct {enum.name} {{
#include <tuple>
#include <utility>
#include <mujoco.h>
#include <mujoco/mujoco.h>
namespace mujoco::python_traits {{
@@ -91,7 +91,7 @@ struct {func.name} {{
#include <tuple>
#include <mujoco.h>
#include <mujoco/mujoco.h>
#include "util/crossplatform.h"
namespace mujoco::python_traits {{
+6 -6
View File
@@ -12,13 +12,13 @@
// See the License for the specific language governing permissions and
// limitations under the License.
#include <utility>
#include <vector>
#include <mjmodel.h>
#include <mjvisualize.h>
#include <mujoco.h>
#include <mujoco/mjmodel.h>
#include <mujoco/mjvisualize.h>
#include <mujoco/mujoco.h>
#include <pybind11/cast.h>
#include <pybind11/pybind11.h>
#include <pybind11/stl.h>
namespace mujoco::python {
namespace {
@@ -32,7 +32,7 @@ py::tuple MakeTuple(
for (int i = 0; i < N; i++) {
result.append(py::str(strings[i]));
}
return result;
return std::move(result);
}
template <auto N>
@@ -44,7 +44,7 @@ py::tuple MakeTuple(const char* (&strings)[N][3]) {
py::str(strings[i][1]),
py::str(strings[i][2])));
}
return result;
return std::move(result);
}
PYBIND11_MODULE(_constants, pymodule) {
+2 -2
View File
@@ -20,7 +20,7 @@
#include <string>
#include <type_traits>
#include <mjexport.h>
#include <mujoco/mjexport.h>
#include "util/crossplatform.h"
#include "util/func_wrap.h"
#include <pybind11/pybind11.h>
@@ -109,7 +109,7 @@ class ErrorBase : public pybind11::builtin_exception {
static thread_local std::jmp_buf mju_error_jmp_buf;
static thread_local std::array<char, 1024> mju_error_msg{0};
static void MjErrorHandler(const char* msg) {
static inline void MjErrorHandler(const char* msg) {
std::strncpy(mju_error_msg.data(), msg, mju_error_msg.size());
std::longjmp(mju_error_jmp_buf, 1);
}
+1 -1
View File
@@ -23,7 +23,7 @@
#include <type_traits>
#include <Eigen/Core>
#include <mujoco.h>
#include <mujoco/mujoco.h>
#include "errors.h"
#include "structs.h"
#include "util/array_traits.h"
+5 -3
View File
@@ -15,7 +15,7 @@
#ifndef MUJOCO_PYTHON_INDEXER_XMACRO_H_
#define MUJOCO_PYTHON_INDEXER_XMACRO_H_
#include <mjxmacro.h>
#include <mujoco/mjxmacro.h>
#define MJMODEL_ACTUATOR \
X( int, actuator_, trntype, nu, 1 ) \
@@ -26,11 +26,13 @@
X( int, actuator_, group, nu, 1 ) \
X( mjtByte, actuator_, ctrllimited, nu, 1 ) \
X( mjtByte, actuator_, forcelimited, nu, 1 ) \
X( mjtByte, actuator_, actlimited, nu, 1 ) \
X( mjtNum, actuator_, dynprm, nu, mjNDYN ) \
X( mjtNum, actuator_, gainprm, nu, mjNGAIN ) \
X( mjtNum, actuator_, biasprm, nu, mjNBIAS ) \
X( mjtNum, actuator_, ctrlrange, nu, 2 ) \
X( mjtNum, actuator_, forcerange, nu, 2 ) \
X( mjtNum, actuator_, actrange, nu, 2 ) \
X( mjtNum, actuator_, gear, nu, 6 ) \
X( mjtNum, actuator_, cranklength, nu, 1 ) \
X( mjtNum, actuator_, acc0, nu, 1 ) \
@@ -361,8 +363,8 @@
X( mjtNum, , qfrc_bias, nv, 1 ) \
X( mjtNum, , qfrc_passive, nv, 1 ) \
X( mjtNum, , qfrc_actuator, nv, 1 ) \
X( mjtNum, , qfrc_unc, nv, 1 ) \
X( mjtNum, , qacc_unc, nv, 1 ) \
X( mjtNum, , qfrc_smooth, nv, 1 ) \
X( mjtNum, , qacc_smooth, nv, 1 ) \
X( mjtNum, , qfrc_constraint, nv, 1 ) \
X( mjtNum, , qfrc_inverse, nv, 1 )
+5 -4
View File
@@ -20,11 +20,10 @@
#include <variant>
#include <vector>
#include "errors.h"
#include "indexers.h"
#include "mjdata_meta.h"
#include "raw.h"
#include <pybind11/pybind11.h>
#include "util/crossplatform.h"
namespace mujoco::python {
@@ -218,13 +217,15 @@ MJDATA_VIEW_GROUPS
#undef XGROUP
#define MAKE_SHAPE(dim) \
[n = (dim)]() -> std::vector<int> { \
MUJOCO_DIAG_IGNORE_UNUSED_LAMBDA_CAPTURE \
[n = (dim)]() -> std::vector<int> { \
if constexpr (std::string_view(#dim) == std::string_view("1")) { \
return {}; \
} else { \
return {n}; \
} \
}()
}() \
MUJOCO_DIAG_UNIGNORE_UNUSED_LAMBDA_CAPTURE
#undef MJ_M
#define MJ_M(n) m_->n
+1 -1
View File
@@ -23,7 +23,7 @@
#include <vector>
#include <absl/container/flat_hash_map.h>
#include <mjxmacro.h>
#include <mujoco/mjxmacro.h>
#include "indexer_xmacro.h"
#include "mjdata_meta.h"
#include "raw.h"
+4 -2
View File
@@ -15,8 +15,9 @@
#ifndef MUJOCO_PYTHON_MJDATA_META_H_
#define MUJOCO_PYTHON_MJDATA_META_H_
#include <mjxmacro.h>
#include <mujoco/mjxmacro.h>
#include "raw.h"
#include "util/crossplatform.h"
namespace mujoco::python {
namespace _impl {
@@ -95,7 +96,8 @@ struct MjDataMetadata {
#undef X
dummy_() {}
bool dummy_; // Dummy variable to terminate X macro sequences.
// Dummy variable to terminate X macro sequences.
MUJOCO_MAYBE_UNUSED bool dummy_;
};
} // namespace mujoco::python
+4 -4
View File
@@ -15,10 +15,10 @@
#ifndef MUJOCO_PYTHON_RAW_H_
#define MUJOCO_PYTHON_RAW_H_
#include <mjdata.h>
#include <mjmodel.h>
#include <mjrender.h>
#include <mjvisualize.h>
#include <mujoco/mjdata.h>
#include <mujoco/mjmodel.h>
#include <mujoco/mjrender.h>
#include <mujoco/mjvisualize.h>
// Type aliases for MuJoCo C structs to allow us refer to consistently refer
// to them under the "raw" namespace.
+2 -2
View File
@@ -16,8 +16,8 @@
#include <cstdint>
#include <Eigen/Core>
#include <mjrender.h>
#include <mujoco.h>
#include <mujoco/mjrender.h>
#include <mujoco/mujoco.h>
#include "errors.h"
#include "function_traits.h"
#include "functions.h"
+1 -1
View File
@@ -17,7 +17,7 @@
#include <iostream>
#include <mjtnum.h>
#include <mujoco/mjtnum.h>
namespace mujoco::python::_impl {
+2 -2
View File
@@ -34,8 +34,8 @@
#include <vector>
#include <absl/container/flat_hash_map.h>
#include <mjxmacro.h>
#include <mujoco.h>
#include <mujoco/mjxmacro.h>
#include <mujoco/mujoco.h>
#include "errors.h"
#include "function_traits.h"
#include "indexers.h"
+3 -3
View File
@@ -25,8 +25,8 @@
#include <vector>
#include <absl/types/span.h>
#include <mujoco.h>
#include <mjxmacro.h>
#include <mujoco/mujoco.h>
#include <mujoco/mjxmacro.h>
#include "indexers.h"
#include "mjdata_meta.h"
#include "raw.h"
@@ -894,7 +894,7 @@ static InitPyArray(Shape&& shape, T* buf, pybind11::handle owner) {
out.append(InitPyArray(block_shape, &buf[i * block_size], owner));
}
}
return out;
return std::move(out);
}
// Same as above, but where we can determine array dimensions through the
+2 -6
View File
@@ -23,11 +23,6 @@ set(CMAKE_CXX_EXTENSIONS OFF)
# INTERPROCEDURAL_OPTIMIZATION is enforced when enabled.
set(CMAKE_POLICY_DEFAULT_CMP0069 NEW)
if(APPLE)
add_compile_options(-Werror=partial-availability -Werror=unguarded-availability)
add_link_options(-Wl,-no_weak_imports)
endif()
add_library(crossplatform INTERFACE)
target_sources(crossplatform INTERFACE crossplatform.h)
set_target_properties(crossplatform PROPERTIES PUBLIC_HEADER crossplatform.h)
@@ -62,7 +57,8 @@ target_link_libraries(
func_traits
)
if(MUJOCO_TEST_PYTHON_UTIL)
if(BUILD_TESTING)
enable_testing()
add_executable(array_traits_test array_traits_test.cc)
target_link_libraries(
array_traits_test
+25
View File
@@ -48,4 +48,29 @@
#define MUJOCO_ALWAYS_INLINE_LAMBDA_MUTABLE
#endif
#ifndef MUJOCO_DIAG_IGNORE_UNUSED_LAMBDA_CAPTURE
#if defined(__clang__)
#define MUJOCO_DIAG_IGNORE_UNUSED_LAMBDA_CAPTURE \
_Pragma("clang diagnostic push") \
_Pragma("clang diagnostic ignored \"-Wunused-lambda-capture\"")
#define MUJOCO_DIAG_UNIGNORE_UNUSED_LAMBDA_CAPTURE \
_Pragma("clang diagnostic pop")
#elif defined(__GNUC__)
#define MUJOCO_DIAG_IGNORE_UNUSED_LAMBDA_CAPTURE \
_Pragma("GCC diagnostic push") \
_Pragma("GCC diagnostic ignored \"-Wunused-lambda-capture\"")
#define MUJOCO_DIAG_UNIGNORE_UNUSED_LAMBDA_CAPTURE _Pragma("GCC diagnostic pop")
#else
#define MUJOCO_DIAG_IGNORE_UNUSED_LAMBDA_CAPTURE
#define MUJOCO_DIAG_UNIGNORE_UNUSED_LAMBDA_CAPTURE
#endif
#endif
// GCC ignores [[maybe_unused]] and emits a -Wattributes
#if defined(__GNUC__) && !defined(__clang__)
#define MUJOCO_MAYBE_UNUSED
#else
#define MUJOCO_MAYBE_UNUSED [[maybe_unused]]
#endif
#endif // MUJOCO_PYTHON_UTIL_CROSSPLATFORM_H_
+34 -18
View File
@@ -30,7 +30,7 @@ from setuptools import find_packages
from setuptools import setup
from setuptools.command import build_ext
__version__ = '2.1.5'
__version__ = '2.2.0'
MUJOCO_CMAKE = 'MUJOCO_CMAKE'
MUJOCO_CMAKE_ARGS = 'MUJOCO_CMAKE_ARGS'
@@ -137,7 +137,10 @@ class BuildCMakeExtension(build_ext.build_ext):
"""Uses CMake to build extensions."""
def run(self):
self._mujoco_library_path, self._mujoco_include_path = self._find_mujoco()
self._is_apple = (platform.system() == 'Darwin')
(self._mujoco_library_path,
self._mujoco_include_path,
self._mujoco_framework_path) = self._find_mujoco()
self._configure_cmake()
for ext in self.extensions:
assert ext.name.startswith(EXT_PREFIX)
@@ -151,13 +154,17 @@ class BuildCMakeExtension(build_ext.build_ext):
raise RuntimeError(f'{MUJOCO_PATH} environment variable is not set')
library_path = None
include_path = None
for directory, _, filenames in os.walk(os.environ['MUJOCO_PATH']):
for directory, subdirs, filenames in os.walk(os.environ['MUJOCO_PATH']):
if self._is_apple and 'mujoco.framework' in subdirs:
return (os.path.join(directory, 'mujoco.framework/Versions/A'),
os.path.join(directory, 'mujoco.framework/Headers'),
directory)
if fnmatch.filter(filenames, get_mujoco_lib_pattern()):
library_path = directory
if fnmatch.filter(filenames, 'mujoco.h'):
if os.path.exists(os.path.join(directory, 'mujoco/mujoco.h')):
include_path = directory
if library_path and include_path:
return library_path, include_path
return library_path, include_path, None
raise RuntimeError('Cannot find MuJoCo library and/or include paths')
def _copy_external_libraries(self):
@@ -171,8 +178,8 @@ class BuildCMakeExtension(build_ext.build_ext):
def _copy_mujoco_headers(self):
dst = os.path.join(
os.path.dirname(self.get_ext_fullpath(self.extensions[0].name)),
'include')
os.mkdir(dst)
'include/mujoco')
os.makedirs(dst)
for directory, _, filenames in os.walk(self._mujoco_include_path):
for filename in fnmatch.filter(filenames, '*.h'):
shutil.copyfile(os.path.join(directory, filename),
@@ -184,18 +191,27 @@ class BuildCMakeExtension(build_ext.build_ext):
build_cfg = 'Debug' if self.debug else 'Release'
cmake_module_path = os.path.join(os.path.dirname(__file__), 'cmake')
cmake_args = [
f'-DPython3_ROOT_DIR={sys.prefix}',
f'-DPython3_EXECUTABLE={sys.executable}',
f'-DMUJOCO_LIBRARY_DIR={self._mujoco_library_path}',
f'-DMUJOCO_INCLUDE_DIR={self._mujoco_include_path}',
f'-DCMAKE_MODULE_PATH={cmake_module_path}',
f'-DCMAKE_BUILD_TYPE={build_cfg}',
f'-DCMAKE_LIBRARY_OUTPUT_DIRECTORY={self.build_temp}',
f'-DCMAKE_INTERPROCEDURAL_OPTIMIZATION={"OFF" if self.debug else "ON"}',
f'-DPython3_ROOT_DIR:PATH={sys.prefix}',
f'-DPython3_EXECUTABLE:STRING={sys.executable}',
f'-DCMAKE_MODULE_PATH:PATH={cmake_module_path}',
f'-DCMAKE_BUILD_TYPE:STRING={build_cfg}',
f'-DCMAKE_LIBRARY_OUTPUT_DIRECTORY:PATH={self.build_temp}',
f'-DCMAKE_INTERPROCEDURAL_OPTIMIZATION=:BOOL{"OFF" if self.debug else "ON"}',
'-DCMAKE_Fortran_COMPILER:STRING=',
'-DCMAKE_VERBOSE_MAKEFILE=ON',
'-DBUILD_TESTING=OFF',
'-DCMAKE_VERBOSE_MAKEFILE:BOOL=ON',
'-DBUILD_TESTING:BOOL=OFF',
]
if self._mujoco_framework_path is not None:
cmake_args.extend([
f'-DMUJOCO_FRAMEWORK_DIR:PATH={self._mujoco_framework_path}',
])
else:
cmake_args.extend([
f'-DMUJOCO_LIBRARY_DIR:PATH={self._mujoco_library_path}',
f'-DMUJOCO_INCLUDE_DIR:PATH={self._mujoco_include_path}',
])
if platform.system() != 'Windows':
cmake_args.extend([
f'-DPython3_LIBRARY={sysconfig.get_paths()["stdlib"]}',
@@ -293,7 +309,7 @@ setup(
'libmujoco.*.dylib',
'libmujoco*.so.*',
'mujoco.dll',
'include/*.h',
'include/mujoco/*.h',
]),
},
)
+363
View File
@@ -0,0 +1,363 @@
# Copyright 2021 DeepMind Technologies Limited
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# https://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
cmake_minimum_required(VERSION 3.18)
# INTERPROCEDURAL_OPTIMIZATION is enforced when enabled.
set(CMAKE_POLICY_DEFAULT_CMP0069 NEW)
# Default to GLVND if available.
set(CMAKE_POLICY_DEFAULT_CMP0072 NEW)
# This line has to appear before 'PROJECT' in order to be able to disable incremental linking
set(MSVC_INCREMENTAL_DEFAULT ON)
project(
mujoco_samples
VERSION 2.1.5
DESCRIPTION "MuJoCo samples binaries"
HOMEPAGE_URL "https://mujoco.org"
)
enable_language(C)
enable_language(CXX)
if(APPLE)
enable_language(OBJC)
enable_language(OBJCXX)
endif()
# Check if we are building as standalone project.
set(SAMPLE_STANDALONE OFF)
set(_INSTALL_SAMPLES ON)
if(CMAKE_SOURCE_DIR STREQUAL CMAKE_CURRENT_SOURCE_DIR)
set(SAMPLE_STANDALONE ON)
# If standalone, do not install the samples.
set(_INSTALL_SAMPLES OFF)
endif()
list(APPEND CMAKE_MODULE_PATH "${PROJECT_SOURCE_DIR}/cmake")
if(SAMPLE_STANDALONE)
include(SampleOptions)
else()
enforce_mujoco_macosx_min_version()
endif()
include(SampleDependencies)
set(MUJOCO_SAMPLE_COMPILE_OPTIONS "${AVX_COMPILE_OPTIONS}" "${EXTRA_COMPILE_OPTIONS}")
set(MUJOCO_SAMPLE_LINK_OPTIONS "${EXTRA_LINK_OPTIONS}")
if(MUJOCO_HARDEN)
if(WIN32)
set(MUJOCO_SAMPLE_LINK_OPTIONS "${MUJOCO_SAMPLE_LINK_OPTIONS}" -Wl,/DYNAMICBASE)
else()
set(MUJOCO_SAMPLE_COMPILE_OPTIONS "${MUJOCO_SAMPLE_COMPILE_OPTIONS}" -fPIE)
if(APPLE)
set(MUJOCO_SAMPLE_LINK_OPTIONS "${MUJOCO_SAMPLE_LINK_OPTIONS}" -Wl,-pie)
else()
set(MUJOCO_SAMPLE_LINK_OPTIONS "${MUJOCO_SAMPLE_LINK_OPTIONS}" -pie)
endif()
endif()
endif()
# Utility library
add_library(uitools STATIC)
target_sources(uitools PRIVATE uitools.h uitools.c)
target_include_directories(uitools PUBLIC ${CMAKE_CURRENT_SOURCE_DIR})
target_compile_options(uitools PUBLIC ${MUJOCO_SAMPLE_COMPILE_OPTIONS})
target_link_libraries(uitools PUBLIC glfw mujoco::mujoco)
target_link_options(uitools PRIVATE ${MUJOCO_SAMPLE_LINK_OPTIONS})
# Build sample binaries
add_executable(compile compile.cc)
target_compile_options(compile PUBLIC ${MUJOCO_SAMPLE_COMPILE_OPTIONS})
target_link_libraries(compile Threads::Threads)
target_link_options(compile PRIVATE ${MUJOCO_SAMPLE_LINK_OPTIONS})
add_executable(derivative derivative.cc)
target_compile_options(derivative PUBLIC ${MUJOCO_SAMPLE_COMPILE_OPTIONS})
target_link_libraries(derivative Threads::Threads)
target_link_options(derivative PRIVATE ${MUJOCO_SAMPLE_LINK_OPTIONS})
add_executable(testspeed testspeed.cc)
target_compile_options(testspeed PUBLIC ${MUJOCO_SAMPLE_COMPILE_OPTIONS})
target_link_libraries(testspeed Threads::Threads)
target_link_options(testspeed PRIVATE ${MUJOCO_SAMPLE_LINK_OPTIONS})
add_executable(testxml testxml.cc array_safety.h)
target_compile_options(testxml PUBLIC ${MUJOCO_SAMPLE_COMPILE_OPTIONS})
target_link_libraries(testxml Threads::Threads)
target_link_options(testxml PRIVATE ${MUJOCO_SAMPLE_LINK_OPTIONS})
target_link_libraries(compile mujoco::mujoco)
target_link_libraries(derivative mujoco::mujoco)
target_link_libraries(testspeed mujoco::mujoco)
target_link_libraries(testxml mujoco::mujoco)
# Build samples that require GLFW.
add_executable(basic basic.cc)
target_compile_options(basic PUBLIC ${MUJOCO_SAMPLE_COMPILE_OPTIONS})
target_link_libraries(
basic
mujoco::mujoco
glfw
Threads::Threads
)
target_link_options(basic PRIVATE ${MUJOCO_SAMPLE_LINK_OPTIONS})
add_executable(record record.cc array_safety.h)
target_compile_options(record PUBLIC ${MUJOCO_SAMPLE_COMPILE_OPTIONS})
target_link_libraries(
record
mujoco::mujoco
glfw
Threads::Threads
)
target_link_options(record PRIVATE ${MUJOCO_SAMPLE_LINK_OPTIONS})
if(APPLE)
set(SIMULATE_RESOURCE_FILES ${CMAKE_CURRENT_SOURCE_DIR}/../dist/mujoco.icns)
elseif(WIN32)
set(SIMULATE_RESOURCE_FILES ${CMAKE_CURRENT_SOURCE_DIR}/../dist/appicon.rc)
else()
set(SIMULATE_RESOURCE_FILES "")
endif()
add_executable(simulate simulate.cc array_safety.h ${SIMULATE_RESOURCE_FILES})
target_compile_options(simulate PUBLIC ${MUJOCO_SAMPLE_COMPILE_OPTIONS})
if(WIN32)
add_custom_command(
TARGET simulate
PRE_BUILD
COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_CURRENT_SOURCE_DIR}/../dist/mujoco.ico
${CMAKE_CURRENT_SOURCE_DIR}
POST_BUILD
COMMAND ${CMAKE_COMMAND} -E rm ${CMAKE_CURRENT_SOURCE_DIR}/mujoco.ico
)
endif()
target_link_libraries(
simulate
mujoco::mujoco
uitools
glfw
Threads::Threads
)
target_link_options(simulate PRIVATE ${MUJOCO_SAMPLE_LINK_OPTIONS})
if(APPLE)
target_sources(simulate PRIVATE macos_save.mm)
target_link_libraries(simulate "-framework Cocoa")
endif()
if(NOT SAMPLE_STANDALONE)
if(APPLE AND MUJOCO_BUILD_MACOS_FRAMEWORKS)
macro(link_to_mujoco_framework target)
get_target_property(interface_link_libraries ${target} INTERFACE_LINK_LIBRARIES)
get_target_property(link_libraries ${target} LINK_LIBRARIES)
# Remove mujoco::mujoco target which is the not-framework library.
list(REMOVE_ITEM interface_link_libraries mujoco::mujoco)
list(REMOVE_ITEM link_libraries mujoco::mujoco)
set_target_properties(
${target} PROPERTIES INTERFACE_LINK_LIBRARIES "${interface_link_libraries}"
)
set_target_properties(${target} PROPERTIES LINK_LIBRARIES "${link_libraries}")
# Add mujoco_framework.
target_link_libraries(${target} mujoco_framework)
endmacro()
include(DuplicateTarget)
duplicate_target(
TARGET
simulate
NEW_TARGET_NAME
simulate_macos
)
link_to_mujoco_framework(simulate_macos)
set_target_properties(
simulate_macos
PROPERTIES INSTALL_RPATH @executable_path/../Frameworks
BUILD_WITH_INSTALL_RPATH TRUE
RESOURCE ${SIMULATE_RESOURCE_FILES}
MACOSX_BUNDLE TRUE
MACOSX_BUNDLE_INFO_PLIST ${CMAKE_CURRENT_SOURCE_DIR}/../dist/Info.plist.simulate.in
MACOSX_BUNDLE_BUNDLE_NAME "MuJoCo"
MACOSX_BUNDLE_GUI_IDENTIFIER "org.mujoco.mujoco"
MACOSX_BUNDLE_BUNDLE_VERSION ${PROJECT_VERSION}
MACOSX_BUNDLE_INFO_STRING ${PROJECT_VERSION}
MACOSX_BUNDLE_LONG_VERSION_STRING ${PROJECT_VERSION}
MACOSX_BUNDLE_SHORT_VERSION_STRING ${PROJECT_VERSION}
MACOSX_BUNDLE_ICON_FILE "mujoco.icns"
MACOSX_BUNDLE_COPYRIGHT "Copyright 2021 DeepMind Technologies Limited."
OUTPUT_NAME "simulate"
)
macro(embed_in_bundle target)
add_dependencies(${target} simulate_macos)
set_target_properties(
${target}
PROPERTIES INSTALL_RPATH @executable_path/../Frameworks
BUILD_WITH_INSTALL_RPATH TRUE
RUNTIME_OUTPUT_DIRECTORY $<TARGET_FILE_DIR:simulate_macos>
)
endmacro()
duplicate_target(
TARGET
basic
NEW_TARGET_NAME
basic_macos
)
set_target_properties(basic_macos PROPERTIES OUTPUT_NAME basic)
link_to_mujoco_framework(basic_macos)
embed_in_bundle(basic_macos simulate_macos)
duplicate_target(
TARGET
compile
NEW_TARGET_NAME
compile_macos
)
set_target_properties(compile_macos PROPERTIES OUTPUT_NAME compile)
link_to_mujoco_framework(compile_macos)
embed_in_bundle(compile_macos simulate_macos)
duplicate_target(
TARGET
derivative
NEW_TARGET_NAME
derivative_macos
)
set_target_properties(derivative_macos PROPERTIES OUTPUT_NAME derivative)
link_to_mujoco_framework(derivative_macos)
embed_in_bundle(derivative_macos simulate_macos)
duplicate_target(
TARGET
record
NEW_TARGET_NAME
record_macos
)
set_target_properties(record_macos PROPERTIES OUTPUT_NAME record)
link_to_mujoco_framework(record_macos)
embed_in_bundle(record_macos simulate_macos)
duplicate_target(
TARGET
testspeed
NEW_TARGET_NAME
testspeed_macos
)
set_target_properties(testspeed_macos PROPERTIES OUTPUT_NAME testspeed)
link_to_mujoco_framework(testspeed_macos)
embed_in_bundle(testspeed_macos simulate_macos)
duplicate_target(
TARGET
testxml
NEW_TARGET_NAME
testxml_macos
)
set_target_properties(testxml_macos PROPERTIES OUTPUT_NAME testxml)
link_to_mujoco_framework(testxml_macos)
embed_in_bundle(testxml_macos simulate_macos)
# Do not add the original binaries to the ALL target. We do this to speed up the
# build assuming the user is interested in the Frameworks.
set_target_properties(simulate PROPERTIES EXCLUDE_FROM_ALL TRUE)
set_target_properties(basic PROPERTIES EXCLUDE_FROM_ALL TRUE)
set_target_properties(derivative PROPERTIES EXCLUDE_FROM_ALL TRUE)
set_target_properties(record PROPERTIES EXCLUDE_FROM_ALL TRUE)
set_target_properties(testxml PROPERTIES EXCLUDE_FROM_ALL TRUE)
# Note: compile and testspeed are needed by the tests.
# Embed mujoco.framework inside the App bundle ane move the icon file over too.
add_custom_command(
TARGET simulate_macos
POST_BUILD
COMMAND mkdir -p $<TARGET_FILE_DIR:simulate_macos>/../Frameworks
COMMAND rm -rf $<TARGET_FILE_DIR:simulate_macos>/../Frameworks/mujoco.framework
COMMAND cp -a $<TARGET_FILE_DIR:mujoco_framework>/../../../mujoco.framework
$<TARGET_FILE_DIR:simulate_macos>/../Frameworks/
# Delete the symlink and the TBD, otherwise we can't sign and notarize.
COMMAND rm -rf $<TARGET_FILE_DIR:simulate_macos>/../Frameworks/mujoco.framework/mujoco.tbd
COMMAND
rm -rf
$<TARGET_FILE_DIR:simulate_macos>/../Frameworks/mujoco.framework/Versions/A/libmujoco.dylib
)
endif()
endif()
# Do not install if macOS Bundles are created as RPATH is managed manually there.
if(APPLE AND MUJOCO_BUILD_MACOS_FRAMEWORKS)
set(_INSTALL_SAMPLES OFF)
endif()
if(_INSTALL_SAMPLES)
include(TargetAddRpath)
# Add support to RPATH for the samples.
target_add_rpath(
TARGETS
basic
compile
derivative
record
testspeed
testxml
simulate
INSTALL_DIRECTORY
"${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_BINDIR}"
LIB_DIRS
"${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_LIBDIR}"
DEPENDS
MUJOCO_ENABLE_RPATH
)
install(
TARGETS basic
compile
derivative
record
testspeed
testxml
simulate
EXPORT ${PROJECT_NAME}
RUNTIME DESTINATION "${CMAKE_INSTALL_BINDIR}" COMPONENT samples
LIBRARY DESTINATION "${CMAKE_INSTALL_LIBDIR}" COMPONENT samples
ARCHIVE DESTINATION "${CMAKE_INSTALL_LIBDIR}" COMPONENT samples
BUNDLE DESTINATION "${CMAKE_INSTALL_BINDIR}" COMPONENT samples
PUBLIC_HEADER DESTINATION ${CMAKE_INSTALL_INCLUDEDIR} COMPONENT samples
)
if(NOT MUJOCO_SAMPLES_USE_SYSTEM_GLFW)
# We downloaded GLFW. Depending if it is a static or shared LIBRARY we might
# need to install it.
get_target_property(MJ_GLFW_LIBRARY_TYPE glfw TYPE)
if(MJ_GLFW_LIBRARY_TYPE STREQUAL SHARED_LIBRARY)
install(
TARGETS glfw
EXPORT ${PROJECT_NAME}
RUNTIME DESTINATION "${CMAKE_INSTALL_BINDIR}" COMPONENT samples
LIBRARY DESTINATION "${CMAKE_INSTALL_LIBDIR}" COMPONENT samples
ARCHIVE DESTINATION "${CMAKE_INSTALL_LIBDIR}" COMPONENT samples
PUBLIC_HEADER DESTINATION ${CMAKE_INSTALL_INCLUDEDIR} COMPONENT samples
)
endif()
endif()
endif()
+1 -1
View File
@@ -2,7 +2,7 @@
# which is commonly available through your distro's package manager.
# On Debian and Ubuntu, GLFW can be installed via `apt install libglfw3-dev`.
COMMON=-O2 -I../include -L../lib -std=c++11 -pthread -Wl,-no-as-needed -Wl,-rpath,'$$ORIGIN'/../lib
COMMON=-O2 -I../include -L../lib -std=c++17 -pthread -Wl,-no-as-needed -Wl,-rpath,'$$ORIGIN'/../lib
all:
$(CXX) $(COMMON) testxml.cc -lmujoco -o ../bin/testxml
+16 -16
View File
@@ -1,23 +1,23 @@
# This Makefile assumes that GLFW is installed via Homebrew, and that Homebrew
# packages are installed in /usr/local. If your setup is different, you will
# need to adjust the HOMEBREW variable accordingly.
# This Makefile assumes that GLFW is installed via Homebrew.
# If your setup is different, you will need to set GLFWROOT manually.
# This Makefile also assumes that MuJoCo.app is present in /Applications.
HOMEBREW?=/usr/local
GLFWROOT?=$(shell brew --prefix)
MUJOCOPATH?=/Applications/MuJoCo.app/Contents/Frameworks
MUJOCO_LIBDIR=/Applications/MuJoCo.app/Contents/Frameworks/MuJoCo.Framework/Versions/A
MUJOCO_INCLUDEDIR=/Applications/MuJoCo.app/Contents/Frameworks/MuJoCo.Framework/Versions/A/Headers
CFLAGS=-O2 -I$(MUJOCO_INCLUDEDIR) -I$(HOMEBREW)/include -pthread
ALLFLAGS=$(CFLAGS) -L$(MUJOCO_LIBDIR) -L$(HOMEBREW)/lib -std=c++11 -stdlib=libc++ -Wl,-rpath,/Applications/MuJoCo.app/Contents/Frameworks
CFLAGS=-O2 -F$(MUJOCOPATH) -I$(GLFWROOT)/include -pthread
CXXFLAGS=$(CFLAGS) -std=c++17 -stdlib=libc++
ALLFLAGS=$(CXXFLAGS) -L$(GLFWROOT)/lib -Wl,-rpath,$(MUJOCOPATH)
all:
clang++ $(ALLFLAGS) testxml.cc -lmujoco.2.1.5 -o testxml
clang++ $(ALLFLAGS) testspeed.cc -lmujoco.2.1.5 -o testspeed
clang++ $(ALLFLAGS) compile.cc -lmujoco.2.1.5 -o compile
clang++ $(ALLFLAGS) derivative.cc -lmujoco.2.1.5 -o derivative
clang++ $(ALLFLAGS) basic.cc -lmujoco.2.1.5 -lglfw -o basic
clang++ $(ALLFLAGS) record.cc -lmujoco.2.1.5 -lglfw -o record
clang -c $(CFLAGS) uitools.c
clang++ $(ALLFLAGS) uitools.o simulate.cc -lmujoco.2.1.5 -lglfw -o simulate
clang++ $(ALLFLAGS) testxml.cc -framework mujoco -o testxml
clang++ $(ALLFLAGS) testspeed.cc -framework mujoco -o testspeed
clang++ $(ALLFLAGS) compile.cc -framework mujoco -o compile
clang++ $(ALLFLAGS) derivative.cc -framework mujoco -o derivative
clang++ $(ALLFLAGS) basic.cc -framework mujoco -lglfw -o basic
clang++ $(ALLFLAGS) record.cc -framework mujoco -lglfw -o record
clang -c $(CFLAGS) uitools.c
clang++ -c $(CXXFLAGS) macos_save.mm
clang++ $(ALLFLAGS) simulate.cc uitools.o macos_save.o -framework mujoco -framework Cocoa -lglfw -o simulate
rm *.o
+2 -2
View File
@@ -15,8 +15,8 @@
#include <cstdio>
#include <cstring>
#include "GLFW/glfw3.h"
#include <mujoco.h>
#include <GLFW/glfw3.h>
#include <mujoco/mujoco.h>
// MuJoCo data structures
mjModel* m = NULL; // MuJoCo model
+53
View File
@@ -0,0 +1,53 @@
# Copyright 2021 DeepMind Technologies Limited
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# https://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
include(CheckCSourceCompiles)
# Assigns compiler options to the given variable based on availability of AVX.
function(get_avx_compile_options OUTPUT_VAR)
message(VERBOSE "Checking if AVX is available...")
if(MSVC)
set(CMAKE_REQUIRED_FLAGS "/arch:AVX")
else()
set(CMAKE_REQUIRED_FLAGS "-mavx")
endif()
if(APPLE AND "x86_64" IN_LIST CMAKE_OSX_ARCHITECTURES)
message(STATUS "Building x86_64 on macOS, forcing CAN_BUILD_AVX to TRUE.")
set(CAN_BUILD_AVX TRUE)
else()
check_c_source_compiles(
"
#include <immintrin.h>
int main(int argc, char* argv[]) {
__m256d ymm;
return 0;
}
"
CAN_BUILD_AVX
)
endif()
if(CAN_BUILD_AVX)
message(VERBOSE "Checking if AVX is available... AVX available.")
set("${OUTPUT_VAR}"
${CMAKE_REQUIRED_FLAGS}
PARENT_SCOPE
)
else()
message(VERBOSE "Checking if AVX is available... AVX not available.")
set("${OUTPUT_VAR}" PARENT_SCOPE)
endif()
endfunction()
+139
View File
@@ -0,0 +1,139 @@
# Copyright 2021 DeepMind Technologies Limited
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# https://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
#.rst:
# FindOrFetch
# ----------------------
#
# Find or fetch a package in order to satisfy target dependencies.
#
# FindOrFetch([USE_SYSTEM_PACKAGE [ON/OFF]]
# [PACKAGE_NAME [name]]
# [LIBRARY_NAME [name]]
# [GIT_REPO [repo]]
# [GIT_TAG [tag]]
# [PATCH_COMMAND [cmd] [args]]
# [TARGETS [targets]]
# [EXCLUDE_FROM_ALL])
#
# The command has the following parameters:
#
# Arguments:
# - ``USE_SYSTEM_PACKAGE`` one-value argument on whether to search for the
# package in the system (ON) or whether to fetch the library using
# FetchContent from the specified Git repository (OFF). Note that
# FetchContent variables will override this behaviour.
# - ``PACKAGE_NAME`` name of the system-package. Ignored if
# ``USE_SYSTEM_PACKAGE`` is ``OFF``.
# - ``LIBRARY_NAME`` name of the library. Ignored if
# ``USE_SYSTEM_PACKAGE`` is ``ON``.
# - ``GIT_REPO`` git repository to fetch the library from. Ignored if
# ``USE_SYSTEM_PACKAGE`` is ``ON``.
# - ``GIT_TAG`` tag reference when fetching the library from the git
# repository. Ignored if ``USE_SYSTEM_PACKAGE`` is ``ON``.
# - ``PATCH_COMMAND`` Specifies a custom command to patch the sources after an
# update. See https://cmake.org/cmake/help/latest/module/ExternalProject.html#command:externalproject_add
# for details on the parameter.
# - ``TARGETS`` list of targets to be satisfied. If any of these targets are
# not currently defined, this macro will attempt to either find or fetch the
# package.
# - ``EXCLUDE_FROM_ALL`` if specified, the targets are not added to the ``all``
# metatarget.
#
# Note: if ``USE_SYSTEM_PACKAGE`` is ``OFF``, FetchContent will be used to
# retrieve the specified targets. It is possible to specify any variable in
# https://cmake.org/cmake/help/latest/module/FetchContent.html#variables to
# override this macro behaviour.
if(COMMAND FindOrFetch)
return()
endif()
macro(FindOrFetch)
if(NOT FetchContent)
include(FetchContent)
endif()
# Parse arguments.
set(options EXCLUDE_FROM_ALL)
set(one_value_args
USE_SYSTEM_PACKAGE
PACKAGE_NAME
LIBRARY_NAME
GIT_REPO
GIT_TAG
)
set(multi_value_args PATCH_COMMAND TARGETS)
cmake_parse_arguments(
_ARGS
"${options}"
"${one_value_args}"
"${multi_value_args}"
${ARGN}
)
# Check if all targets are found.
if(NOT _ARGS_TARGETS)
message(FATAL_ERROR "mujoco::FindOrFetch: TARGETS must be specified.")
endif()
set(targets_found TRUE)
message(CHECK_START
"mujoco::FindOrFetch: checking for targets in package `${_ARGS_PACKAGE_NAME}`"
)
foreach(target ${_ARGS_TARGETS})
if(NOT TARGET ${target})
message(CHECK_FAIL "target `${target}` not defined.")
set(targets_found FALSE)
break()
endif()
endforeach()
# If targets are not found, use `find_package` or `FetchContent...` to get it.
if(NOT targets_found)
if(${_ARGS_USE_SYSTEM_PACKAGE})
message(CHECK_START
"mujoco::FindOrFetch: finding `${_ARGS_PACKAGE_NAME}` in system packages..."
)
find_package(${_ARGS_PACKAGE_NAME} REQUIRED)
message(CHECK_PASS "found")
else()
message(CHECK_START
"mujoco::FindOrFetch: Using FetchContent to retrieve `${_ARGS_LIBRARY_NAME}`"
)
FetchContent_Declare(
${_ARGS_LIBRARY_NAME}
GIT_REPOSITORY ${_ARGS_GIT_REPO}
GIT_TAG ${_ARGS_GIT_TAG}
GIT_SHALLOW FALSE
PATCH_COMMAND ${_ARGS_PATCH_COMMAND}
)
if(${_ARGS_EXCLUDE_FROM_ALL})
FetchContent_GetProperties(${_ARGS_LIBRARY_NAME})
if(NOT ${${_ARGS_LIBRARY_NAME}_POPULATED})
FetchContent_Populate(${_ARGS_LIBRARY_NAME})
add_subdirectory(
${${_ARGS_LIBRARY_NAME}_SOURCE_DIR} ${${_ARGS_LIBRARY_NAME}_BINARY_DIR}
EXCLUDE_FROM_ALL
)
endif()
else()
FetchContent_MakeAvailable(${_ARGS_LIBRARY_NAME})
endif()
message(CHECK_PASS "Done")
endif()
else()
message(CHECK_PASS "found")
endif()
endmacro()
+35
View File
@@ -0,0 +1,35 @@
# Copyright 2022 DeepMind Technologies Limited
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# https://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
option(MUJOCO_HARDEN "Enable build hardening for MuJoCo." OFF)
if(MUJOCO_HARDEN
AND NOT
CMAKE_CXX_COMPILER_ID
MATCHES
".*Clang.*"
)
message(FATAL_ERROR "MUJOCO_HARDEN is only supported when building with Clang")
endif()
if(MUJOCO_HARDEN)
set(MUJOCO_HARDEN_COMPILE_OPTIONS -D_FORTIFY_SOURCE=2 -fstack-protector)
if(${CMAKE_SYSTEM_NAME} MATCHES "Darwin")
set(MUJOCO_HARDEN_LINK_OPTIONS -Wl,-bind_at_load)
elseif(${CMAKE_SYSTEM_NAME} MATCHES "Linux")
set(MUJOCO_HARDEN_LINK_OPTIONS -Wl,-z,relro -Wl,-z,now)
endif()
else()
set(MUJOCO_HARDEN_COMPILE_OPTIONS "")
set(MUJOCO_HARDEN_LINK_OPTIONS "")
endif()
+67
View File
@@ -0,0 +1,67 @@
# Copyright 2021 DeepMind Technologies Limited
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# https://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
include(CheckCSourceCompiles)
# Gets the appropriate linker options for building MuJoCo, based on features available on the
# linker.
function(get_mujoco_extra_link_options OUTPUT_VAR)
if(MSVC)
set(EXTRA_LINK_OPTIONS /OPT:REF /OPT:ICF=5)
else()
set(EXTRA_LINK_OPTIONS)
if(WIN32)
set(CMAKE_REQUIRED_FLAGS "-fuse-ld=lld-link")
check_c_source_compiles("int main() {}" SUPPORTS_LLD)
if(SUPPORTS_LLD)
set(EXTRA_LINK_OPTIONS
${EXTRA_LINK_OPTIONS}
-fuse-ld=lld-link
-Wl,/OPT:REF
-Wl,/OPT:ICF
)
endif()
else()
set(CMAKE_REQUIRED_FLAGS "-fuse-ld=lld")
check_c_source_compiles("int main() {}" SUPPORTS_LLD)
if(SUPPORTS_LLD)
set(EXTRA_LINK_OPTIONS ${EXTRA_LINK_OPTIONS} -fuse-ld=lld)
else()
set(CMAKE_REQUIRED_FLAGS "-fuse-ld=gold")
check_c_source_compiles("int main() {}" SUPPORTS_GOLD)
if(SUPPORTS_GOLD)
set(EXTRA_LINK_OPTIONS ${EXTRA_LINK_OPTIONS} -fuse-ld=gold)
endif()
endif()
set(CMAKE_REQUIRED_FLAGS ${EXTRA_LINK_OPTIONS} "-Wl,--gc-sections")
check_c_source_compiles("int main() {}" SUPPORTS_GC_SECTIONS)
if(SUPPORTS_GC_SECTIONS)
set(EXTRA_LINK_OPTIONS ${EXTRA_LINK_OPTIONS} -Wl,--gc-sections)
else()
set(CMAKE_REQUIRED_FLAGS ${EXTRA_LINK_OPTIONS} "-Wl,-dead_strip")
check_c_source_compiles("int main() {}" SUPPORTS_DEAD_STRIP)
if(SUPPORTS_DEAD_STRIP)
set(EXTRA_LINK_OPTIONS ${EXTRA_LINK_OPTIONS} -Wl,-dead_strip)
endif()
endif()
endif()
endif()
set("${OUTPUT_VAR}"
${EXTRA_LINK_OPTIONS}
PARENT_SCOPE
)
endfunction()
+38
View File
@@ -0,0 +1,38 @@
# Copyright 2022 DeepMind Technologies Limited
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# https://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
if(APPLE)
# 10.12 is the oldest version of macOS that supports C++17, launched 2016.
set(MUJOCO_MACOSX_VERSION_MIN 10.12)
# We are setting the -mmacosx-version-min compiler flag directly rather than using the
# CMAKE_OSX_DEPLOYMENT_TARGET variable since we do not want to affect choice of SDK,
# and also we only want to apply the version restriction locally.
set(MUJOCO_MACOS_COMPILE_OPTIONS -mmacosx-version-min=${MUJOCO_MACOSX_VERSION_MIN}
-Werror=partial-availability -Werror=unguarded-availability
)
set(MUJOCO_MACOS_LINK_OPTIONS -mmacosx-version-min=${MUJOCO_MACOSX_VERSION_MIN}
-Wl,-no_weak_imports
)
else()
set(MUJOCO_MACOS_COMPILE_OPTIONS "")
set(MUJOCO_MACOS_LINK_OPTIONS "")
endif()
function(enforce_mujoco_macosx_min_version)
if(APPLE)
add_compile_options(${MUJOCO_MACOS_COMPILE_OPTIONS})
add_link_options(${MUJOCO_MACOS_LINK_OPTIONS})
endif()
endfunction()
+102
View File
@@ -0,0 +1,102 @@
# Copyright 2021 DeepMind Technologies Limited
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# https://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
include(FindOrFetch)
if(SAMPLE_STANDALONE)
# If standalone, by default look for MuJoCo binary version.
set(DEFAULT_USE_SYSTEM_MUJOCO ON)
else()
set(DEFAULT_USE_SYSTEM_MUJOCO OFF)
endif()
option(MUJOCO_SAMPLES_USE_SYSTEM_MUJOCO "Use installed MuJoCo version."
${DEFAULT_USE_SYSTEM_MUJOCO}
)
unset(DEFAULT_USE_SYSTEM_MUJOCO)
option(MUJOCO_SAMPLES_USE_SYSTEM_MUJOCO "Use installed MuJoCo version." OFF)
option(MUJOCO_SAMPLES_USE_SYSTEM_GLFW "Use installed GLFW version." OFF)
set(MUJOCO_DEP_VERSION_glfw
7d5a16ce714f0b5f4efa3262de22e4d948851525 # 3.3.6
CACHE STRING "Version of `glfw` to be fetched."
)
mark_as_advanced(MUJOCO_DEP_VERSION_glfw)
find_package(Threads REQUIRED)
set(MUJOCO_BUILD_EXAMPLES OFF)
set(MUJOCO_BUILD_TESTS OFF)
set(MUJOCO_BUILD_PYTHON OFF)
set(MUJOCO_TEST_PYTHON_UTIL OFF)
findorfetch(
USE_SYSTEM_PACKAGE
MUJOCO_SAMPLES_USE_SYSTEM_MUJOCO
PACKAGE_NAME
mujoco
LIBRARY_NAME
mujoco
GIT_REPO
https://github.com/deepmind/mujoco.git
GIT_TAG
main
TARGETS
mujoco
EXCLUDE_FROM_ALL
)
option(MUJOCO_SAMPLES_STATIC_GLFW "Link MuJoCo sample apps against GLFW statically." ON)
if(MUJOCO_SAMPLES_STATIC_GLFW)
set(BUILD_SHARED_LIBS_OLD ${BUILD_SHARED_LIBS})
set(BUILD_SHARED_LIBS
OFF
CACHE INTERNAL "Build SHARED libraries"
)
endif()
set(GLFW_BUILD_EXAMPLES OFF)
set(GLFW_BUILD_TESTS OFF)
set(GLFW_BUILD_DOCS OFF)
set(GLFW_INSTALL OFF)
findorfetch(
USE_SYSTEM_PACKAGE
MUJOCO_SAMPLES_USE_SYSTEM_GLFW
PACKAGE_NAME
glfw
LIBRARY_NAME
glfw
GIT_REPO
https://github.com/glfw/glfw.git
GIT_TAG
${MUJOCO_DEP_VERSION_glfw}
TARGETS
glfw
EXCLUDE_FROM_ALL
)
if(MUJOCO_SAMPLES_STATIC_GLFW)
set(BUILD_SHARED_LIBS
${BUILD_SHARED_LIBS_OLD}
CACHE BOOL "Build SHARED libraries" FORCE
)
unset(BUILD_SHARED_LIBS_OLD)
endif()
if(NOT SAMPLE_STANDALONE)
target_compile_options(glfw PRIVATE ${MUJOCO_MACOS_COMPILE_OPTIONS})
target_link_options(glfw PRIVATE ${MUJOCO_MACOS_LINK_OPTIONS})
endif()
+106
View File
@@ -0,0 +1,106 @@
# Copyright 2021 DeepMind Technologies Limited
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# https://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
# Global compilation settings
set(CMAKE_C_STANDARD 11)
set(CMAKE_C_STANDARD_REQUIRED ON)
set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(CMAKE_CXX_EXTENSIONS OFF)
set(CMAKE_C_EXTENSIONS OFF)
set(CMAKE_EXPORT_COMPILE_COMMANDS ON) # For LLVM tooling
if(NOT CMAKE_CONFIGURATION_TYPES)
if(NOT CMAKE_BUILD_TYPE)
message(STATUS "Setting build type to 'Release' as none was specified.")
set(CMAKE_BUILD_TYPE
"Release"
CACHE STRING "Choose the type of build, recommanded options are: Debug or Release" FORCE
)
endif()
set(BUILD_TYPES
"Debug"
"Release"
"MinSizeRel"
"RelWithDebInfo"
)
set_property(CACHE CMAKE_BUILD_TYPE PROPERTY STRINGS ${BUILD_TYPES})
endif()
include(GNUInstallDirs)
# Change the default output directory in the build structure. This is not stricly needed, but helps
# running in Windows, such that all built executables have DLLs in the same folder as the .exe
# files.
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/${CMAKE_INSTALL_BINDIR}")
set(CMAKE_LIBRARY_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/${CMAKE_INSTALL_LIBDIR}")
set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/${CMAKE_INSTALL_LIBDIR}")
set(OpenGL_GL_PREFERENCE GLVND)
set(CMAKE_POSITION_INDEPENDENT_CODE ON)
set(CMAKE_C_VISIBILITY_PRESET hidden)
set(CMAKE_CXX_VISIBILITY_PRESET hidden)
set(CMAKE_VISIBILITY_INLINES_HIDDEN ON)
if(MSVC)
add_compile_options(/Gy /Gw /Oi)
elseif(CMAKE_CXX_COMPILER_ID STREQUAL "GNU" OR CMAKE_CXX_COMPILER_ID MATCHES "Clang")
add_compile_options(-fdata-sections -ffunction-sections)
endif()
# We default to shared library.
set(BUILD_SHARED_LIBS
ON
CACHE BOOL "Build Mujoco as shared library."
)
option(MUJOCO_ENABLE_AVX "Build binaries that require AVX instructions, if possible." ON)
option(MUJOCO_ENABLE_AVX_INTRINSICS "Make use of hand-written AVX intrinsics, if possible." ON)
option(MUJOCO_ENABLE_RPATH "Enable RPath support when installing Mujoco." ON)
mark_as_advanced(MUJOCO_ENABLE_RPATH)
if(MUJOCO_ENABLE_AVX)
include(CheckAvxSupport)
get_avx_compile_options(AVX_COMPILE_OPTIONS)
else()
set(AVX_COMPILE_OPTIONS)
endif()
option(MUJOCO_BUILD_MACOS_FRAMEWORKS "Build libraries as macOS Frameworks" OFF)
# Get some extra link options.
include(MujocoLinkOptions)
get_mujoco_extra_link_options(EXTRA_LINK_OPTIONS)
if(CMAKE_CXX_COMPILER_ID STREQUAL "GNU" OR (CMAKE_CXX_COMPILER_ID MATCHES "Clang" AND NOT MSVC))
set(EXTRA_COMPILE_OPTIONS -Wall -Werror)
if(CMAKE_CXX_COMPILER_ID STREQUAL "GNU")
set(EXTRA_COMPILE_OPTIONS
-Wno-int-in-bool-context
-Wno-maybe-uninitialized
-Wno-sign-compare
-Wno-stringop-overflow
-Wno-stringop-truncation
)
endif()
endif()
if(WIN32)
add_compile_definitions(_CRT_SECURE_NO_WARNINGS)
endif()
include(MujocoHarden)
set(EXTRA_COMPILE_OPTIONS ${EXTRA_COMPILE_OPTIONS} ${MUJOCO_HARDEN_COMPILE_OPTIONS})
set(EXTRA_LINK_OPTIONS ${EXTRA_LINK_OPTIONS} ${MUJOCO_HARDEN_LINK_OPTIONS})
+1 -1
View File
@@ -17,7 +17,7 @@
#include <cstdio>
#include <cstring>
#include <mujoco.h>
#include <mujoco/mujoco.h>
// help
const char helpstring[] =
+1 -1
View File
@@ -16,7 +16,7 @@
#include <cstdio>
#include <cstring>
#include <mujoco.h>
#include <mujoco/mujoco.h>
// enable compilation with and without OpenMP support
#if defined(_OPENMP)
+33
View File
@@ -0,0 +1,33 @@
// Copyright 2022 DeepMind Technologies Limited
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#include <sstream>
#include <string>
#include <Cocoa/Cocoa.h>
std::string getSavePath(const char* filename) {
NSSavePanel* panel = [NSSavePanel savePanel];
NSURL* userDocumentsDir = [NSFileManager.defaultManager URLsForDirectory:NSDocumentDirectory
inDomains:NSUserDomainMask].firstObject;
[panel setDirectoryURL:userDocumentsDir];
[panel setNameFieldStringValue:[NSString stringWithUTF8String:filename]];
if ([panel runModal] == NSModalResponseOK) {
std::ostringstream s;
s << [panel.URL.path cStringUsingEncoding:NSUTF8StringEncoding];
return s.str();
} else {
return "";
}
}
+1 -1
View File
@@ -16,7 +16,7 @@
#include <cstdlib>
#include <cstring>
#include <mujoco.h>
#include <mujoco/mujoco.h>
// select EGL, OSMESA or GLFW
#if defined(MJ_EGL)
+27 -4
View File
@@ -19,7 +19,7 @@
#include <string>
#include <thread>
#include <mjxmacro.h>
#include <mujoco/mjxmacro.h>
#include "uitools.h"
#include "array_safety.h"
@@ -1289,6 +1289,21 @@ void uiLayout(mjuiState* state) {
// When launched via an App Bundle on macOS, the working directory is the path to the App Bundle's
// resource directory. This causes files to be saved into the bundle, which is not the desired
// behavior. Instead, we open a save dialog box to ask the user where to put the file.
// Since the dialog box logic needs to be written in Objective-C, we separate it into a different
// source file.
#ifdef __APPLE__
std::string getSavePath(const char* filename);
#else
static std::string getSavePath(const char* filename) {
return filename;
}
#endif
// handle UI event
void uiEvent(mjuiState* state) {
int i;
@@ -1305,13 +1320,21 @@ void uiEvent(mjuiState* state) {
if (it && it->sectionid==SECT_FILE) {
switch (it->itemid) {
case 0: // Save xml
if (!mj_saveLastXML("mjmodel.xml", m, err, 200)) {
std::printf("Save XML error: %s", err);
{
const std::string path = getSavePath("mjmodel.xml");
if (!path.empty() && !mj_saveLastXML(path.c_str(), m, err, 200)) {
std::printf("Save XML error: %s", err);
}
}
break;
case 1: // Save mjb
mj_saveModel(m, "mjmodel.mjb", NULL, 0);
{
const std::string path = getSavePath("mjmodel.mjb");
if (!path.empty()) {
mj_saveModel(m, path.c_str(), NULL, 0);
}
}
break;
case 2: // Print model
+3 -2
View File
@@ -18,7 +18,7 @@
#include <string>
#include <thread>
#include <mujoco.h>
#include <mujoco/mujoco.h>
// maximum number of threads
@@ -94,7 +94,8 @@ void simulate(int id, int nstep, mjtNum ctrlnoise) {
// main function
int main(int argc, const char** argv) {
int main(int argc, char** argv) {
// print help if arguments are missing
if (argc<2 || argc>6) {
return finish("\n Usage: testspeed modelfile [nstep nthread ctrlnoise profile]\n");
+2 -2
View File
@@ -17,8 +17,8 @@
#include <cstring>
#include <string>
#include <mjxmacro.h>
#include <mujoco.h>
#include <mujoco/mjxmacro.h>
#include <mujoco/mujoco.h>
#include "array_safety.h"
namespace mju = ::mujoco::sample_util;
+2 -2
View File
@@ -16,8 +16,8 @@
#define MUJOCO_UITOOLS_H_
#include "GLFW/glfw3.h"
#include <mujoco.h>
#include <GLFW/glfw3.h>
#include <mujoco/mujoco.h>
// this is a C-API
#if defined(__cplusplus)
+96
View File
@@ -0,0 +1,96 @@
// Copyright 2021 DeepMind Technologies Limited
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#ifndef MUJOCO_SRC_CC_ARRAY_SAFETY_H_
#define MUJOCO_SRC_CC_ARRAY_SAFETY_H_
#include <algorithm>
#include <cstdarg>
#include <cstddef>
#include <cstdio>
#include <cstring>
// Provides safe alternatives to the sizeof() operator and standard library functions for handling
// null-terminated (C-style) strings in raw char arrays.
//
// These functions make use of compile-time array sizes to limit read and write operations to within
// the array bounds. They are designed to trigger a compile error if the array size cannot be
// determined at compile time (e.g. when an array has decayed into a pointer).
//
// They do not perform runtime bound checks.
namespace mujoco {
namespace util {
// returns sizeof(arr)
// use instead of sizeof() to avoid unintended array-to-pointer decay
template <typename T, int N>
static constexpr std::size_t sizeof_arr(const T(&arr)[N]) {
return sizeof(arr);
}
// like std::strcmp but it will not read beyond the bound of either lhs or rhs
template <std::size_t N1, std::size_t N2>
static inline int strcmp_arr(const char (&lhs)[N1], const char (&rhs)[N2]) {
return std::strncmp(lhs, rhs, std::min(N1, N2));
}
// like std::strlen but it will not read beyond the bound of str
// if str is not null-terminated, returns sizeof(str)
template <std::size_t N>
static inline std::size_t strlen_arr(const char (&str)[N]) {
for (std::size_t i = 0; i < N; ++i) {
if (str[i] == '\0') {
return i;
}
}
return N;
}
// like std::sprintf but will not write beyond the bound of dest
// dest is guaranteed to be null-terminated
template <std::size_t N>
static inline int sprintf_arr(char (&dest)[N], const char* format, ...) {
std::va_list vargs;
va_start(vargs, format);
int retval = std::vsnprintf(dest, N, format, vargs);
va_end(vargs);
return retval;
}
// like std::strcat but will not write beyond the bound of dest
// dest is guaranteed to be null-terminated
template <std::size_t N>
static inline char* strcat_arr(char (&dest)[N], const char* src) {
return std::strncat(dest, src, sizeof_arr(dest) - strlen_arr(dest) - 1);
}
// like std::strcpy but won't write beyond the bound of dest
// dest is guaranteed to be null-terminated
template <std::size_t N>
static inline char* strcpy_arr(char (&dest)[N], const char* src) {
{
std::size_t i = 0;
for (; src[i] && i < N - 1; ++i) {
dest[i] = src[i];
}
dest[i] = '\0';
}
return &dest[0];
}
} // namespace util
} // namespace mujoco
#endif // MUJOCO_SRC_CC_ARRAY_SAFETY_H_
+74
View File
@@ -0,0 +1,74 @@
# Copyright 2021 DeepMind Technologies Limited
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# https://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
set(MUJOCO_ENGINE_SRCS
engine_array_safety.h
engine_callback.c
engine_callback.h
engine_collision_box.c
engine_collision_convex.c
engine_collision_convex.h
engine_collision_driver.c
engine_collision_driver.h
engine_collision_primitive.c
engine_collision_primitive.h
engine_core_constraint.c
engine_core_constraint.h
engine_core_smooth.c
engine_core_smooth.h
engine_crossplatform.h
engine_file.c
engine_file.h
engine_forward.c
engine_forward.h
engine_inverse.c
engine_inverse.h
engine_io.c
engine_io.h
engine_macro.h
engine_print.c
engine_print.h
engine_ray.c
engine_ray.h
engine_sensor.c
engine_sensor.h
engine_setconst.c
engine_setconst.h
engine_solver.c
engine_solver.h
engine_support.c
engine_support.h
engine_util_blas.c
engine_util_blas.h
engine_util_errmem.c
engine_util_errmem.h
engine_util_misc.c
engine_util_misc.h
engine_util_solve.c
engine_util_solve.h
engine_util_sparse.c
engine_util_sparse.h
engine_util_spatial.c
engine_util_spatial.h
engine_vfs.c
engine_vfs.h
engine_vis_init.c
engine_vis_init.h
engine_vis_interact.c
engine_vis_interact.h
engine_vis_visualize.c
engine_vis_visualize.h
)
target_sources(mujoco PRIVATE ${MUJOCO_ENGINE_SRCS})
+31
View File
@@ -0,0 +1,31 @@
// Copyright 2021 DeepMind Technologies Limited
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#ifndef MUJOCO_SRC_ENGINE_ENGINE_ARRAY_SAFETY_H_
#define MUJOCO_SRC_ENGINE_ENGINE_ARRAY_SAFETY_H_
#include <stdio.h>
#include <string.h>
// Evaluates to sizeof(arr) if arr is a char array, and emits a compiler error
// otherwise. In particular, emits a compiler error if arr is a char*.
#define mjSIZEOFARRAY(arr) _Generic(&(arr), char(*)[sizeof(arr)]: sizeof(arr))
#define mjSNPRINTF(dest, ...) snprintf(dest, mjSIZEOFARRAY(dest), __VA_ARGS__)
#define mjSTRNCAT(dest, src) strncat(dest, src, mjSIZEOFARRAY(dest) - strlen(dest) - 1)
#define mjSTRNCPY(dest, src) mju_strncpy(dest, src, mjSIZEOFARRAY(dest))
#endif // MUJOCO_SRC_ENGINE_ENGINE_ARRAY_SAFETY_H_
+42
View File
@@ -0,0 +1,42 @@
// Copyright 2021 DeepMind Technologies Limited
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#include "engine/engine_callback.h"
#include <mujoco/mjdata.h>
//------------------------- global callback pointers -----------------------------------------------
mjfGeneric mjcb_passive = 0;
mjfGeneric mjcb_control = 0;
mjfConFilt mjcb_contactfilter = 0;
mjfSensor mjcb_sensor = 0;
mjfTime mjcb_time = 0;
mjfAct mjcb_act_bias = 0;
mjfAct mjcb_act_gain = 0;
mjfAct mjcb_act_dyn = 0;
// reset callbacks to defauls
void mj_resetCallbacks(void) {
mjcb_passive = 0;
mjcb_control = 0;
mjcb_contactfilter = 0;
mjcb_sensor = 0;
mjcb_time = 0;
mjcb_act_bias = 0;
mjcb_act_gain = 0;
mjcb_act_dyn = 0;
}
+42
View File
@@ -0,0 +1,42 @@
// Copyright 2021 DeepMind Technologies Limited
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#ifndef MUJOCO_SRC_ENGINE_ENGINE_CALLBACK_H_
#define MUJOCO_SRC_ENGINE_ENGINE_CALLBACK_H_
#include <mujoco/mjdata.h>
#include <mujoco/mjexport.h>
#ifdef __cplusplus
extern "C" {
#endif
// global callback function pointers
MJAPI extern mjfGeneric mjcb_passive;
MJAPI extern mjfGeneric mjcb_control;
MJAPI extern mjfConFilt mjcb_contactfilter;
MJAPI extern mjfSensor mjcb_sensor;
MJAPI extern mjfTime mjcb_time;
MJAPI extern mjfAct mjcb_act_bias;
MJAPI extern mjfAct mjcb_act_gain;
MJAPI extern mjfAct mjcb_act_dyn;
// reset callbacks to defaults
MJAPI void mj_resetCallbacks(void);
#ifdef __cplusplus
}
#endif
#endif // MUJOCO_SRC_ENGINE_ENGINE_CALLBACK_H_
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
+64
View File
@@ -0,0 +1,64 @@
// Copyright 2021 DeepMind Technologies Limited
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#ifndef MUJOCO_SRC_ENGINE_ENGINE_COLLISION_CONVEX_H_
#define MUJOCO_SRC_ENGINE_ENGINE_COLLISION_CONVEX_H_
// libCCD has an unconditional `#define _CRT_SECURE_NO_WARNINGS` on Windows.
// TODO(stunya): Remove once https://github.com/danfis/libccd/pull/77 is merged
#ifdef _CRT_SECURE_NO_WARNINGS
#undef _CRT_SECURE_NO_WARNINGS
#endif
#include <ccd/vec3.h>
#include <mujoco/mjdata.h>
#include <mujoco/mjmodel.h>
#ifdef __cplusplus
extern "C" {
#endif
// ccd general object type
struct _mjtCCD {
const mjModel* model;
const mjData* data;
int geom;
int meshindex;
mjtNum margin;
mjtNum rotate[4];
};
typedef struct _mjtCCD mjtCCD;
// ccd support function
void mjccd_support(const void *obj, const ccd_vec3_t *dir, ccd_vec3_t *vec);
// pairwise collision functions using ccd
int mjc_PlaneConvex (const mjModel* m, const mjData* d,
mjContact* con, int g1, int g2, mjtNum margin);
int mjc_ConvexHField (const mjModel* m, const mjData* d,
mjContact* con, int g1, int g2, mjtNum margin);
int mjc_Convex (const mjModel* m, const mjData* d,
mjContact* con, int g1, int g2, mjtNum margin);
// fix contact frame normal
void mjc_fixNormal(const mjModel* m, const mjData* d, mjContact* con, int g1, int g2);
#ifdef __cplusplus
}
#endif
#endif // MUJOCO_SRC_ENGINE_ENGINE_COLLISION_CONVEX_H_
+784
View File
@@ -0,0 +1,784 @@
// Copyright 2021 DeepMind Technologies Limited
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#include "engine/engine_collision_driver.h"
#include <stddef.h>
#include <string.h>
#include <mujoco/mjdata.h>
#include <mujoco/mjmodel.h>
#include "engine/engine_callback.h"
#include "engine/engine_collision_convex.h"
#include "engine/engine_collision_primitive.h"
#include "engine/engine_core_constraint.h"
#include "engine/engine_crossplatform.h"
#include "engine/engine_io.h"
#include "engine/engine_macro.h"
#include "engine/engine_util_blas.h"
#include "engine/engine_util_errmem.h"
#include "engine/engine_util_misc.h"
#include "engine/engine_util_solve.h"
#include "engine/engine_util_spatial.h"
// table of pair-wise collision functions
mjfCollision mjCOLLISIONFUNC[mjNGEOMTYPES][mjNGEOMTYPES] = {
/* PLANE HFIELD SPHERE CAPSULE ELLIPSOID CYLINDER BOX MESH */
/*PLANE */ {0, 0, mjc_PlaneSphere, mjc_PlaneCapsule, mjc_PlaneConvex, mjc_PlaneCylinder, mjc_PlaneBox, mjc_PlaneConvex},
/*HFIELD */ {0, 0, mjc_ConvexHField, mjc_ConvexHField, mjc_ConvexHField, mjc_ConvexHField, mjc_ConvexHField, mjc_ConvexHField},
/*SHPERE */ {0, 0, mjc_SphereSphere, mjc_SphereCapsule, mjc_Convex, mjc_Convex, mjc_SphereBox, mjc_Convex},
/*CAPSULE */ {0, 0, 0, mjc_CapsuleCapsule, mjc_Convex, mjc_Convex, mjc_CapsuleBox, mjc_Convex},
/*ELLIPSOID */ {0, 0, 0, 0, mjc_Convex, mjc_Convex, mjc_Convex, mjc_Convex},
/*CYLINDER */ {0, 0, 0, 0, 0, mjc_Convex, mjc_Convex, mjc_Convex},
/*BOX */ {0, 0, 0, 0, 0, 0, mjc_BoxBox, mjc_Convex},
/*MESH */ {0, 0, 0, 0, 0, 0, 0, mjc_Convex}
};
//----------------------------- collision detection entry point ------------------------------------
void mj_collision(const mjModel* m, mjData* d) {
int g1, g2, signature, merged, b1 = 0, b2 = 0, exadr = 0, pairadr = 0, startadr;
int nexclude = m->nexclude, npair = m->npair, nbodypair = ((m->nbody-1)*m->nbody)/2;
int *broadphasepair = 0;
mjMARKSTACK;
// clear size
d->ncon = 0;
// return if disabled
if (mjDISABLED(mjDSBL_CONSTRAINT) || mjDISABLED(mjDSBL_CONTACT)
|| m->nconmax==0 || m->nbody < 2) {
return;
}
// predefined only; ignore exclude
if (m->opt.collision==mjCOL_PAIR) {
for (pairadr=0; pairadr<npair; pairadr++) {
mj_collideGeoms(m, d, pairadr, -1, 0, 0);
}
}
// dynamic only or merge; apply exclude
else {
// call broadphase collision detector
broadphasepair = (int*)mj_stackAlloc(d, (m->nbody*(m->nbody-1))/2);
nbodypair = mj_broadphase(m, d, broadphasepair, (m->nbody*(m->nbody-1))/2);
// loop over body pairs (broadphase or all)
for (int i=0; i<nbodypair; i++) {
// reconstruct body pair ids
b1 = (broadphasepair[i]>>16) & 0xFFFF;
b2 = broadphasepair[i] & 0xFFFF;
// compute signature for this body pair
signature = ((b1+1)<<16) + (b2+1);
// merge predefined pairs
merged = 0;
startadr = pairadr;
if (npair && m->opt.collision==mjCOL_ALL) {
// test all predefined pairs for which pair_signature<=signature
while (pairadr<npair && m->pair_signature[pairadr]<=signature) {
if (m->pair_signature[pairadr]==signature) {
merged = 1;
}
mj_collideGeoms(m, d, pairadr++, -1, 0, 0);
}
}
// handle exclusion
if (nexclude) {
// advance exadr while exclude_signature < signature
while (m->exclude_signature[exadr]<signature && exadr<nexclude) {
exadr++;
}
// skip this body pair if its signature is found in exclude array
if (exadr<nexclude && m->exclude_signature[exadr]==signature) {
continue;
}
}
// test all geom pairs within this body pair
if (m->body_geomnum[b1] && m->body_geomnum[b2]) {
for (g1=m->body_geomadr[b1]; g1<m->body_geomadr[b1]+m->body_geomnum[b1]; g1++) {
for (g2=m->body_geomadr[b2]; g2<m->body_geomadr[b2]+m->body_geomnum[b2]; g2++) {
// merged: make sure geom pair is not repeated
if (merged) {
// find matching pair
int found = 0;
for (int k=startadr; k<pairadr; k++) {
if ((m->pair_geom1[k]==g1 && m->pair_geom2[k]==g2) ||
(m->pair_geom1[k]==g2 && m->pair_geom2[k]==g1)) {
found = 1;
break;
}
}
// not found: test
if (!found) {
mj_collideGeoms(m, d, g1, g2, 0, 0);
}
}
// not merged: always test
else {
mj_collideGeoms(m, d, g1, g2, 0, 0);
}
}
}
}
}
// finish merging predefined pairs
if (npair && m->opt.collision==mjCOL_ALL)
while (pairadr<npair) {
mj_collideGeoms(m, d, pairadr++, -1, 0, 0);
}
}
mjFREESTACK;
}
//----------------------------- broad-phase collision detection ------------------------------------
// helper structure for SAP sorting
struct _mjtBroadphase {
float value;
int body_ismax;
};
typedef struct _mjtBroadphase mjtBroadphase;
// make AABB for one body
static void makeAABB(const mjModel* m, mjData* d, mjtNum* aabb, int body, const mjtNum* frame) {
int geom;
mjtNum _aabb[6], cen;
// no geoms attached to body: set to 0
if (m->body_geomnum[body]==0) {
mju_zero(aabb, 6);
return;
}
// process all body geoms
for (int i=0; i<m->body_geomnum[body]; i++) {
// get geom id
geom = m->body_geomadr[body]+i;
// set _aabb for this geom
for (int j=0; j<3; j++) {
cen = mju_dot3(d->geom_xpos+3*geom, frame+3*j);
_aabb[2*j] = cen - m->geom_rbound[geom] - m->geom_margin[geom];
_aabb[2*j+1] = cen + m->geom_rbound[geom] + m->geom_margin[geom];
}
// update body aabb
if (i==0) {
mju_copy(aabb, _aabb, 6);
} else {
for (int j=0; j<3; j++) {
aabb[2*j] = mju_min(aabb[2*j], _aabb[2*j]);
aabb[2*j+1] = mju_max(aabb[2*j+1], _aabb[2*j+1]);
}
}
}
}
// return 1 if body has plane or hfield geom, 0 otherwise
static int has_plane_or_hfield(const mjModel* m, int body) {
int start = m->body_geomadr[body];
int end = m->body_geomadr[body] + m->body_geomnum[body];
// scan geoms belonging to body
int g;
for (g=start; g<end; g++) {
if (m->geom_type[g]==mjGEOM_PLANE || m->geom_type[g]==mjGEOM_HFIELD) {
return 1;
}
}
return 0;
}
// add body pair in buffer
static void add_pair(const mjModel* m, int b1, int b2, int* npair, int* pair, int maxpair) {
// add pair if there is room in buffer
if ((*npair)<maxpair) {
// exlude based on contype and conaffinity
if (m && m->body_geomnum[b1]==1 && m->body_geomnum[b2]==1) {
// get contypes and conaffinities
int contype1 = m->geom_contype[m->body_geomadr[b1]];
int conaffinity1 = m->geom_conaffinity[m->body_geomadr[b1]];
int contype2 = m->geom_contype[m->body_geomadr[b2]];
int conaffinity2 = m->geom_conaffinity[m->body_geomadr[b2]];
// compatibility check
if (!(contype1 & conaffinity2) && !(contype2 & conaffinity1)) {
return;
}
}
// add pair
if (b1<b2) {
pair[*npair] = (b1<<16) + b2;
} else {
pair[*npair] = (b2<<16) + b1;
}
(*npair)++;
} else {
mju_error("Broadphase buffer full");
}
}
// comparison function for broadphase
quicksortfunc(broadcompare, context, el1, el2) {
mjtBroadphase* b1 = (mjtBroadphase*)el1;
mjtBroadphase* b2 = (mjtBroadphase*)el2;
if (b1->value<b2->value) {
return -1;
} else if (b1->value==b2->value) {
return 0;
} else {
return 1;
}
}
// comparison function for pair sorting
quicksortfunc(paircompare, context, el1, el2) {
int signature1 = *(int*)el1;
int signature2 = *(int*)el2;
if (signature1<signature2) {
return -1;
} else if (signature1==signature2) {
return 0;
} else {
return 1;
}
}
// does body have collidable geoms
static int can_collide(const mjModel* m, int b) {
int g;
// scan geoms; return if collidable
for (g=0; g<m->body_geomnum[b]; g++) {
int ind = m->body_geomadr[b] + g;
if (m->geom_contype[ind] || m->geom_conaffinity[ind]) {
return 1;
}
}
// none found
return 0;
}
// broadphase collision detector
int mj_broadphase(const mjModel* m, mjData* d, int* pair, int maxpair) {
int i, j, b1, b2, toremove, cnt, npair = 0, nbody = m->nbody, ngeom = m->ngeom;
mjtNum cov[9], cen[3], dif[3], eigval[3], frame[9], quat[4];
mjtBroadphase *sortbuf, *activebuf;
mjtNum *aabb;
mjMARKSTACK;
// world with geoms, and body with plane or hfield, can collide all bodies
for (b1=0; b1<nbody; b1++) {
// cannot colide
if (!can_collide(m, b1)) {
continue;
}
// world with geoms, or welded body with plane or hfield
if ((b1==0 && m->body_geomnum[b1]>0) || (m->body_weldid[b1]==0 && has_plane_or_hfield(m, b1))) {
for (b2=0; b2<nbody; b2++) {
if (b1!=b2) {
add_pair(NULL, b1, b2, &npair, pair, maxpair);
}
}
}
}
// find center of non-world geoms; return if none
cnt = 0;
mju_zero3(cen);
for (i=0; i<ngeom; i++) {
if (m->geom_bodyid[i]) {
mju_addTo3(cen, d->geom_xpos+3*i);
cnt++;
}
}
if (cnt==0) {
return npair;
} else {
for (i=0; i<3; i++) {
cen[i] /= cnt;
}
}
// compute covariance
mju_zero(cov, 9);
for (i=0; i<ngeom; i++) {
if (m->geom_bodyid[i]) {
mju_sub3(dif, d->geom_xpos+3*i, cen);
mjtNum D00 = dif[0]*dif[0];
mjtNum D01 = dif[0]*dif[1];
mjtNum D02 = dif[0]*dif[2];
mjtNum D11 = dif[1]*dif[1];
mjtNum D12 = dif[1]*dif[2];
mjtNum D22 = dif[2]*dif[2];
cov[0] += D00;
cov[1] += D01;
cov[2] += D02;
cov[3] += D01;
cov[4] += D11;
cov[5] += D12;
cov[6] += D02;
cov[7] += D12;
cov[8] += D22;
}
}
for (i=0; i<9; i++) {
cov[i] /= cnt;
}
// construct covariance-aligned 3D frame
mju_eig3(eigval, frame, quat, cov);
// allocate AABB; clear world entry (not used)
aabb = mj_stackAlloc(d, 6*nbody);
mju_zero(aabb, 6);
// construct body AABB for the aligned frame, count collidable
int bufcnt = 0;
for (i=1; i<nbody; i++) {
makeAABB(m, d, aabb+6*i, i, frame);
if (can_collide(m, i)) {
bufcnt++;
}
}
// nothing collidable
if (!bufcnt) {
goto endbroad;
}
// allocate sort buffer
i = sizeof(mjtBroadphase)/sizeof(mjtNum);
j = sizeof(mjtBroadphase)%sizeof(mjtNum);
sortbuf = (mjtBroadphase*)mj_stackAlloc(d, 2*bufcnt*(i + (j ? 1 : 0)));
activebuf = (mjtBroadphase*)mj_stackAlloc(d, 2*bufcnt*(i + (j ? 1 : 0)));
// init sortbuf with axis0
j = 0;
for (i=1; i<nbody; i++) {
// cannot colide
if (!can_collide(m, i)) {
continue;
}
// init
sortbuf[2*j].body_ismax = i;
sortbuf[2*j].value = (float)aabb[6*i];
sortbuf[2*j+1].body_ismax = i + 0x10000;
sortbuf[2*j+1].value = (float)aabb[6*i+1];
j++;
}
// sanity check; SHOULD NOT OCCUR
if (j!=bufcnt) {
mju_error("Internal error in broadphase: unexpected bufcnt");
}
// sort along axis0
mjQUICKSORT(sortbuf, 2*bufcnt, sizeof(mjtBroadphase), broadcompare, 0);
// sweep and prune
cnt = 0; // size of active list
for (i=0; i<2*bufcnt; i++) {
// min value: collide with all in list, add
if (!(sortbuf[i].body_ismax & 0x10000)) {
for (j=0; j<cnt; j++) {
// get body ids
b1 = activebuf[j].body_ismax;
b2 = sortbuf[i].body_ismax;
// use the other two axes to prune if possible
if (aabb[6*b1+2] > aabb[6*b2+3] ||
aabb[6*b1+3] < aabb[6*b2+2] ||
aabb[6*b1+4] > aabb[6*b2+5] ||
aabb[6*b1+5] < aabb[6*b2+4]) {
continue;
}
// add body pair if there is room in buffer
add_pair(m, b1, b2, &npair, pair, maxpair);
}
// add to list
activebuf[cnt] = sortbuf[i];
cnt++;
}
// max value: remove corresponding min value from list
else {
toremove = sortbuf[i].body_ismax & 0xFFFF;
for (j=0; j<cnt; j++) {
if (activebuf[j].body_ismax==toremove) {
if (j<cnt-1) {
memmove(activebuf+j, activebuf+j+1, sizeof(mjtBroadphase)*(cnt-1-j));
}
cnt--;
break;
}
}
}
}
endbroad:
// sort pairs by signature
if (npair) {
mjQUICKSORT(pair, npair, sizeof(int), paircompare, 0);
}
mjFREESTACK;
return npair;
}
//----------------------------- narrow-phase collision detection -----------------------------------
// plane : geom_center distance, assuming g1 is plane
static mjtNum plane_geom(const mjModel* m, mjData* d, int g1, int g2) {
mjtNum* mat1 = d->geom_xmat + 9*g1;
mjtNum norm[3] = {mat1[2], mat1[5], mat1[8]};
mjtNum dif[3];
mju_sub3(dif, d->geom_xpos + 3*g2, d->geom_xpos + 3*g1);
return mju_dot3(dif, norm);
}
// test two geoms for collision, apply filters, add to contact list
// flg_user disables filters and uses usermargin
void mj_collideGeoms(const mjModel* m, mjData* d, int g1, int g2, int flg_user, mjtNum usermargin) {
int i, num, type1, type2, b1, b2, weld1, weld2, condim;
mjtNum margin, gap, mix, friction[5], solref[mjNREF], solimp[mjNIMP];
mjContact con[mjMAXCONPAIR];
int ipair = (g2<0 ? g1 : -1);
// get explicit geom ids from pair
if (ipair>=0) {
g1 = m->pair_geom1[ipair];
g2 = m->pair_geom2[ipair];
}
// order geoms by type
if (m->geom_type[g1] > m->geom_type[g2]) {
i = g1;
g1 = g2;
g2 = i;
}
// copy types and bodies
type1 = m->geom_type[g1];
type2 = m->geom_type[g2];
b1 = m->geom_bodyid[g1];
b2 = m->geom_bodyid[g2];
weld1 = m->body_weldid[b1];
weld2 = m->body_weldid[b2];
// return if no collision function
if (!mjCOLLISIONFUNC[type1][type2]) {
return;
}
// apply filters if not predefined pair and not flg_user
if (ipair<0 && !flg_user) {
// user filter if defined
if (mjcb_contactfilter) {
if (mjcb_contactfilter(m, d, g1, g2)) {
return;
}
}
// otherwise built-in filter
else if (mj_contactFilter(
type1, m->geom_contype[g1], m->geom_conaffinity[g1],
weld1, m->body_weldid[m->body_parentid[weld1]],
type2, m->geom_contype[g2], m->geom_conaffinity[g2],
weld2, m->body_weldid[m->body_parentid[weld2]],
!mjDISABLED(mjDSBL_FILTERPARENT) && weld1 && weld2)) {
return;
}
}
// set margin, gap, condim: dynamic
if (ipair<0) {
// margin and gap: max
margin = mju_max(m->geom_margin[g1], m->geom_margin[g2]);
gap = mju_max(m->geom_gap[g1], m->geom_gap[g2]);
// condim: priority or max
if (m->geom_priority[g1]!=m->geom_priority[g2]) {
int gp = (m->geom_priority[g1]>m->geom_priority[g2] ? g1 : g2);
condim = m->geom_condim[gp];
} else {
condim = mjMAX(m->geom_condim[g1], m->geom_condim[g2]);
}
}
// set margin, gap, condim: pair
else {
margin = m->pair_margin[ipair];
gap = m->pair_gap[ipair];
condim = m->pair_dim[ipair];
}
// adjust margin
if (flg_user) {
margin = usermargin;
} else {
margin = mj_assignMargin(m, margin);
}
// bounding sphere filter
if (m->geom_rbound[g1]>0 && m->geom_rbound[g2]>0 &&
(mju_dist3(d->geom_xpos+3*g1, d->geom_xpos+3*g2) >
m->geom_rbound[g1] + m->geom_rbound[g2] + margin)) {
return;
}
// plane : bounding sphere filter
if (m->geom_type[g1]==mjGEOM_PLANE && m->geom_rbound[g2]>0
&& plane_geom(m, d, g1, g2) > margin+m->geom_rbound[g2]) {
return;
}
if (m->geom_type[g2]==mjGEOM_PLANE && m->geom_rbound[g1]>0
&& plane_geom(m, d, g2, g1) > margin+m->geom_rbound[g1]) {
return;
}
// call collision detector to generate contacts
num = mjCOLLISIONFUNC[type1][type2](m, d, con, g1, g2, margin);
// no contacts from near-phase
if (!num) {
return;
}
// check number of contacts, SHOULD NOT OCCUR
if (num>mjMAXCONPAIR) {
mju_error("Too many contacts returned by collision function");
}
// remove repeated contacts in box-box
if (type1==mjGEOM_BOX && type2==mjGEOM_BOX) {
// use dim field to mark: -1: bad, 0: good
for (i=0; i<num; i++) {
con[i].dim = 0;
}
// find bad
int j;
for (i=0; i<num-1; i++) {
for (j=i+1; j<num; j++) {
if (con[i].pos[0]==con[j].pos[0] &&
con[i].pos[1]==con[j].pos[1] &&
con[i].pos[2]==con[j].pos[2]) {
con[i].dim = -1;
break;
}
}
}
// consolidate good
i = 0;
for (j=0; j<num; j++) {
if (con[j].dim==0) {
// different: copy
if (i<j) {
con[i] = con[j];
}
// advance either way
i++;
}
}
// adjust size
num = i;
}
// set friction, solref, solimp: dynamic
if (ipair<0) {
// different priority
if (m->geom_priority[g1]!=m->geom_priority[g2]) {
int gp = (m->geom_priority[g1]>m->geom_priority[g2] ? g1 : g2);
// friction
for (i=0; i<3; i++) {
friction[2*i] = m->geom_friction[3*gp+i];
}
// reference
mju_copy(solref, m->geom_solref+mjNREF*gp, mjNREF);
// impedance
mju_copy(solimp, m->geom_solimp+mjNIMP*gp, mjNIMP);
}
// same priority
else {
// friction: max
for (i=0; i<3; i++) {
friction[2*i] = mju_max(m->geom_friction[3*g1+i], m->geom_friction[3*g2+i]);
}
// solver mix factor
if (m->geom_solmix[g1]>=mjMINVAL && m->geom_solmix[g2]>=mjMINVAL) {
mix = m->geom_solmix[g1] / (m->geom_solmix[g1] + m->geom_solmix[g2]);
} else if (m->geom_solmix[g1]<mjMINVAL && m->geom_solmix[g2]<mjMINVAL) {
mix = 0.5;
} else if (m->geom_solmix[g1]<mjMINVAL) {
mix = 0.0;
} else {
mix = 1.0;
}
// reference standard: mix
if (m->geom_solref[mjNREF*g1]>0 && m->geom_solref[mjNREF*g2]>0) {
for (i=0; i<mjNREF; i++) {
solref[i] = mix*m->geom_solref[mjNREF*g1+i] + (1-mix)*m->geom_solref[mjNREF*g2+i];
}
}
// reference direct: min
else {
for (i=0; i<mjNREF; i++) {
solref[i] = mju_min(m->geom_solref[mjNREF*g1+i], m->geom_solref[mjNREF*g2+i]);
}
}
// impedance: mix
mju_scl(solimp, m->geom_solimp+mjNIMP*g1, mix, mjNIMP);
mju_addToScl(solimp, m->geom_solimp+mjNIMP*g2, 1-mix, mjNIMP);
}
// unpack 5D friction
friction[1] = friction[0];
friction[3] = friction[4];
}
// set friction, solref, solimp: pair
else {
// friction
for (i=0; i<5; i++) {
friction[i] = m->pair_friction[5*ipair+i];
}
// reference
mju_copy(solref, m->pair_solref+mjNREF*ipair, mjNREF);
// impedance
mju_copy(solimp, m->pair_solimp+mjNIMP*ipair, mjNIMP);
}
// clamp friction to mjMINMU
for (i=0; i<5; i++) {
friction[i] = mju_max(mjMINMU, friction[i]);
}
// add contact returned by collision detector
for (i=0; i<num; i++) {
// set contact data
if (condim > 6 || condim < 0) { // SHOULD NOT OCCUR
mju_error_i("Invalid condim value: %d", i);
}
con[i].dim = condim;
con[i].geom1 = g1;
con[i].geom2 = g2;
con[i].includemargin = margin-gap;
mju_copy(con[i].friction, friction, 5);
mj_assignRef(m, con[i].solref, solref);
mj_assignImp(m, con[i].solimp, solimp);
// exclude in gap
if (con[i].dist<con[i].includemargin) {
con[i].exclude = 0;
} else {
con[i].exclude = 1;
}
// complete frame
mju_makeFrame(con[i].frame);
// clear fields that are computed later
con[i].efc_address = -1;
con[i].mu = 0;
mju_zero(con[i].H, 36);
// add to mjData, abort if too many contacts
if (mj_addContact(m, d, con + i)) {
return;
}
}
}
// filter contacts: 1- discard, 0- proceed
int mj_contactFilter(int type1, int contype1, int conaffinity1, int weldbody1, int weldparent1,
int type2, int contype2, int conaffinity2, int weldbody2, int weldparent2,
int filterparent) {
// compatibility check
if (!(contype1 & conaffinity2) && !(contype2 & conaffinity1)) {
return 1;
}
// same weldbody check
if (weldbody1==weldbody2) {
return 1;
}
// weldparent check
if (filterparent && (weldbody1==weldparent2 || weldbody2==weldparent1)) {
return 1;
}
// all tests passed
return 0;
}
+49
View File
@@ -0,0 +1,49 @@
// Copyright 2021 DeepMind Technologies Limited
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#ifndef MUJOCO_SRC_ENGINE_ENGINE_COLLISION_DRIVER_H_
#define MUJOCO_SRC_ENGINE_ENGINE_COLLISION_DRIVER_H_
#include <mujoco/mjdata.h>
#include <mujoco/mjexport.h>
#include <mujoco/mjmodel.h>
#ifdef __cplusplus
extern "C" {
#endif
// collision function pointers and max contact pairs
MJAPI extern mjfCollision mjCOLLISIONFUNC[mjNGEOMTYPES][mjNGEOMTYPES];
// collision detection entry point
MJAPI void mj_collision(const mjModel* m, mjData* d);
// broad phase collistion detection; return list of body pairs for narrow phase
int mj_broadphase(const mjModel* m, mjData* d, int* bodypair, int maxpair);
// test two geoms for collision, apply filters, add to contact list
// flg_user disables filters and uses usermargin
void mj_collideGeoms(const mjModel* m, mjData* d,
int g1, int g2, int flg_user, mjtNum usermargin);
// number of possible collisions based on fitlers and geom types
int mj_contactFilter(int type1, int contype1, int conaffinity1, int weldbody1, int weldparent1,
int type2, int contype2, int conaffinity2, int weldbody2, int weldparent2,
int filterparent);
#ifdef __cplusplus
}
#endif
#endif // MUJOCO_SRC_ENGINE_ENGINE_COLLISION_DRIVER_H_
+460
View File
@@ -0,0 +1,460 @@
// Copyright 2021 DeepMind Technologies Limited
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#include "engine/engine_collision_primitive.h"
#include <math.h>
#include <mujoco/mjdata.h>
#include <mujoco/mjmodel.h>
#include "engine/engine_util_blas.h"
#include "engine/engine_util_spatial.h"
//--------------------------- plane collisions -----------------------------------------------------
// plane : sphere (actual implementation, can be called with modified parameters)
static int _PlaneSphere(mjContact* con, mjtNum margin,
mjtNum* pos1, mjtNum* mat1, mjtNum* size1,
mjtNum* pos2, mjtNum* mat2, mjtNum* size2) {
mjtNum tmp[3];
mjtNum cdist;
// set normal
con[0].frame[0] = mat1[2];
con[0].frame[1] = mat1[5];
con[0].frame[2] = mat1[8];
// compute distance, return if too large
mju_sub3(tmp, pos2, pos1);
cdist = mju_dot3(tmp, con[0].frame);
if (cdist > margin + size2[0]) {
return 0;
}
// depth and position
con[0].dist = cdist - size2[0];
mju_scl3(tmp, con[0].frame, -con[0].dist/2 - size2[0]);
mju_add3(con[0].pos, pos2, tmp);
mju_zero3(con[0].frame+3);
return 1;
}
// plane : sphere
int mjc_PlaneSphere(const mjModel* m, const mjData* d,
mjContact* con, int g1, int g2, mjtNum margin) {
mjGETINFO
return _PlaneSphere(con, margin, pos1, mat1, size1, pos2, mat2, size2);
}
// plane : capsule
int mjc_PlaneCapsule(const mjModel* m, const mjData* d,
mjContact* con, int g1, int g2, mjtNum margin) {
mjGETINFO
mjtNum pos[3], axis[3], segment[3];
int n1, n2;
// get capsule axis, segment = scaled axis
axis[0] = mat2[2];
axis[1] = mat2[5];
axis[2] = mat2[8];
mju_scl3(segment, axis, size2[1]);
// get point 1, do sphere-plane test
mju_add3(pos, pos2, segment);
n1 = _PlaneSphere(con, margin, pos1, mat1, size1, pos, mat2, size2);
// get point 2, do sphere-plane test
mju_sub3(pos, pos2, segment);
n2 = _PlaneSphere(con+n1, margin, pos1, mat1, size1, pos, mat2, size2);
// align contact frames with capsule axis
if (n1) {
mju_copy3(con->frame+3, axis);
}
if (n2) {
mju_copy3((con+n1)->frame+3, axis);
}
return n1+n2;
}
// plane : cylinder
int mjc_PlaneCylinder(const mjModel* m, const mjData* d,
mjContact* con, int g1, int g2, mjtNum margin) {
mjGETINFO
mjtNum normal[3] = {mat1[2], mat1[5], mat1[8]};
mjtNum axis[3] = {mat2[2], mat2[5], mat2[8]};
mjtNum vec[3], vec1[3];
mjtNum len, scl, dist0, prjaxis, prjvec, prjvec1;
int cnt = 0;
// project, make sure axis points towards plane
prjaxis = mju_dot3(normal, axis);
if (prjaxis > 0) {
mju_scl3(axis, axis, -1);
prjaxis = -prjaxis;
}
// compute normal distance to cylinder center
mju_sub3(vec, pos2, pos1);
dist0 = mju_dot3(vec, normal);
// remove component of -normal along axis, compute length
mju_scl3(vec, axis, prjaxis);
mju_subFrom3(vec, normal);
len = mju_norm3(vec);
// general configuration: normalize vector, scale by radius
if (len >= mjMINVAL) {
scl = size2[0]/len;
vec[0] *= scl;
vec[1] *= scl;
vec[2] *= scl;
}
// disk parallel to plane: pick x-axis of cylinder, scale by radius
else {
vec[0] = mat2[0]*size2[0];
vec[1] = mat2[3]*size2[0];
vec[2] = mat2[6]*size2[0];
}
// project vector on normal
prjvec = mju_dot3(vec, normal);
// scale axis by half-length
mju_scl3(axis, axis, size2[1]);
prjaxis *= size2[1];
// check first point, construct contact
if (dist0 + prjaxis + prjvec <= margin) {
con[cnt].dist = dist0 + prjaxis + prjvec;
mju_add3(con[cnt].pos, pos2, vec);
mju_addTo3(con[cnt].pos, axis);
mju_addToScl3(con[cnt].pos, normal, -con[cnt].dist*0.5);
mju_copy3(con[cnt].frame, normal);
mju_zero3(con[cnt].frame+3);
cnt++;
} else {
return 0; // nearest point is above margin: no contacts
}
// check second point, construct contact
if (dist0 - prjaxis + prjvec <= margin) {
con[cnt].dist = dist0 - prjaxis + prjvec;
mju_add3(con[cnt].pos, pos2, vec);
mju_subFrom3(con[cnt].pos, axis);
mju_addToScl3(con[cnt].pos, normal, -con[cnt].dist*0.5);
mju_copy3(con[cnt].frame, normal);
mju_zero3(con[cnt].frame+3);
cnt++;
}
// try to add triangle points on side closer to plane
prjvec1 = -prjvec*0.5;
if (dist0 + prjaxis + prjvec1 <= margin) {
// compute sideways vector: vec1
mju_cross(vec1, vec, axis);
mju_normalize3(vec1);
mju_scl3(vec1, vec1, size2[0]*mju_sqrt(3.0)/2);
// add point A
con[cnt].dist = dist0 + prjaxis + prjvec1;
mju_add3(con[cnt].pos, pos2, vec1);
mju_addTo3(con[cnt].pos, axis);
mju_addToScl3(con[cnt].pos, vec, -0.5);
mju_addToScl3(con[cnt].pos, normal, -con[cnt].dist*0.5);
mju_copy3(con[cnt].frame, normal);
mju_zero3(con[cnt].frame+3);
cnt++;
// add point B
con[cnt].dist = dist0 + prjaxis + prjvec1;
mju_sub3(con[cnt].pos, pos2, vec1);
mju_addTo3(con[cnt].pos, axis);
mju_addToScl3(con[cnt].pos, vec, -0.5);
mju_addToScl3(con[cnt].pos, normal, -con[cnt].dist*0.5);
mju_copy3(con[cnt].frame, normal);
mju_zero3(con[cnt].frame+3);
cnt++;
}
return cnt;
}
// plane : box
int mjc_PlaneBox(const mjModel* m, const mjData* d,
mjContact* con, int g1, int g2, mjtNum margin) {
mjGETINFO
int cnt = 0;
// get normal, difference between centers, normal distance
mjtNum norm[3] = {mat1[2], mat1[5], mat1[8]};
mjtNum dif[3], vec[3], corner[3], dist, ldist;
mju_sub3(dif, pos2, pos1);
dist = mju_dot3(dif, norm);
// test all corners, pick bottom 4
for (int i=0; i<8; i++) {
// get corner in local coordinates
vec[0] = (i&1 ? size2[0] : -size2[0]);
vec[1] = (i&2 ? size2[1] : -size2[1]);
vec[2] = (i&4 ? size2[2] : -size2[2]);
// get corner in global coordinates relative to box center
mju_rotVecMat(corner, vec, mat2);
// compute distance to plane, skip if too far or pointing up
ldist = mju_dot3(norm, corner);
if (dist + ldist > margin || ldist > 0) {
continue;
}
// construct contact
con[cnt].dist = dist + ldist;
mju_copy3(con[cnt].frame, norm);
mju_zero3(con[cnt].frame+3);
mju_addTo3(corner, pos2);
mju_scl3(vec, norm, -con[cnt].dist/2);
mju_add3(con[cnt].pos, corner, vec);
// count; max is 4
if (++cnt >= 4) {
return 4;
}
}
return cnt;
}
//--------------------------- sphere and capsule collisions ----------------------------------------
// sphere : sphere (actual implementation, can be called with modified parameters)
static int _SphereSphere(mjContact* con, mjtNum margin,
mjtNum* pos1, mjtNum* mat1, mjtNum* size1,
mjtNum* pos2, mjtNum* mat2, mjtNum* size2) {
mjtNum len, cdist;
mjtNum axis1[3], axis2[3];
// check bounding spheres (this is called from other functions)
cdist = mju_dist3(pos1, pos2);
if (cdist > margin + size1[0] + size2[0]) {
return 0;
}
// depth and normal
con[0].dist = cdist - size1[0] - size2[0];
mju_sub3(con[0].frame, pos2, pos1);
len = mju_normalize3(con[0].frame);
// if centers are the same, norm = cross-product of z axes
// if z axes are parallel, norm = [1;0;0]
if (len < mjMINVAL) {
axis1[0] = mat1[2];
axis1[1] = mat1[5];
axis1[2] = mat1[8];
axis2[0] = mat2[2];
axis2[1] = mat2[5];
axis2[2] = mat2[8];
mju_cross(con[0].frame, axis1, axis2);
mju_normalize3(con[0].frame);
}
// position
mju_scl3(con[0].pos, con[0].frame, size1[0] + con[0].dist/2);
mju_addTo3(con[0].pos, pos1);
mju_zero3(con[0].frame+3);
return 1;
}
// sphere : sphere
int mjc_SphereSphere(const mjModel* m, const mjData* d,
mjContact* con, int g1, int g2, mjtNum margin) {
mjGETINFO
return _SphereSphere(con, margin, pos1, mat1, size1, pos2, mat2, size2);
}
// sphere : capsule
int mjc_SphereCapsule(const mjModel* m, const mjData* d,
mjContact* con, int g1, int g2, mjtNum margin) {
mjGETINFO
mjtNum x, axis[3], vec[3];
// get capsule axis (scaled)
axis[0] = mat2[2] * size2[1];
axis[1] = mat2[5] * size2[1];
axis[2] = mat2[8] * size2[1];
// find projection, clip to segment
mju_sub3(vec, pos1, pos2);
x = mju_dot3(axis, vec) / mju_dot3(axis, axis);
if (x > 1) {
x = 1;
} else if (x < -1) {
x = -1;
}
// find nearest point on segment, do sphere-sphere test
mju_scl3(vec, axis, x);
mju_addTo3(vec, pos2);
return _SphereSphere(con, margin, pos1, mat1, size1, vec, mat2, size2);
}
// capsule : capsule
int mjc_CapsuleCapsule(const mjModel* m, const mjData* d,
mjContact* con, int g1, int g2, mjtNum margin) {
mjGETINFO
mjtNum axis1[3], axis2[3], dif[3], vec1[3], vec2[3];
mjtNum ma, mb, mc, u, v, det, x1, x2;
int n1, n2, n3, n4;
// get capsule axes (scaled) and center difference
axis1[0] = mat1[2] * size1[1];
axis1[1] = mat1[5] * size1[1];
axis1[2] = mat1[8] * size1[1];
axis2[0] = mat2[2] * size2[1];
axis2[1] = mat2[5] * size2[1];
axis2[2] = mat2[8] * size2[1];
mju_sub3(dif, pos1, pos2);
// compute matrix coefficients and determinant
ma = mju_dot3(axis1, axis1);
mb = -mju_dot3(axis1, axis2);
mc = mju_dot3(axis2, axis2);
u = -mju_dot3(axis1, dif);
v = mju_dot3(axis2, dif);
det = ma*mc - mb*mb;
// general configuration (non-parallel axes)
if (fabs(det) >= mjMINVAL) {
// find projections, clip to segments
x1 = (mc*u - mb*v) / det;
x2 = (ma*v - mb*u) / det;
if (x1 > 1) {
x1 = 1;
x2 = (v-mb)/mc;
} else if (x1 < -1) {
x1 = -1;
x2 = (v+mb)/mc;
}
if (x2 > 1) {
x2 = 1;
x1 = (u-mb)/ma;
if (x1 > 1) {
x1 = 1;
} else if (x1 < -1) {
x1 = -1;
}
} else if (x2 < -1) {
x2 = -1;
x1 = (u+mb)/ma;
if (x1 > 1) {
x1 = 1;
} else if (x1 < -1) {
x1 = -1;
}
}
// find nearest points, do sphere-sphere test
mju_scl3(vec1, axis1, x1);
mju_addTo3(vec1, pos1);
mju_scl3(vec2, axis2, x2);
mju_addTo3(vec2, pos2);
return _SphereSphere(con, margin, vec1, mat1, size1, vec2, mat2, size2);
}
// parallel axes
else {
// x1 = 1
mju_add3(vec1, pos1, axis1);
x2 = (v - mb) / mc;
if (x2 > 1) {
x2 = 1;
} else if (x2 < -1) {
x2 = -1;
}
mju_scl3(vec2, axis2, x2);
mju_addTo3(vec2, pos2);
n1 = _SphereSphere(con, margin, vec1, mat1, size1, vec2, mat2, size2);
// x1 = -1
mju_sub3(vec1, pos1, axis1);
x2 = (v + mb) / mc;
if (x2 > 1) {
x2 = 1;
} else if (x2 < -1) {
x2 = -1;
}
mju_scl3(vec2, axis2, x2);
mju_addTo3(vec2, pos2);
n2 = _SphereSphere(con+n1, margin, vec1, mat1, size1, vec2, mat2, size2);
// return if two contacts already found
if (n1+n2>=2) {
return n1+n2;
}
// x2 = 1
mju_add3(vec2, pos2, axis2);
x1 = (u - mb) / ma;
if (x1 > 1) {
x1 = 1;
} else if (x1 < -1) {
x1 = -1;
}
mju_scl3(vec1, axis1, x1);
mju_addTo3(vec1, pos1);
n3 = _SphereSphere(con+n1+n2, margin, vec1, mat1, size1, vec2, mat2, size2);
// return if two contacts already found
if (n1+n2+n3>=2) {
return n1+n2+n3;
}
// x2 = -1
mju_sub3(vec2, pos2, axis2);
x1 = (u + mb) / ma;
if (x1 > 1) {
x1 = 1;
} else if (x1 < -1) {
x1 = -1;
}
mju_scl3(vec1, axis1, x1);
mju_addTo3(vec1, pos1);
n4 = _SphereSphere(con+n1+n2+n3, margin, vec1, mat1, size1, vec2, mat2, size2);
return n1+n2+n3+n4;
}
}
+64
View File
@@ -0,0 +1,64 @@
// Copyright 2021 DeepMind Technologies Limited
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#ifndef MUJOCO_SRC_ENGINE_ENGINE_COLLISION_PRIMITIVE_H_
#define MUJOCO_SRC_ENGINE_ENGINE_COLLISION_PRIMITIVE_H_
#include <mujoco/mjdata.h>
#include <mujoco/mjmodel.h>
// define and extract geom info
#define mjGETINFO \
mjtNum* pos1 = d->geom_xpos + 3*g1; \
mjtNum* mat1 = d->geom_xmat + 9*g1; \
mjtNum* size1= m->geom_size + 3*g1; \
mjtNum* pos2 = d->geom_xpos + 3*g2; \
mjtNum* mat2 = d->geom_xmat + 9*g2; \
mjtNum* size2= m->geom_size + 3*g2; \
(void) size1; (void) size2;
#ifdef __cplusplus
extern "C" {
#endif
// plane collisions
int mjc_PlaneSphere (const mjModel* m, const mjData* d,
mjContact* con, int g1, int g2, mjtNum margin);
int mjc_PlaneCapsule (const mjModel* m, const mjData* d,
mjContact* con, int g1, int g2, mjtNum margin);
int mjc_PlaneCylinder (const mjModel* m, const mjData* d,
mjContact* con, int g1, int g2, mjtNum margin);
int mjc_PlaneBox (const mjModel* m, const mjData* d,
mjContact* con, int g1, int g2, mjtNum margin);
// sphere and capsule collisions
int mjc_SphereSphere (const mjModel* m, const mjData* d,
mjContact* con, int g1, int g2, mjtNum margin);
int mjc_SphereCapsule (const mjModel* m, const mjData* d,
mjContact* con, int g1, int g2, mjtNum margin);
int mjc_CapsuleCapsule (const mjModel* m, const mjData* d,
mjContact* con, int g1, int g2, mjtNum margin);
// box collisions: from boxcollisions.c
int mjc_CapsuleBox (const mjModel* m, const mjData* d,
mjContact* con, int g1, int g2, mjtNum margin);
int mjc_SphereBox (const mjModel* m, const mjData* d,
mjContact* con, int g1, int g2, mjtNum margin);
int mjc_BoxBox (const mjModel* m, const mjData* d,
mjContact* con, int g1, int g2, mjtNum margin);
#ifdef __cplusplus
}
#endif
#endif // MUJOCO_SRC_ENGINE_ENGINE_COLLISION_PRIMITIVE_H_

Some files were not shown because too many files have changed in this diff Show More