├── README.md
├── communication
├── CMakeLists.txt
├── msg
│ ├── ActuatorCmds.msg
│ └── MotionCommands.msg
├── package.xml
└── srv
│ ├── GaitSwitch.srv
│ └── SimulationReset.srv
├── core
├── CMakeLists.txt
├── cmake
│ ├── deepbreak_cxx_flags.cmake
│ └── pinocchio_config.cmake
├── include
│ └── core
│ │ ├── Types.h
│ │ └── misc
│ │ ├── Benchmark.h
│ │ ├── Buffer.h
│ │ ├── LinearAlgebra.h
│ │ ├── LoadData.h
│ │ ├── Lookup.h
│ │ ├── NumericTraits.h
│ │ └── Numerics.h
├── package.xml
└── src
│ ├── Types.cpp
│ └── misc
│ └── LinearAlgebra.cpp
├── description
├── CMakeLists.txt
├── model
│ └── xml
│ │ ├── digit.xml
│ │ └── meshes
│ │ ├── achilles-rod.stl
│ │ ├── arm-L1.stl
│ │ ├── arm-L2.stl
│ │ ├── arm-L3.stl
│ │ ├── arm-L4.stl
│ │ ├── heel-spring.stl
│ │ ├── hip-pitch-housing.stl
│ │ ├── hip-pitch.stl
│ │ ├── hip-roll-housing.stl
│ │ ├── hip-yaw-housing.stl
│ │ ├── knee.stl
│ │ ├── left-shoulder-cap.stl
│ │ ├── left-waist-cap.stl
│ │ ├── right-shoulder-cap.stl
│ │ ├── right-waist-cap.stl
│ │ ├── shin.stl
│ │ ├── shoulder-roll-housing.stl
│ │ ├── tarsus.stl
│ │ ├── toe-A-rod.stl
│ │ ├── toe-B-rod.stl
│ │ ├── toe-output-ll.stl
│ │ ├── toe-output-lr.stl
│ │ ├── toe-output-rl.stl
│ │ ├── toe-output-rr.stl
│ │ ├── toe-output.stl
│ │ ├── toe-pitch.stl
│ │ ├── toe-roll.stl
│ │ └── torso.stl
└── package.xml
├── results.png
└── simulation
└── mujoco
├── CMakeLists.txt
├── cmake
├── CheckAvxSupport.cmake
├── FindOrFetch.cmake
├── MujocoHarden.cmake
├── MujocoLinkOptions.cmake
├── MujocoMacOS.cmake
├── SimulateDependencies.cmake
└── SimulateOptions.cmake
├── include
├── MuJoCoMessageHandler.h
├── array_safety.h
├── glfw_adapter.h
├── glfw_dispatch.h
├── lodepng.h
├── mujoco
│ ├── mjdata.h
│ ├── mjexport.h
│ ├── mjmodel.h
│ ├── mjplugin.h
│ ├── mjrender.h
│ ├── mjtnum.h
│ ├── mjui.h
│ ├── mjvisualize.h
│ ├── mjxmacro.h
│ └── mujoco.h
├── platform_ui_adapter.h
└── simulate.h
├── launch
└── simulation_launch.py
├── lib
├── libmujoco.so
└── libmujoco.so.2.3.2
├── package.xml
└── src
├── MuJoCoMessageHandler.cpp
├── glfw_adapter.cc
├── glfw_dispatch.cc
├── lodepng.cpp
├── main.cc
├── platform_ui_adapter.cc
└── simulate.cc
/README.md:
--------------------------------------------------------------------------------
1 | # Digit MuJoCo ROS2
2 |
3 |
4 |

5 |
6 |
7 | ## Introduction
8 |
9 | This package is developed with [ROS2](https://docs.ros.org/en/humble/index.html) based on [Digit-V3_SDF_Model](https://github.com/yu-fz/Digit-V3_SDF_Model).
10 |
11 | The files include:
12 |
13 | 1. The XML file `(description/model/xml/digit.xml)` of [Digit](https://agilityrobotics.com/news/2022/future-robotics-l3mjh) for the simulation in [MuJoCo](https://mujoco.org/).
14 | 2. A class named `MuJoCoMessageHandler` is also provided, which publishes the robot joint state and imu message. The `odom` message is just the real pose of the robot in simulation. More details can be found in the cpp file `simulation/mujoco/src/MuJoCoMessageHandler.cpp`.
15 | 3. ROS2 ([version](https://docs.ros.org/en/humble/index.html)) is needed to run this package.
16 |
17 | ## Installation
18 |
19 | ```
20 | # Create your own workspace
21 | cd ~/ & mkdir -p your_workspace/src
22 | ```
23 |
24 | ```
25 | # Clone this package to your_workspace/src
26 | cd ~/your_workspace/src & git clone https://github.com/MindSpaceInc/Digit-MuJoCo-ROS2.git
27 | ```
28 |
29 | ```
30 | # Build (DO NOT remove `--symlink-install`)
31 | colcon build --symlink-install
32 | ```
33 |
34 | ```
35 | # Setup env
36 | source ../install/setup.bash
37 | ```
38 |
39 | ```
40 | # Run simulation
41 | ros2 launch mujoco simulation_launch.py
42 | ```
43 |
44 | Now your can open a new terminal and use command `ros2 topic list` to see the below topics
45 | ```
46 | /parameter_events
47 | /rosout
48 | /simulation/actuators_cmds
49 | /simulation/imu_data
50 | /simulation/joint_states
51 | /simulation/odom
52 |
53 | ```
54 |
55 | # Copyright
56 | Permission to repackage and re-distribute software from Agility Robotics hereby granted under:
57 | ```
58 | Copyright (c) Agility Robotics
59 |
60 | Permission is hereby granted, free of charge, to any person obtaining a copy
61 | of this software and associated documentation files (the "Software"), to
62 | deal in the Software without restriction, including without limitation the
63 | rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
64 | sell copies of the Software, and to permit persons to whom the Software is
65 | furnished to do so, subject to the following conditions:
66 |
67 | The above copyright notice and this permission notice shall be included in
68 | all copies or substantial portions of the Software.
69 |
70 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
71 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
72 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
73 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
74 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
75 | FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
76 | IN THE SOFTWARE.
77 | ```
78 |
--------------------------------------------------------------------------------
/communication/CMakeLists.txt:
--------------------------------------------------------------------------------
1 | cmake_minimum_required(VERSION 3.5)
2 | project(communication)
3 |
4 | # Default to C99
5 | if(NOT CMAKE_C_STANDARD)
6 | set(CMAKE_C_STANDARD 99)
7 | endif()
8 |
9 | # Default to C++14
10 | if(NOT CMAKE_CXX_STANDARD)
11 | set(CMAKE_CXX_STANDARD 14)
12 | endif()
13 |
14 | # if(CMAKE_COMPILER_IS_GNUCXX OR CMAKE_CXX_COMPILER_ID MATCHES "Clang")
15 | # add_compile_options(-Wall -Wextra -Wpedantic)
16 | # endif()
17 |
18 | # find dependencies
19 | find_package(ament_cmake REQUIRED)
20 | find_package(std_msgs REQUIRED)
21 | find_package(geometry_msgs REQUIRED)
22 | find_package(sensor_msgs REQUIRED)
23 | find_package(rosidl_default_generators REQUIRED)
24 |
25 | file(GLOB_RECURSE source ${CMAKE_CURRENT_SOURCE_DIR}/msg/* ${CMAKE_CURRENT_SOURCE_DIR}/srv/* )
26 | rosidl_generate_interfaces(${PROJECT_NAME}
27 | msg/ActuatorCmds.msg
28 | msg/MotionCommands.msg
29 | srv/SimulationReset.srv
30 | srv/GaitSwitch.srv
31 | DEPENDENCIES ament_cmake std_msgs geometry_msgs sensor_msgs
32 | )
33 |
34 | ament_package()
--------------------------------------------------------------------------------
/communication/msg/ActuatorCmds.msg:
--------------------------------------------------------------------------------
1 | std_msgs/Header header
2 | string[<=30] actuators_name
3 | float32[<=30] kp
4 | float32[<=30] pos
5 | float32[<=30] kd
6 | float32[<=30] vel
7 | float32[<=30] torque
--------------------------------------------------------------------------------
/communication/msg/MotionCommands.msg:
--------------------------------------------------------------------------------
1 | std_msgs/Header header
2 | geometry_msgs/Vector3 vel_des
3 | float32 height_des
4 | float32 yawdot_des
--------------------------------------------------------------------------------
/communication/package.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | communication
5 | 0.0.0
6 | TODO: Package description
7 | DeepBreak
8 | BSD
9 |
10 | ament_cmake
11 |
12 | std_msgs
13 | builtin_interfaces
14 | rosidl_default_generators
15 | rosidl_default_runtime
16 | rosidl_interface_packages
17 |
18 | ament_lint_auto
19 | ament_lint_common
20 |
21 |
22 | ament_cmake
23 |
24 |
25 |
--------------------------------------------------------------------------------
/communication/srv/GaitSwitch.srv:
--------------------------------------------------------------------------------
1 | std_msgs/Header header
2 | string gait_name
3 | ---
4 | bool is_success
--------------------------------------------------------------------------------
/communication/srv/SimulationReset.srv:
--------------------------------------------------------------------------------
1 | std_msgs/Header header
2 | geometry_msgs/Pose base_pose
3 | sensor_msgs/JointState joint_state
4 | ---
5 | bool is_success
--------------------------------------------------------------------------------
/core/CMakeLists.txt:
--------------------------------------------------------------------------------
1 | cmake_minimum_required(VERSION 3.8)
2 | project(core)
3 |
4 | if(CMAKE_COMPILER_IS_GNUCXX OR CMAKE_CXX_COMPILER_ID MATCHES "Clang")
5 | add_compile_options(-Wall -Wextra -Wpedantic)
6 | endif()
7 |
8 | # find dependencies
9 | find_package(ament_cmake REQUIRED)
10 | find_package(Boost REQUIRED)
11 | find_package(Eigen3 3.3 REQUIRED NO_MODULE)
12 | find_package(rcpputils REQUIRED)
13 |
14 | set(TARGET_DEPENDENCE
15 | ament_cmake
16 | Boost
17 | Eigen3
18 | rcpputils
19 | )
20 |
21 | include(cmake/deepbreak_cxx_flags.cmake)
22 |
23 | file(GLOB_RECURSE source ${CMAKE_CURRENT_SOURCE_DIR}/src/*.cpp)
24 | add_library(${PROJECT_NAME} SHARED ${source})
25 | target_link_libraries(${PROJECT_NAME}
26 | ${Boost_LIBRARIES}
27 | )
28 | target_compile_options(${PROJECT_NAME} PUBLIC ${DEEPBREAK_CXX_FLAGS})
29 |
30 | target_include_directories(${PROJECT_NAME}
31 | PUBLIC
32 | ${EIGEN3_INCLUDE_DIRS}
33 | $
34 | $)
35 |
36 | ament_target_dependencies(${PROJECT_NAME} ${TARGET_DEPENDENCE})
37 | ament_export_targets(${PROJECT_NAME}_Targets HAS_LIBRARY_TARGET)
38 | ament_export_dependencies(${TARGET_DEPENDENCE})
39 |
40 | install(
41 | DIRECTORY include/
42 | DESTINATION include
43 | )
44 |
45 | install(
46 | TARGETS ${PROJECT_NAME}
47 | EXPORT ${PROJECT_NAME}_Targets
48 | LIBRARY DESTINATION lib
49 | ARCHIVE DESTINATION lib
50 | RUNTIME DESTINATION bin
51 | INCLUDES DESTINATION include
52 | )
53 |
54 | ament_package()
55 |
--------------------------------------------------------------------------------
/core/cmake/deepbreak_cxx_flags.cmake:
--------------------------------------------------------------------------------
1 | # The list of compiler flags used in deepbreak can be prefixed with catkin config
2 | # Addition flags are to be separated by \;
3 | # For example, to turn on architecture specific optimizations:
4 | # catkin config --cmake-args -DDEEPBREAK_CXX_FLAGS=-march=native\;-mtune=native
5 | list(APPEND DEEPBREAK_CXX_FLAGS
6 | "-march=native"
7 | "-mtune=native"
8 | "-fPIC"
9 | "-pthread"
10 | "-Wfatal-errors"
11 | "-Wl,--no-as-needed"
12 | )
13 |
14 | # Force Boost dynamic linking
15 | list(APPEND DEEPBREAK_CXX_FLAGS
16 | "-DBOOST_ALL_DYN_LINK"
17 | )
18 |
19 | # Cpp standard version
20 | set(CMAKE_CXX_STANDARD 17)
21 | set(CMAKE_CXX_STANDARD_REQUIRED ON)
22 |
--------------------------------------------------------------------------------
/core/cmake/pinocchio_config.cmake:
--------------------------------------------------------------------------------
1 | # Add pinocchio library to the linker's search path
2 | link_directories(
3 | ${pinocchio_LIBRARY_DIRS}
4 | )
5 |
6 | # Add pinocchio flags
7 | set(DEEPBREAK_PINOCCHIO_FLAGS
8 | ${DEEPBREAK_CXX_FLAGS}
9 | ${pinocchio_CFLAGS_OTHER}
10 | -Wno-ignored-attributes
11 | # -Wno-invalid-partial-specialization # to silence warning with unsupported Eigen Tensor
12 | -DPINOCCHIO_URDFDOM_TYPEDEF_SHARED_PTR
13 | -DPINOCCHIO_URDFDOM_USE_STD_SHARED_PTR
14 | )
--------------------------------------------------------------------------------
/core/include/core/Types.h:
--------------------------------------------------------------------------------
1 | /******************************************************************************
2 | Copyright (c) 2020, Farbod Farshidian. All rights reserved.
3 |
4 | Redistribution and use in source and binary forms, with or without
5 | modification, are permitted provided that the following conditions are met:
6 |
7 | * Redistributions of source code must retain the above copyright notice, this
8 | list of conditions and the following disclaimer.
9 |
10 | * Redistributions in binary form must reproduce the above copyright notice,
11 | this list of conditions and the following disclaimer in the documentation
12 | and/or other materials provided with the distribution.
13 |
14 | * Neither the name of the copyright holder nor the names of its
15 | contributors may be used to endorse or promote products derived from
16 | this software without specific prior written permission.
17 |
18 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
19 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
21 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
22 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
23 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
24 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
25 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
26 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
27 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28 | ******************************************************************************/
29 |
30 | #pragma once
31 |
32 | #include
33 | #include
34 | #include
35 | #include
36 |
37 | namespace deepbreak {
38 |
39 | /** size_t trajectory type. */
40 | using size_array_t = std::vector;
41 | /** Array of size_t trajectory type. */
42 | using size_array2_t = std::vector;
43 |
44 | /** Scalar type. */
45 | using scalar_t = double;
46 | /** Scalar trajectory type. */
47 | using scalar_array_t = std::vector;
48 | /** Array of scalar trajectory type. */
49 | using scalar_array2_t = std::vector;
50 | /** Array of arrays of scalar trajectory type. */
51 | using scalar_array3_t = std::vector;
52 |
53 | using quaternion_t = Eigen::Quaternion;
54 | using vector2_t = Eigen::Matrix;
55 | using vector3_t = Eigen::Matrix;
56 | using vector4_t = Eigen::Matrix;
57 | using vector6_t = Eigen::Matrix;
58 | using vector12_t = Eigen::Matrix;
59 | /** Dynamic-size vector type. */
60 | using vector_t = Eigen::Matrix;
61 | /** Dynamic vector's trajectory type. */
62 | using vector_array_t = std::vector;
63 | /** Array of dynamic vector's trajectory type. */
64 | using vector_array2_t = std::vector;
65 | /** Array of arrays of dynamic vector trajectory type. */
66 | using vector_array3_t = std::vector;
67 |
68 | /** Dynamic-size row vector type. */
69 | using row_vector_t = Eigen::Matrix;
70 |
71 | using matrix3_t = Eigen::Matrix;
72 | using matrix4_t = Eigen::Matrix;
73 | using matrix6_t = Eigen::Matrix;
74 | using matrix3x_t = Eigen::Matrix;
75 | using matrix4x_t = Eigen::Matrix;
76 | using matrix6x_t = Eigen::Matrix;
77 | /** Dynamic-size matrix type. */
78 | using matrix_t = Eigen::Matrix;
79 | /** Dynamic matrix's trajectory type. */
80 | using matrix_array_t = std::vector;
81 | /** Array of dynamic matrix's trajectory type. */
82 | using matrix_array2_t = std::vector;
83 | /** Array of arrays of dynamic matrix trajectory type. */
84 | using matrix_array3_t = std::vector;
85 |
86 | /**
87 | * Defines the linear approximation of a scalar function
88 | * f(x,u) = dfdx' dx + dfdu' du + f
89 | */
90 | struct ScalarFunctionLinearApproximation {
91 | /** First derivative w.r.t state */
92 | vector_t dfdx;
93 | /** First derivative w.r.t input */
94 | vector_t dfdu;
95 | /** Constant term */
96 | scalar_t f = 0.;
97 |
98 | /** Default constructor */
99 | ScalarFunctionLinearApproximation() = default;
100 |
101 | /** Construct and resize the members to given size. (Pass nu = -1 for no
102 | * inputs) */
103 | explicit ScalarFunctionLinearApproximation(int nx, int nu = -1);
104 |
105 | /** Compound addition assignment operator */
106 | ScalarFunctionLinearApproximation &
107 | operator+=(const ScalarFunctionLinearApproximation &rhs);
108 |
109 | /** Compound scalar multiplication and assignment operator */
110 | ScalarFunctionLinearApproximation &operator*=(scalar_t scalar);
111 |
112 | /**
113 | * Resize the members to the given size
114 | * @param[in] nx State dimension
115 | * @param[in] nu Input dimension (Pass nu = -1 for no inputs)
116 | */
117 | ScalarFunctionLinearApproximation &resize(int nx, int nu = -1);
118 |
119 | /**
120 | * Resizes the members to the given size, and sets all coefficients to zero.
121 | * @param[in] nx State dimension
122 | * @param[in] nu Input dimension (Pass nu = -1 for no inputs)
123 | */
124 | ScalarFunctionLinearApproximation &setZero(int nx, int nu = -1);
125 |
126 | /**
127 | * Factory function with zero initialization
128 | * @param[in] nx State dimension
129 | * @param[in] nu Input dimension (Pass nu = -1 for no inputs)
130 | * @return Zero initialized object of given size.
131 | */
132 | static ScalarFunctionLinearApproximation Zero(int nx, int nu = -1);
133 | };
134 |
135 | std::ostream &operator<<(std::ostream &out,
136 | const ScalarFunctionLinearApproximation &f);
137 |
138 | /**
139 | * Checks the size of the given linear approximation.
140 | *
141 | * @param[in] stateDim: Number of states.
142 | * @param[in] inputDim: Number of inputs.
143 | * @param[in] data: Given linear approximation.
144 | * @param[in] dataName: The name of the data which appears in the output error
145 | * message.
146 | * @return The description of the error. If there was no error it would be
147 | * empty;
148 | */
149 | std::string checkSize(int stateDim, int inputDim,
150 | const ScalarFunctionLinearApproximation &data,
151 | const std::string &dataName);
152 |
153 | inline ScalarFunctionLinearApproximation
154 | operator*(ScalarFunctionLinearApproximation lhs, scalar_t scalar) {
155 | return lhs *= scalar;
156 | }
157 |
158 | inline ScalarFunctionLinearApproximation
159 | operator*(scalar_t scalar, ScalarFunctionLinearApproximation rhs) {
160 | return rhs *= scalar;
161 | }
162 |
163 | /**
164 | * Defines the quadratic approximation of a scalar function
165 | * f(x,u) = 1/2 dx' dfdxx dx + du' dfdux dx + 1/2 du' dfduu du + dfdx' dx +
166 | * dfdu' du + f
167 | */
168 | struct ScalarFunctionQuadraticApproximation {
169 | /** Second derivative w.r.t state */
170 | matrix_t dfdxx;
171 | /** Second derivative w.r.t input (lhs) and state (rhs) */
172 | matrix_t dfdux;
173 | /** Second derivative w.r.t input */
174 | matrix_t dfduu;
175 | /** First derivative w.r.t state */
176 | vector_t dfdx;
177 | /** First derivative w.r.t input */
178 | vector_t dfdu;
179 | /** Constant term */
180 | scalar_t f = 0.;
181 |
182 | /** Default constructor */
183 | ScalarFunctionQuadraticApproximation() = default;
184 |
185 | /** Construct and resize the members to given size. Pass nu = -1 for no inputs
186 | */
187 | explicit ScalarFunctionQuadraticApproximation(int nx, int nu = -1);
188 |
189 | /** Compound addition assignment operator */
190 | ScalarFunctionQuadraticApproximation &
191 | operator+=(const ScalarFunctionQuadraticApproximation &rhs);
192 |
193 | /** Compound scalar multiplication and assignment operator */
194 | ScalarFunctionQuadraticApproximation &operator*=(scalar_t scalar);
195 |
196 | /**
197 | * Resize the members to the given size
198 | * @param[in] nx State dimension
199 | * @param[in] nu Input dimension (Pass nu = -1 for no inputs)
200 | */
201 | ScalarFunctionQuadraticApproximation &resize(int nx, int nu = -1);
202 |
203 | /**
204 | * Resizes the members to the given size, and sets all coefficients to zero.
205 | * @param[in] nx State dimension
206 | * @param[in] nu Input dimension (Pass nu = -1 for no inputs)
207 | */
208 | ScalarFunctionQuadraticApproximation &setZero(int nx, int nu = -1);
209 |
210 | /**
211 | * Factory function with zero initialization
212 | * @param[in] nx State dimension
213 | * @param[in] nu Input dimension (Pass nu = -1 for no inputs)
214 | * @return Zero initialized object of given size.
215 | */
216 | static ScalarFunctionQuadraticApproximation Zero(int nx, int nu = -1);
217 | };
218 |
219 | std::ostream &operator<<(std::ostream &out,
220 | const ScalarFunctionQuadraticApproximation &f);
221 |
222 | /**
223 | * Checks that the given matrix is valid, self-adjoint, and positive
224 | * semi-definite (PSD).
225 | * @param[in] data: Given matrix.
226 | * @param[in] dataName: The name of the data which appears in the output error
227 | * message.
228 | * @return The description of the error. If there was no error it would be
229 | * empty;
230 | */
231 | std::string checkBeingPSD(const matrix_t &data, const std::string &dataName);
232 |
233 | /**
234 | * Checks that the given quadratic approximation is valid, self-adjoint, and
235 | * positive semi-definite (PSD).
236 | * @param[in] data: Given quadratic approximation.
237 | * @param[in] dataName: The name of the data which appears in the output error
238 | * message.
239 | * @return The description of the error. If there was no error it would be
240 | * empty;
241 | */
242 | std::string checkBeingPSD(const ScalarFunctionQuadraticApproximation &data,
243 | const std::string &dataName);
244 |
245 | /**
246 | * Checks the size of the given quadratic approximation.
247 | *
248 | * @param[in] stateDim: Number of states.
249 | * @param[in] inputDim: Number of inputs.
250 | * @param[in] data: Given quadratic approximation.
251 | * @param[in] dataName: The name of the data which appears in the output error
252 | * message.
253 | * @return The description of the error. If there was no error it would be
254 | * empty;
255 | */
256 | std::string checkSize(int stateDim, int inputDim,
257 | const ScalarFunctionQuadraticApproximation &data,
258 | const std::string &dataName);
259 |
260 | inline ScalarFunctionQuadraticApproximation
261 | operator*(ScalarFunctionQuadraticApproximation lhs, scalar_t scalar) {
262 | return lhs *= scalar;
263 | }
264 |
265 | inline ScalarFunctionQuadraticApproximation
266 | operator*(scalar_t scalar, ScalarFunctionQuadraticApproximation rhs) {
267 | return rhs *= scalar;
268 | }
269 |
270 | /**
271 | * Defines the linear model of a vector-valued function
272 | * f(x,u) = dfdx dx + dfdu du + f
273 | */
274 | struct VectorFunctionLinearApproximation {
275 | /** Derivative w.r.t state */
276 | matrix_t dfdx;
277 | /** Derivative w.r.t input */
278 | matrix_t dfdu;
279 | /** Constant term */
280 | vector_t f;
281 |
282 | /** Default constructor */
283 | VectorFunctionLinearApproximation() = default;
284 |
285 | /** Construct and resize the members to given size. (Pass nu = -1 for no
286 | * inputs) */
287 | explicit VectorFunctionLinearApproximation(int nv, int nx, int nu = -1);
288 |
289 | /**
290 | * Resize the members to the given size
291 | * @param[in] nv Vector dimension
292 | * @param[in] nx State dimension
293 | * @param[in] nu Input dimension (Pass nu = -1 for no inputs)
294 | */
295 | VectorFunctionLinearApproximation &resize(int nv, int nx, int nu = -1);
296 |
297 | /**
298 | * Resizes the members to the given size, and sets all coefficients to zero.
299 | * @param[in] nv Vector dimension
300 | * @param[in] nx State dimension
301 | * @param[in] nu Input dimension (Pass nu = -1 for no inputs)
302 | */
303 | VectorFunctionLinearApproximation &setZero(int nv, int nx, int nu = -1);
304 |
305 | /**
306 | * Factory function with zero initialization
307 | * @param[in] nv Vector dimension
308 | * @param[in] nx State dimension
309 | * @param[in] nu Input dimension (Pass nu = -1 for no inputs)
310 | * @return Zero initialized object of given size.
311 | */
312 | static VectorFunctionLinearApproximation Zero(int nv, int nx, int nu = -1);
313 | };
314 |
315 | std::ostream &operator<<(std::ostream &out,
316 | const VectorFunctionLinearApproximation &f);
317 |
318 | /**
319 | * Checks the size of the given vector-function linear approximation.
320 | *
321 | * @param[in] vectorDim: The vector function dimension.
322 | * @param[in] stateDim: Number of states.
323 | * @param[in] inputDim: Number of inputs.
324 | * @param[in] data: Given linear approximation.
325 | * @param[in] dataName: The name of the data which appears in the output error
326 | * message.
327 | * @return The description of the error. If there was no error it would be
328 | * empty;
329 | */
330 | std::string checkSize(int vectorDim, int stateDim, int inputDim,
331 | const VectorFunctionLinearApproximation &data,
332 | const std::string &dataName);
333 |
334 | /**
335 | * Defines quadratic approximation of a vector-valued function
336 | * f[i](x,u) = 1/2 dx' dfdxx[i] dx + du' dfdux[i] dx + 1/2 du' dfduu[i] du +
337 | * dfdx[i,:] dx + dfdu[i,:] du + f[i]
338 | */
339 | struct VectorFunctionQuadraticApproximation {
340 | /** Second derivative w.r.t state */
341 | matrix_array_t dfdxx;
342 | /** Second derivative w.r.t input (lhs) and state (rhs) */
343 | matrix_array_t dfdux;
344 | /** Second derivative w.r.t input */
345 | matrix_array_t dfduu;
346 | /** First derivative w.r.t state */
347 | matrix_t dfdx;
348 | /** First derivative w.r.t input */
349 | matrix_t dfdu;
350 | /** Constant term */
351 | vector_t f;
352 |
353 | /** Default constructor */
354 | VectorFunctionQuadraticApproximation() = default;
355 |
356 | /** Construct and resize the members to given size. */
357 | explicit VectorFunctionQuadraticApproximation(int nv, int nx, int nu = -1);
358 |
359 | /**
360 | * Resize the members to the given size
361 | * @param[in] nv Vector dimension
362 | * @param[in] nx State dimension
363 | * @param[in] nu Input dimension (Pass nu = -1 for no inputs)
364 | */
365 | VectorFunctionQuadraticApproximation &resize(int nv, int nx, int nu = -1);
366 |
367 | /**
368 | * Resizes the members to the given size, and sets all coefficients to zero.
369 | * @param[in] nv Vector dimension
370 | * @param[in] nx State dimension
371 | * @param[in] nu Input dimension (Pass nu = -1 for no inputs)
372 | */
373 | VectorFunctionQuadraticApproximation &setZero(int nv, int nx, int nu = -1);
374 |
375 | /**
376 | * Factory function with zero initialization
377 | * @param[in] nv Vector dimension
378 | * @param[in] nx State dimension
379 | * @param[in] nu Input dimension (Pass nu = -1 for no inputs)
380 | * @return Zero initialized object of given size.
381 | */
382 | static VectorFunctionQuadraticApproximation Zero(int nv, int nx, int nu = -1);
383 | };
384 |
385 | std::ostream &operator<<(std::ostream &out,
386 | const VectorFunctionQuadraticApproximation &f);
387 |
388 | struct InequalityConstraintsLinearApproximation {
389 | VectorFunctionLinearApproximation approx;
390 | vector_t lb;
391 | vector_t ub;
392 |
393 | /** Default constructor */
394 | InequalityConstraintsLinearApproximation() = default;
395 |
396 | /** Construct and resize the members to given size. (Pass nu = -1 for no
397 | * inputs) */
398 | explicit InequalityConstraintsLinearApproximation(int nv, int nx,
399 | int nu = -1);
400 |
401 | /**
402 | * Resize the members to the given size
403 | * @param[in] nv Vector dimension
404 | * @param[in] nx State dimension
405 | * @param[in] nu Input dimension (Pass nu = -1 for no inputs)
406 | */
407 | InequalityConstraintsLinearApproximation &resize(int nv, int nx, int nu = -1);
408 |
409 | /**
410 | * Resizes the members to the given size, and sets all coefficients to zero.
411 | * @param[in] nv Vector dimension
412 | * @param[in] nx State dimension
413 | * @param[in] nu Input dimension (Pass nu = -1 for no inputs)
414 | */
415 | InequalityConstraintsLinearApproximation &setZero(int nv, int nx,
416 | int nu = -1);
417 |
418 | /**
419 | * Factory function with zero initialization
420 | * @param[in] nv Vector dimension
421 | * @param[in] nx State dimension
422 | * @param[in] nu Input dimension (Pass nu = -1 for no inputs)
423 | * @return Zero initialized object of given size.
424 | */
425 | static InequalityConstraintsLinearApproximation Zero(int nv, int nx,
426 | int nu = -1);
427 | };
428 |
429 | std::ostream &operator<<(std::ostream &out,
430 | const InequalityConstraintsLinearApproximation &ineq);
431 |
432 | } // namespace deepbreak
433 |
--------------------------------------------------------------------------------
/core/include/core/misc/Benchmark.h:
--------------------------------------------------------------------------------
1 | /******************************************************************************
2 | Copyright (c) 2020, Farbod Farshidian. All rights reserved.
3 |
4 | Redistribution and use in source and binary forms, with or without
5 | modification, are permitted provided that the following conditions are met:
6 |
7 | * Redistributions of source code must retain the above copyright notice, this
8 | list of conditions and the following disclaimer.
9 |
10 | * Redistributions in binary form must reproduce the above copyright notice,
11 | this list of conditions and the following disclaimer in the documentation
12 | and/or other materials provided with the distribution.
13 |
14 | * Neither the name of the copyright holder nor the names of its
15 | contributors may be used to endorse or promote products derived from
16 | this software without specific prior written permission.
17 |
18 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
19 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
21 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
22 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
23 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
24 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
25 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
26 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
27 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28 | ******************************************************************************/
29 |
30 | #pragma once
31 |
32 | #include
33 |
34 | #include "core/Types.h"
35 |
36 | namespace deepbreak {
37 | namespace benchmark {
38 |
39 | /**
40 | * Timer class that can be repeatedly started and stopped. Statistics are
41 | * collected for all measured intervals .
42 | */
43 | class RepeatedTimer {
44 | public:
45 | RepeatedTimer()
46 | : numTimedIntervals_(0), totalTime_(std::chrono::nanoseconds::zero()),
47 | maxIntervalTime_(std::chrono::nanoseconds::zero()),
48 | lastIntervalTime_(std::chrono::nanoseconds::zero()),
49 | startTime_(std::chrono::steady_clock::now()) {}
50 |
51 | /**
52 | * Reset the timer statistics
53 | */
54 | void reset() {
55 | numTimedIntervals_ = 0;
56 | totalTime_ = std::chrono::nanoseconds::zero();
57 | maxIntervalTime_ = std::chrono::nanoseconds::zero();
58 | lastIntervalTime_ = std::chrono::nanoseconds::zero();
59 | }
60 |
61 | /**
62 | * Start timing an interval
63 | */
64 | void startTimer() { startTime_ = std::chrono::steady_clock::now(); }
65 |
66 | /**
67 | * Stop timing of an interval
68 | */
69 | void endTimer() {
70 | auto endTime = std::chrono::steady_clock::now();
71 | lastIntervalTime_ = std::chrono::duration_cast(
72 | endTime - startTime_);
73 | maxIntervalTime_ = std::max(maxIntervalTime_, lastIntervalTime_);
74 | totalTime_ += lastIntervalTime_;
75 | numTimedIntervals_++;
76 | };
77 |
78 | /**
79 | * @return Number of intervals that were timed
80 | */
81 | int getNumTimedIntervals() const { return numTimedIntervals_; }
82 |
83 | /**
84 | * @return Total cumulative time of timed intervals
85 | */
86 | scalar_t getTotalInMilliseconds() const {
87 | return std::chrono::duration(totalTime_).count();
88 | }
89 |
90 | /**
91 | * @return Maximum duration of a single interval
92 | */
93 | scalar_t getMaxIntervalInMilliseconds() const {
94 | return std::chrono::duration(maxIntervalTime_)
95 | .count();
96 | }
97 |
98 | /**
99 | * @return Duration of the last timed interval
100 | */
101 | scalar_t getLastIntervalInMilliseconds() const {
102 | return std::chrono::duration(lastIntervalTime_)
103 | .count();
104 | }
105 |
106 | /**
107 | * @return Average duration of all timed intervals
108 | */
109 | scalar_t getAverageInMilliseconds() const {
110 | return getTotalInMilliseconds() / numTimedIntervals_;
111 | }
112 |
113 | private:
114 | int numTimedIntervals_;
115 | std::chrono::nanoseconds totalTime_;
116 | std::chrono::nanoseconds maxIntervalTime_;
117 | std::chrono::nanoseconds lastIntervalTime_;
118 | std::chrono::steady_clock::time_point startTime_;
119 | };
120 |
121 | } // namespace benchmark
122 | } // namespace deepbreak
123 |
--------------------------------------------------------------------------------
/core/include/core/misc/Buffer.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | #include
4 |
5 | namespace deepbreak {
6 |
7 | template
8 | class Buffer {
9 | public:
10 | Buffer() = default;
11 | ~Buffer() = default;
12 |
13 | void push(T data) {
14 | const std::lock_guard guard(lock_);
15 | data_ = data;
16 | }
17 |
18 | T get() const {
19 | const std::lock_guard guard(lock_);
20 | return data_;
21 | }
22 |
23 | T clear() {
24 | const std::lock_guard guard(lock_);
25 | data_ = T();
26 | }
27 |
28 | private:
29 | T data_;
30 | mutable std::mutex lock_;
31 | };
32 |
33 | } // namespace deepbreak
--------------------------------------------------------------------------------
/core/include/core/misc/LinearAlgebra.h:
--------------------------------------------------------------------------------
1 | /******************************************************************************
2 | Copyright (c) 2020, Farbod Farshidian. All rights reserved.
3 |
4 | Redistribution and use in source and binary forms, with or without
5 | modification, are permitted provided that the following conditions are met:
6 |
7 | * Redistributions of source code must retain the above copyright notice, this
8 | list of conditions and the following disclaimer.
9 |
10 | * Redistributions in binary form must reproduce the above copyright notice,
11 | this list of conditions and the following disclaimer in the documentation
12 | and/or other materials provided with the distribution.
13 |
14 | * Neither the name of the copyright holder nor the names of its
15 | contributors may be used to endorse or promote products derived from
16 | this software without specific prior written permission.
17 |
18 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
19 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
21 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
22 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
23 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
24 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
25 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
26 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
27 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28 | ******************************************************************************/
29 |
30 | #pragma once
31 |
32 | #include
33 | #include
34 |
35 | #include
36 | #include
37 |
38 | namespace deepbreak {
39 | namespace LinearAlgebra {
40 |
41 | /**
42 | * Set the eigenvalues of a triangular matrix to a minimum magnitude (maintaining the sign).
43 | */
44 | void setTriangularMinimumEigenvalues(matrix_t& Lr, scalar_t minEigenValue = numeric_traits::weakEpsilon());
45 |
46 | /**
47 | * Makes the input matrix PSD using a eigenvalue decomposition.
48 | *
49 | * @param [in, out] squareMatrix: The matrix to become PSD.
50 | * @param [in] minEigenvalue: minimum eigenvalue.
51 | */
52 | void makePsdEigenvalue(matrix_t& squareMatrix, scalar_t minEigenvalue = numeric_traits::limitEpsilon());
53 |
54 | /**
55 | * Makes the input matrix PSD based on Gershgorin circle theorem. If the input matrix is positive definite and diagonally dominant,
56 | * the method will not modify the matrix.
57 | *
58 | * How it works:
59 | * Assume that the Ri is the sum of the absolute values of the non-diagonal entries in the i-th row (Gershgorin radius).
60 | * This methods updates the diagonal elements as Aii = max(Aii, minEigenvalue + Ri).
61 | *
62 | * To understand this update rule note that the Gershgorin radius (Ri) of the new matrix is the same as original one.
63 | * Now if we use the Gershgorin circle theorem we have:
64 | * | lambda - max(Aii, minEigenvalue + Ri) | < Ri ==> max(Aii, minEigenvalue + Ri) - Ri < lambda < max(Aii, minEigenvalue + Ri) + Ri
65 | * Two cases are possible:
66 | * (1) Aii < minEigenvalue + Ri ==> minEigenvalue < lambda < minEigenvalue + 2 Ri
67 | * (2) Aii > minEigenvalue + Ri ==> minEigenvalue < Aii - Ri < lambda < Aii + Ri
68 | *
69 | * @param [in, out] squareMatrix: The matrix to become PSD.
70 | * @param [in] minEigenvalue: minimum eigenvalue.
71 | */
72 | void makePsdGershgorin(matrix_t& squareMatrix, scalar_t minEigenvalue = numeric_traits::limitEpsilon());
73 |
74 | /**
75 | * Makes the input matrix PSD based on modified Cholesky decomposition.
76 | *
77 | * S P' (A + E) P S = L L'
78 | * where P is a permutation matrix, E is a diagonal perturbation matrix, L is unit lower triangular, and D is diagonal.
79 | * If A is sufficiently positive definite, then the perturbation matrix E will be zero and this method is equivalent to
80 | * the pivoted Cholesky algorithm. For indefinite matrices, the perturbation matrix E is computed to ensure that A + E
81 | * is positive definite and well conditioned.
82 | *
83 | * References : C-J. Lin and J. J. Moré, Incomplete Cholesky Factorizations with Limited memory, SIAM J. Sci. Comput.
84 | * 21(1), pp. 24-45, 1999
85 | *
86 | * @param [in, out] A: The matrix to become PSD.
87 | * @param [in] minEigenvalue: minimum eigenvalue.
88 | */
89 | void makePsdCholesky(matrix_t& A, scalar_t minEigenvalue = numeric_traits::limitEpsilon());
90 |
91 | /**
92 | * Computes the U*U^T decomposition associated to the inverse of the input matrix, where U is an upper triangular
93 | * matrix. Note that the U*U^T decomposition is different from the Cholesky decomposition (U^T*U).
94 | *
95 | * @param [in] Am: A symmetric square positive definite matrix
96 | * @param [out] AmInvUmUmT: The upper-triangular matrix associated to the UUT decomposition of inv(Am) matrix.
97 | */
98 | void computeInverseMatrixUUT(const matrix_t& Am, matrix_t& AmInvUmUmT);
99 |
100 | /**
101 | * Computes constraint projection for linear constraints C*x + D*u - e = 0, with the weighting inv(Rm)
102 | * The input cost matrix Rm should be already inverted and decomposed such that inv(Rm) = RmInvUmUmT * RmInvUmUmT^T.
103 | *
104 | * @param [in] Dm: A full row rank constraint matrix
105 | * @param [in] RmInvUmUmT: The upper-triangular matrix associated to the UUT decomposition of inv(Rm) matrix.
106 | * @param [out] DmDagger: The right weighted pseudo inverse of Dm, DmDagger = inv(Rm)*Dm'*inv(Dm*inv(Rm)*Dm')
107 | * @param [out] DmDaggerTRmDmDaggerUUT: The UUT decomposition of DmDagger^T * Rm * DmDagger = Um * Um^T
108 | * @param [out] RmInvConstrainedUUT: The VVT decomposition of (I-DmDagger*Dm) * inv(Rm) * (I-DmDagger*Dm)^T where V is of
109 | * the dimension n_u*(n_u-n_c) with n_u = Rm.rows() and n_c = Dm.rows().
110 | */
111 | void computeConstraintProjection(const matrix_t& Dm, const matrix_t& RmInvUmUmT, matrix_t& DmDagger, matrix_t& DmDaggerTRmDmDaggerUUT,
112 | matrix_t& RmInvConstrainedUUT);
113 |
114 | /**
115 | * Returns the linear projection
116 | * u = Pu * \tilde{u} + Px * x + Pe
117 | *
118 | * s.t. C*x + D*u + e = 0 is satisfied for any \tilde{u}
119 | *
120 | * Implementation based on the QR decomposition
121 | *
122 | * @param [in] constraint : C = dfdx, D = dfdu, e = f;
123 | * @return Projection terms Px = dfdx, Pu = dfdu, Pe = f (first) and left pseudo-inverse of D^T (second);
124 | */
125 | std::pair qrConstraintProjection(const VectorFunctionLinearApproximation& constraint);
126 |
127 | /**
128 | * Returns the linear projection
129 | * u = Pu * \tilde{u} + Px * x + Pe
130 | *
131 | * s.t. C*x + D*u + e = 0 is satisfied for any \tilde{u}
132 | *
133 | * Implementation based on the LU decomposition
134 | *
135 | * @param [in] constraint : C = dfdx, D = dfdu, e = f;
136 | * @param [in] extractPseudoInverse : If true, left pseudo-inverse of D^T is returned. If false, an empty matrix is returned;
137 | * @return Projection terms Px = dfdx, Pu = dfdu, Pe = f (first) and left pseudo-inverse of D^T (second);
138 | */
139 | std::pair luConstraintProjection(const VectorFunctionLinearApproximation& constraint,
140 | bool extractPseudoInverse = false);
141 |
142 | /** Computes the rank of a matrix */
143 | template
144 | int rank(const Derived& A) {
145 | return A.colPivHouseholderQr().rank();
146 | }
147 |
148 | /** Computes the complex eigenvalues of A */
149 | template
150 | Eigen::VectorXcd eigenvalues(const Derived& A) {
151 | return A.eigenvalues();
152 | }
153 |
154 | /** Computes the eigenvalues for a symmetric matrix A */
155 | template
156 | vector_t symmetricEigenvalues(const Derived& A) {
157 | return A.template selfadjointView().eigenvalues();
158 | }
159 |
160 | // Declaring explicit instantiations for dynamic sized matrices
161 | extern template int rank(const matrix_t& A);
162 | extern template Eigen::VectorXcd eigenvalues(const matrix_t& A);
163 | extern template vector_t symmetricEigenvalues(const matrix_t& A);
164 |
165 | } // namespace LinearAlgebra
166 | } // namespace deepbreak
167 |
--------------------------------------------------------------------------------
/core/include/core/misc/LoadData.h:
--------------------------------------------------------------------------------
1 | /******************************************************************************
2 | Copyright (c) 2020, Farbod Farshidian. All rights reserved.
3 |
4 | Redistribution and use in source and binary forms, with or without
5 | modification, are permitted provided that the following conditions are met:
6 |
7 | * Redistributions of source code must retain the above copyright notice, this
8 | list of conditions and the following disclaimer.
9 |
10 | * Redistributions in binary form must reproduce the above copyright notice,
11 | this list of conditions and the following disclaimer in the documentation
12 | and/or other materials provided with the distribution.
13 |
14 | * Neither the name of the copyright holder nor the names of its
15 | contributors may be used to endorse or promote products derived from
16 | this software without specific prior written permission.
17 |
18 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
19 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
21 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
22 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
23 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
24 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
25 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
26 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
27 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28 | ******************************************************************************/
29 |
30 | #pragma once
31 |
32 | #include
33 | #include
34 | #include
35 | #include
36 |
37 | #include
38 | #include
39 |
40 | namespace deepbreak {
41 | namespace loadData {
42 |
43 | /**
44 | * Print settings option
45 | *
46 | * @param[in] stream: Output stream
47 | * @param[in] value: Value to be printed
48 | * @param[in] name: Property field name
49 | * @param[in] updated: True if the value was updated
50 | * @param[in] printWidth: The aligned printout width
51 | */
52 | template
53 | static inline void printValue(std::ostream& stream, const T& value, const std::string& name, bool updated = true, long printWidth = 80) {
54 | const std::string nameString = " #### '" + name + "'";
55 | stream << nameString;
56 |
57 | printWidth = std::max(printWidth, nameString.size() + 15);
58 | stream.width(printWidth - nameString.size());
59 | const char fill = stream.fill('.');
60 |
61 | if (updated) {
62 | stream << value << '\n';
63 | } else {
64 | stream << value << " (default)\n";
65 | }
66 |
67 | stream.fill(fill);
68 | }
69 |
70 | /**
71 | * An auxiliary function to help loading DEEPBREAK settings from a property tree
72 | *
73 | * @param[in] pt: Fully initialized tree object
74 | * @param[out] value: The value to be read (unchanged if tree does not contain a corresponding entry)
75 | * @param[in] name: Property field name
76 | * @param[in] verbose: Whether or not to print the extreacted value (or error)
77 | * @param[in] printWidth: Optional argument to change the width of the aligned printout
78 | */
79 | template
80 | inline void loadPtreeValue(const boost::property_tree::ptree& pt, T& value, const std::string& name, bool verbose, long printWidth = 80) {
81 | bool updated = true;
82 |
83 | try {
84 | value = pt.get(name);
85 | } catch (const boost::property_tree::ptree_bad_path&) {
86 | updated = false;
87 | }
88 |
89 | if (verbose) {
90 | const std::string nameString = name.substr(name.find_last_of('.') + 1);
91 | printValue(std::cerr, value, nameString, updated, printWidth);
92 | }
93 | }
94 |
95 | /**
96 | * An auxiliary function which loads value of the c++ data types from a file. The file uses property tree data structure with INFO format
97 | * (refer to https://www.boost.org/doc/libs/1_65_1/doc/html/property_tree.html).
98 | *
99 | * @param [in] filename: File name which contains the configuration data.
100 | * @param [in] dataName: The key name assigned to the data in the config file.
101 | * @param [out] value: The loaded value.
102 | */
103 | template
104 | inline void loadCppDataType(const std::string& filename, const std::string& dataName, cpp_data_t& value) {
105 | boost::property_tree::ptree pt;
106 | boost::property_tree::read_info(filename, pt);
107 |
108 | value = pt.get(dataName);
109 | }
110 |
111 | /**
112 | * An auxiliary function which loads an Eigen matrix from a file. The file uses property tree data structure with INFO format (refer to
113 | * www.goo.gl/fV3yWA).
114 | *
115 | * It has the following format:
116 | * matrixName
117 | * {
118 | * scaling 1e+0
119 | * (0,0) value ; M(0,0)
120 | * (1,0) value ; M(1,0)
121 | * (0,1) value ; M(0,1)
122 | * (1,1) value ; M(1,1)
123 | * }
124 | *
125 | * If a value for a specific element is not defined it will set by default to zero.
126 | *
127 | * @param [in] filename: File name which contains the configuration data.
128 | * @param [in] matrixName: The key name assigned to the matrix in the config file.
129 | * @param [out] matrix: The loaded matrix, must have desired size.
130 | */
131 | template
132 | inline void loadEigenMatrix(const std::string& filename, const std::string& matrixName, Eigen::MatrixBase& matrix) {
133 | using scalar_t = typename Eigen::MatrixBase::Scalar;
134 |
135 | size_t rows = matrix.rows();
136 | size_t cols = matrix.cols();
137 |
138 | if (rows == 0 && cols == 0) {
139 | throw std::runtime_error("[loadEigenMatrix] Loading empty matrix \"" + matrixName + "\" is not allowed.");
140 | }
141 |
142 | boost::property_tree::ptree pt;
143 | boost::property_tree::read_info(filename, pt);
144 |
145 | const scalar_t scaling = pt.get(matrixName + ".scaling", 1.0);
146 | const scalar_t defaultValue = pt.get(matrixName + ".default", 0.0);
147 |
148 | size_t numFailed = 0;
149 | for (size_t i = 0; i < rows; i++) {
150 | for (size_t j = 0; j < cols; j++) {
151 | scalar_t aij;
152 | try {
153 | aij = pt.get(matrixName + "." + "(" + std::to_string(i) + "," + std::to_string(j) + ")");
154 | } catch (const std::exception&) {
155 | aij = defaultValue;
156 | numFailed++;
157 | }
158 | matrix(i, j) = scaling * aij;
159 | }
160 | }
161 |
162 | if (numFailed == matrix.size()) {
163 | throw std::runtime_error("[loadEigenMatrix] Could not load matrix \"" + matrixName + "\" from file \"" + filename + "\".");
164 | } else if (numFailed > 0) {
165 | std::cerr << "WARNING: Loaded at least one default value in matrix: \"" + matrixName + "\"\n";
166 | }
167 | }
168 |
169 | template
170 | inline void loadStdVector(const std::string& filename, const std::string& topicName, std::vector& loadVector, bool verbose = true) {
171 | boost::property_tree::ptree pt;
172 | boost::property_tree::read_info(filename, pt);
173 |
174 | std::vector backup;
175 | backup.swap(loadVector);
176 | loadVector.clear();
177 |
178 | size_t vectorSize = 0;
179 | while (true) {
180 | try {
181 | loadVector.push_back(pt.get(topicName + ".[" + std::to_string(vectorSize) + "]"));
182 | vectorSize++;
183 | } catch (const std::exception&) {
184 | if (vectorSize == 0) {
185 | loadVector.swap(backup); // if nothing could be loaded, keep the old data
186 | }
187 | break;
188 | }
189 | } // end of while loop
190 |
191 | // display
192 | if (verbose) {
193 | std::cerr << " #### '" << topicName << "': {";
194 | if (vectorSize == 0) {
195 | std::cerr << " }\n";
196 | } else {
197 | for (size_t i = 0; i < vectorSize; i++) {
198 | std::cerr << loadVector[i] << ", ";
199 | }
200 | std::cerr << "\b\b}\n";
201 | }
202 | }
203 | }
204 |
205 | } // namespace loadData
206 | } // namespace deepbreak
207 |
--------------------------------------------------------------------------------
/core/include/core/misc/Lookup.h:
--------------------------------------------------------------------------------
1 | /******************************************************************************
2 | Copyright (c) 2020, Farbod Farshidian. All rights reserved.
3 |
4 | Redistribution and use in source and binary forms, with or without
5 | modification, are permitted provided that the following conditions are met:
6 |
7 | * Redistributions of source code must retain the above copyright notice, this
8 | list of conditions and the following disclaimer.
9 |
10 | * Redistributions in binary form must reproduce the above copyright notice,
11 | this list of conditions and the following disclaimer in the documentation
12 | and/or other materials provided with the distribution.
13 |
14 | * Neither the name of the copyright holder nor the names of its
15 | contributors may be used to endorse or promote products derived from
16 | this software without specific prior written permission.
17 |
18 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
19 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
21 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
22 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
23 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
24 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
25 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
26 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
27 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28 | ******************************************************************************/
29 |
30 | #pragma once
31 |
32 | #include
33 | #include
34 | #include
35 |
36 | #include
37 | #include
38 |
39 | namespace deepbreak {
40 | namespace lookup {
41 |
42 | /**
43 | * finds the index of an element in a sorted dataArray which is equal to value
44 | * (epsilon distance)
45 | *
46 | * @tparam SCALAR : scalar type
47 | * @param [in] dataArray: data array
48 | * @param [in] value: enquiry value
49 | * @return: index
50 | */
51 | template
52 | size_t
53 | findFirstIndexWithinTol(const std::vector &dataArray, SCALAR value,
54 | SCALAR eps = numeric_traits::weakEpsilon()) {
55 | // Search for a match by linearly traversing the data, returning first match
56 | for (size_t i = 0; i < dataArray.size(); i++) {
57 | if (std::abs(dataArray[i] - value) < eps) {
58 | return i;
59 | }
60 | }
61 |
62 | // If we reach here, no match was found
63 | std::stringstream msg;
64 | msg << "[findFirstIndexWithinTol] Value not found within tolerance, with "
65 | "\n\t dataArray: ";
66 | for (const auto d : dataArray) {
67 | msg << d << ", ";
68 | }
69 | msg << "\n\t value: " << value << "\n\t epsilon: " << eps << std::endl;
70 | throw std::runtime_error(msg.str());
71 | }
72 |
73 | /**
74 | * Find index into a sorted time Array
75 | *
76 | * Indices are counted as follows:
77 | * ------ | ----- | --- ... --- | -----
78 | * t0 t1 t(n-1)
79 | * Index 0 1 2 ... (n-1) n
80 | *
81 | * Corner cases:
82 | * - If time equal to a time in the timeArray is requested, the lower index
83 | * is taken (e.g. t = t1 -> index = 1)
84 | * - If multiple times in the timeArray are equal, the index before the
85 | * first occurrence is taken. for example: if t1 = t2 = t3 and the requested
86 | * time t <= t3 -> index = 1
87 | *
88 | *
89 | * @tparam SCALAR : numerical type of time
90 | * @param timeArray : sorted time array to perform the lookup in
91 | * @param time : enquiry time
92 | * @return index between [0, size(timeArray)]
93 | */
94 | template
95 | int findIndexInTimeArray(const std::vector &timeArray, SCALAR time) {
96 | auto firstLargerValueIterator =
97 | std::lower_bound(timeArray.begin(), timeArray.end(), time);
98 | return static_cast(firstLargerValueIterator - timeArray.begin());
99 | }
100 |
101 | /**
102 | * Find interval into a sorted time Array
103 | *
104 | * Intervals are counted as follows:
105 | * ------ | ----- | --- ... --- | -----
106 | * t0 t1 t(n-1)
107 | * Interval -1 0 1 ... (n-2) (n-1)
108 | *
109 | * Corner cases are handled as in findIndexInTimeArray
110 | *
111 | * @tparam SCALAR : numerical type of time
112 | * @param timeArray : sorted time array to perform the lookup in
113 | * @param time : enquiry time
114 | * @return interval between [-1, size(timeArray)-1]
115 | */
116 | template
117 | int findIntervalInTimeArray(const std::vector &timeArray, SCALAR time) {
118 | if (!timeArray.empty()) {
119 | return findIndexInTimeArray(timeArray, time) - 1;
120 | } else {
121 | return 0;
122 | }
123 | }
124 |
125 | /**
126 | * Same as findIntervalInTimeArray except for 1 rule:
127 | * if t = t0, a 0 is returned instead of -1
128 | * This means that any query t_front <= t <= t_back gets assigned to a partition
129 | * [0, size -2]
130 | *
131 | * @tparam SCALAR : scalar type
132 | * @param timeArray : sorted time array to perform the lookup in
133 | * @param time : enquiry time
134 | * @return partition between [-1, size(timeArray)-1]
135 | */
136 | template
137 | int findActiveIntervalInTimeArray(const std::vector &timeArray,
138 | SCALAR time) {
139 | if (!timeArray.empty() && !numerics::almost_eq(time, timeArray.front())) {
140 | return findIntervalInTimeArray(timeArray, time);
141 | } else { // t = t0
142 | return 0;
143 | }
144 | }
145 |
146 | /**
147 | * Wraps findActiveIntervalInTimeArray with bound check
148 | * throws an error if time before of after the end is selected.
149 | * Also throws on timeArrays that are empty or with 1 element only.
150 | *
151 | * @tparam SCALAR : scalar type
152 | * @param timeArray : sorted time array to perform the lookup in
153 | * @param time : enquiry time
154 | * @return partition between [0, size(timeArray)-2]
155 | */
156 | template
157 | int findBoundedActiveIntervalInTimeArray(const std::vector &timeArray,
158 | SCALAR time) {
159 | auto partition = findActiveIntervalInTimeArray(timeArray, time);
160 |
161 | if (timeArray.empty()) {
162 | std::string mesg =
163 | "[findBoundedActiveIntervalInTimeArray] Time array is empty";
164 | throw std::runtime_error(mesg);
165 | }
166 |
167 | if (partition < 0) {
168 | std::string mesg =
169 | "[findBoundedActiveIntervalInTimeArray] Given time is less than the "
170 | "start time (i.e. givenTime < timeArray.front()): " +
171 | std::to_string(time) + " < " + std::to_string(timeArray.front());
172 | throw std::runtime_error(mesg);
173 | }
174 |
175 | if (partition >= timeArray.size() - 1) {
176 | std::string mesg =
177 | "[findBoundedActiveIntervalInTimeArray] Given time is greater than the "
178 | "final time (i.e. timeArray.back() < givenTime): " +
179 | std::to_string(timeArray.back()) + " < " + std::to_string(time);
180 | throw std::runtime_error(mesg);
181 | }
182 |
183 | return partition;
184 | }
185 |
186 | } // namespace lookup
187 | } // namespace deepbreak
188 |
--------------------------------------------------------------------------------
/core/include/core/misc/NumericTraits.h:
--------------------------------------------------------------------------------
1 | /******************************************************************************
2 | Copyright (c) 2017, Farbod Farshidian. All rights reserved.
3 |
4 | Redistribution and use in source and binary forms, with or without
5 | modification, are permitted provided that the following conditions are met:
6 |
7 | * Redistributions of source code must retain the above copyright notice, this
8 | list of conditions and the following disclaimer.
9 |
10 | * Redistributions in binary form must reproduce the above copyright notice,
11 | this list of conditions and the following disclaimer in the documentation
12 | and/or other materials provided with the distribution.
13 |
14 | * Neither the name of the copyright holder nor the names of its
15 | contributors may be used to endorse or promote products derived from
16 | this software without specific prior written permission.
17 |
18 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
19 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
21 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
22 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
23 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
24 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
25 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
26 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
27 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28 | ******************************************************************************/
29 |
30 | #pragma once
31 |
32 | namespace deepbreak {
33 | namespace numeric_traits {
34 | /**
35 | * If a floating number v is in limit epsilon vicinity of w, then we assume that v approaches to w.
36 | * This limit_epsilon value should be greater than the weak_epsilon value.
37 | *
38 | * @return limit epsilon value.
39 | */
40 | template
41 | constexpr T limitEpsilon() {
42 | return T(1e-6);
43 | }
44 |
45 | /**
46 | * Defines the precision during comparison.
47 | *
48 | * @return weak epsilon value
49 | */
50 | template
51 | constexpr T weakEpsilon() {
52 | return T(1e-9);
53 | }
54 |
55 | } // namespace numeric_traits
56 | } // namespace deepbreak
57 |
--------------------------------------------------------------------------------
/core/include/core/misc/Numerics.h:
--------------------------------------------------------------------------------
1 | /******************************************************************************
2 | Copyright (c) 2020, Farbod Farshidian. All rights reserved.
3 |
4 | Redistribution and use in source and binary forms, with or without
5 | modification, are permitted provided that the following conditions are met:
6 |
7 | * Redistributions of source code must retain the above copyright notice, this
8 | list of conditions and the following disclaimer.
9 |
10 | * Redistributions in binary form must reproduce the above copyright notice,
11 | this list of conditions and the following disclaimer in the documentation
12 | and/or other materials provided with the distribution.
13 |
14 | * Neither the name of the copyright holder nor the names of its
15 | contributors may be used to endorse or promote products derived from
16 | this software without specific prior written permission.
17 |
18 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
19 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
21 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
22 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
23 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
24 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
25 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
26 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
27 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28 | ******************************************************************************/
29 |
30 | #pragma once
31 |
32 | #include
33 | #include
34 | #include
35 | #include
36 |
37 | namespace deepbreak {
38 | namespace numerics {
39 |
40 | /**
41 | * Almost equal which uses machine epsilon to compare floating-point values for equality.
42 | * refer to: https://en.cppreference.com/w/cpp/types/numeric_limits/epsilon
43 | *
44 | * @tparam T1: data type of x.
45 | * @tparam T2: data type of y.
46 | * @tparam T3: data type of prec.
47 | * @param [in] x: First floating-point number.
48 | * @param [in] y: Second floating-point number.
49 | * @param [in] prec: The comparison precision.
50 | * @return bool: true if x=y.
51 | */
52 | template
53 | bool almost_eq(T1&& x, T2&& y, T3&& prec) {
54 | rcpputils::assert_true(std::is_floating_point::type>::value, "First argument is not floating point!");
55 | rcpputils::assert_true(std::is_floating_point::type>::value, "Second argument is not floating point!");
56 | rcpputils::assert_true(std::is_floating_point::type>::value, "prec is not floating point!");
57 | // the machine epsilon has to be scaled to the magnitude of the values used
58 | // and multiplied by the desired precision unless the result is subnormal
59 | using Type = const std::remove_reference_t;
60 | const auto absDiff = std::abs(x - static_cast(y));
61 | const auto magnitude = std::min(std::abs(x), std::abs(static_cast(y)));
62 | return absDiff <= static_cast(prec) * magnitude || absDiff < std::numeric_limits::min();
63 | }
64 |
65 | /**
66 | * Almost equal which uses machine epsilon to compare floating-point values for equality.
67 | * refer to: https://en.cppreference.com/w/cpp/types/numeric_limits/epsilon
68 | *
69 | * @tparam T1: data type of x.
70 | * @tparam T2: data type of y.
71 | * @param [in] x: First floating-point number.
72 | * @param [in] y: Second floating-point number.
73 | * @return bool: true if x=y.
74 | */
75 | template
76 | bool almost_eq(T1&& x, T2&& y) {
77 | const auto prec = std::numeric_limits>::epsilon();
78 | return almost_eq(x, y, prec);
79 | }
80 |
81 | /**
82 | * Almost less-equal which uses machine epsilon to compare floating-point values for equality.
83 | *
84 | * @tparam T1: data type of x.
85 | * @tparam T2: data type of y.
86 | * @tparam T3: data type of prec.
87 | * @param [in] x: First floating-point number.
88 | * @param [in] y: Second floating-point number.
89 | * @param [in] prec: The comparison precision.
90 | * @return bool: true if x<=y.
91 | */
92 | template
93 | bool almost_le(T1&& x, T2&& y, T3&& prec) {
94 | return x < y || almost_eq(x, y, prec);
95 | }
96 |
97 | /**
98 | * Almost less-equal which uses machine epsilon to compare floating-point values for equality.
99 | *
100 | * @tparam T1: data type of x.
101 | * @tparam T2: data type of y.
102 | * @param [in] x: First floating-point number.
103 | * @param [in] y: Second floating-point number.
104 | * @return bool: true if x<=y.
105 | */
106 | template
107 | bool almost_le(T1&& x, T2&& y) {
108 | return x < y || almost_eq(x, y);
109 | }
110 |
111 | /**
112 | * Almost greater-equal which uses machine epsilon to compare floating-point values for equality.
113 | *
114 | * @tparam T1: data type of x.
115 | * @tparam T2: data type of y.
116 | * @tparam T3: data type of prec.
117 | * @param [in] x: First floating-point number.
118 | * @param [in] y: Second floating-point number.
119 | * @param [in] prec: The comparison precision.
120 | * @return bool: true if x>=y.
121 | */
122 | template
123 | bool almost_ge(T1&& x, T2&& y, T3&& prec) {
124 | return x > y || almost_eq(x, y, prec);
125 | }
126 |
127 | /**
128 | * Almost greater-equal which uses machine epsilon to compare floating-point values for equality.
129 | *
130 | * @tparam T1: data type of x.
131 | * @tparam T2: data type of y.
132 | * @param [in] x: First floating-point number.
133 | * @param [in] y: Second floating-point number.
134 | * @return bool: true if x>=y.
135 | */
136 | template
137 | bool almost_ge(T1&& x, T2&& y) {
138 | return x > y || almost_eq(x, y);
139 | }
140 |
141 | } // namespace numerics
142 | } // namespace deepbreak
143 |
--------------------------------------------------------------------------------
/core/package.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | core
5 | 0.0.0
6 | TODO: Package description
7 | DeepBreak
8 | BSD
9 |
10 | ament_cmake
11 |
12 | ament_lint_auto
13 | ament_lint_common
14 |
15 | Boost
16 | Eigen3
17 | rcpputils
18 |
19 |
20 | ament_cmake
21 |
22 |
23 |
--------------------------------------------------------------------------------
/core/src/misc/LinearAlgebra.cpp:
--------------------------------------------------------------------------------
1 | /******************************************************************************
2 | Copyright (c) 2017, Farbod Farshidian. All rights reserved.
3 |
4 | Redistribution and use in source and binary forms, with or without
5 | modification, are permitted provided that the following conditions are met:
6 |
7 | * Redistributions of source code must retain the above copyright notice, this
8 | list of conditions and the following disclaimer.
9 |
10 | * Redistributions in binary form must reproduce the above copyright notice,
11 | this list of conditions and the following disclaimer in the documentation
12 | and/or other materials provided with the distribution.
13 |
14 | * Neither the name of the copyright holder nor the names of its
15 | contributors may be used to endorse or promote products derived from
16 | this software without specific prior written permission.
17 |
18 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
19 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
21 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
22 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
23 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
24 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
25 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
26 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
27 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28 | ******************************************************************************/
29 |
30 | #include
31 | #include
32 |
33 | namespace deepbreak {
34 | namespace LinearAlgebra {
35 |
36 | /******************************************************************************************************/
37 | /******************************************************************************************************/
38 | /******************************************************************************************************/
39 | void setTriangularMinimumEigenvalues(matrix_t& Lr, scalar_t minEigenValue) {
40 | for (Eigen::Index i = 0; i < Lr.rows(); ++i) {
41 | scalar_t& eigenValue = Lr(i, i); // diagonal element is the eigenvalue
42 | if (eigenValue < 0.0) {
43 | eigenValue = std::min(-minEigenValue, eigenValue);
44 | } else {
45 | eigenValue = std::max(minEigenValue, eigenValue);
46 | }
47 | }
48 | }
49 |
50 | /******************************************************************************************************/
51 | /******************************************************************************************************/
52 | /******************************************************************************************************/
53 | void makePsdEigenvalue(matrix_t& squareMatrix, scalar_t minEigenvalue) {
54 | rcpputils::assert_true(squareMatrix.rows() == squareMatrix.cols());
55 |
56 | Eigen::SelfAdjointEigenSolver eig(squareMatrix, Eigen::EigenvaluesOnly);
57 | vector_t lambda = eig.eigenvalues();
58 |
59 | bool hasNegativeEigenValue = false;
60 | for (int j = 0; j < lambda.size(); j++) {
61 | if (lambda(j) < minEigenvalue) {
62 | hasNegativeEigenValue = true;
63 | lambda(j) = minEigenvalue;
64 | }
65 | }
66 |
67 | if (hasNegativeEigenValue) {
68 | eig.compute(squareMatrix, Eigen::ComputeEigenvectors);
69 | squareMatrix = eig.eigenvectors() * lambda.asDiagonal() * eig.eigenvectors().inverse();
70 | } else {
71 | squareMatrix = 0.5 * (squareMatrix + squareMatrix.transpose()).eval();
72 | }
73 | }
74 |
75 | /******************************************************************************************************/
76 | /******************************************************************************************************/
77 | /******************************************************************************************************/
78 | void makePsdGershgorin(matrix_t& squareMatrix, scalar_t minEigenvalue) {
79 | rcpputils::assert_true(squareMatrix.rows() == squareMatrix.cols());
80 | squareMatrix = 0.5 * (squareMatrix + squareMatrix.transpose()).eval();
81 | for (int i = 0; i < squareMatrix.rows(); i++) {
82 | // Gershgorin radius: since the matrix is symmetric we use column sum instead of row sum
83 | auto Ri = squareMatrix.col(i).cwiseAbs().sum() - std::abs(squareMatrix(i, i));
84 | squareMatrix(i, i) = std::max(squareMatrix(i, i), Ri + minEigenvalue);
85 | }
86 | }
87 |
88 | /******************************************************************************************************/
89 | /******************************************************************************************************/
90 | /******************************************************************************************************/
91 | void makePsdCholesky(matrix_t& A, scalar_t minEigenvalue) {
92 | using sparse_matrix_t = Eigen::SparseMatrix;
93 |
94 | rcpputils::assert_true(A.rows() == A.cols());
95 |
96 | // set the minimum eigenvalue
97 | A.diagonal().array() -= minEigenvalue;
98 |
99 | // S P' (A + E) P S = L L'
100 | sparse_matrix_t squareMatrix = 0.5 * A.sparseView();
101 | A.transposeInPlace();
102 | squareMatrix += 0.5 * A.sparseView();
103 | Eigen::IncompleteCholesky incompleteCholesky(squareMatrix);
104 | // P' A P = M M'
105 | sparse_matrix_t M = (incompleteCholesky.scalingS().asDiagonal().inverse() * incompleteCholesky.matrixL());
106 | // L L' = P M M' P'
107 | sparse_matrix_t LmTwisted;
108 | LmTwisted.selfadjointView() = M.selfadjointView().twistedBy(incompleteCholesky.permutationP());
109 | const matrix_t L(LmTwisted);
110 | // A = L L'
111 | A = L * L.transpose();
112 |
113 | // correction for the minimum eigenvalue
114 | A.diagonal().array() += minEigenvalue;
115 | }
116 |
117 | /******************************************************************************************************/
118 | /******************************************************************************************************/
119 | /******************************************************************************************************/
120 | void computeInverseMatrixUUT(const matrix_t& Am, matrix_t& AmInvUmUmT) {
121 | // Am = Lm Lm^T --> inv(Am) = inv(Lm^T) inv(Lm) where Lm^T is upper triangular
122 | Eigen::LLT lltOfA(Am);
123 | AmInvUmUmT.setIdentity(Am.rows(), Am.cols()); // for dynamic size matrices
124 | lltOfA.matrixU().solveInPlace(AmInvUmUmT);
125 | }
126 |
127 | /******************************************************************************************************/
128 | /******************************************************************************************************/
129 | /******************************************************************************************************/
130 | void computeConstraintProjection(const matrix_t& Dm, const matrix_t& RmInvUmUmT, matrix_t& DmDagger, matrix_t& DmDaggerTRmDmDaggerUUT,
131 | matrix_t& RmInvConstrainedUUT) {
132 | const auto numConstraints = Dm.rows();
133 | const auto numInputs = Dm.cols();
134 |
135 | // Constraint Projectors are based on the QR decomposition
136 | Eigen::HouseholderQR QRof_RmInvUmUmTT_DmT(RmInvUmUmT.transpose() * Dm.transpose());
137 |
138 | matrix_t QRof_RmInvUmUmTT_DmT_Rc = QRof_RmInvUmUmTT_DmT.matrixQR().topRows(numConstraints).triangularView();
139 | setTriangularMinimumEigenvalues(QRof_RmInvUmUmTT_DmT_Rc);
140 |
141 | // Computes the inverse of Rc with an efficient in-place forward-backward substitution
142 | // Turns out that this is equal to the UUT decomposition of DmDagger^T * R * DmDagger after simplification
143 | DmDaggerTRmDmDaggerUUT.setIdentity(numConstraints, numConstraints);
144 | QRof_RmInvUmUmTT_DmT_Rc.triangularView().solveInPlace(DmDaggerTRmDmDaggerUUT);
145 |
146 | matrix_t QRof_RmInvUmUmTT_DmT_Q = QRof_RmInvUmUmTT_DmT.householderQ();
147 | // Auto take reference to the column view here without making a temporary
148 | auto QRof_RmInvUmUmTT_DmT_Qc = QRof_RmInvUmUmTT_DmT_Q.leftCols(numConstraints);
149 | auto QRof_RmInvUmUmTT_DmT_Qu = QRof_RmInvUmUmTT_DmT_Q.rightCols(numInputs - numConstraints);
150 |
151 | // Compute Weighted Pseudo Inverse, brackets used to compute the smaller, right-side product first
152 | DmDagger.noalias() = RmInvUmUmT * (QRof_RmInvUmUmTT_DmT_Qc * DmDaggerTRmDmDaggerUUT.transpose());
153 |
154 | // Constraint input cost UUT decomposition
155 | RmInvConstrainedUUT.noalias() = RmInvUmUmT * QRof_RmInvUmUmTT_DmT_Qu;
156 | }
157 |
158 | /******************************************************************************************************/
159 | /******************************************************************************************************/
160 | /******************************************************************************************************/
161 | std::pair qrConstraintProjection(const VectorFunctionLinearApproximation& constraint) {
162 | // Constraint Projectors are based on the QR decomposition
163 | const auto numConstraints = constraint.dfdu.rows();
164 | const auto numInputs = constraint.dfdu.cols();
165 | const Eigen::HouseholderQR QRof_DT(constraint.dfdu.transpose());
166 |
167 | const matrix_t Q = QRof_DT.householderQ();
168 | const auto Q1 = Q.leftCols(numConstraints);
169 |
170 | const auto R = QRof_DT.matrixQR().topRows(numConstraints).triangularView();
171 | const matrix_t pseudoInverse = R.solve(Q1.transpose()); // left pseudo-inverse of D^T
172 |
173 | VectorFunctionLinearApproximation projectionTerms;
174 | projectionTerms.dfdu = Q.rightCols(numInputs - numConstraints);
175 | projectionTerms.dfdx.noalias() = -pseudoInverse.transpose() * constraint.dfdx;
176 | projectionTerms.f.noalias() = -pseudoInverse.transpose() * constraint.f;
177 |
178 | return std::make_pair(std::move(projectionTerms), std::move(pseudoInverse));
179 | }
180 |
181 | /******************************************************************************************************/
182 | /******************************************************************************************************/
183 | /******************************************************************************************************/
184 | std::pair luConstraintProjection(const VectorFunctionLinearApproximation& constraint,
185 | bool extractPseudoInverse) {
186 | // Constraint Projectors are based on the LU decomposition
187 | const Eigen::FullPivLU lu(constraint.dfdu);
188 |
189 | VectorFunctionLinearApproximation projectionTerms;
190 | projectionTerms.dfdu = lu.kernel();
191 | projectionTerms.dfdx.noalias() = -lu.solve(constraint.dfdx);
192 | projectionTerms.f.noalias() = -lu.solve(constraint.f);
193 |
194 | matrix_t pseudoInverse;
195 | if (extractPseudoInverse) {
196 | pseudoInverse = lu.solve(matrix_t::Identity(constraint.f.size(), constraint.f.size())).transpose(); // left pseudo-inverse of D^T
197 | }
198 |
199 | return std::make_pair(std::move(projectionTerms), std::move(pseudoInverse));
200 | }
201 |
202 | // Explicit instantiations for dynamic sized matrices
203 | template int rank(const matrix_t& A);
204 | template Eigen::VectorXcd eigenvalues(const matrix_t& A);
205 | template vector_t symmetricEigenvalues(const matrix_t& A);
206 |
207 | } // namespace LinearAlgebra
208 | } // namespace deepbreak
209 |
--------------------------------------------------------------------------------
/description/CMakeLists.txt:
--------------------------------------------------------------------------------
1 | cmake_minimum_required(VERSION 3.8)
2 | project(description)
3 |
4 | if(CMAKE_COMPILER_IS_GNUCXX OR CMAKE_CXX_COMPILER_ID MATCHES "Clang")
5 | add_compile_options(-Wall -Wextra -Wpedantic)
6 | endif()
7 |
8 | # find dependencies
9 | find_package(ament_cmake REQUIRED)
10 |
11 | install(DIRECTORY model
12 | DESTINATION share/${PROJECT_NAME})
13 |
14 | if(BUILD_TESTING)
15 | find_package(ament_lint_auto REQUIRED)
16 | # the following line skips the linter which checks for copyrights
17 | # comment the line when a copyright and license is added to all source files
18 | set(ament_cmake_copyright_FOUND TRUE)
19 | # the following line skips cpplint (only works in a git repo)
20 | # comment the line when this package is in a git repo and when
21 | # a copyright and license is added to all source files
22 | set(ament_cmake_cpplint_FOUND TRUE)
23 | ament_lint_auto_find_test_dependencies()
24 | endif()
25 |
26 | ament_package()
27 |
--------------------------------------------------------------------------------
/description/model/xml/meshes/achilles-rod.stl:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/MindSpaceInc/Digit-MuJoCo-ROS2/1a263e07331cb22cf86b80ee2435febdb3be3bf2/description/model/xml/meshes/achilles-rod.stl
--------------------------------------------------------------------------------
/description/model/xml/meshes/arm-L1.stl:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/MindSpaceInc/Digit-MuJoCo-ROS2/1a263e07331cb22cf86b80ee2435febdb3be3bf2/description/model/xml/meshes/arm-L1.stl
--------------------------------------------------------------------------------
/description/model/xml/meshes/arm-L2.stl:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/MindSpaceInc/Digit-MuJoCo-ROS2/1a263e07331cb22cf86b80ee2435febdb3be3bf2/description/model/xml/meshes/arm-L2.stl
--------------------------------------------------------------------------------
/description/model/xml/meshes/arm-L3.stl:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/MindSpaceInc/Digit-MuJoCo-ROS2/1a263e07331cb22cf86b80ee2435febdb3be3bf2/description/model/xml/meshes/arm-L3.stl
--------------------------------------------------------------------------------
/description/model/xml/meshes/arm-L4.stl:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/MindSpaceInc/Digit-MuJoCo-ROS2/1a263e07331cb22cf86b80ee2435febdb3be3bf2/description/model/xml/meshes/arm-L4.stl
--------------------------------------------------------------------------------
/description/model/xml/meshes/heel-spring.stl:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/MindSpaceInc/Digit-MuJoCo-ROS2/1a263e07331cb22cf86b80ee2435febdb3be3bf2/description/model/xml/meshes/heel-spring.stl
--------------------------------------------------------------------------------
/description/model/xml/meshes/hip-pitch-housing.stl:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/MindSpaceInc/Digit-MuJoCo-ROS2/1a263e07331cb22cf86b80ee2435febdb3be3bf2/description/model/xml/meshes/hip-pitch-housing.stl
--------------------------------------------------------------------------------
/description/model/xml/meshes/hip-pitch.stl:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/MindSpaceInc/Digit-MuJoCo-ROS2/1a263e07331cb22cf86b80ee2435febdb3be3bf2/description/model/xml/meshes/hip-pitch.stl
--------------------------------------------------------------------------------
/description/model/xml/meshes/hip-roll-housing.stl:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/MindSpaceInc/Digit-MuJoCo-ROS2/1a263e07331cb22cf86b80ee2435febdb3be3bf2/description/model/xml/meshes/hip-roll-housing.stl
--------------------------------------------------------------------------------
/description/model/xml/meshes/hip-yaw-housing.stl:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/MindSpaceInc/Digit-MuJoCo-ROS2/1a263e07331cb22cf86b80ee2435febdb3be3bf2/description/model/xml/meshes/hip-yaw-housing.stl
--------------------------------------------------------------------------------
/description/model/xml/meshes/knee.stl:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/MindSpaceInc/Digit-MuJoCo-ROS2/1a263e07331cb22cf86b80ee2435febdb3be3bf2/description/model/xml/meshes/knee.stl
--------------------------------------------------------------------------------
/description/model/xml/meshes/left-shoulder-cap.stl:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/MindSpaceInc/Digit-MuJoCo-ROS2/1a263e07331cb22cf86b80ee2435febdb3be3bf2/description/model/xml/meshes/left-shoulder-cap.stl
--------------------------------------------------------------------------------
/description/model/xml/meshes/left-waist-cap.stl:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/MindSpaceInc/Digit-MuJoCo-ROS2/1a263e07331cb22cf86b80ee2435febdb3be3bf2/description/model/xml/meshes/left-waist-cap.stl
--------------------------------------------------------------------------------
/description/model/xml/meshes/right-shoulder-cap.stl:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/MindSpaceInc/Digit-MuJoCo-ROS2/1a263e07331cb22cf86b80ee2435febdb3be3bf2/description/model/xml/meshes/right-shoulder-cap.stl
--------------------------------------------------------------------------------
/description/model/xml/meshes/right-waist-cap.stl:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/MindSpaceInc/Digit-MuJoCo-ROS2/1a263e07331cb22cf86b80ee2435febdb3be3bf2/description/model/xml/meshes/right-waist-cap.stl
--------------------------------------------------------------------------------
/description/model/xml/meshes/shin.stl:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/MindSpaceInc/Digit-MuJoCo-ROS2/1a263e07331cb22cf86b80ee2435febdb3be3bf2/description/model/xml/meshes/shin.stl
--------------------------------------------------------------------------------
/description/model/xml/meshes/shoulder-roll-housing.stl:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/MindSpaceInc/Digit-MuJoCo-ROS2/1a263e07331cb22cf86b80ee2435febdb3be3bf2/description/model/xml/meshes/shoulder-roll-housing.stl
--------------------------------------------------------------------------------
/description/model/xml/meshes/tarsus.stl:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/MindSpaceInc/Digit-MuJoCo-ROS2/1a263e07331cb22cf86b80ee2435febdb3be3bf2/description/model/xml/meshes/tarsus.stl
--------------------------------------------------------------------------------
/description/model/xml/meshes/toe-A-rod.stl:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/MindSpaceInc/Digit-MuJoCo-ROS2/1a263e07331cb22cf86b80ee2435febdb3be3bf2/description/model/xml/meshes/toe-A-rod.stl
--------------------------------------------------------------------------------
/description/model/xml/meshes/toe-B-rod.stl:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/MindSpaceInc/Digit-MuJoCo-ROS2/1a263e07331cb22cf86b80ee2435febdb3be3bf2/description/model/xml/meshes/toe-B-rod.stl
--------------------------------------------------------------------------------
/description/model/xml/meshes/toe-output-ll.stl:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/MindSpaceInc/Digit-MuJoCo-ROS2/1a263e07331cb22cf86b80ee2435febdb3be3bf2/description/model/xml/meshes/toe-output-ll.stl
--------------------------------------------------------------------------------
/description/model/xml/meshes/toe-output-lr.stl:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/MindSpaceInc/Digit-MuJoCo-ROS2/1a263e07331cb22cf86b80ee2435febdb3be3bf2/description/model/xml/meshes/toe-output-lr.stl
--------------------------------------------------------------------------------
/description/model/xml/meshes/toe-output-rl.stl:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/MindSpaceInc/Digit-MuJoCo-ROS2/1a263e07331cb22cf86b80ee2435febdb3be3bf2/description/model/xml/meshes/toe-output-rl.stl
--------------------------------------------------------------------------------
/description/model/xml/meshes/toe-output-rr.stl:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/MindSpaceInc/Digit-MuJoCo-ROS2/1a263e07331cb22cf86b80ee2435febdb3be3bf2/description/model/xml/meshes/toe-output-rr.stl
--------------------------------------------------------------------------------
/description/model/xml/meshes/toe-output.stl:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/MindSpaceInc/Digit-MuJoCo-ROS2/1a263e07331cb22cf86b80ee2435febdb3be3bf2/description/model/xml/meshes/toe-output.stl
--------------------------------------------------------------------------------
/description/model/xml/meshes/toe-pitch.stl:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/MindSpaceInc/Digit-MuJoCo-ROS2/1a263e07331cb22cf86b80ee2435febdb3be3bf2/description/model/xml/meshes/toe-pitch.stl
--------------------------------------------------------------------------------
/description/model/xml/meshes/toe-roll.stl:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/MindSpaceInc/Digit-MuJoCo-ROS2/1a263e07331cb22cf86b80ee2435febdb3be3bf2/description/model/xml/meshes/toe-roll.stl
--------------------------------------------------------------------------------
/description/model/xml/meshes/torso.stl:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/MindSpaceInc/Digit-MuJoCo-ROS2/1a263e07331cb22cf86b80ee2435febdb3be3bf2/description/model/xml/meshes/torso.stl
--------------------------------------------------------------------------------
/description/package.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | description
5 | 0.0.0
6 | TODO: Package description
7 | DeepBreak
8 | BSD
9 |
10 | ament_cmake
11 |
12 | ament_lint_auto
13 | ament_lint_common
14 |
15 |
16 | ament_cmake
17 |
18 |
19 |
--------------------------------------------------------------------------------
/results.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/MindSpaceInc/Digit-MuJoCo-ROS2/1a263e07331cb22cf86b80ee2435febdb3be3bf2/results.png
--------------------------------------------------------------------------------
/simulation/mujoco/CMakeLists.txt:
--------------------------------------------------------------------------------
1 | cmake_minimum_required(VERSION 3.5)
2 | project(mujoco)
3 |
4 | # if(CMAKE_COMPILER_IS_GNUCXX OR CMAKE_CXX_COMPILER_ID MATCHES "Clang")
5 | # add_compile_options(-Wall -Wextra -Wpedantic)
6 | # endif()
7 |
8 | # find dependencies
9 | find_package(ament_cmake REQUIRED)
10 | # uncomment the following section in order to fill in
11 | # further dependencies manually.
12 | # find_package( REQUIRED)
13 |
14 | list(APPEND ${PROJECT_NAME}_CONFIG_EXTRAS
15 | cmake/CheckAvxSupport.cmake
16 | cmake/FindOrFetch.cmake
17 | cmake/MujocoHarden.cmake
18 | cmake/MujocoLinkOptions.cmake
19 | cmake/MujocoMacOS.cmake
20 | cmake/SimulateDependencies.cmake
21 | cmake/SimulateOptions.cmake
22 | )
23 |
24 | # find dependencies
25 | find_package(ament_cmake REQUIRED)
26 | find_package(sensor_msgs REQUIRED)
27 | find_package(communication REQUIRED)
28 | find_package(rclcpp REQUIRED)
29 | find_package(geometry_msgs REQUIRED)
30 | find_package(tf2 REQUIRED)
31 | find_package(tf2_ros REQUIRED)
32 | find_package(nav_msgs REQUIRED)
33 | find_package(cv_bridge REQUIRED)
34 | # BLASFEO Option
35 | if(NOT TARGET mujoco)
36 | add_library(mujoco SHARED IMPORTED)
37 | set_target_properties(mujoco PROPERTIES IMPORTED_LOCATION ${CMAKE_CURRENT_SOURCE_DIR}/lib/libmujoco.so)
38 | endif()
39 |
40 | file(GLOB_RECURSE source ${CMAKE_CURRENT_SOURCE_DIR}/src/*.cpp ${CMAKE_CURRENT_SOURCE_DIR}/src/*.cc)
41 | add_executable(simulation ${source})
42 | target_link_libraries(simulation mujoco glfw pthread rt ${CMAKE_DL_LIBS})
43 | ament_target_dependencies(simulation sensor_msgs rclcpp communication geometry_msgs tf2 tf2_ros nav_msgs cv_bridge)
44 | target_include_directories(simulation PUBLIC
45 | $
46 | $)
47 | target_compile_options(simulation PUBLIC ${DEEPBREAK_CXX_FLAGS})
48 |
49 |
50 | install(TARGETS simulation
51 | DESTINATION lib/${PROJECT_NAME})
52 |
53 | install(DIRECTORY launch
54 | DESTINATION share/${PROJECT_NAME})
55 |
56 | ament_package()
57 |
--------------------------------------------------------------------------------
/simulation/mujoco/cmake/CheckAvxSupport.cmake:
--------------------------------------------------------------------------------
1 | # Copyright 2021 DeepMind Technologies Limited
2 | #
3 | # Licensed under the Apache License, Version 2.0 (the "License");
4 | # you may not use this file except in compliance with the License.
5 | # You may obtain a copy of the License at
6 | #
7 | # https://www.apache.org/licenses/LICENSE-2.0
8 | #
9 | # Unless required by applicable law or agreed to in writing, software
10 | # distributed under the License is distributed on an "AS IS" BASIS,
11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | # See the License for the specific language governing permissions and
13 | # limitations under the License.
14 |
15 | include(CheckCSourceCompiles)
16 |
17 | # Assigns compiler options to the given variable based on availability of AVX.
18 | function(get_avx_compile_options OUTPUT_VAR)
19 | message(VERBOSE "Checking if AVX is available...")
20 |
21 | if(MSVC)
22 | set(CMAKE_REQUIRED_FLAGS "/arch:AVX")
23 | elseif(WIN32)
24 | # Abseil LTS 20230125.0 assumes that AVX implies PCLMUL on Windows.
25 | set(CMAKE_REQUIRED_FLAGS "-mavx" "-mpclmul")
26 | else()
27 | set(CMAKE_REQUIRED_FLAGS "-mavx")
28 | endif()
29 |
30 | if(APPLE AND "x86_64" IN_LIST CMAKE_OSX_ARCHITECTURES)
31 | message(STATUS "Building x86_64 on macOS, forcing CAN_BUILD_AVX to TRUE.")
32 | set(CAN_BUILD_AVX TRUE)
33 | else()
34 | check_c_source_compiles(
35 | "
36 | #include
37 | int main(int argc, char* argv[]) {
38 | __m256d ymm;
39 | return 0;
40 | }
41 | "
42 | CAN_BUILD_AVX
43 | )
44 | endif()
45 |
46 | if(CAN_BUILD_AVX)
47 | message(VERBOSE "Checking if AVX is available... AVX available.")
48 | set("${OUTPUT_VAR}"
49 | ${CMAKE_REQUIRED_FLAGS}
50 | PARENT_SCOPE
51 | )
52 | else()
53 | message(VERBOSE "Checking if AVX is available... AVX not available.")
54 | set("${OUTPUT_VAR}" PARENT_SCOPE)
55 | endif()
56 | endfunction()
57 |
--------------------------------------------------------------------------------
/simulation/mujoco/cmake/FindOrFetch.cmake:
--------------------------------------------------------------------------------
1 | # Copyright 2021 DeepMind Technologies Limited
2 | #
3 | # Licensed under the Apache License, Version 2.0 (the "License");
4 | # you may not use this file except in compliance with the License.
5 | # You may obtain a copy of the License at
6 | #
7 | # https://www.apache.org/licenses/LICENSE-2.0
8 | #
9 | # Unless required by applicable law or agreed to in writing, software
10 | # distributed under the License is distributed on an "AS IS" BASIS,
11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | # See the License for the specific language governing permissions and
13 | # limitations under the License.
14 | #
15 | #.rst:
16 | # FindOrFetch
17 | # ----------------------
18 | #
19 | # Find or fetch a package in order to satisfy target dependencies.
20 | #
21 | # FindOrFetch([USE_SYSTEM_PACKAGE [ON/OFF]]
22 | # [PACKAGE_NAME [name]]
23 | # [LIBRARY_NAME [name]]
24 | # [GIT_REPO [repo]]
25 | # [GIT_TAG [tag]]
26 | # [PATCH_COMMAND [cmd] [args]]
27 | # [TARGETS [targets]]
28 | # [EXCLUDE_FROM_ALL])
29 | #
30 | # The command has the following parameters:
31 | #
32 | # Arguments:
33 | # - ``USE_SYSTEM_PACKAGE`` one-value argument on whether to search for the
34 | # package in the system (ON) or whether to fetch the library using
35 | # FetchContent from the specified Git repository (OFF). Note that
36 | # FetchContent variables will override this behaviour.
37 | # - ``PACKAGE_NAME`` name of the system-package. Ignored if
38 | # ``USE_SYSTEM_PACKAGE`` is ``OFF``.
39 | # - ``LIBRARY_NAME`` name of the library. Ignored if
40 | # ``USE_SYSTEM_PACKAGE`` is ``ON``.
41 | # - ``GIT_REPO`` git repository to fetch the library from. Ignored if
42 | # ``USE_SYSTEM_PACKAGE`` is ``ON``.
43 | # - ``GIT_TAG`` tag reference when fetching the library from the git
44 | # repository. Ignored if ``USE_SYSTEM_PACKAGE`` is ``ON``.
45 | # - ``PATCH_COMMAND`` Specifies a custom command to patch the sources after an
46 | # update. See https://cmake.org/cmake/help/latest/module/ExternalProject.html#command:externalproject_add
47 | # for details on the parameter.
48 | # - ``TARGETS`` list of targets to be satisfied. If any of these targets are
49 | # not currently defined, this macro will attempt to either find or fetch the
50 | # package.
51 | # - ``EXCLUDE_FROM_ALL`` if specified, the targets are not added to the ``all``
52 | # metatarget.
53 | #
54 | # Note: if ``USE_SYSTEM_PACKAGE`` is ``OFF``, FetchContent will be used to
55 | # retrieve the specified targets. It is possible to specify any variable in
56 | # https://cmake.org/cmake/help/latest/module/FetchContent.html#variables to
57 | # override this macro behaviour.
58 |
59 | if(COMMAND FindOrFetch)
60 | return()
61 | endif()
62 |
63 | macro(FindOrFetch)
64 | if(NOT FetchContent)
65 | include(FetchContent)
66 | endif()
67 |
68 | # Parse arguments.
69 | set(options EXCLUDE_FROM_ALL)
70 | set(one_value_args
71 | USE_SYSTEM_PACKAGE
72 | PACKAGE_NAME
73 | LIBRARY_NAME
74 | GIT_REPO
75 | GIT_TAG
76 | )
77 | set(multi_value_args PATCH_COMMAND TARGETS)
78 | cmake_parse_arguments(
79 | _ARGS
80 | "${options}"
81 | "${one_value_args}"
82 | "${multi_value_args}"
83 | ${ARGN}
84 | )
85 |
86 | # Check if all targets are found.
87 | if(NOT _ARGS_TARGETS)
88 | message(FATAL_ERROR "mujoco::FindOrFetch: TARGETS must be specified.")
89 | endif()
90 |
91 | set(targets_found TRUE)
92 | message(CHECK_START
93 | "mujoco::FindOrFetch: checking for targets in package `${_ARGS_PACKAGE_NAME}`"
94 | )
95 | foreach(target ${_ARGS_TARGETS})
96 | if(NOT TARGET ${target})
97 | message(CHECK_FAIL "target `${target}` not defined.")
98 | set(targets_found FALSE)
99 | break()
100 | endif()
101 | endforeach()
102 |
103 | # If targets are not found, use `find_package` or `FetchContent...` to get it.
104 | if(NOT targets_found)
105 | if(${_ARGS_USE_SYSTEM_PACKAGE})
106 | message(CHECK_START
107 | "mujoco::FindOrFetch: finding `${_ARGS_PACKAGE_NAME}` in system packages..."
108 | )
109 | find_package(${_ARGS_PACKAGE_NAME} REQUIRED)
110 | message(CHECK_PASS "found")
111 | else()
112 | message(CHECK_START
113 | "mujoco::FindOrFetch: Using FetchContent to retrieve `${_ARGS_LIBRARY_NAME}`"
114 | )
115 | FetchContent_Declare(
116 | ${_ARGS_LIBRARY_NAME}
117 | GIT_REPOSITORY ${_ARGS_GIT_REPO}
118 | GIT_TAG ${_ARGS_GIT_TAG}
119 | GIT_SHALLOW FALSE
120 | PATCH_COMMAND ${_ARGS_PATCH_COMMAND}
121 | )
122 | if(${_ARGS_EXCLUDE_FROM_ALL})
123 | FetchContent_GetProperties(${_ARGS_LIBRARY_NAME})
124 | if(NOT ${${_ARGS_LIBRARY_NAME}_POPULATED})
125 | FetchContent_Populate(${_ARGS_LIBRARY_NAME})
126 | add_subdirectory(
127 | ${${_ARGS_LIBRARY_NAME}_SOURCE_DIR} ${${_ARGS_LIBRARY_NAME}_BINARY_DIR}
128 | EXCLUDE_FROM_ALL
129 | )
130 | endif()
131 | else()
132 | FetchContent_MakeAvailable(${_ARGS_LIBRARY_NAME})
133 | endif()
134 | message(CHECK_PASS "Done")
135 | endif()
136 | else()
137 | message(CHECK_PASS "found")
138 | endif()
139 | endmacro()
140 |
--------------------------------------------------------------------------------
/simulation/mujoco/cmake/MujocoHarden.cmake:
--------------------------------------------------------------------------------
1 | # Copyright 2022 DeepMind Technologies Limited
2 | #
3 | # Licensed under the Apache License, Version 2.0 (the "License");
4 | # you may not use this file except in compliance with the License.
5 | # You may obtain a copy of the License at
6 | #
7 | # https://www.apache.org/licenses/LICENSE-2.0
8 | #
9 | # Unless required by applicable law or agreed to in writing, software
10 | # distributed under the License is distributed on an "AS IS" BASIS,
11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | # See the License for the specific language governing permissions and
13 | # limitations under the License.
14 |
15 | option(MUJOCO_HARDEN "Enable build hardening for MuJoCo." OFF)
16 | if(MUJOCO_HARDEN
17 | AND NOT
18 | CMAKE_CXX_COMPILER_ID
19 | MATCHES
20 | ".*Clang.*"
21 | )
22 | message(FATAL_ERROR "MUJOCO_HARDEN is only supported when building with Clang")
23 | endif()
24 |
25 | if(MUJOCO_HARDEN)
26 | set(MUJOCO_HARDEN_COMPILE_OPTIONS -D_FORTIFY_SOURCE=2 -fstack-protector)
27 | if(${CMAKE_SYSTEM_NAME} MATCHES "Darwin")
28 | set(MUJOCO_HARDEN_LINK_OPTIONS -Wl,-bind_at_load)
29 | elseif(${CMAKE_SYSTEM_NAME} MATCHES "Linux")
30 | set(MUJOCO_HARDEN_LINK_OPTIONS -Wl,-z,relro -Wl,-z,now)
31 | endif()
32 | else()
33 | set(MUJOCO_HARDEN_COMPILE_OPTIONS "")
34 | set(MUJOCO_HARDEN_LINK_OPTIONS "")
35 | endif()
36 |
--------------------------------------------------------------------------------
/simulation/mujoco/cmake/MujocoLinkOptions.cmake:
--------------------------------------------------------------------------------
1 | # Copyright 2021 DeepMind Technologies Limited
2 | #
3 | # Licensed under the Apache License, Version 2.0 (the "License");
4 | # you may not use this file except in compliance with the License.
5 | # You may obtain a copy of the License at
6 | #
7 | # https://www.apache.org/licenses/LICENSE-2.0
8 | #
9 | # Unless required by applicable law or agreed to in writing, software
10 | # distributed under the License is distributed on an "AS IS" BASIS,
11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | # See the License for the specific language governing permissions and
13 | # limitations under the License.
14 |
15 | include(CheckCSourceCompiles)
16 |
17 | # Gets the appropriate linker options for building MuJoCo, based on features available on the
18 | # linker.
19 | function(get_mujoco_extra_link_options OUTPUT_VAR)
20 | if(MSVC)
21 | set(EXTRA_LINK_OPTIONS /OPT:REF /OPT:ICF=5)
22 | else()
23 | set(EXTRA_LINK_OPTIONS)
24 |
25 | if(WIN32)
26 | set(CMAKE_REQUIRED_FLAGS "-fuse-ld=lld-link")
27 | check_c_source_compiles("int main() {}" SUPPORTS_LLD)
28 | if(SUPPORTS_LLD)
29 | set(EXTRA_LINK_OPTIONS
30 | ${EXTRA_LINK_OPTIONS}
31 | -fuse-ld=lld-link
32 | -Wl,/OPT:REF
33 | -Wl,/OPT:ICF
34 | )
35 | endif()
36 | else()
37 | set(CMAKE_REQUIRED_FLAGS "-fuse-ld=lld")
38 | check_c_source_compiles("int main() {}" SUPPORTS_LLD)
39 | if(SUPPORTS_LLD)
40 | set(EXTRA_LINK_OPTIONS ${EXTRA_LINK_OPTIONS} -fuse-ld=lld)
41 | else()
42 | set(CMAKE_REQUIRED_FLAGS "-fuse-ld=gold")
43 | check_c_source_compiles("int main() {}" SUPPORTS_GOLD)
44 | if(SUPPORTS_GOLD)
45 | set(EXTRA_LINK_OPTIONS ${EXTRA_LINK_OPTIONS} -fuse-ld=gold)
46 | endif()
47 | endif()
48 |
49 | set(CMAKE_REQUIRED_FLAGS ${EXTRA_LINK_OPTIONS} "-Wl,--gc-sections")
50 | check_c_source_compiles("int main() {}" SUPPORTS_GC_SECTIONS)
51 | if(SUPPORTS_GC_SECTIONS)
52 | set(EXTRA_LINK_OPTIONS ${EXTRA_LINK_OPTIONS} -Wl,--gc-sections)
53 | else()
54 | set(CMAKE_REQUIRED_FLAGS ${EXTRA_LINK_OPTIONS} "-Wl,-dead_strip")
55 | check_c_source_compiles("int main() {}" SUPPORTS_DEAD_STRIP)
56 | if(SUPPORTS_DEAD_STRIP)
57 | set(EXTRA_LINK_OPTIONS ${EXTRA_LINK_OPTIONS} -Wl,-dead_strip)
58 | endif()
59 | endif()
60 | endif()
61 | endif()
62 |
63 | set("${OUTPUT_VAR}"
64 | ${EXTRA_LINK_OPTIONS}
65 | PARENT_SCOPE
66 | )
67 | endfunction()
68 |
--------------------------------------------------------------------------------
/simulation/mujoco/cmake/MujocoMacOS.cmake:
--------------------------------------------------------------------------------
1 | # Copyright 2022 DeepMind Technologies Limited
2 | #
3 | # Licensed under the Apache License, Version 2.0 (the "License");
4 | # you may not use this file except in compliance with the License.
5 | # You may obtain a copy of the License at
6 | #
7 | # https://www.apache.org/licenses/LICENSE-2.0
8 | #
9 | # Unless required by applicable law or agreed to in writing, software
10 | # distributed under the License is distributed on an "AS IS" BASIS,
11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | # See the License for the specific language governing permissions and
13 | # limitations under the License.
14 |
15 | if(APPLE)
16 | # 10.12 is the oldest version of macOS that supports C++17, launched 2016.
17 | set(MUJOCO_MACOSX_VERSION_MIN 10.12)
18 |
19 | # We are setting the -mmacosx-version-min compiler flag directly rather than using the
20 | # CMAKE_OSX_DEPLOYMENT_TARGET variable since we do not want to affect choice of SDK,
21 | # and also we only want to apply the version restriction locally.
22 | set(MUJOCO_MACOS_COMPILE_OPTIONS -mmacosx-version-min=${MUJOCO_MACOSX_VERSION_MIN}
23 | -Werror=partial-availability -Werror=unguarded-availability
24 | )
25 | set(MUJOCO_MACOS_LINK_OPTIONS -mmacosx-version-min=${MUJOCO_MACOSX_VERSION_MIN}
26 | -Wl,-no_weak_imports
27 | )
28 | else()
29 | set(MUJOCO_MACOS_COMPILE_OPTIONS "")
30 | set(MUJOCO_MACOS_LINK_OPTIONS "")
31 | endif()
32 |
33 | function(enforce_mujoco_macosx_min_version)
34 | if(APPLE)
35 | add_compile_options(${MUJOCO_MACOS_COMPILE_OPTIONS})
36 | add_link_options(${MUJOCO_MACOS_LINK_OPTIONS})
37 | endif()
38 | endfunction()
39 |
--------------------------------------------------------------------------------
/simulation/mujoco/cmake/SimulateDependencies.cmake:
--------------------------------------------------------------------------------
1 | # Copyright 2021 DeepMind Technologies Limited
2 | #
3 | # Licensed under the Apache License, Version 2.0 (the "License");
4 | # you may not use this file except in compliance with the License.
5 | # You may obtain a copy of the License at
6 | #
7 | # https://www.apache.org/licenses/LICENSE-2.0
8 | #
9 | # Unless required by applicable law or agreed to in writing, software
10 | # distributed under the License is distributed on an "AS IS" BASIS,
11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | # See the License for the specific language governing permissions and
13 | # limitations under the License.
14 |
15 | include(FindOrFetch)
16 |
17 | if(SIMULATE_STANDALONE)
18 | # If standalone, by default look for MuJoCo binary version.
19 | set(DEFAULT_USE_SYSTEM_MUJOCO ON)
20 | else()
21 | set(DEFAULT_USE_SYSTEM_MUJOCO OFF)
22 | endif()
23 |
24 | option(MUJOCO_SIMULATE_USE_SYSTEM_MUJOCO "Use installed MuJoCo version."
25 | ${DEFAULT_USE_SYSTEM_MUJOCO}
26 | )
27 | unset(DEFAULT_USE_SYSTEM_MUJOCO)
28 |
29 | option(MUJOCO_SIMULATE_USE_SYSTEM_MUJOCO "Use installed MuJoCo version." OFF)
30 | option(MUJOCO_SIMULATE_USE_SYSTEM_GLFW "Use installed GLFW version." OFF)
31 |
32 | set(MUJOCO_DEP_VERSION_glfw3
33 | 7482de6071d21db77a7236155da44c172a7f6c9e # 3.3.8
34 | CACHE STRING "Version of `glfw` to be fetched."
35 | )
36 | mark_as_advanced(MUJOCO_DEP_VERSION_glfw3)
37 |
38 | find_package(Threads REQUIRED)
39 |
40 | set(MUJOCO_BUILD_EXAMPLES OFF)
41 | set(MUJOCO_BUILD_TESTS OFF)
42 | set(MUJOCO_BUILD_PYTHON OFF)
43 | set(MUJOCO_TEST_PYTHON_UTIL OFF)
44 |
45 | findorfetch(
46 | USE_SYSTEM_PACKAGE
47 | MUJOCO_SIMULATE_USE_SYSTEM_MUJOCO
48 | PACKAGE_NAME
49 | mujoco
50 | LIBRARY_NAME
51 | mujoco
52 | GIT_REPO
53 | https://github.com/deepmind/mujoco.git
54 | GIT_TAG
55 | main
56 | TARGETS
57 | mujoco
58 | EXCLUDE_FROM_ALL
59 | )
60 |
61 | option(MUJOCO_EXTRAS_STATIC_GLFW
62 | "Link MuJoCo sample apps and simulate libraries against GLFW statically." ON
63 | )
64 | if(MUJOCO_EXTRAS_STATIC_GLFW)
65 | set(BUILD_SHARED_LIBS_OLD ${BUILD_SHARED_LIBS})
66 | set(BUILD_SHARED_LIBS
67 | OFF
68 | CACHE INTERNAL "Build SHARED libraries"
69 | )
70 | endif()
71 |
72 | set(GLFW_BUILD_EXAMPLES OFF)
73 | set(GLFW_BUILD_TESTS OFF)
74 | set(GLFW_BUILD_DOCS OFF)
75 | set(GLFW_INSTALL OFF)
76 |
77 | findorfetch(
78 | USE_SYSTEM_PACKAGE
79 | MUJOCO_SIMULATE_USE_SYSTEM_GLFW
80 | PACKAGE_NAME
81 | glfw3
82 | LIBRARY_NAME
83 | glfw3
84 | GIT_REPO
85 | https://github.com/glfw/glfw.git
86 | GIT_TAG
87 | ${MUJOCO_DEP_VERSION_glfw3}
88 | TARGETS
89 | glfw
90 | EXCLUDE_FROM_ALL
91 | )
92 |
93 | if(MUJOCO_EXTRAS_STATIC_GLFW)
94 | set(BUILD_SHARED_LIBS
95 | ${BUILD_SHARED_LIBS_OLD}
96 | CACHE BOOL "Build SHARED libraries" FORCE
97 | )
98 | unset(BUILD_SHARED_LIBS_OLD)
99 | endif()
100 |
101 | if(NOT SIMULATE_STANDALONE)
102 | target_compile_options(glfw PRIVATE ${MUJOCO_MACOS_COMPILE_OPTIONS})
103 | target_link_options(glfw PRIVATE ${MUJOCO_MACOS_LINK_OPTIONS})
104 | endif()
105 |
--------------------------------------------------------------------------------
/simulation/mujoco/cmake/SimulateOptions.cmake:
--------------------------------------------------------------------------------
1 | # Copyright 2021 DeepMind Technologies Limited
2 | #
3 | # Licensed under the Apache License, Version 2.0 (the "License");
4 | # you may not use this file except in compliance with the License.
5 | # You may obtain a copy of the License at
6 | #
7 | # https://www.apache.org/licenses/LICENSE-2.0
8 | #
9 | # Unless required by applicable law or agreed to in writing, software
10 | # distributed under the License is distributed on an "AS IS" BASIS,
11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | # See the License for the specific language governing permissions and
13 | # limitations under the License.
14 |
15 | # Global compilation settings
16 | set(CMAKE_C_STANDARD 11)
17 | set(CMAKE_C_STANDARD_REQUIRED ON)
18 | set(CMAKE_CXX_STANDARD 17)
19 | set(CMAKE_CXX_STANDARD_REQUIRED ON)
20 | set(CMAKE_CXX_EXTENSIONS OFF)
21 | set(CMAKE_C_EXTENSIONS OFF)
22 | set(CMAKE_EXPORT_COMPILE_COMMANDS ON) # For LLVM tooling
23 |
24 | if(NOT CMAKE_CONFIGURATION_TYPES)
25 | if(NOT CMAKE_BUILD_TYPE)
26 | message(STATUS "Setting build type to 'Release' as none was specified.")
27 | set(CMAKE_BUILD_TYPE
28 | "Release"
29 | CACHE STRING "Choose the type of build, recommanded options are: Debug or Release" FORCE
30 | )
31 | endif()
32 | set(BUILD_TYPES
33 | "Debug"
34 | "Release"
35 | "MinSizeRel"
36 | "RelWithDebInfo"
37 | )
38 | set_property(CACHE CMAKE_BUILD_TYPE PROPERTY STRINGS ${BUILD_TYPES})
39 | endif()
40 |
41 | include(GNUInstallDirs)
42 |
43 | # Change the default output directory in the build structure. This is not stricly needed, but helps
44 | # running in Windows, such that all built executables have DLLs in the same folder as the .exe
45 | # files.
46 | set(CMAKE_RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/${CMAKE_INSTALL_BINDIR}")
47 | set(CMAKE_LIBRARY_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/${CMAKE_INSTALL_LIBDIR}")
48 | set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/${CMAKE_INSTALL_LIBDIR}")
49 |
50 | set(OpenGL_GL_PREFERENCE GLVND)
51 |
52 | set(CMAKE_POSITION_INDEPENDENT_CODE ON)
53 | set(CMAKE_C_VISIBILITY_PRESET hidden)
54 | set(CMAKE_CXX_VISIBILITY_PRESET hidden)
55 | set(CMAKE_VISIBILITY_INLINES_HIDDEN ON)
56 |
57 | if(MSVC)
58 | add_compile_options(/Gy /Gw /Oi)
59 | elseif(CMAKE_CXX_COMPILER_ID STREQUAL "GNU" OR CMAKE_CXX_COMPILER_ID MATCHES "Clang")
60 | add_compile_options(-fdata-sections -ffunction-sections)
61 | endif()
62 |
63 | # We default to shared library.
64 | set(BUILD_SHARED_LIBS
65 | ON
66 | CACHE BOOL "Build Mujoco as shared library."
67 | )
68 |
69 | option(MUJOCO_ENABLE_AVX "Build binaries that require AVX instructions, if possible." ON)
70 | option(MUJOCO_ENABLE_AVX_INTRINSICS "Make use of hand-written AVX intrinsics, if possible." ON)
71 | option(MUJOCO_ENABLE_RPATH "Enable RPath support when installing Mujoco." ON)
72 | mark_as_advanced(MUJOCO_ENABLE_RPATH)
73 |
74 | if(MUJOCO_ENABLE_AVX)
75 | include(CheckAvxSupport)
76 | get_avx_compile_options(AVX_COMPILE_OPTIONS)
77 | else()
78 | set(AVX_COMPILE_OPTIONS)
79 | endif()
80 |
81 | option(MUJOCO_BUILD_MACOS_FRAMEWORKS "Build libraries as macOS Frameworks" OFF)
82 |
83 | # Get some extra link options.
84 | include(MujocoLinkOptions)
85 | get_mujoco_extra_link_options(EXTRA_LINK_OPTIONS)
86 |
87 | if(CMAKE_CXX_COMPILER_ID STREQUAL "GNU" OR (CMAKE_CXX_COMPILER_ID MATCHES "Clang" AND NOT MSVC))
88 | set(EXTRA_COMPILE_OPTIONS -Wall -Werror)
89 | if(CMAKE_CXX_COMPILER_ID STREQUAL "GNU")
90 | # TODO: This should add to EXTRA_COMPILE_OPTIONS rather than overwrite it.
91 | set(EXTRA_COMPILE_OPTIONS
92 | -Wno-int-in-bool-context
93 | -Wno-maybe-uninitialized
94 | -Wno-sign-compare
95 | -Wno-stringop-overflow
96 | -Wno-stringop-truncation
97 | )
98 | endif()
99 | endif()
100 |
101 | if(WIN32)
102 | add_compile_definitions(_CRT_SECURE_NO_WARNINGS)
103 | endif()
104 |
105 | include(MujocoHarden)
106 | set(EXTRA_COMPILE_OPTIONS ${EXTRA_COMPILE_OPTIONS} ${MUJOCO_HARDEN_COMPILE_OPTIONS})
107 | set(EXTRA_LINK_OPTIONS ${EXTRA_LINK_OPTIONS} ${MUJOCO_HARDEN_LINK_OPTIONS})
108 |
--------------------------------------------------------------------------------
/simulation/mujoco/include/MuJoCoMessageHandler.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | #include
4 | #include
5 | #include
6 | #include
7 | #include
8 | #include
9 | #include
10 | #include
11 | #include
12 |
13 | #include "communication/msg/actuator_cmds.hpp"
14 | #include "communication/srv/simulation_reset.hpp"
15 |
16 | #include "array_safety.h"
17 | #include "simulate.h"
18 |
19 | using namespace rclcpp;
20 |
21 | using namespace std::chrono_literals;
22 |
23 | namespace deepbreak {
24 | namespace mj = ::mujoco;
25 | namespace mju = ::mujoco::sample_util;
26 |
27 | class MuJoCoMessageHandler : public rclcpp::Node {
28 | public:
29 | struct ActuatorCmds {
30 | double time = 0.0;
31 | std::vector actuators_name;
32 | std::vector kp;
33 | std::vector pos;
34 | std::vector kd;
35 | std::vector vel;
36 | std::vector torque;
37 | };
38 |
39 | MuJoCoMessageHandler(mj::Simulate *sim);
40 | ~MuJoCoMessageHandler();
41 |
42 | std::shared_ptr get_actuator_cmds_ptr();
43 |
44 | private:
45 | void reset_callback(
46 | const std::shared_ptr request,
47 | std::shared_ptr response);
48 |
49 | void imu_callback();
50 |
51 | void odom_callback();
52 |
53 | void joint_callback();
54 |
55 | void actuator_cmd_callback(
56 | const communication::msg::ActuatorCmds::SharedPtr msg) const;
57 |
58 | void parameter_callback(const rclcpp::Parameter &);
59 |
60 | void drop_old_message();
61 |
62 |
63 | mj::Simulate *sim_;
64 | std::string name_prefix, model_param_name;
65 | std::vector timers_;
66 | rclcpp::Publisher::SharedPtr imu_publisher_;
67 | rclcpp::Publisher::SharedPtr
68 | joint_state_publisher_;
69 | rclcpp::Publisher::SharedPtr odom_publisher_;
70 |
71 | rclcpp::Subscription::SharedPtr
72 | actuator_cmd_subscription_;
73 | rclcpp::Service::SharedPtr reset_service_;
74 |
75 | std::shared_ptr param_subscriber_;
76 |
77 | std::shared_ptr cb_handle_;
78 |
79 | std::shared_ptr actuator_cmds_ptr_;
80 |
81 | std::thread spin_thread;
82 | };
83 |
84 | } // namespace deepbreak
85 |
--------------------------------------------------------------------------------
/simulation/mujoco/include/array_safety.h:
--------------------------------------------------------------------------------
1 | // Copyright 2021 DeepMind Technologies Limited
2 | //
3 | // Licensed under the Apache License, Version 2.0 (the "License");
4 | // you may not use this file except in compliance with the License.
5 | // You may obtain a copy of the License at
6 | //
7 | // http://www.apache.org/licenses/LICENSE-2.0
8 | //
9 | // Unless required by applicable law or agreed to in writing, software
10 | // distributed under the License is distributed on an "AS IS" BASIS,
11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | // See the License for the specific language governing permissions and
13 | // limitations under the License.
14 |
15 | #ifndef MUJOCO_SAMPLE_ARRAY_SAFETY_H_
16 | #define MUJOCO_SAMPLE_ARRAY_SAFETY_H_
17 |
18 | #include
19 | #include
20 | #include
21 | #include
22 | #include
23 |
24 | // Provides safe alternatives to the sizeof() operator and standard library functions for handling
25 | // null-terminated (C-style) strings in raw char arrays.
26 | //
27 | // These functions make use of compile-time array sizes to limit read and write operations to within
28 | // the array bounds. They are designed to trigger a compile error if the array size cannot be
29 | // determined at compile time (e.g. when an array has decayed into a pointer).
30 | //
31 | // They do not perform runtime bound checks.
32 |
33 | namespace mujoco {
34 | namespace sample_util {
35 |
36 | // returns sizeof(arr)
37 | // use instead of sizeof() to avoid unintended array-to-pointer decay
38 | template
39 | static constexpr std::size_t sizeof_arr(const T(&arr)[N]) {
40 | return sizeof(arr);
41 | }
42 |
43 | // like std::strcmp but it will not read beyond the bound of either lhs or rhs
44 | template
45 | static inline int strcmp_arr(const char (&lhs)[N1], const char (&rhs)[N2]) {
46 | return std::strncmp(lhs, rhs, std::min(N1, N2));
47 | }
48 |
49 | // like std::strlen but it will not read beyond the bound of str
50 | // if str is not null-terminated, returns sizeof(str)
51 | template
52 | static inline std::size_t strlen_arr(const char (&str)[N]) {
53 | for (std::size_t i = 0; i < N; ++i) {
54 | if (str[i] == '\0') {
55 | return i;
56 | }
57 | }
58 | return N;
59 | }
60 |
61 | // like std::sprintf but will not write beyond the bound of dest
62 | // dest is guaranteed to be null-terminated
63 | template
64 | static inline int sprintf_arr(char (&dest)[N], const char* format, ...) {
65 | std::va_list vargs;
66 | va_start(vargs, format);
67 | int retval = std::vsnprintf(dest, N, format, vargs);
68 | va_end(vargs);
69 | return retval;
70 | }
71 |
72 | // like std::strcat but will not write beyond the bound of dest
73 | // dest is guaranteed to be null-terminated
74 | template
75 | static inline char* strcat_arr(char (&dest)[N], const char* src) {
76 | return std::strncat(dest, src, sizeof_arr(dest) - strlen_arr(dest) - 1);
77 | }
78 |
79 | // like std::strcpy but won't write beyond the bound of dest
80 | // dest is guaranteed to be null-terminated
81 | template
82 | static inline char* strcpy_arr(char (&dest)[N], const char* src) {
83 | {
84 | std::size_t i = 0;
85 | for (; src[i] && i < N - 1; ++i) {
86 | dest[i] = src[i];
87 | }
88 | dest[i] = '\0';
89 | }
90 | return &dest[0];
91 | }
92 |
93 | } // namespace sample_util
94 | } // namespace mujoco
95 |
96 | #endif // MUJOCO_SAMPLE_ARRAY_SAFETY_H_
97 |
--------------------------------------------------------------------------------
/simulation/mujoco/include/glfw_adapter.h:
--------------------------------------------------------------------------------
1 | // Copyright 2023 DeepMind Technologies Limited
2 | //
3 | // Licensed under the Apache License, Version 2.0 (the "License");
4 | // you may not use this file except in compliance with the License.
5 | // You may obtain a copy of the License at
6 | //
7 | // http://www.apache.org/licenses/LICENSE-2.0
8 | //
9 | // Unless required by applicable law or agreed to in writing, software
10 | // distributed under the License is distributed on an "AS IS" BASIS,
11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | // See the License for the specific language governing permissions and
13 | // limitations under the License.
14 |
15 | #ifndef MUJOCO_SIMULATE_GLFW_ADAPTER_H_
16 | #define MUJOCO_SIMULATE_GLFW_ADAPTER_H_
17 |
18 | #include
19 |
20 | #include
21 | #include
22 | #include "platform_ui_adapter.h"
23 |
24 | namespace mujoco {
25 | class GlfwAdapter : public PlatformUIAdapter {
26 | public:
27 | GlfwAdapter();
28 | ~GlfwAdapter() override;
29 |
30 | std::pair GetCursorPosition() const override;
31 | double GetDisplayPixelsPerInch() const override;
32 | std::pair GetFramebufferSize() const override;
33 | std::pair GetWindowSize() const override;
34 | bool IsGPUAccelerated() const override;
35 | void PollEvents() override;
36 | void SetClipboardString(const char* text) override;
37 | void SetVSync(bool enabled) override;
38 | void SetWindowTitle(const char* title) override;
39 | bool ShouldCloseWindow() const override;
40 | void SwapBuffers() override;
41 | void ToggleFullscreen() override;
42 |
43 | bool IsLeftMouseButtonPressed() const override;
44 | bool IsMiddleMouseButtonPressed() const override;
45 | bool IsRightMouseButtonPressed() const override;
46 |
47 | bool IsAltKeyPressed() const override;
48 | bool IsCtrlKeyPressed() const override;
49 | bool IsShiftKeyPressed() const override;
50 |
51 | bool IsMouseButtonDownEvent(int act) const override;
52 | bool IsKeyDownEvent(int act) const override;
53 |
54 | int TranslateKeyCode(int key) const override;
55 | mjtButton TranslateMouseButton(int button) const override;
56 |
57 | private:
58 | GLFWvidmode vidmode_;
59 | GLFWwindow* window_;
60 |
61 | // store last window information when going to full screen
62 | std::pair window_pos_;
63 | std::pair window_size_;
64 | };
65 | } // namespace mujoco
66 |
67 | #endif // MUJOCO_SIMULATE_GLFW_ADAPTER_H_
68 |
--------------------------------------------------------------------------------
/simulation/mujoco/include/glfw_dispatch.h:
--------------------------------------------------------------------------------
1 | // Copyright 2022 DeepMind Technologies Limited
2 | //
3 | // Licensed under the Apache License, Version 2.0 (the "License");
4 | // you may not use this file except in compliance with the License.
5 | // You may obtain a copy of the License at
6 | //
7 | // http://www.apache.org/licenses/LICENSE-2.0
8 | //
9 | // Unless required by applicable law or agreed to in writing, software
10 | // distributed under the License is distributed on an "AS IS" BASIS,
11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | // See the License for the specific language governing permissions and
13 | // limitations under the License.
14 |
15 | #ifndef MUJOCO_SIMULATE_GLFW_DISPATCH_H_
16 | #define MUJOCO_SIMULATE_GLFW_DISPATCH_H_
17 |
18 | #include
19 |
20 | namespace mujoco {
21 | // Dynamic dispatch table for GLFW functions required by Simulate.
22 | // This allows us to use GLFW without introducing a link-time dependency on the
23 | // library, which is useful e.g. when using GLFW via Python.
24 | struct Glfw {
25 | #define mjGLFW_DECLARE_SYMBOL(func) decltype(&::func) func
26 | // go/keep-sorted start
27 | mjGLFW_DECLARE_SYMBOL(glfwCreateWindow);
28 | mjGLFW_DECLARE_SYMBOL(glfwDestroyWindow);
29 | mjGLFW_DECLARE_SYMBOL(glfwGetCursorPos);
30 | mjGLFW_DECLARE_SYMBOL(glfwGetFramebufferSize);
31 | mjGLFW_DECLARE_SYMBOL(glfwGetKey);
32 | mjGLFW_DECLARE_SYMBOL(glfwGetMonitorPhysicalSize);
33 | mjGLFW_DECLARE_SYMBOL(glfwGetMouseButton);
34 | mjGLFW_DECLARE_SYMBOL(glfwGetPrimaryMonitor);
35 | mjGLFW_DECLARE_SYMBOL(glfwGetTime);
36 | mjGLFW_DECLARE_SYMBOL(glfwGetVideoMode);
37 | mjGLFW_DECLARE_SYMBOL(glfwGetWindowMonitor);
38 | mjGLFW_DECLARE_SYMBOL(glfwGetWindowPos);
39 | mjGLFW_DECLARE_SYMBOL(glfwGetWindowSize);
40 | mjGLFW_DECLARE_SYMBOL(glfwGetWindowUserPointer);
41 | mjGLFW_DECLARE_SYMBOL(glfwInit);
42 | mjGLFW_DECLARE_SYMBOL(glfwMakeContextCurrent);
43 | mjGLFW_DECLARE_SYMBOL(glfwPollEvents);
44 | mjGLFW_DECLARE_SYMBOL(glfwSetClipboardString);
45 | mjGLFW_DECLARE_SYMBOL(glfwSetCursorPosCallback);
46 | mjGLFW_DECLARE_SYMBOL(glfwSetDropCallback);
47 | mjGLFW_DECLARE_SYMBOL(glfwSetKeyCallback);
48 | mjGLFW_DECLARE_SYMBOL(glfwSetMouseButtonCallback);
49 | mjGLFW_DECLARE_SYMBOL(glfwSetScrollCallback);
50 | mjGLFW_DECLARE_SYMBOL(glfwSetWindowMonitor);
51 | mjGLFW_DECLARE_SYMBOL(glfwSetWindowRefreshCallback);
52 | mjGLFW_DECLARE_SYMBOL(glfwSetWindowSizeCallback);
53 | mjGLFW_DECLARE_SYMBOL(glfwSetWindowTitle);
54 | mjGLFW_DECLARE_SYMBOL(glfwSetWindowUserPointer);
55 | mjGLFW_DECLARE_SYMBOL(glfwSwapBuffers);
56 | mjGLFW_DECLARE_SYMBOL(glfwSwapInterval);
57 | mjGLFW_DECLARE_SYMBOL(glfwTerminate);
58 | mjGLFW_DECLARE_SYMBOL(glfwWindowHint);
59 | mjGLFW_DECLARE_SYMBOL(glfwWindowShouldClose);
60 | // go/keep-sorted end
61 | #undef mjGLFW_DECLARE_SYMBOL
62 | };
63 |
64 | const struct Glfw& Glfw(void* dlhandle = nullptr);
65 | } // namespace mujoco
66 |
67 | #endif // MUJOCO_SIMULATE_GLFW_DISPATCH_H_
68 |
--------------------------------------------------------------------------------
/simulation/mujoco/include/mujoco/mjexport.h:
--------------------------------------------------------------------------------
1 | // Copyright 2021 DeepMind Technologies Limited
2 | //
3 | // Licensed under the Apache License, Version 2.0 (the "License");
4 | // you may not use this file except in compliance with the License.
5 | // You may obtain a copy of the License at
6 | //
7 | // http://www.apache.org/licenses/LICENSE-2.0
8 | //
9 | // Unless required by applicable law or agreed to in writing, software
10 | // distributed under the License is distributed on an "AS IS" BASIS,
11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | // See the License for the specific language governing permissions and
13 | // limitations under the License.
14 |
15 | #ifndef MUJOCO_MJEXPORT_H_
16 | #define MUJOCO_MJEXPORT_H_
17 |
18 | #if defined _WIN32 || defined __CYGWIN__
19 | #define MUJOCO_HELPER_DLL_IMPORT __declspec(dllimport)
20 | #define MUJOCO_HELPER_DLL_EXPORT __declspec(dllexport)
21 | #define MUJOCO_HELPER_DLL_LOCAL
22 | #else
23 | #if __GNUC__ >= 4
24 | #define MUJOCO_HELPER_DLL_IMPORT __attribute__ ((visibility ("default")))
25 | #define MUJOCO_HELPER_DLL_EXPORT __attribute__ ((visibility ("default")))
26 | #define MUJOCO_HELPER_DLL_LOCAL __attribute__ ((visibility ("hidden")))
27 | #else
28 | #define MUJOCO_HELPER_DLL_IMPORT
29 | #define MUJOCO_HELPER_DLL_EXPORT
30 | #define MUJOCO_HELPER_DLL_LOCAL
31 | #endif
32 | #endif
33 |
34 | #ifdef MJ_STATIC
35 | // static library
36 | #define MJAPI
37 | #define MJLOCAL
38 | #else
39 | #ifdef MUJOCO_DLL_EXPORTS
40 | #define MJAPI MUJOCO_HELPER_DLL_EXPORT
41 | #else
42 | #define MJAPI MUJOCO_HELPER_DLL_IMPORT
43 | #endif
44 | #define MJLOCAL MUJOCO_HELPER_DLL_LOCAL
45 | #endif
46 |
47 | #endif // MUJOCO_MJEXPORT_H_
48 |
--------------------------------------------------------------------------------
/simulation/mujoco/include/mujoco/mjplugin.h:
--------------------------------------------------------------------------------
1 | // Copyright 2022 DeepMind Technologies Limited
2 | //
3 | // Licensed under the Apache License, Version 2.0 (the "License");
4 | // you may not use this file except in compliance with the License.
5 | // You may obtain a copy of the License at
6 | //
7 | // http://www.apache.org/licenses/LICENSE-2.0
8 | //
9 | // Unless required by applicable law or agreed to in writing, software
10 | // distributed under the License is distributed on an "AS IS" BASIS,
11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | // See the License for the specific language governing permissions and
13 | // limitations under the License.
14 |
15 | #ifndef MUJOCO_INCLUDE_MJPLUGIN_H_
16 | #define MUJOCO_INCLUDE_MJPLUGIN_H_
17 |
18 | #include
19 | #include
20 | #include
21 |
22 |
23 | typedef enum mjtPluginCapabilityBit_ {
24 | mjPLUGIN_ACTUATOR = 1<<0,
25 | mjPLUGIN_SENSOR = 1<<1,
26 | mjPLUGIN_PASSIVE = 1<<2,
27 | } mjtPluginCapabilityBit;
28 |
29 | struct mjpPlugin_ {
30 | const char* name; // globally unique name identifying the plugin
31 |
32 | int nattribute; // number of configuration attributes
33 | const char* const* attributes; // name of configuration attributes
34 |
35 | int capabilityflags; // bitfield of mjtPluginCapabilityBit specifying plugin capabilities
36 | int needstage; // an mjtStage enum value specifying the sensor computation stage
37 |
38 | // number of mjtNums needed to store the state of a plugin instance (required)
39 | int (*nstate)(const mjModel* m, int instance);
40 |
41 | // dimension of the specified sensor's output (required only for sensor plugins)
42 | int (*nsensordata)(const mjModel* m, int instance, int sensor_id);
43 |
44 | // called when a new mjData is being created (required), returns 0 on success or -1 on failure
45 | int (*init)(const mjModel* m, mjData* d, int instance);
46 |
47 | // called when an mjData is being freed (optional)
48 | void (*destroy)(mjData* d, int instance);
49 |
50 | // called when an mjData is being copied (optional)
51 | void (*copy)(mjData* dest, const mjModel* m, const mjData* src, int instance);
52 |
53 | // called when an mjData is being reset (required)
54 | void (*reset)(const mjModel* m, double* plugin_state, void* plugin_data, int instance);
55 |
56 | // called when the plugin needs to update its outputs (required)
57 | void (*compute)(const mjModel* m, mjData* d, int instance, int capability_bit);
58 |
59 | // called when time integration occurs (optional)
60 | void (*advance)(const mjModel* m, mjData* d, int instance);
61 |
62 | // called by mjv_updateScene (optional)
63 | void (*visualize)(const mjModel*m, mjData* d, mjvScene* scn, int instance);
64 | };
65 | typedef struct mjpPlugin_ mjpPlugin;
66 |
67 | #if defined(__has_attribute)
68 |
69 | #if __has_attribute(constructor)
70 | #define mjPLUGIN_DYNAMIC_LIBRARY_INIT \
71 | __attribute__((constructor)) static void _mjplugin_init(void)
72 | #endif
73 |
74 | #elif defined(_MSC_VER)
75 |
76 | #ifndef mjDLLMAIN
77 | #define mjDLLMAIN DllMain
78 | #endif
79 |
80 | #if !defined(mjEXTERNC)
81 | #if defined(__cplusplus)
82 | #define mjEXTERNC extern "C"
83 | #else
84 | #define mjEXTERNC
85 | #endif // defined(__cplusplus)
86 | #endif // !defined(mjEXTERNC)
87 |
88 | // NOLINTBEGIN(runtime/int)
89 | #define mjPLUGIN_DYNAMIC_LIBRARY_INIT \
90 | static void _mjplugin_dllmain(void); \
91 | mjEXTERNC int __stdcall mjDLLMAIN(void* hinst, unsigned long reason, void* reserved) { \
92 | if (reason == 1) { \
93 | _mjplugin_dllmain(); \
94 | } \
95 | return 1; \
96 | } \
97 | static void _mjplugin_dllmain(void)
98 | // NOLINTEND(runtime/int)
99 |
100 | #endif // defined(_MSC_VER)
101 |
102 | // function pointer type for mj_loadAllPluginLibraries callback
103 | typedef void (*mjfPluginLibraryLoadCallback)(const char* filename, int first, int count);
104 |
105 | #endif // MUJOCO_INCLUDE_MJPLUGIN_H_
106 |
--------------------------------------------------------------------------------
/simulation/mujoco/include/mujoco/mjrender.h:
--------------------------------------------------------------------------------
1 | // Copyright 2021 DeepMind Technologies Limited
2 | //
3 | // Licensed under the Apache License, Version 2.0 (the "License");
4 | // you may not use this file except in compliance with the License.
5 | // You may obtain a copy of the License at
6 | //
7 | // http://www.apache.org/licenses/LICENSE-2.0
8 | //
9 | // Unless required by applicable law or agreed to in writing, software
10 | // distributed under the License is distributed on an "AS IS" BASIS,
11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | // See the License for the specific language governing permissions and
13 | // limitations under the License.
14 |
15 | #ifndef MUJOCO_MJRENDER_H_
16 | #define MUJOCO_MJRENDER_H_
17 |
18 | #include
19 |
20 | #if defined(__cplusplus)
21 | extern "C" {
22 | #endif
23 |
24 | #define mjNAUX 10 // number of auxiliary buffers
25 | #define mjMAXTEXTURE 1000 // maximum number of textures
26 |
27 |
28 | //---------------------------------- primitive types (mjt) -----------------------------------------
29 |
30 | typedef enum mjtGridPos_ { // grid position for overlay
31 | mjGRID_TOPLEFT = 0, // top left
32 | mjGRID_TOPRIGHT, // top right
33 | mjGRID_BOTTOMLEFT, // bottom left
34 | mjGRID_BOTTOMRIGHT // bottom right
35 | } mjtGridPos;
36 |
37 |
38 | typedef enum mjtFramebuffer_ { // OpenGL framebuffer option
39 | mjFB_WINDOW = 0, // default/window buffer
40 | mjFB_OFFSCREEN // offscreen buffer
41 | } mjtFramebuffer;
42 |
43 |
44 | typedef enum mjtFontScale_ { // font scale, used at context creation
45 | mjFONTSCALE_50 = 50, // 50% scale, suitable for low-res rendering
46 | mjFONTSCALE_100 = 100, // normal scale, suitable in the absence of DPI scaling
47 | mjFONTSCALE_150 = 150, // 150% scale
48 | mjFONTSCALE_200 = 200, // 200% scale
49 | mjFONTSCALE_250 = 250, // 250% scale
50 | mjFONTSCALE_300 = 300 // 300% scale
51 | } mjtFontScale;
52 |
53 |
54 | typedef enum mjtFont_ { // font type, used at each text operation
55 | mjFONT_NORMAL = 0, // normal font
56 | mjFONT_SHADOW, // normal font with shadow (for higher contrast)
57 | mjFONT_BIG // big font (for user alerts)
58 | } mjtFont;
59 |
60 |
61 | struct mjrRect_ { // OpenGL rectangle
62 | int left; // left (usually 0)
63 | int bottom; // bottom (usually 0)
64 | int width; // width (usually buffer width)
65 | int height; // height (usually buffer height)
66 | };
67 | typedef struct mjrRect_ mjrRect;
68 |
69 |
70 | //---------------------------------- mjrContext ----------------------------------------------------
71 |
72 | struct mjrContext_ { // custom OpenGL context
73 | // parameters copied from mjVisual
74 | float lineWidth; // line width for wireframe rendering
75 | float shadowClip; // clipping radius for directional lights
76 | float shadowScale; // fraction of light cutoff for spot lights
77 | float fogStart; // fog start = stat.extent * vis.map.fogstart
78 | float fogEnd; // fog end = stat.extent * vis.map.fogend
79 | float fogRGBA[4]; // fog rgba
80 | int shadowSize; // size of shadow map texture
81 | int offWidth; // width of offscreen buffer
82 | int offHeight; // height of offscreen buffer
83 | int offSamples; // number of offscreen buffer multisamples
84 |
85 | // parameters specified at creation
86 | int fontScale; // font scale
87 | int auxWidth[mjNAUX]; // auxiliary buffer width
88 | int auxHeight[mjNAUX]; // auxiliary buffer height
89 | int auxSamples[mjNAUX]; // auxiliary buffer multisamples
90 |
91 | // offscreen rendering objects
92 | unsigned int offFBO; // offscreen framebuffer object
93 | unsigned int offFBO_r; // offscreen framebuffer for resolving multisamples
94 | unsigned int offColor; // offscreen color buffer
95 | unsigned int offColor_r; // offscreen color buffer for resolving multisamples
96 | unsigned int offDepthStencil; // offscreen depth and stencil buffer
97 | unsigned int offDepthStencil_r; // offscreen depth and stencil buffer for resolving multisamples
98 |
99 | // shadow rendering objects
100 | unsigned int shadowFBO; // shadow map framebuffer object
101 | unsigned int shadowTex; // shadow map texture
102 |
103 | // auxiliary buffers
104 | unsigned int auxFBO[mjNAUX]; // auxiliary framebuffer object
105 | unsigned int auxFBO_r[mjNAUX]; // auxiliary framebuffer object for resolving
106 | unsigned int auxColor[mjNAUX]; // auxiliary color buffer
107 | unsigned int auxColor_r[mjNAUX];// auxiliary color buffer for resolving
108 |
109 | // texture objects and info
110 | int ntexture; // number of allocated textures
111 | int textureType[100]; // type of texture (mjtTexture) (ntexture)
112 | unsigned int texture[100]; // texture names
113 |
114 | // displaylist starting positions
115 | unsigned int basePlane; // all planes from model
116 | unsigned int baseMesh; // all meshes from model
117 | unsigned int baseHField; // all hfields from model
118 | unsigned int baseBuiltin; // all buildin geoms, with quality from model
119 | unsigned int baseFontNormal; // normal font
120 | unsigned int baseFontShadow; // shadow font
121 | unsigned int baseFontBig; // big font
122 |
123 | // displaylist ranges
124 | int rangePlane; // all planes from model
125 | int rangeMesh; // all meshes from model
126 | int rangeHField; // all hfields from model
127 | int rangeBuiltin; // all builtin geoms, with quality from model
128 | int rangeFont; // all characters in font
129 |
130 | // skin VBOs
131 | int nskin; // number of skins
132 | unsigned int* skinvertVBO; // skin vertex position VBOs (nskin)
133 | unsigned int* skinnormalVBO; // skin vertex normal VBOs (nskin)
134 | unsigned int* skintexcoordVBO; // skin vertex texture coordinate VBOs (nskin)
135 | unsigned int* skinfaceVBO; // skin face index VBOs (nskin)
136 |
137 | // character info
138 | int charWidth[127]; // character widths: normal and shadow
139 | int charWidthBig[127]; // chacarter widths: big
140 | int charHeight; // character heights: normal and shadow
141 | int charHeightBig; // character heights: big
142 |
143 | // capabilities
144 | int glInitialized; // is OpenGL initialized
145 | int windowAvailable; // is default/window framebuffer available
146 | int windowSamples; // number of samples for default/window framebuffer
147 | int windowStereo; // is stereo available for default/window framebuffer
148 | int windowDoublebuffer; // is default/window framebuffer double buffered
149 |
150 | // framebuffer
151 | int currentBuffer; // currently active framebuffer: mjFB_WINDOW or mjFB_OFFSCREEN
152 |
153 | // pixel output format
154 | int readPixelFormat; // default color pixel format for mjr_readPixels
155 | };
156 | typedef struct mjrContext_ mjrContext;
157 |
158 | #if defined(__cplusplus)
159 | }
160 | #endif
161 | #endif // MUJOCO_MJRENDER_H_
162 |
--------------------------------------------------------------------------------
/simulation/mujoco/include/mujoco/mjtnum.h:
--------------------------------------------------------------------------------
1 | // Copyright 2021 DeepMind Technologies Limited
2 | //
3 | // Licensed under the Apache License, Version 2.0 (the "License");
4 | // you may not use this file except in compliance with the License.
5 | // You may obtain a copy of the License at
6 | //
7 | // http://www.apache.org/licenses/LICENSE-2.0
8 | //
9 | // Unless required by applicable law or agreed to in writing, software
10 | // distributed under the License is distributed on an "AS IS" BASIS,
11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | // See the License for the specific language governing permissions and
13 | // limitations under the License.
14 |
15 | #ifndef MUJOCO_INCLUDE_MJTNUM_H_
16 | #define MUJOCO_INCLUDE_MJTNUM_H_
17 |
18 | //---------------------------------- floating-point definitions ------------------------------------
19 |
20 | // compile-time configuration options
21 | #define mjUSEDOUBLE // single or double precision for mjtNum
22 |
23 |
24 | // floating point data type and minval
25 | #ifdef mjUSEDOUBLE
26 | typedef double mjtNum;
27 | #define mjMINVAL 1E-15 // minimum value in any denominator
28 | #else
29 | typedef float mjtNum;
30 | #define mjMINVAL 1E-15f
31 | #endif
32 |
33 |
34 | #endif // MUJOCO_INCLUDE_MJTNUM_H_
35 |
--------------------------------------------------------------------------------
/simulation/mujoco/include/mujoco/mjui.h:
--------------------------------------------------------------------------------
1 | // Copyright 2021 DeepMind Technologies Limited
2 | //
3 | // Licensed under the Apache License, Version 2.0 (the "License");
4 | // you may not use this file except in compliance with the License.
5 | // You may obtain a copy of the License at
6 | //
7 | // http://www.apache.org/licenses/LICENSE-2.0
8 | //
9 | // Unless required by applicable law or agreed to in writing, software
10 | // distributed under the License is distributed on an "AS IS" BASIS,
11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | // See the License for the specific language governing permissions and
13 | // limitations under the License.
14 |
15 | #ifndef MUJOCO_MJUI_H_
16 | #define MUJOCO_MJUI_H_
17 |
18 | #include
19 |
20 | #define mjMAXUISECT 10 // maximum number of sections
21 | #define mjMAXUIITEM 80 // maximum number of items per section
22 | #define mjMAXUITEXT 300 // maximum number of chars in edittext and other
23 | #define mjMAXUINAME 40 // maximum number of chars in name
24 | #define mjMAXUIMULTI 35 // maximum number of radio/select items in group
25 | #define mjMAXUIEDIT 7 // maximum number of elements in edit list
26 | #define mjMAXUIRECT 25 // maximum number of rectangles
27 |
28 | #define mjSEPCLOSED 1000 // closed state of adjustable separator
29 |
30 |
31 | // key codes matching GLFW (user must remap for other frameworks)
32 | #define mjKEY_ESCAPE 256
33 | #define mjKEY_ENTER 257
34 | #define mjKEY_TAB 258
35 | #define mjKEY_BACKSPACE 259
36 | #define mjKEY_INSERT 260
37 | #define mjKEY_DELETE 261
38 | #define mjKEY_RIGHT 262
39 | #define mjKEY_LEFT 263
40 | #define mjKEY_DOWN 264
41 | #define mjKEY_UP 265
42 | #define mjKEY_PAGE_UP 266
43 | #define mjKEY_PAGE_DOWN 267
44 | #define mjKEY_HOME 268
45 | #define mjKEY_END 269
46 | #define mjKEY_F1 290
47 | #define mjKEY_F2 291
48 | #define mjKEY_F3 292
49 | #define mjKEY_F4 293
50 | #define mjKEY_F5 294
51 | #define mjKEY_F6 295
52 | #define mjKEY_F7 296
53 | #define mjKEY_F8 297
54 | #define mjKEY_F9 298
55 | #define mjKEY_F10 299
56 | #define mjKEY_F11 300
57 | #define mjKEY_F12 301
58 |
59 |
60 | //---------------------------------- primitive types (mjt) -----------------------------------------
61 |
62 | typedef enum mjtButton_ { // mouse button
63 | mjBUTTON_NONE = 0, // no button
64 | mjBUTTON_LEFT, // left button
65 | mjBUTTON_RIGHT, // right button
66 | mjBUTTON_MIDDLE // middle button
67 | } mjtButton;
68 |
69 |
70 | typedef enum mjtEvent_ { // mouse and keyboard event type
71 | mjEVENT_NONE = 0, // no event
72 | mjEVENT_MOVE, // mouse move
73 | mjEVENT_PRESS, // mouse button press
74 | mjEVENT_RELEASE, // mouse button release
75 | mjEVENT_SCROLL, // scroll
76 | mjEVENT_KEY, // key press
77 | mjEVENT_RESIZE, // resize
78 | mjEVENT_REDRAW, // redraw
79 | mjEVENT_FILESDROP // files drop
80 | } mjtEvent;
81 |
82 |
83 | typedef enum mjtItem_ { // UI item type
84 | mjITEM_END = -2, // end of definition list (not an item)
85 | mjITEM_SECTION = -1, // section (not an item)
86 | mjITEM_SEPARATOR = 0, // separator
87 | mjITEM_STATIC, // static text
88 | mjITEM_BUTTON, // button
89 |
90 | // the rest have data pointer
91 | mjITEM_CHECKINT, // check box, int value
92 | mjITEM_CHECKBYTE, // check box, mjtByte value
93 | mjITEM_RADIO, // radio group
94 | mjITEM_RADIOLINE, // radio group, single line
95 | mjITEM_SELECT, // selection box
96 | mjITEM_SLIDERINT, // slider, int value
97 | mjITEM_SLIDERNUM, // slider, mjtNum value
98 | mjITEM_EDITINT, // editable array, int values
99 | mjITEM_EDITNUM, // editable array, mjtNum values
100 | mjITEM_EDITTXT, // editable text
101 |
102 | mjNITEM // number of item types
103 | } mjtItem;
104 |
105 |
106 | // predicate function: set enable/disable based on item category
107 | typedef int (*mjfItemEnable)(int category, void* data);
108 |
109 |
110 | //---------------------------------- mjuiState -----------------------------------------------------
111 |
112 | struct mjuiState_ { // mouse and keyboard state
113 | // constants set by user
114 | int nrect; // number of rectangles used
115 | mjrRect rect[mjMAXUIRECT]; // rectangles (index 0: entire window)
116 | void* userdata; // pointer to user data (for callbacks)
117 |
118 | // event type
119 | int type; // (type mjtEvent)
120 |
121 | // mouse buttons
122 | int left; // is left button down
123 | int right; // is right button down
124 | int middle; // is middle button down
125 | int doubleclick; // is last press a double click
126 | int button; // which button was pressed (mjtButton)
127 | double buttontime; // time of last button press
128 |
129 | // mouse position
130 | double x; // x position
131 | double y; // y position
132 | double dx; // x displacement
133 | double dy; // y displacement
134 | double sx; // x scroll
135 | double sy; // y scroll
136 |
137 | // keyboard
138 | int control; // is control down
139 | int shift; // is shift down
140 | int alt; // is alt down
141 | int key; // which key was pressed
142 | double keytime; // time of last key press
143 |
144 | // rectangle ownership and dragging
145 | int mouserect; // which rectangle contains mouse
146 | int dragrect; // which rectangle is dragged with mouse
147 | int dragbutton; // which button started drag (mjtButton)
148 |
149 | // files dropping (only valid when type == mjEVENT_FILESDROP)
150 | int dropcount; // number of files dropped
151 | const char** droppaths; // paths to files dropped
152 | };
153 | typedef struct mjuiState_ mjuiState;
154 |
155 |
156 | //---------------------------------- mjuiThemeSpacing ----------------------------------------------
157 |
158 | struct mjuiThemeSpacing_ { // UI visualization theme spacing
159 | int total; // total width
160 | int scroll; // scrollbar width
161 | int label; // label width
162 | int section; // section gap
163 | int itemside; // item side gap
164 | int itemmid; // item middle gap
165 | int itemver; // item vertical gap
166 | int texthor; // text horizontal gap
167 | int textver; // text vertical gap
168 | int linescroll; // number of pixels to scroll
169 | int samples; // number of multisamples
170 | };
171 | typedef struct mjuiThemeSpacing_ mjuiThemeSpacing;
172 |
173 |
174 | //---------------------------------- mjuiThemeColor ------------------------------------------------
175 |
176 | struct mjuiThemeColor_ { // UI visualization theme color
177 | float master[3]; // master background
178 | float thumb[3]; // scrollbar thumb
179 | float secttitle[3]; // section title
180 | float sectfont[3]; // section font
181 | float sectsymbol[3]; // section symbol
182 | float sectpane[3]; // section pane
183 | float shortcut[3]; // shortcut background
184 | float fontactive[3]; // font active
185 | float fontinactive[3]; // font inactive
186 | float decorinactive[3]; // decor inactive
187 | float decorinactive2[3]; // inactive slider color 2
188 | float button[3]; // button
189 | float check[3]; // check
190 | float radio[3]; // radio
191 | float select[3]; // select
192 | float select2[3]; // select pane
193 | float slider[3]; // slider
194 | float slider2[3]; // slider color 2
195 | float edit[3]; // edit
196 | float edit2[3]; // edit invalid
197 | float cursor[3]; // edit cursor
198 | };
199 | typedef struct mjuiThemeColor_ mjuiThemeColor;
200 |
201 |
202 | //---------------------------------- mjuiItem ------------------------------------------------------
203 |
204 | struct mjuiItemSingle_ { // check and button-related
205 | int modifier; // 0: none, 1: control, 2: shift; 4: alt
206 | int shortcut; // shortcut key; 0: undefined
207 | };
208 |
209 |
210 | struct mjuiItemMulti_ { // static, radio and select-related
211 | int nelem; // number of elements in group
212 | char name[mjMAXUIMULTI][mjMAXUINAME]; // element names
213 | };
214 |
215 |
216 | struct mjuiItemSlider_ { // slider-related
217 | double range[2]; // slider range
218 | double divisions; // number of range divisions
219 | };
220 |
221 |
222 | struct mjuiItemEdit_ { // edit-related
223 | int nelem; // number of elements in list
224 | double range[mjMAXUIEDIT][2]; // element range (min>=max: ignore)
225 | };
226 |
227 |
228 | struct mjuiItem_ { // UI item
229 | // common properties
230 | int type; // type (mjtItem)
231 | char name[mjMAXUINAME]; // name
232 | int state; // 0: disable, 1: enable, 2+: use predicate
233 | void *pdata; // data pointer (type-specific)
234 | int sectionid; // id of section containing item
235 | int itemid; // id of item within section
236 |
237 | // type-specific properties
238 | union {
239 | struct mjuiItemSingle_ single; // check and button
240 | struct mjuiItemMulti_ multi; // static, radio and select
241 | struct mjuiItemSlider_ slider; // slider
242 | struct mjuiItemEdit_ edit; // edit
243 | };
244 |
245 | // internal
246 | mjrRect rect; // rectangle occupied by item
247 | };
248 | typedef struct mjuiItem_ mjuiItem;
249 |
250 |
251 | //---------------------------------- mjuiSection ---------------------------------------------------
252 |
253 | struct mjuiSection_ { // UI section
254 | // properties
255 | char name[mjMAXUINAME]; // name
256 | int state; // 0: closed, 1: open
257 | int modifier; // 0: none, 1: control, 2: shift; 4: alt
258 | int shortcut; // shortcut key; 0: undefined
259 | int nitem; // number of items in use
260 | mjuiItem item[mjMAXUIITEM]; // preallocated array of items
261 |
262 | // internal
263 | mjrRect rtitle; // rectangle occupied by title
264 | mjrRect rcontent; // rectangle occupied by content
265 | };
266 | typedef struct mjuiSection_ mjuiSection;
267 |
268 |
269 | //---------------------------------- mjUI ----------------------------------------------------------
270 |
271 | struct mjUI_ { // entire UI
272 | // constants set by user
273 | mjuiThemeSpacing spacing; // UI theme spacing
274 | mjuiThemeColor color; // UI theme color
275 | mjfItemEnable predicate; // callback to set item state programmatically
276 | void* userdata; // pointer to user data (passed to predicate)
277 | int rectid; // index of this ui rectangle in mjuiState
278 | int auxid; // aux buffer index of this ui
279 | int radiocol; // number of radio columns (0 defaults to 2)
280 |
281 | // UI sizes (framebuffer units)
282 | int width; // width
283 | int height; // current heigth
284 | int maxheight; // height when all sections open
285 | int scroll; // scroll from top of UI
286 |
287 | // mouse focus
288 | int mousesect; // 0: none, -1: scroll, otherwise 1+section
289 | int mouseitem; // item within section
290 | int mousehelp; // help button down: print shortcuts
291 |
292 | // keyboard focus and edit
293 | int editsect; // 0: none, otherwise 1+section
294 | int edititem; // item within section
295 | int editcursor; // cursor position
296 | int editscroll; // horizontal scroll
297 | char edittext[mjMAXUITEXT]; // current text
298 | mjuiItem* editchanged; // pointer to changed edit in last mjui_event
299 |
300 | // sections
301 | int nsect; // number of sections in use
302 | mjuiSection sect[mjMAXUISECT]; // preallocated array of sections
303 | };
304 | typedef struct mjUI_ mjUI;
305 |
306 |
307 | //---------------------------------- mjuiDef -------------------------------------------------------
308 |
309 | struct mjuiDef_ { // table passed to mjui_add()
310 | int type; // type (mjtItem); -1: section
311 | char name[mjMAXUINAME]; // name
312 | int state; // state
313 | void* pdata; // pointer to data
314 | char other[mjMAXUITEXT]; // string with type-specific properties
315 | };
316 | typedef struct mjuiDef_ mjuiDef;
317 |
318 | #endif // MUJOCO_MJUI_H_
319 |
--------------------------------------------------------------------------------
/simulation/mujoco/include/mujoco/mjvisualize.h:
--------------------------------------------------------------------------------
1 | // Copyright 2021 DeepMind Technologies Limited
2 | //
3 | // Licensed under the Apache License, Version 2.0 (the "License");
4 | // you may not use this file except in compliance with the License.
5 | // You may obtain a copy of the License at
6 | //
7 | // http://www.apache.org/licenses/LICENSE-2.0
8 | //
9 | // Unless required by applicable law or agreed to in writing, software
10 | // distributed under the License is distributed on an "AS IS" BASIS,
11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | // See the License for the specific language governing permissions and
13 | // limitations under the License.
14 |
15 | #ifndef MUJOCO_MJVISUALIZE_H_
16 | #define MUJOCO_MJVISUALIZE_H_
17 |
18 | #include
19 | #include
20 |
21 | #define mjNGROUP 6 // number of geom, site, joint, skin groups with visflags
22 | #define mjMAXLIGHT 100 // maximum number of lights in a scene
23 | #define mjMAXOVERLAY 500 // maximum number of characters in overlay text
24 | #define mjMAXLINE 100 // maximum number of lines per plot
25 | #define mjMAXLINEPNT 1000 // maximum number points per line
26 | #define mjMAXPLANEGRID 200 // maximum number of grid divisions for plane
27 |
28 |
29 | //---------------------------------- primitive types (mjt) -----------------------------------------
30 |
31 | typedef enum mjtCatBit_ { // bitflags for mjvGeom category
32 | mjCAT_STATIC = 1, // model elements in body 0
33 | mjCAT_DYNAMIC = 2, // model elements in all other bodies
34 | mjCAT_DECOR = 4, // decorative geoms
35 | mjCAT_ALL = 7 // select all categories
36 | } mjtCatBit;
37 |
38 |
39 | typedef enum mjtMouse_ { // mouse interaction mode
40 | mjMOUSE_NONE = 0, // no action
41 | mjMOUSE_ROTATE_V, // rotate, vertical plane
42 | mjMOUSE_ROTATE_H, // rotate, horizontal plane
43 | mjMOUSE_MOVE_V, // move, vertical plane
44 | mjMOUSE_MOVE_H, // move, horizontal plane
45 | mjMOUSE_ZOOM, // zoom
46 | mjMOUSE_SELECT // selection
47 | } mjtMouse;
48 |
49 |
50 | typedef enum mjtPertBit_ { // mouse perturbations
51 | mjPERT_TRANSLATE = 1, // translation
52 | mjPERT_ROTATE = 2 // rotation
53 | } mjtPertBit;
54 |
55 |
56 | typedef enum mjtCamera_ { // abstract camera type
57 | mjCAMERA_FREE = 0, // free camera
58 | mjCAMERA_TRACKING, // tracking camera; uses trackbodyid
59 | mjCAMERA_FIXED, // fixed camera; uses fixedcamid
60 | mjCAMERA_USER // user is responsible for setting OpenGL camera
61 | } mjtCamera;
62 |
63 |
64 | typedef enum mjtLabel_ { // object labeling
65 | mjLABEL_NONE = 0, // nothing
66 | mjLABEL_BODY, // body labels
67 | mjLABEL_JOINT, // joint labels
68 | mjLABEL_GEOM, // geom labels
69 | mjLABEL_SITE, // site labels
70 | mjLABEL_CAMERA, // camera labels
71 | mjLABEL_LIGHT, // light labels
72 | mjLABEL_TENDON, // tendon labels
73 | mjLABEL_ACTUATOR, // actuator labels
74 | mjLABEL_CONSTRAINT, // constraint labels
75 | mjLABEL_SKIN, // skin labels
76 | mjLABEL_SELECTION, // selected object
77 | mjLABEL_SELPNT, // coordinates of selection point
78 | mjLABEL_CONTACTFORCE, // magnitude of contact force
79 |
80 | mjNLABEL // number of label types
81 | } mjtLabel;
82 |
83 |
84 | typedef enum mjtFrame_ { // frame visualization
85 | mjFRAME_NONE = 0, // no frames
86 | mjFRAME_BODY, // body frames
87 | mjFRAME_GEOM, // geom frames
88 | mjFRAME_SITE, // site frames
89 | mjFRAME_CAMERA, // camera frames
90 | mjFRAME_LIGHT, // light frames
91 | mjFRAME_CONTACT, // contact frames
92 | mjFRAME_WORLD, // world frame
93 |
94 | mjNFRAME // number of visualization frames
95 | } mjtFrame;
96 |
97 |
98 | typedef enum mjtVisFlag_ { // flags enabling model element visualization
99 | mjVIS_CONVEXHULL = 0, // mesh convex hull
100 | mjVIS_TEXTURE, // textures
101 | mjVIS_JOINT, // joints
102 | mjVIS_CAMERA, // cameras
103 | mjVIS_ACTUATOR, // actuators
104 | mjVIS_ACTIVATION, // activations
105 | mjVIS_LIGHT, // lights
106 | mjVIS_TENDON, // tendons
107 | mjVIS_RANGEFINDER, // rangefinder sensors
108 | mjVIS_CONSTRAINT, // point constraints
109 | mjVIS_INERTIA, // equivalent inertia boxes
110 | mjVIS_SCLINERTIA, // scale equivalent inertia boxes with mass
111 | mjVIS_PERTFORCE, // perturbation force
112 | mjVIS_PERTOBJ, // perturbation object
113 | mjVIS_CONTACTPOINT, // contact points
114 | mjVIS_CONTACTFORCE, // contact force
115 | mjVIS_CONTACTSPLIT, // split contact force into normal and tanget
116 | mjVIS_TRANSPARENT, // make dynamic geoms more transparent
117 | mjVIS_AUTOCONNECT, // auto connect joints and body coms
118 | mjVIS_COM, // center of mass
119 | mjVIS_SELECT, // selection point
120 | mjVIS_STATIC, // static bodies
121 | mjVIS_SKIN, // skin
122 |
123 | mjNVISFLAG // number of visualization flags
124 | } mjtVisFlag;
125 |
126 |
127 | typedef enum mjtRndFlag_ { // flags enabling rendering effects
128 | mjRND_SHADOW = 0, // shadows
129 | mjRND_WIREFRAME, // wireframe
130 | mjRND_REFLECTION, // reflections
131 | mjRND_ADDITIVE, // additive transparency
132 | mjRND_SKYBOX, // skybox
133 | mjRND_FOG, // fog
134 | mjRND_HAZE, // haze
135 | mjRND_SEGMENT, // segmentation with random color
136 | mjRND_IDCOLOR, // segmentation with segid+1 color
137 | mjRND_CULL_FACE, // cull backward faces
138 |
139 | mjNRNDFLAG // number of rendering flags
140 | } mjtRndFlag;
141 |
142 |
143 | typedef enum mjtStereo_ { // type of stereo rendering
144 | mjSTEREO_NONE = 0, // no stereo; use left eye only
145 | mjSTEREO_QUADBUFFERED, // quad buffered; revert to side-by-side if no hardware support
146 | mjSTEREO_SIDEBYSIDE // side-by-side
147 | } mjtStereo;
148 |
149 |
150 | //---------------------------------- mjvPerturb ----------------------------------------------------
151 |
152 | struct mjvPerturb_ { // object selection and perturbation
153 | int select; // selected body id; non-positive: none
154 | int skinselect; // selected skin id; negative: none
155 | int active; // perturbation bitmask (mjtPertBit)
156 | int active2; // secondary perturbation bitmask (mjtPertBit)
157 | mjtNum refpos[3]; // reference position for selected object
158 | mjtNum refquat[4]; // reference orientation for selected object
159 | mjtNum reflocalpos[3]; // reference selection point in object coordinates
160 | mjtNum localpos[3]; // selection point in object coordinates
161 | mjtNum scale; // relative mouse motion-to-space scaling (set by initPerturb)
162 | };
163 | typedef struct mjvPerturb_ mjvPerturb;
164 |
165 |
166 | //---------------------------------- mjvCamera -----------------------------------------------------
167 |
168 | struct mjvCamera_ { // abstract camera
169 | // type and ids
170 | int type; // camera type (mjtCamera)
171 | int fixedcamid; // fixed camera id
172 | int trackbodyid; // body id to track
173 |
174 | // abstract camera pose specification
175 | mjtNum lookat[3]; // lookat point
176 | mjtNum distance; // distance to lookat point or tracked body
177 | mjtNum azimuth; // camera azimuth (deg)
178 | mjtNum elevation; // camera elevation (deg)
179 | };
180 | typedef struct mjvCamera_ mjvCamera;
181 |
182 |
183 | //---------------------------------- mjvGLCamera ---------------------------------------------------
184 |
185 | struct mjvGLCamera_ { // OpenGL camera
186 | // camera frame
187 | float pos[3]; // position
188 | float forward[3]; // forward direction
189 | float up[3]; // up direction
190 |
191 | // camera projection
192 | float frustum_center; // hor. center (left,right set to match aspect)
193 | float frustum_bottom; // bottom
194 | float frustum_top; // top
195 | float frustum_near; // near
196 | float frustum_far; // far
197 | };
198 | typedef struct mjvGLCamera_ mjvGLCamera;
199 |
200 |
201 | //---------------------------------- mjvGeom -------------------------------------------------------
202 |
203 | struct mjvGeom_ { // abstract geom
204 | // type info
205 | int type; // geom type (mjtGeom)
206 | int dataid; // mesh, hfield or plane id; -1: none
207 | int objtype; // mujoco object type; mjOBJ_UNKNOWN for decor
208 | int objid; // mujoco object id; -1 for decor
209 | int category; // visual category
210 | int texid; // texture id; -1: no texture
211 | int texuniform; // uniform cube mapping
212 | int texcoord; // mesh geom has texture coordinates
213 | int segid; // segmentation id; -1: not shown
214 |
215 | // OpenGL info
216 | float texrepeat[2]; // texture repetition for 2D mapping
217 | float size[3]; // size parameters
218 | float pos[3]; // Cartesian position
219 | float mat[9]; // Cartesian orientation
220 | float rgba[4]; // color and transparency
221 | float emission; // emission coef
222 | float specular; // specular coef
223 | float shininess; // shininess coef
224 | float reflectance; // reflectance coef
225 | char label[100]; // text label
226 |
227 | // transparency rendering (set internally)
228 | float camdist; // distance to camera (used by sorter)
229 | float modelrbound; // geom rbound from model, 0 if not model geom
230 | mjtByte transparent; // treat geom as transparent
231 | };
232 | typedef struct mjvGeom_ mjvGeom;
233 |
234 |
235 | //---------------------------------- mjvLight ------------------------------------------------------
236 |
237 | struct mjvLight_ { // OpenGL light
238 | float pos[3]; // position rel. to body frame
239 | float dir[3]; // direction rel. to body frame
240 | float attenuation[3]; // OpenGL attenuation (quadratic model)
241 | float cutoff; // OpenGL cutoff
242 | float exponent; // OpenGL exponent
243 | float ambient[3]; // ambient rgb (alpha=1)
244 | float diffuse[3]; // diffuse rgb (alpha=1)
245 | float specular[3]; // specular rgb (alpha=1)
246 | mjtByte headlight; // headlight
247 | mjtByte directional; // directional light
248 | mjtByte castshadow; // does light cast shadows
249 | };
250 | typedef struct mjvLight_ mjvLight;
251 |
252 |
253 | //---------------------------------- mjvOption -----------------------------------------------------
254 |
255 | struct mjvOption_ { // abstract visualization options
256 | int label; // what objects to label (mjtLabel)
257 | int frame; // which frame to show (mjtFrame)
258 | mjtByte geomgroup[mjNGROUP]; // geom visualization by group
259 | mjtByte sitegroup[mjNGROUP]; // site visualization by group
260 | mjtByte jointgroup[mjNGROUP]; // joint visualization by group
261 | mjtByte tendongroup[mjNGROUP]; // tendon visualization by group
262 | mjtByte actuatorgroup[mjNGROUP]; // actuator visualization by group
263 | mjtByte skingroup[mjNGROUP]; // skin visualization by group
264 | mjtByte flags[mjNVISFLAG]; // visualization flags (indexed by mjtVisFlag)
265 | };
266 | typedef struct mjvOption_ mjvOption;
267 |
268 |
269 | //---------------------------------- mjvScene ------------------------------------------------------
270 |
271 | struct mjvScene_ { // abstract scene passed to OpenGL renderer
272 | // abstract geoms
273 | int maxgeom; // size of allocated geom buffer
274 | int ngeom; // number of geoms currently in buffer
275 | mjvGeom* geoms; // buffer for geoms (ngeom)
276 | int* geomorder; // buffer for ordering geoms by distance to camera (ngeom)
277 |
278 | // skin data
279 | int nskin; // number of skins
280 | int* skinfacenum; // number of faces in skin (nskin)
281 | int* skinvertadr; // address of skin vertices (nskin)
282 | int* skinvertnum; // number of vertices in skin (nskin)
283 | float* skinvert; // skin vertex data (nskin)
284 | float* skinnormal; // skin normal data (nskin)
285 |
286 | // OpenGL lights
287 | int nlight; // number of lights currently in buffer
288 | mjvLight lights[mjMAXLIGHT]; // buffer for lights (nlight)
289 |
290 | // OpenGL cameras
291 | mjvGLCamera camera[2]; // left and right camera
292 |
293 | // OpenGL model transformation
294 | mjtByte enabletransform; // enable model transformation
295 | float translate[3]; // model translation
296 | float rotate[4]; // model quaternion rotation
297 | float scale; // model scaling
298 |
299 | // OpenGL rendering effects
300 | int stereo; // stereoscopic rendering (mjtStereo)
301 | mjtByte flags[mjNRNDFLAG]; // rendering flags (indexed by mjtRndFlag)
302 |
303 | // framing
304 | int framewidth; // frame pixel width; 0: disable framing
305 | float framergb[3]; // frame color
306 | };
307 | typedef struct mjvScene_ mjvScene;
308 |
309 |
310 | //---------------------------------- mjvFigure -----------------------------------------------------
311 |
312 | struct mjvFigure_ { // abstract 2D figure passed to OpenGL renderer
313 | // enable flags
314 | int flg_legend; // show legend
315 | int flg_ticklabel[2]; // show grid tick labels (x,y)
316 | int flg_extend; // automatically extend axis ranges to fit data
317 | int flg_barplot; // isolated line segments (i.e. GL_LINES)
318 | int flg_selection; // vertical selection line
319 | int flg_symmetric; // symmetric y-axis
320 |
321 | // style settings
322 | float linewidth; // line width
323 | float gridwidth; // grid line width
324 | int gridsize[2]; // number of grid points in (x,y)
325 | float gridrgb[3]; // grid line rgb
326 | float figurergba[4]; // figure color and alpha
327 | float panergba[4]; // pane color and alpha
328 | float legendrgba[4]; // legend color and alpha
329 | float textrgb[3]; // text color
330 | float linergb[mjMAXLINE][3]; // line colors
331 | float range[2][2]; // axis ranges; (min>=max) automatic
332 | char xformat[20]; // x-tick label format for sprintf
333 | char yformat[20]; // y-tick label format for sprintf
334 | char minwidth[20]; // string used to determine min y-tick width
335 |
336 | // text labels
337 | char title[1000]; // figure title; subplots separated with 2+ spaces
338 | char xlabel[100]; // x-axis label
339 | char linename[mjMAXLINE][100]; // line names for legend
340 |
341 | // dynamic settings
342 | int legendoffset; // number of lines to offset legend
343 | int subplot; // selected subplot (for title rendering)
344 | int highlight[2]; // if point is in legend rect, highlight line
345 | int highlightid; // if id>=0 and no point, highlight id
346 | float selection; // selection line x-value
347 |
348 | // line data
349 | int linepnt[mjMAXLINE]; // number of points in line; (0) disable
350 | float linedata[mjMAXLINE][2*mjMAXLINEPNT]; // line data (x,y)
351 |
352 | // output from renderer
353 | int xaxispixel[2]; // range of x-axis in pixels
354 | int yaxispixel[2]; // range of y-axis in pixels
355 | float xaxisdata[2]; // range of x-axis in data units
356 | float yaxisdata[2]; // range of y-axis in data units
357 | };
358 | typedef struct mjvFigure_ mjvFigure;
359 |
360 | #endif // MUJOCO_MJVISUALIZE_H_
361 |
--------------------------------------------------------------------------------
/simulation/mujoco/include/platform_ui_adapter.h:
--------------------------------------------------------------------------------
1 | // Copyright 2023 DeepMind Technologies Limited
2 | //
3 | // Licensed under the Apache License, Version 2.0 (the "License");
4 | // you may not use this file except in compliance with the License.
5 | // You may obtain a copy of the License at
6 | //
7 | // http://www.apache.org/licenses/LICENSE-2.0
8 | //
9 | // Unless required by applicable law or agreed to in writing, software
10 | // distributed under the License is distributed on an "AS IS" BASIS,
11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | // See the License for the specific language governing permissions and
13 | // limitations under the License.
14 |
15 | #ifndef MUJOCO_SIMULATE_PLATFORM_UI_ADAPTER_H_
16 | #define MUJOCO_SIMULATE_PLATFORM_UI_ADAPTER_H_
17 |
18 | #include
19 |
20 | #include
21 |
22 | namespace mujoco {
23 | class PlatformUIAdapter {
24 | public:
25 | virtual ~PlatformUIAdapter();
26 |
27 | inline mjuiState& state() { return state_; }
28 | inline const mjuiState& state() const { return state_; }
29 |
30 | inline mjrContext& mjr_context() { return con_; }
31 | inline const mjrContext& mjr_context() const { return con_; }
32 |
33 | inline void SetEventCallback(void (*event_callback)(mjuiState*)) {
34 | event_callback_ = event_callback;
35 | }
36 |
37 | inline void SetLayoutCallback(void (*layout_callback)(mjuiState*)) {
38 | layout_callback_ = layout_callback;
39 | }
40 |
41 | // Optionally overrideable function to (re)create an mjrContext for an mjModel
42 | virtual bool RefreshMjrContext(const mjModel* m, int fontscale);
43 |
44 | // Pure virtual functions to be implemented by individual adapters
45 | virtual std::pair GetCursorPosition() const = 0;
46 | virtual double GetDisplayPixelsPerInch() const = 0;
47 | virtual std::pair GetFramebufferSize() const = 0;
48 | virtual std::pair GetWindowSize() const = 0;
49 | virtual bool IsGPUAccelerated() const = 0;
50 | virtual void PollEvents() = 0;
51 | virtual void SetClipboardString(const char* text) = 0;
52 | virtual void SetVSync(bool enabled) = 0;
53 | virtual void SetWindowTitle(const char* title) = 0;
54 | virtual bool ShouldCloseWindow() const = 0;
55 | virtual void SwapBuffers() = 0;
56 | virtual void ToggleFullscreen() = 0;
57 |
58 | virtual bool IsLeftMouseButtonPressed() const = 0;
59 | virtual bool IsMiddleMouseButtonPressed() const = 0;
60 | virtual bool IsRightMouseButtonPressed() const = 0;
61 |
62 | virtual bool IsAltKeyPressed() const = 0;
63 | virtual bool IsCtrlKeyPressed() const = 0;
64 | virtual bool IsShiftKeyPressed() const = 0;
65 |
66 | virtual bool IsMouseButtonDownEvent(int act) const = 0;
67 | virtual bool IsKeyDownEvent(int act) const = 0;
68 |
69 | virtual int TranslateKeyCode(int key) const = 0;
70 | virtual mjtButton TranslateMouseButton(int button) const = 0;
71 |
72 | protected:
73 | PlatformUIAdapter();
74 |
75 | // Event handlers
76 | void OnFilesDrop(int count, const char** paths);
77 | void OnKey(int key, int scancode, int act);
78 | void OnMouseButton(int button, int act);
79 | void OnMouseMove(double x, double y);
80 | void OnScroll(double xoffset, double yoffset);
81 | void OnWindowRefresh();
82 | void OnWindowResize(int width, int height);
83 |
84 | mjuiState state_;
85 | void (*event_callback_)(mjuiState*);
86 | void (*layout_callback_)(mjuiState*);
87 |
88 | mjrContext con_;
89 | const mjModel* last_model_ = nullptr;
90 | int last_fontscale_ = -1;
91 |
92 | private:
93 | void UpdateMjuiState();
94 | };
95 | } // namespace mujoco
96 |
97 | #endif // MUJOCO_SIMULATE_PLATFORM_UI_ADAPTER_H_
98 |
--------------------------------------------------------------------------------
/simulation/mujoco/include/simulate.h:
--------------------------------------------------------------------------------
1 | // Copyright 2021 DeepMind Technologies Limited
2 | //
3 | // Licensed under the Apache License, Version 2.0 (the "License");
4 | // you may not use this file except in compliance with the License.
5 | // You may obtain a copy of the License at
6 | //
7 | // http://www.apache.org/licenses/LICENSE-2.0
8 | //
9 | // Unless required by applicable law or agreed to in writing, software
10 | // distributed under the License is distributed on an "AS IS" BASIS,
11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | // See the License for the specific language governing permissions and
13 | // limitations under the License.
14 |
15 | #ifndef MUJOCO_SIMULATE_SIMULATE_H_
16 | #define MUJOCO_SIMULATE_SIMULATE_H_
17 |
18 | #include
19 | #include
20 | #include
21 | #include
22 | #include
23 | #include
24 | #include
25 |
26 | #include
27 | #include "platform_ui_adapter.h"
28 |
29 | namespace mujoco {
30 |
31 | //-------------------------------- global -----------------------------------------------
32 |
33 | // Simulate states not contained in MuJoCo structures
34 | class Simulate {
35 | public:
36 | using Clock = std::chrono::steady_clock;
37 | static_assert(std::ratio_less_equal_v);
38 |
39 | // create object and initialize the simulate ui
40 | Simulate(std::unique_ptr platform_ui_adapter);
41 |
42 | // Apply UI pose perturbations to model and data
43 | void applyposepertubations(int flg_paused);
44 |
45 | // Apply UI force perturbations to model and data
46 | void applyforceperturbations();
47 |
48 | // Request that the Simulate UI thread render a new model
49 | // optionally delete the old model and data when done
50 | void load(const char* file, mjModel* m, mjData* d);
51 |
52 | // functions below are used by the renderthread
53 | // load mjb or xml model that has been requested by load()
54 | void loadmodel();
55 |
56 | // prepare to render
57 | void prepare();
58 |
59 | // render the ui to the window
60 | void render();
61 |
62 | // loop to render the UI (must be called from main thread because of MacOS)
63 | void renderloop();
64 |
65 | // constants
66 | static constexpr int kMaxFilenameLength = 1000;
67 |
68 | // model and data to be visualized
69 | mjModel* mnew = nullptr;
70 | mjData* dnew = nullptr;
71 |
72 | mjModel* m = nullptr;
73 | mjData* d = nullptr;
74 | std::mutex mtx;
75 | std::condition_variable cond_loadrequest;
76 |
77 | // options
78 | int spacing = 0;
79 | int color = 3;
80 | int font = 0;
81 | int ui0_enable = 0;
82 | int ui1_enable = 0;
83 | int help = 0;
84 | int info = 0;
85 | int profiler = 0;
86 | int sensor = 0;
87 | int fullscreen = 0;
88 | int vsync = 1;
89 | int busywait = 0;
90 |
91 | // keyframe index
92 | int key = 0;
93 |
94 | // simulation
95 | int run = 1;
96 |
97 | // atomics for cross-thread messages
98 | std::atomic_int exitrequest = false;
99 | std::atomic_int droploadrequest = false;
100 | std::atomic_int screenshotrequest = false;
101 | std::atomic_int uiloadrequest = 0;
102 |
103 | // loadrequest
104 | // 2: render thread asked to update its model
105 | // 1: showing "loading" label, about to load
106 | // 0: model loaded or no load requested.
107 | int loadrequest = 0;
108 |
109 | // strings
110 | char loadError[kMaxFilenameLength] = "";
111 | char dropfilename[kMaxFilenameLength] = "";
112 | char filename[kMaxFilenameLength] = "";
113 | char previous_filename[kMaxFilenameLength] = "";
114 |
115 | // time synchronization
116 | int realTimeIndex;
117 | bool speedChanged = true;
118 | float measuredSlowdown = 1.0;
119 | // logarithmically spaced realtime slow-down coefficients (percent)
120 | static constexpr float percentRealTime[] = {
121 | 100, 80, 66, 50, 40, 33, 25, 20, 16, 13,
122 | 10, 8, 6.6, 5.0, 4, 3.3, 2.5, 2, 1.6, 1.3,
123 | 1, .8, .66, .5, .4, .33, .25, .2, .16, .13,
124 | .1
125 | };
126 |
127 | // control noise
128 | double ctrlnoisestd = 0.0;
129 | double ctrlnoiserate = 0.0;
130 |
131 | // watch
132 | char field[mjMAXUITEXT] = "qpos";
133 | int index = 0;
134 |
135 | // physics: need sync
136 | int disable[mjNDISABLE] = {0};
137 | int enable[mjNENABLE] = {0};
138 |
139 | // rendering: need sync
140 | int camera = 0;
141 |
142 | // abstract visualization
143 | mjvScene scn = {};
144 | mjvCamera cam = {};
145 | mjvOption vopt = {};
146 | mjvPerturb pert = {};
147 | mjvFigure figconstraint = {};
148 | mjvFigure figcost = {};
149 | mjvFigure figtimer = {};
150 | mjvFigure figsize = {};
151 | mjvFigure figsensor = {};
152 |
153 | // OpenGL rendering and UI
154 | int refreshRate = 60;
155 | int windowpos[2] = {0};
156 | int windowsize[2] = {0};
157 | std::unique_ptr platform_ui;
158 | mjuiState& uistate;
159 | mjUI ui0 = {};
160 | mjUI ui1 = {};
161 |
162 | // Constant arrays needed for the option section of UI and the UI interface
163 | // TODO setting the size here is not ideal
164 | const mjuiDef defOption[14] = {
165 | {mjITEM_SECTION, "Option", 1, nullptr, "AO"},
166 | {mjITEM_SELECT, "Spacing", 1, &this->spacing, "Tight\nWide"},
167 | {mjITEM_SELECT, "Color", 1, &this->color, "Default\nOrange\nWhite\nBlack"},
168 | {mjITEM_SELECT, "Font", 1, &this->font, "50 %\n100 %\n150 %\n200 %\n250 %\n300 %"},
169 | {mjITEM_CHECKINT, "Left UI (Tab)", 1, &this->ui0_enable, " #258"},
170 | {mjITEM_CHECKINT, "Right UI", 1, &this->ui1_enable, "S#258"},
171 | {mjITEM_CHECKINT, "Help", 2, &this->help, " #290"},
172 | {mjITEM_CHECKINT, "Info", 2, &this->info, " #291"},
173 | {mjITEM_CHECKINT, "Profiler", 2, &this->profiler, " #292"},
174 | {mjITEM_CHECKINT, "Sensor", 2, &this->sensor, " #293"},
175 | #ifdef __APPLE__
176 | {mjITEM_CHECKINT, "Fullscreen", 0, &this->fullscreen, " #294"},
177 | #else
178 | {mjITEM_CHECKINT, "Fullscreen", 1, &this->fullscreen, " #294"},
179 | #endif
180 | {mjITEM_CHECKINT, "Vertical Sync", 1, &this->vsync, ""},
181 | {mjITEM_CHECKINT, "Busy Wait", 1, &this->busywait, ""},
182 | {mjITEM_END}
183 | };
184 |
185 |
186 | // simulation section of UI
187 | const mjuiDef defSimulation[12] = {
188 | {mjITEM_SECTION, "Simulation", 1, nullptr, "AS"},
189 | {mjITEM_RADIO, "", 2, &this->run, "Pause\nRun"},
190 | {mjITEM_BUTTON, "Reset", 2, nullptr, " #259"},
191 | {mjITEM_BUTTON, "Reload", 2, nullptr, "CL"},
192 | {mjITEM_BUTTON, "Align", 2, nullptr, "CA"},
193 | {mjITEM_BUTTON, "Copy pose", 2, nullptr, "CC"},
194 | {mjITEM_SLIDERINT, "Key", 3, &this->key, "0 0"},
195 | {mjITEM_BUTTON, "Load key", 3},
196 | {mjITEM_BUTTON, "Save key", 3},
197 | {mjITEM_SLIDERNUM, "Noise scale", 2, &this->ctrlnoisestd, "0 2"},
198 | {mjITEM_SLIDERNUM, "Noise rate", 2, &this->ctrlnoiserate, "0 2"},
199 | {mjITEM_END}
200 | };
201 |
202 |
203 | // watch section of UI
204 | const mjuiDef defWatch[5] = {
205 | {mjITEM_SECTION, "Watch", 0, nullptr, "AW"},
206 | {mjITEM_EDITTXT, "Field", 2, this->field, "qpos"},
207 | {mjITEM_EDITINT, "Index", 2, &this->index, "1"},
208 | {mjITEM_STATIC, "Value", 2, nullptr, " "},
209 | {mjITEM_END}
210 | };
211 |
212 | // info strings
213 | char info_title[Simulate::kMaxFilenameLength] = {0};
214 | char info_content[Simulate::kMaxFilenameLength] = {0};
215 | };
216 | } // namespace mujoco
217 |
218 | #endif
219 |
--------------------------------------------------------------------------------
/simulation/mujoco/launch/simulation_launch.py:
--------------------------------------------------------------------------------
1 | import os
2 | from ament_index_python.packages import get_package_share_path
3 | from launch import LaunchDescription
4 | from launch.actions import DeclareLaunchArgument
5 | from launch.substitutions import LaunchConfiguration
6 | from launch_ros.actions import Node
7 |
8 |
9 | def generate_launch_description():
10 | xml_file_name = "model/xml/digit.xml"
11 | xml_file = os.path.join(get_package_share_path("description"), xml_file_name)
12 |
13 | return LaunchDescription(
14 | [
15 | Node(
16 | package="mujoco",
17 | executable="simulation",
18 | name="simulation_mujoco",
19 | output="screen",
20 | parameters=[
21 | {"simulation/model_file": xml_file},
22 | ],
23 | emulate_tty=True,
24 | arguments=[("__log_level:=debug")],
25 | ),
26 | ]
27 | )
28 |
--------------------------------------------------------------------------------
/simulation/mujoco/lib/libmujoco.so:
--------------------------------------------------------------------------------
1 | libmujoco.so.2.3.2
--------------------------------------------------------------------------------
/simulation/mujoco/lib/libmujoco.so.2.3.2:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/MindSpaceInc/Digit-MuJoCo-ROS2/1a263e07331cb22cf86b80ee2435febdb3be3bf2/simulation/mujoco/lib/libmujoco.so.2.3.2
--------------------------------------------------------------------------------
/simulation/mujoco/package.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | mujoco
5 | 0.0.0
6 | TODO: Package description
7 | DeepBreak
8 | BSD
9 |
10 | ament_cmake
11 |
12 | ament_lint_auto
13 | ament_lint_common
14 |
15 | rclcpp
16 | communication
17 | geometry_msgs
18 | tf2
19 | tf2_ros
20 | nav_msgs
21 | sensor_msgs
22 | cv_bridge
23 | ros2launch
24 |
25 |
26 | ament_cmake
27 |
28 |
29 |
--------------------------------------------------------------------------------
/simulation/mujoco/src/MuJoCoMessageHandler.cpp:
--------------------------------------------------------------------------------
1 | #include "MuJoCoMessageHandler.h"
2 |
3 | #include "cv_bridge/cv_bridge.h"
4 | #include "sensor_msgs/image_encodings.hpp"
5 |
6 | namespace deepbreak {
7 |
8 | MuJoCoMessageHandler::MuJoCoMessageHandler(mj::Simulate *sim)
9 | : Node("MuJoCoMessageHandler"), sim_(sim), name_prefix("simulation/") {
10 | model_param_name = name_prefix + "model_file";
11 | this->declare_parameter(model_param_name, "");
12 |
13 | reset_service_ = this->create_service(
14 | name_prefix + "sim_reset",
15 | std::bind(&MuJoCoMessageHandler::reset_callback, this,
16 | std::placeholders::_1, std::placeholders::_2));
17 |
18 | auto qos = rclcpp::QoS(rclcpp::KeepLast(1), rmw_qos_profile_sensor_data);
19 | imu_publisher_ = this->create_publisher(
20 | name_prefix + "imu_data", qos);
21 | joint_state_publisher_ = this->create_publisher(
22 | name_prefix + "joint_states", qos);
23 | odom_publisher_ = this->create_publisher(
24 | name_prefix + "odom", qos);
25 |
26 |
27 | timers_.emplace_back(this->create_wall_timer(
28 | 2.5ms, std::bind(&MuJoCoMessageHandler::imu_callback, this)));
29 | timers_.emplace_back(this->create_wall_timer(
30 | 1ms, std::bind(&MuJoCoMessageHandler::joint_callback, this)));
31 | timers_.emplace_back(this->create_wall_timer(
32 | 20ms, std::bind(&MuJoCoMessageHandler::odom_callback, this)));
33 | timers_.emplace_back(this->create_wall_timer(
34 | 100ms, std::bind(&MuJoCoMessageHandler::drop_old_message, this)));
35 |
36 | actuator_cmd_subscription_ =
37 | this->create_subscription(
38 | name_prefix + "actuators_cmds", qos,
39 | std::bind(&MuJoCoMessageHandler::actuator_cmd_callback, this,
40 | std::placeholders::_1));
41 |
42 | param_subscriber_ = std::make_shared(this);
43 | cb_handle_ = param_subscriber_->add_parameter_callback(
44 | model_param_name, std::bind(&MuJoCoMessageHandler::parameter_callback,
45 | this, std::placeholders::_1));
46 |
47 | actuator_cmds_ptr_ = std::make_shared();
48 |
49 | RCLCPP_INFO(this->get_logger(), "Start MuJoCoMessageHandler ...");
50 |
51 | std::string model_file = this->get_parameter(model_param_name)
52 | .get_parameter_value()
53 | .get();
54 | mju::strcpy_arr(sim_->filename, model_file.c_str());
55 | sim_->uiloadrequest.fetch_add(1);
56 | }
57 |
58 | MuJoCoMessageHandler::~MuJoCoMessageHandler() {
59 | RCLCPP_INFO(this->get_logger(), "close node ...");
60 | }
61 |
62 | void MuJoCoMessageHandler::reset_callback(
63 | const std::shared_ptr request,
64 | std::shared_ptr response) {
65 | while (sim_->d == nullptr && rclcpp::ok()) {
66 | std::this_thread::sleep_for(std::chrono::seconds(1));
67 | }
68 | if (sim_->d != nullptr) {
69 | if (request->header.frame_id != std::string(&sim_->m->names[0])) {
70 | RCLCPP_ERROR(this->get_logger(), "reset request is not for %s",
71 | &sim_->m->names[0]);
72 | response->is_success = false;
73 | } else {
74 | sim_->mtx.lock();
75 | mj_resetData(sim_->m, sim_->d);
76 | sim_->d->qpos[0] = request->base_pose.position.x;
77 | sim_->d->qpos[1] = request->base_pose.position.y;
78 | sim_->d->qpos[2] = request->base_pose.position.z;
79 | sim_->d->qpos[3] = request->base_pose.orientation.w;
80 | sim_->d->qpos[4] = request->base_pose.orientation.x;
81 | sim_->d->qpos[5] = request->base_pose.orientation.y;
82 | sim_->d->qpos[6] = request->base_pose.orientation.z;
83 |
84 | for (int i = 0; i < request->joint_state.position.size(); i++) {
85 | int joint_id = mj_name2id(sim_->m, mjOBJ_JOINT,
86 | request->joint_state.name[i].c_str());
87 | if (joint_id > -1) {
88 | sim_->d->qpos[sim_->m->jnt_qposadr[joint_id]] =
89 | request->joint_state.position[i];
90 | } else {
91 | RCLCPP_WARN(this->get_logger(), "Request joint %s does not exist",
92 | request->joint_state.name[i].c_str());
93 | }
94 | }
95 | for (size_t k = 0; k < actuator_cmds_ptr_->actuators_name.size(); k++) {
96 | actuator_cmds_ptr_->kp[k] = 0;
97 | actuator_cmds_ptr_->pos[k] = 0;
98 | actuator_cmds_ptr_->kd[k] = 0;
99 | actuator_cmds_ptr_->vel[k] = 0;
100 | actuator_cmds_ptr_->torque[k] = 0.0;
101 | }
102 | sim_->mtx.unlock();
103 | response->is_success = true;
104 | RCLCPP_INFO(this->get_logger(), "reset robot state...");
105 | RCLCPP_INFO(this->get_logger(), "robot total mass: %f",
106 | sim_->m->body_subtreemass[0]);
107 | }
108 | } else {
109 | response->is_success = false;
110 | }
111 | }
112 |
113 | void MuJoCoMessageHandler::imu_callback() {
114 | if (sim_->d != nullptr) {
115 | auto message = sensor_msgs::msg::Imu();
116 | message.header.frame_id = &sim_->m->names[0];
117 | message.header.stamp = rclcpp::Clock().now();
118 | const std::lock_guard lock(sim_->mtx);
119 |
120 | for (int i = 0; i < sim_->m->nsensor; i++) {
121 | if (sim_->m->sensor_type[i] == mjtSensor::mjSENS_ACCELEROMETER) {
122 | message.linear_acceleration.x =
123 | sim_->d->sensordata[sim_->m->sensor_adr[i]];
124 | message.linear_acceleration.y =
125 | sim_->d->sensordata[sim_->m->sensor_adr[i] + 1];
126 | message.linear_acceleration.z =
127 | sim_->d->sensordata[sim_->m->sensor_adr[i] + 2];
128 | } else if (sim_->m->sensor_type[i] == mjtSensor::mjSENS_FRAMEQUAT) {
129 | message.orientation.w = sim_->d->sensordata[sim_->m->sensor_adr[i]];
130 | message.orientation.x = sim_->d->sensordata[sim_->m->sensor_adr[i] + 1];
131 | message.orientation.y = sim_->d->sensordata[sim_->m->sensor_adr[i] + 2];
132 | message.orientation.z = sim_->d->sensordata[sim_->m->sensor_adr[i] + 3];
133 | } else if (sim_->m->sensor_type[i] == mjtSensor::mjSENS_GYRO) {
134 | message.angular_velocity.x =
135 | sim_->d->sensordata[sim_->m->sensor_adr[i]];
136 | message.angular_velocity.y =
137 | sim_->d->sensordata[sim_->m->sensor_adr[i] + 1];
138 | message.angular_velocity.z =
139 | sim_->d->sensordata[sim_->m->sensor_adr[i] + 2];
140 | }
141 | }
142 | imu_publisher_->publish(message);
143 | }
144 | }
145 |
146 | void MuJoCoMessageHandler::odom_callback() {
147 | const std::lock_guard lock(sim_->mtx);
148 | if (sim_->d != nullptr) {
149 | auto message = nav_msgs::msg::Odometry();
150 | message.header.frame_id = &sim_->m->names[0];
151 | message.header.stamp = rclcpp::Clock().now();
152 | message.pose.pose.position.x = sim_->d->qpos[0];
153 | message.pose.pose.position.y = sim_->d->qpos[1];
154 | message.pose.pose.position.z = sim_->d->qpos[2];
155 | message.pose.pose.orientation.w = sim_->d->qpos[3];
156 | message.pose.pose.orientation.x = sim_->d->qpos[4];
157 | message.pose.pose.orientation.y = sim_->d->qpos[5];
158 | message.pose.pose.orientation.z = sim_->d->qpos[6];
159 | message.twist.twist.linear.x = sim_->d->qvel[0];
160 | message.twist.twist.linear.y = sim_->d->qvel[1];
161 | message.twist.twist.linear.z = sim_->d->qvel[2];
162 | message.twist.twist.angular.x = sim_->d->qvel[3];
163 | message.twist.twist.angular.y = sim_->d->qvel[4];
164 | message.twist.twist.angular.z = sim_->d->qvel[5];
165 | odom_publisher_->publish(message);
166 | }
167 | }
168 |
169 | void MuJoCoMessageHandler::joint_callback() {
170 | const std::lock_guard lock(sim_->mtx);
171 |
172 | if (sim_->d != nullptr) {
173 | sensor_msgs::msg::JointState jointState;
174 | jointState.header.frame_id = &sim_->m->names[0];
175 | jointState.header.stamp = rclcpp::Clock().now();
176 | for (int i = 0; i < sim_->m->njnt; i++) {
177 | if (sim_->m->jnt_type[i] == mjtJoint::mjJNT_HINGE) {
178 | std::string jnt_name(mj_id2name(sim_->m, mjtObj::mjOBJ_JOINT, i));
179 | jointState.name.emplace_back(jnt_name);
180 | jointState.position.push_back(sim_->d->qpos[sim_->m->jnt_qposadr[i]]);
181 | jointState.velocity.push_back(sim_->d->qvel[sim_->m->jnt_dofadr[i]]);
182 | jointState.effort.push_back(
183 | sim_->d->qfrc_actuator[sim_->m->jnt_dofadr[i]]);
184 | }
185 | }
186 | joint_state_publisher_->publish(jointState);
187 | }
188 | }
189 |
190 | void MuJoCoMessageHandler::actuator_cmd_callback(
191 | const communication::msg::ActuatorCmds::SharedPtr msg) const {
192 | if (sim_->d != nullptr) {
193 | actuator_cmds_ptr_->time = this->now().seconds();
194 | actuator_cmds_ptr_->actuators_name.resize(msg->actuators_name.size());
195 | actuator_cmds_ptr_->kp.resize(msg->kp.size());
196 | actuator_cmds_ptr_->pos.resize(msg->pos.size());
197 | actuator_cmds_ptr_->kd.resize(msg->kd.size());
198 | actuator_cmds_ptr_->vel.resize(msg->vel.size());
199 | actuator_cmds_ptr_->torque.resize(msg->torque.size());
200 | for (size_t k = 0; k < msg->actuators_name.size(); k++) {
201 | actuator_cmds_ptr_->actuators_name[k] = msg->actuators_name[k];
202 | actuator_cmds_ptr_->kp[k] = msg->kp[k];
203 | actuator_cmds_ptr_->pos[k] = msg->pos[k];
204 | actuator_cmds_ptr_->kd[k] = msg->kd[k];
205 | actuator_cmds_ptr_->vel[k] = msg->vel[k];
206 | actuator_cmds_ptr_->torque[k] = msg->torque[k];
207 | }
208 | // RCLCPP_INFO(this->get_logger(), "subscribe actuator cmds");
209 | }
210 | }
211 |
212 | void MuJoCoMessageHandler::parameter_callback(const rclcpp::Parameter &) {
213 | std::string model_file = this->get_parameter(model_param_name)
214 | .get_parameter_value()
215 | .get();
216 | RCLCPP_INFO(this->get_logger(), "load model from: %s", model_file.c_str());
217 | mju::strcpy_arr(sim_->filename, model_file.c_str());
218 | sim_->uiloadrequest.fetch_add(1);
219 | }
220 |
221 | void MuJoCoMessageHandler::drop_old_message() {
222 | if (abs(actuator_cmds_ptr_->time - this->now().seconds()) > 0.2) {
223 | for (size_t k = 0; k < actuator_cmds_ptr_->actuators_name.size(); k++) {
224 | actuator_cmds_ptr_->kp[k] = 0.0;
225 | actuator_cmds_ptr_->pos[k] = 0.0;
226 | actuator_cmds_ptr_->kd[k] = 1.0;
227 | actuator_cmds_ptr_->vel[k] = 0.0;
228 | actuator_cmds_ptr_->torque[k] = 0.0;
229 | }
230 | }
231 | }
232 |
233 | std::shared_ptr
234 | MuJoCoMessageHandler::get_actuator_cmds_ptr() {
235 | return actuator_cmds_ptr_;
236 | }
237 |
238 | } // namespace deepbreak
239 |
--------------------------------------------------------------------------------
/simulation/mujoco/src/glfw_adapter.cc:
--------------------------------------------------------------------------------
1 | // Copyright 2023 DeepMind Technologies Limited
2 | //
3 | // Licensed under the Apache License, Version 2.0 (the "License");
4 | // you may not use this file except in compliance with the License.
5 | // You may obtain a copy of the License at
6 | //
7 | // http://www.apache.org/licenses/LICENSE-2.0
8 | //
9 | // Unless required by applicable law or agreed to in writing, software
10 | // distributed under the License is distributed on an "AS IS" BASIS,
11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | // See the License for the specific language governing permissions and
13 | // limitations under the License.
14 |
15 | #include "glfw_adapter.h"
16 |
17 | #include
18 | #include
19 |
20 | #include
21 | #include
22 | #include
23 | #include "glfw_dispatch.h"
24 |
25 | namespace mujoco {
26 | namespace {
27 | int MaybeGlfwInit() {
28 | static const int is_initialized = []() {
29 | auto success = Glfw().glfwInit();
30 | if (success == GLFW_TRUE) {
31 | std::atexit(Glfw().glfwTerminate);
32 | }
33 | return success;
34 | }();
35 | return is_initialized;
36 | }
37 |
38 | GlfwAdapter& GlfwAdapterFromWindow(GLFWwindow* window) {
39 | return *static_cast(Glfw().glfwGetWindowUserPointer(window));
40 | }
41 | } // namespace
42 |
43 | GlfwAdapter::GlfwAdapter() {
44 | if (MaybeGlfwInit() != GLFW_TRUE) {
45 | mju_error("could not initialize GLFW");
46 | }
47 |
48 | // multisampling
49 | Glfw().glfwWindowHint(GLFW_SAMPLES, 4);
50 | Glfw().glfwWindowHint(GLFW_VISIBLE, 1);
51 |
52 | // get video mode and save
53 | vidmode_ = *Glfw().glfwGetVideoMode(Glfw().glfwGetPrimaryMonitor());
54 |
55 | // create window
56 | window_ = Glfw().glfwCreateWindow((2 * vidmode_.width) / 3,
57 | (2 * vidmode_.height) / 3,
58 | "MuJoCo", nullptr, nullptr);
59 | if (!window_) {
60 | mju_error("could not create window");
61 | }
62 |
63 | // save window position and size
64 | Glfw().glfwGetWindowPos(window_, &window_pos_.first, &window_pos_.second);
65 | Glfw().glfwGetWindowSize(window_, &window_size_.first, &window_size_.second);
66 |
67 | // set callbacks
68 | Glfw().glfwSetWindowUserPointer(window_, this);
69 | Glfw().glfwSetDropCallback(
70 | window_, +[](GLFWwindow* window, int count, const char** paths) {
71 | GlfwAdapterFromWindow(window).OnFilesDrop(count, paths);
72 | });
73 | Glfw().glfwSetKeyCallback(
74 | window_, +[](GLFWwindow* window, int key, int scancode, int act, int mods) {
75 | GlfwAdapterFromWindow(window).OnKey(key, scancode, act);
76 | });
77 | Glfw().glfwSetMouseButtonCallback(
78 | window_, +[](GLFWwindow* window, int button, int act, int mods) {
79 | GlfwAdapterFromWindow(window).OnMouseButton(button, act);
80 | });
81 | Glfw().glfwSetCursorPosCallback(
82 | window_, +[](GLFWwindow* window, double x, double y) {
83 | GlfwAdapterFromWindow(window).OnMouseMove(x, y);
84 | });
85 | Glfw().glfwSetScrollCallback(
86 | window_, +[](GLFWwindow* window, double xoffset, double yoffset) {
87 | GlfwAdapterFromWindow(window).OnScroll(xoffset, yoffset);
88 | });
89 | Glfw().glfwSetWindowRefreshCallback(
90 | window_, +[](GLFWwindow* window) {
91 | GlfwAdapterFromWindow(window).OnWindowRefresh();
92 | });
93 | Glfw().glfwSetWindowSizeCallback(
94 | window_, +[](GLFWwindow* window, int width, int height) {
95 | GlfwAdapterFromWindow(window).OnWindowResize(width, height);
96 | });
97 |
98 | // make context current
99 | Glfw().glfwMakeContextCurrent(window_);
100 | }
101 |
102 | GlfwAdapter::~GlfwAdapter() {
103 | Glfw().glfwMakeContextCurrent(nullptr);
104 | Glfw().glfwDestroyWindow(window_);
105 | }
106 |
107 | std::pair GlfwAdapter::GetCursorPosition() const {
108 | double x, y;
109 | Glfw().glfwGetCursorPos(window_, &x, &y);
110 | return {x, y};
111 | }
112 |
113 | double GlfwAdapter::GetDisplayPixelsPerInch() const {
114 | int width_mm, height_mm;
115 | Glfw().glfwGetMonitorPhysicalSize(
116 | Glfw().glfwGetPrimaryMonitor(), &width_mm, &height_mm);
117 | return 25.4 * vidmode_.width / width_mm;
118 | }
119 |
120 | std::pair GlfwAdapter::GetFramebufferSize() const {
121 | int width, height;
122 | Glfw().glfwGetFramebufferSize(window_, &width, &height);
123 | return {width, height};
124 | }
125 |
126 | std::pair GlfwAdapter::GetWindowSize() const {
127 | int width, height;
128 | Glfw().glfwGetWindowSize(window_, &width, &height);
129 | return {width, height};
130 | }
131 |
132 | bool GlfwAdapter::IsGPUAccelerated() const {
133 | return true;
134 | }
135 |
136 | void GlfwAdapter::PollEvents() {
137 | Glfw().glfwPollEvents();
138 | }
139 |
140 | void GlfwAdapter::SetClipboardString(const char* text) {
141 | Glfw().glfwSetClipboardString(window_, text);
142 | }
143 |
144 | void GlfwAdapter::SetVSync(bool enabled){
145 | Glfw().glfwSwapInterval(enabled);
146 | }
147 |
148 | void GlfwAdapter::SetWindowTitle(const char* title) {
149 | Glfw().glfwSetWindowTitle(window_, title);
150 | }
151 |
152 | bool GlfwAdapter::ShouldCloseWindow() const {
153 | return Glfw().glfwWindowShouldClose(window_);
154 | }
155 |
156 | void GlfwAdapter::SwapBuffers() {
157 | Glfw().glfwSwapBuffers(window_);
158 | }
159 |
160 | void GlfwAdapter::ToggleFullscreen() {
161 | // currently full screen: switch to windowed
162 | if (Glfw().glfwGetWindowMonitor(window_)) {
163 | // restore window from saved data
164 | Glfw().glfwSetWindowMonitor(window_, nullptr, window_pos_.first, window_pos_.second,
165 | window_size_.first, window_size_.second, 0);
166 | }
167 |
168 | // currently windowed: switch to full screen
169 | else {
170 | // save window data
171 | Glfw().glfwGetWindowPos(window_, &window_pos_.first, &window_pos_.second);
172 | Glfw().glfwGetWindowSize(window_, &window_size_.first,
173 | &window_size_.second);
174 |
175 | // switch
176 | Glfw().glfwSetWindowMonitor(window_, Glfw().glfwGetPrimaryMonitor(), 0,
177 | 0, vidmode_.width, vidmode_.height,
178 | vidmode_.refreshRate);
179 | }
180 | }
181 |
182 | bool GlfwAdapter::IsLeftMouseButtonPressed() const {
183 | return Glfw().glfwGetMouseButton(window_, GLFW_MOUSE_BUTTON_LEFT) == GLFW_PRESS;
184 | }
185 |
186 | bool GlfwAdapter::IsMiddleMouseButtonPressed() const {
187 | return Glfw().glfwGetMouseButton(window_, GLFW_MOUSE_BUTTON_MIDDLE) == GLFW_PRESS;
188 | }
189 |
190 | bool GlfwAdapter::IsRightMouseButtonPressed() const {
191 | return Glfw().glfwGetMouseButton(window_, GLFW_MOUSE_BUTTON_RIGHT) == GLFW_PRESS;
192 | }
193 |
194 | bool GlfwAdapter::IsAltKeyPressed() const {
195 | return Glfw().glfwGetKey(window_, GLFW_KEY_LEFT_ALT) == GLFW_PRESS ||
196 | Glfw().glfwGetKey(window_, GLFW_KEY_RIGHT_ALT) == GLFW_PRESS;
197 | }
198 |
199 | bool GlfwAdapter::IsCtrlKeyPressed() const {
200 | return Glfw().glfwGetKey(window_, GLFW_KEY_LEFT_CONTROL) == GLFW_PRESS ||
201 | Glfw().glfwGetKey(window_, GLFW_KEY_RIGHT_CONTROL) == GLFW_PRESS;
202 | }
203 |
204 | bool GlfwAdapter::IsShiftKeyPressed() const {
205 | return Glfw().glfwGetKey(window_, GLFW_KEY_LEFT_SHIFT) == GLFW_PRESS ||
206 | Glfw().glfwGetKey(window_, GLFW_KEY_RIGHT_SHIFT) == GLFW_PRESS;
207 | }
208 |
209 | bool GlfwAdapter::IsMouseButtonDownEvent(int act) const {
210 | return act == GLFW_PRESS;
211 | }
212 |
213 | bool GlfwAdapter::IsKeyDownEvent(int act) const { return act == GLFW_PRESS; }
214 |
215 | int GlfwAdapter::TranslateKeyCode(int key) const { return key; }
216 |
217 | mjtButton GlfwAdapter::TranslateMouseButton(int button) const {
218 | if (button == GLFW_MOUSE_BUTTON_LEFT) {
219 | return mjBUTTON_LEFT;
220 | } else if (button == GLFW_MOUSE_BUTTON_RIGHT) {
221 | return mjBUTTON_RIGHT;
222 | } else if (button == GLFW_MOUSE_BUTTON_MIDDLE) {
223 | return mjBUTTON_MIDDLE;
224 | }
225 | return mjBUTTON_NONE;
226 | }
227 | } // namespace mujoco
228 |
--------------------------------------------------------------------------------
/simulation/mujoco/src/glfw_dispatch.cc:
--------------------------------------------------------------------------------
1 | // Copyright 2022 DeepMind Technologies Limited
2 | //
3 | // Licensed under the Apache License, Version 2.0 (the "License");
4 | // you may not use this file except in compliance with the License.
5 | // You may obtain a copy of the License at
6 | //
7 | // http://www.apache.org/licenses/LICENSE-2.0
8 | //
9 | // Unless required by applicable law or agreed to in writing, software
10 | // distributed under the License is distributed on an "AS IS" BASIS,
11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | // See the License for the specific language governing permissions and
13 | // limitations under the License.
14 |
15 | #include "glfw_dispatch.h"
16 |
17 | #ifdef mjGLFW_DYNAMIC_SYMBOLS
18 | #ifdef _MSC_VER
19 | #include
20 | #include
21 | #else
22 | #include
23 | #endif
24 | #endif
25 |
26 | #include
27 | #include
28 |
29 | namespace mujoco {
30 |
31 | // return dispatch table for glfw functions
32 | const struct Glfw& Glfw(void* dlhandle) {
33 | {
34 | // set static init_dlhandle
35 | static const void* init_dlhandle = dlhandle;
36 |
37 | // check that not already initialized
38 | if (dlhandle && dlhandle != init_dlhandle) {
39 | std::cerr << "dlhandle is specified when GLFW dispatch table is already "
40 | "initialized\n";
41 | abort();
42 | }
43 | }
44 |
45 | // make and intialize dispatch table
46 | static const struct Glfw glfw = [&]() { // create and call constructor
47 | // allocate
48 | struct Glfw glfw;
49 |
50 | // load glfw dynamically
51 | #ifdef mjGLFW_DYNAMIC_SYMBOLS
52 | #ifdef _MSC_VER
53 | if (!dlhandle) dlhandle = LoadLibraryA("glfw3.dll");
54 | if (!dlhandle) {
55 | std::cerr << "cannot obtain a shared object handle\n";
56 | abort();
57 | }
58 | #define mjGLFW_RESOLVE_SYMBOL(func) \
59 | glfw.func = reinterpret_cast( \
60 | GetProcAddress(reinterpret_cast(dlhandle), #func))
61 | #else
62 | if (!dlhandle) dlhandle = dlopen("nullptr", RTLD_GLOBAL | RTLD_NOW);
63 | if (!dlhandle) {
64 | std::cerr << "cannot obtain a shared object handle\n";
65 | abort();
66 | }
67 | #define mjGLFW_RESOLVE_SYMBOL(func) \
68 | glfw.func = reinterpret_cast(dlsym(dlhandle, #func))
69 | #endif
70 | #else
71 | #define mjGLFW_RESOLVE_SYMBOL(func) glfw.func = &::func
72 | #endif
73 |
74 | // set pointers in dispatch table
75 | #define mjGLFW_INITIALIZE_SYMBOL(func) \
76 | if (!(mjGLFW_RESOLVE_SYMBOL(func))) { \
77 | std::cerr << "cannot dlsym " #func "\n"; \
78 | abort(); \
79 | }
80 |
81 | // go/keep-sorted start
82 | mjGLFW_INITIALIZE_SYMBOL(glfwCreateWindow);
83 | mjGLFW_INITIALIZE_SYMBOL(glfwDestroyWindow);
84 | mjGLFW_INITIALIZE_SYMBOL(glfwGetCursorPos);
85 | mjGLFW_INITIALIZE_SYMBOL(glfwGetFramebufferSize);
86 | mjGLFW_INITIALIZE_SYMBOL(glfwGetKey);
87 | mjGLFW_INITIALIZE_SYMBOL(glfwGetMonitorPhysicalSize);
88 | mjGLFW_INITIALIZE_SYMBOL(glfwGetMouseButton);
89 | mjGLFW_INITIALIZE_SYMBOL(glfwGetPrimaryMonitor);
90 | mjGLFW_INITIALIZE_SYMBOL(glfwGetTime);
91 | mjGLFW_INITIALIZE_SYMBOL(glfwGetVideoMode);
92 | mjGLFW_INITIALIZE_SYMBOL(glfwGetWindowMonitor);
93 | mjGLFW_INITIALIZE_SYMBOL(glfwGetWindowPos);
94 | mjGLFW_INITIALIZE_SYMBOL(glfwGetWindowSize);
95 | mjGLFW_INITIALIZE_SYMBOL(glfwGetWindowUserPointer);
96 | mjGLFW_INITIALIZE_SYMBOL(glfwInit);
97 | mjGLFW_INITIALIZE_SYMBOL(glfwMakeContextCurrent);
98 | mjGLFW_INITIALIZE_SYMBOL(glfwPollEvents);
99 | mjGLFW_INITIALIZE_SYMBOL(glfwSetClipboardString);
100 | mjGLFW_INITIALIZE_SYMBOL(glfwSetCursorPosCallback);
101 | mjGLFW_INITIALIZE_SYMBOL(glfwSetDropCallback);
102 | mjGLFW_INITIALIZE_SYMBOL(glfwSetKeyCallback);
103 | mjGLFW_INITIALIZE_SYMBOL(glfwSetMouseButtonCallback);
104 | mjGLFW_INITIALIZE_SYMBOL(glfwSetScrollCallback);
105 | mjGLFW_INITIALIZE_SYMBOL(glfwSetWindowMonitor);
106 | mjGLFW_INITIALIZE_SYMBOL(glfwSetWindowRefreshCallback);
107 | mjGLFW_INITIALIZE_SYMBOL(glfwSetWindowSizeCallback);
108 | mjGLFW_INITIALIZE_SYMBOL(glfwSetWindowTitle);
109 | mjGLFW_INITIALIZE_SYMBOL(glfwSetWindowUserPointer);
110 | mjGLFW_INITIALIZE_SYMBOL(glfwSwapBuffers);
111 | mjGLFW_INITIALIZE_SYMBOL(glfwSwapInterval);
112 | mjGLFW_INITIALIZE_SYMBOL(glfwTerminate);
113 | mjGLFW_INITIALIZE_SYMBOL(glfwWindowHint);
114 | mjGLFW_INITIALIZE_SYMBOL(glfwWindowShouldClose);
115 | // go/keep-sorted end
116 |
117 | #undef mjGLFW_INITIALIZE_SYMBOL
118 |
119 | return glfw;
120 | }();
121 | return glfw;
122 | }
123 | } // namespace mujoco
124 |
--------------------------------------------------------------------------------
/simulation/mujoco/src/platform_ui_adapter.cc:
--------------------------------------------------------------------------------
1 | // Copyright 2023 DeepMind Technologies Limited
2 | //
3 | // Licensed under the Apache License, Version 2.0 (the "License");
4 | // you may not use this file except in compliance with the License.
5 | // You may obtain a copy of the License at
6 | //
7 | // http://www.apache.org/licenses/LICENSE-2.0
8 | //
9 | // Unless required by applicable law or agreed to in writing, software
10 | // distributed under the License is distributed on an "AS IS" BASIS,
11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | // See the License for the specific language governing permissions and
13 | // limitations under the License.
14 |
15 | #include "platform_ui_adapter.h"
16 |
17 | #include
18 |
19 | namespace mujoco {
20 | PlatformUIAdapter::PlatformUIAdapter() {
21 | mjr_defaultContext(&con_);
22 | }
23 |
24 | PlatformUIAdapter::~PlatformUIAdapter() {
25 | mjr_freeContext(&con_);
26 | }
27 |
28 | bool PlatformUIAdapter::RefreshMjrContext(const mjModel* m, int fontscale) {
29 | if (m != last_model_ || fontscale != last_fontscale_) {
30 | mjr_makeContext(m, &con_, fontscale);
31 | last_model_ = m;
32 | last_fontscale_ = fontscale;
33 | return true;
34 | }
35 | return false;
36 | }
37 |
38 | void PlatformUIAdapter::OnFilesDrop(int count, const char** paths) {
39 | state_.type = mjEVENT_FILESDROP;
40 | state_.dropcount = count;
41 | state_.droppaths = paths;
42 |
43 | // application-specific processing
44 | if (event_callback_) {
45 | event_callback_(&state_);
46 | }
47 |
48 | // remove paths pointer from mjuiState since we don't own it
49 | state_.dropcount = 0;
50 | state_.droppaths = nullptr;
51 | }
52 |
53 | void PlatformUIAdapter::OnKey(int key, int scancode, int act) {
54 | // translate API-specific key code
55 | int mj_key = TranslateKeyCode(key);
56 |
57 | // release: nothing to do
58 | if (!IsKeyDownEvent(act)) {
59 | return;
60 | }
61 |
62 | // update state
63 | UpdateMjuiState();
64 |
65 | // set key info
66 | state_.type = mjEVENT_KEY;
67 | state_.key = mj_key;
68 | state_.keytime = std::chrono::duration(
69 | std::chrono::steady_clock::now().time_since_epoch()).count();
70 |
71 | // application-specific processing
72 | if (event_callback_) {
73 | event_callback_(&state_);
74 | }
75 | }
76 |
77 | void PlatformUIAdapter::OnMouseButton(int button, int act) {
78 | // translate API-specific mouse button code
79 | mjtButton mj_button = TranslateMouseButton(button);
80 |
81 | // update state
82 | UpdateMjuiState();
83 |
84 | // swap left and right if Alt
85 | if (state_.alt) {
86 | if (mj_button == mjBUTTON_LEFT) {
87 | mj_button = mjBUTTON_RIGHT;
88 | } else if (mj_button == mjBUTTON_RIGHT) {
89 | mj_button = mjBUTTON_LEFT;
90 | }
91 | }
92 |
93 | // press
94 | if (IsMouseButtonDownEvent(act)) {
95 | double now = std::chrono::duration(
96 | std::chrono::steady_clock::now().time_since_epoch()).count();
97 |
98 | // detect doubleclick: 250 ms
99 | if (mj_button == state_.button && now - state_.buttontime < 0.25) {
100 | state_.doubleclick = 1;
101 | } else {
102 | state_.doubleclick = 0;
103 | }
104 |
105 | // set info
106 | state_.type = mjEVENT_PRESS;
107 | state_.button = mj_button;
108 | state_.buttontime = now;
109 |
110 | // start dragging
111 | if (state_.mouserect) {
112 | state_.dragbutton = state_.button;
113 | state_.dragrect = state_.mouserect;
114 | }
115 | }
116 |
117 | // release
118 | else {
119 | state_.type = mjEVENT_RELEASE;
120 | }
121 |
122 | // application-specific processing
123 | if (event_callback_) {
124 | event_callback_(&state_);
125 | }
126 |
127 | // stop dragging after application processing
128 | if (state_.type == mjEVENT_RELEASE) {
129 | state_.dragrect = 0;
130 | state_.dragbutton = 0;
131 | }
132 | }
133 |
134 | void PlatformUIAdapter::OnMouseMove(double x, double y) {
135 | // no buttons down: nothing to do
136 | if (!state_.left && !state_.right && !state_.middle) {
137 | return;
138 | }
139 |
140 | // update state
141 | UpdateMjuiState();
142 |
143 | // set move info
144 | state_.type = mjEVENT_MOVE;
145 |
146 | // application-specific processing
147 | if (event_callback_) {
148 | event_callback_(&state_);
149 | }
150 | }
151 |
152 | void PlatformUIAdapter::OnScroll(double xoffset, double yoffset) {
153 | // update state
154 | UpdateMjuiState();
155 |
156 | // set scroll info, scale by buffer-to-window ratio
157 | const double buffer_window_ratio =
158 | static_cast(GetFramebufferSize().first) / GetWindowSize().first;
159 | state_.type = mjEVENT_SCROLL;
160 | state_.sx = xoffset * buffer_window_ratio;
161 | state_.sy = yoffset * buffer_window_ratio;
162 |
163 | // application-specific processing
164 | if (event_callback_) {
165 | event_callback_(&state_);
166 | }
167 | }
168 |
169 | void PlatformUIAdapter::OnWindowRefresh() {
170 | state_.type = mjEVENT_REDRAW;
171 |
172 | // application-specific processing
173 | if (event_callback_) {
174 | event_callback_(&state_);
175 | }
176 | }
177 |
178 | void PlatformUIAdapter::OnWindowResize(int width, int height) {
179 | auto [buf_width, buf_height] = GetFramebufferSize();
180 | state_.rect[0].width = buf_width;
181 | state_.rect[0].height = buf_height;
182 | if (state_.nrect < 1) state_.nrect = 1;
183 |
184 | // update window layout
185 | if (layout_callback_) {
186 | layout_callback_(&state_);
187 | }
188 |
189 | // update state
190 | UpdateMjuiState();
191 |
192 | // set resize info
193 | state_.type = mjEVENT_RESIZE;
194 |
195 | // stop dragging
196 | state_.dragbutton = 0;
197 | state_.dragrect = 0;
198 |
199 | // application-specific processing
200 | if (event_callback_) {
201 | event_callback_(&state_);
202 | }
203 | }
204 |
205 | void PlatformUIAdapter::UpdateMjuiState() {
206 | // mouse buttons
207 | state_.left = IsLeftMouseButtonPressed();
208 | state_.right = IsRightMouseButtonPressed();
209 | state_.middle = IsMiddleMouseButtonPressed();
210 |
211 | // keyboard modifiers
212 | state_.control = IsCtrlKeyPressed();
213 | state_.shift = IsShiftKeyPressed();
214 | state_.alt = IsAltKeyPressed();
215 |
216 | // swap left and right if Alt
217 | if (state_.alt) {
218 | int tmp = state_.left;
219 | state_.left = state_.right;
220 | state_.right = tmp;
221 | }
222 |
223 | // get mouse position, scale by buffer-to-window ratio
224 | auto [x, y] = GetCursorPosition();
225 | const double buffer_window_ratio =
226 | static_cast(GetFramebufferSize().first) / GetWindowSize().first;
227 | x *= buffer_window_ratio;
228 | y *= buffer_window_ratio;
229 |
230 | // invert y to match OpenGL convention
231 | y = state_.rect[0].height - y;
232 |
233 | // save
234 | state_.dx = x - state_.x;
235 | state_.dy = y - state_.y;
236 | state_.x = x;
237 | state_.y = y;
238 |
239 | // find mouse rectangle
240 | state_.mouserect = mjr_findRect(mju_round(x), mju_round(y), state_.nrect-1, state_.rect+1) + 1;
241 | }
242 | } // namespace mujoco
243 |
--------------------------------------------------------------------------------