mirror of
https://github.com/wassname/pyrobolearn.git
synced 2026-09-11 12:31:07 +08:00
update simulators
This commit is contained in:
@@ -1,34 +1,43 @@
|
||||
#!/usr/bin/env python
|
||||
"""Define the RaiSim Simulator API.
|
||||
|
||||
Warnings: Currently, the RaiSim simulator is closed-source and is only available for researchers at RSL and ETH Zurich.
|
||||
This is the main interface that communicates with the RaiSim simulator [1-5]. By defining this interface, it
|
||||
allows to decouple the PyRoboLearn framework from the simulator. It also converts some data types to the ones required
|
||||
by RaiSim. Because it didn't have a Python wrapper, one has been written in the ``raisim_wrapper`` folder using
|
||||
pybind11 [6].
|
||||
|
||||
This is the main interface that communicates with the RaiSim simulator [1, 2]. By defining this interface, it allows to
|
||||
decouple the PyRoboLearn framework from the simulator. It also converts some data types to the ones required by
|
||||
RaiSim.
|
||||
The signature of each method defined here are inspired by [1,2] but in accordance with the PEP8 style guide [7].
|
||||
Parts of the documentation for the methods have been copied-pasted from [2-5] for completeness purposes.
|
||||
|
||||
The signature of each method defined here are inspired by [1,2] but in accordance with the PEP8 style guide [3].
|
||||
Parts of the documentation for the methods have been copied-pasted from [2] for completeness purposes.
|
||||
RaiSim is distributed under the End-User License Agreement (EULA) [8], and officially works on Ubuntu 16.04 and 18.04.
|
||||
|
||||
Dependencies in PRL:
|
||||
* `pyrobolearn.simulators.simulator.Simulator`
|
||||
|
||||
References:
|
||||
[1] "Per-Contact Iteration Method for Solving Contact Dynamics", Hwangbo et al., 2018
|
||||
[2] RaiSim: https://leggedrobotics.github.io/SimBenchmark/about/sims.html
|
||||
[3] PEP8: https://www.python.org/dev/peps/pep-0008/
|
||||
- [1] "Per-Contact Iteration Method for Solving Contact Dynamics", Hwangbo et al., 2018
|
||||
- [2] RaiSim benchmarks: https://leggedrobotics.github.io/SimBenchmark/about/sims.html
|
||||
- [3] RaiSim, a physics engine for robotics and AI research: https://github.com/leggedrobotics/raisimLib
|
||||
- [4] raisimOgre - Visualizer for raisim: https://github.com/leggedrobotics/raisimOgre
|
||||
- [5] raisimGym - RL examples using raisim: https://github.com/leggedrobotics/raisimGym
|
||||
- [6] pybind11 (documentation): https://pybind11.readthedocs.io/en/stable/
|
||||
- [7] PEP8: https://www.python.org/dev/peps/pep-0008/
|
||||
- [8] RaiSim license: https://github.com/leggedrobotics/raisimLib/blob/master/LICENSE.md
|
||||
"""
|
||||
|
||||
# TODO:
|
||||
# 1. wait for ETH to release the simulator (not sure if they will ever do it...)
|
||||
# 2. check if a Python wrapper is provided, if not, will have to implement it
|
||||
# import raisim
|
||||
try:
|
||||
import raisimpy as raisim
|
||||
except ImportError as e:
|
||||
print(e.__str__() + "\nHINT: you need to install `raisimLib` and `raisimOgre`, and build the Python wrappers "
|
||||
"that are located in the `raisim_wrapper` folder.")
|
||||
|
||||
# import PRL simulator
|
||||
from pyrobolearn.simulators.simulator import Simulator
|
||||
|
||||
__author__ = "Brian Delhaisse"
|
||||
__copyright__ = "Copyright 2018, PyRoboLearn"
|
||||
__credits__ = ["RaiSim (ETHz)", "Brian Delhaisse"]
|
||||
__credits__ = ["RaiSim (ETHz, Hwangbo, Kang, Lee)", "Brian Delhaisse (Python wrappers + PRL)"]
|
||||
__license__ = "GNU GPLv3"
|
||||
__version__ = "1.0.0"
|
||||
__maintainer__ = "Brian Delhaisse"
|
||||
@@ -52,6 +61,14 @@ class Raisim(Simulator):
|
||||
|
||||
def __init__(self, render=True, **kwargs):
|
||||
super(Raisim, self).__init__(render, **kwargs)
|
||||
|
||||
# create world
|
||||
self.world = raisim.World()
|
||||
self.sim = self.world # alias
|
||||
|
||||
# create visualizer if specified
|
||||
self.visualizer = None
|
||||
|
||||
raise NotImplementedError("The RaiSim simulator is not currently available as it has not been released for "
|
||||
"the moment")
|
||||
|
||||
|
||||
@@ -0,0 +1,25 @@
|
||||
# Run: cmake -DPYBIND11_PYTHON_VERSION=<PYTHON_VERSION> -DCMAKE_PREFIX_PATH=$LOCAL_BUILD ..
|
||||
# where <PYTHON_VERSION>=2.7 or 3.*, LOCAL_BUILD is the build for raisimLib and raisimOgre
|
||||
|
||||
cmake_minimum_required(VERSION 2.8.9)
|
||||
project (raisim_wrapper)
|
||||
|
||||
# find the various packages
|
||||
find_package(pybind11 REQUIRED)
|
||||
find_package(Eigen3 REQUIRED eigen3)
|
||||
# find_package(OpenMP REQUIRED)
|
||||
find_package(raisim CONFIG REQUIRED)
|
||||
find_package(raisimOgre CONFIG REQUIRED)
|
||||
|
||||
# header files
|
||||
include_directories(include ${EIGEN3_INCLUDE_DIRS})
|
||||
|
||||
# set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${OpenMP_C_FLAGS}")
|
||||
# set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${OpenMP_CXX_FLAGS}")
|
||||
# set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} ${OpenMP_EXE_LINKER_FLAGS}")
|
||||
|
||||
# source files
|
||||
file(GLOB SOURCES "src/*.cpp")
|
||||
|
||||
pybind11_add_module(raisimpy ${SOURCES})
|
||||
target_link_libraries(raisimpy raisim::raisim raisim::raisimOgre)
|
||||
@@ -0,0 +1,21 @@
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2019, Brian Delhaisse <briandelhaisse@gmail.com>
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
@@ -0,0 +1,61 @@
|
||||
Python wrapper for RaiSim
|
||||
=========================
|
||||
|
||||
This folder contains a python wrapper around RaiSim (``raisimLib`` and ``raisimOgre``) using ``pybind11``.
|
||||
|
||||
Parts of the wrappers were taken and modified from (or inspired by) the code given in the ``raisimGym/raisim_gym/env/``
|
||||
folder. If you use these wrappers in PRL, please acknowledge their contribution as well by citing [1-4].
|
||||
|
||||
|
||||
How to use the wrappers?
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
In order to use the wrappers, you will have to install at least
|
||||
`raisimLib <https://github.com/leggedrobotics/raisimLib>`_ and
|
||||
`raisimOgre <https://github.com/leggedrobotics/raisimOgre>`_. You will also have to install
|
||||
`pybind11 <https://pybind11.readthedocs.io/en/stable/>`_ as we use this to wrap the C++ code.
|
||||
|
||||
Then you will have to compile the code from the ``raisim_wrapper`` folder by typing:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
mkdir build && cd build
|
||||
cmake -DPYBIND11_PYTHON_VERSION=$PYTHON_VERSION -DCMAKE_PREFIX_PATH=$LOCAL_BUILD ..
|
||||
make
|
||||
|
||||
where ``PYTHON_VERSION=2.7 or 3.*`` and ``LOCAL_BUILD`` is the build directory where we installed the exported cmake
|
||||
libraries (as described in [2-4]).
|
||||
|
||||
Once it has been compiled, you can access to the Python library ``raisim`` in your code with:
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
import raisim
|
||||
|
||||
print(dir(raisim))
|
||||
|
||||
|
||||
References
|
||||
~~~~~~~~~~
|
||||
|
||||
- [1] "Per-contact iteration method for solving contact dynamics", Hwangbo et al., 2018
|
||||
- [2] raisimLib: https://github.com/leggedrobotics/raisimLib
|
||||
- [3] raisimOgre: https://github.com/leggedrobotics/raisimOgre
|
||||
- [4] raisimGym: https://github.com/leggedrobotics/raisimGym
|
||||
- [5] pybind11: https://pybind11.readthedocs.io/en/stable/
|
||||
|
||||
|
||||
Troubleshooting
|
||||
~~~~~~~~~~~~~~~
|
||||
|
||||
- ``fatal error: Eigen/*: No such file or directory``
|
||||
- If you have Eigen3 installed on your system, you probably have to replace all the ``#include <Eigen/*>`` by
|
||||
``#include <eigen3/Eigen/*>``. You can create symlinks to solve this issue:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
cd /usr/local/include
|
||||
sudo ln -sf eigen3/Eigen Eigen
|
||||
sudo ln -sf eigen3/unsupported unsupported
|
||||
|
||||
or you can replace the ``#include <Eigen/*>`` by ``#include <eigen3/Eigen/*>``.
|
||||
@@ -0,0 +1,141 @@
|
||||
/**
|
||||
* Type converters used to convert between different data types.
|
||||
*
|
||||
* Copyright (c) 2019, Brian Delhaisse <briandelhaisse@gmail.com>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef CONVERTER_H
|
||||
#define CONVERTER_H
|
||||
|
||||
#include <pybind11/pybind11.h>
|
||||
#include <pybind11/numpy.h> // numpy types
|
||||
|
||||
#include <sstream> // for ostringstream
|
||||
#include "raisim/math.hpp" // contains the definitions of Vec, Mat, VecDyn, MatDyn, etc.
|
||||
|
||||
namespace py = pybind11;
|
||||
|
||||
|
||||
/// \brief: convert from raisim::Vec<n> to np.array
|
||||
template<size_t n>
|
||||
py::array_t<double> convert_vec_to_np(const raisim::Vec<n> &vec) {
|
||||
const double *ptr = vec.ptr(); // get data pointer
|
||||
|
||||
// return np.array[float64[n]]
|
||||
return py::array_t<double>(
|
||||
{n}, // shape
|
||||
{sizeof(double)}, // C-style contiguous strides for double (double=8 bytes)
|
||||
ptr); // data pointer
|
||||
// vec); // numpy array references this parent
|
||||
}
|
||||
|
||||
|
||||
/// \brief: convert from np.array[float[n]] to raisim::Vec<n>
|
||||
template<size_t n>
|
||||
raisim::Vec<n> convert_np_to_vec(py::array_t<double> array) {
|
||||
|
||||
// check size
|
||||
if (array.size() != n) {
|
||||
std::ostringstream s;
|
||||
s << "error: expecting the given vector to be of size " << n << " but got instead a size of "
|
||||
<< array.size() << ".";
|
||||
throw std::domain_error(s.str());
|
||||
}
|
||||
|
||||
// reshape if necessary
|
||||
if (array.ndim() > 1)
|
||||
array.resize({n});
|
||||
|
||||
// create raisim vector
|
||||
raisim::Vec<n> vec;
|
||||
|
||||
// copy the data
|
||||
for(size_t i=0; i<n; i++) {
|
||||
vec[i] = *array.data(i);
|
||||
}
|
||||
|
||||
// return vector
|
||||
return vec;
|
||||
}
|
||||
|
||||
|
||||
/// \brief: convert from raisim::Mat<n,m> to np.array[float64[n,m]]
|
||||
template<size_t n, size_t m>
|
||||
py::array_t<double> convert_mat_to_np(const raisim::Mat<n, m> &mat) {
|
||||
const double *ptr = mat.ptr(); // get data pointer
|
||||
|
||||
// return np.array[float64[n,m]]
|
||||
return py::array_t<double>(
|
||||
{n, m}, // shape
|
||||
{sizeof(double), sizeof(double)}, // C-style contiguous strides for double (double=8bytes)
|
||||
ptr);
|
||||
// mat); // numpy array references this parent
|
||||
}
|
||||
|
||||
|
||||
/// \brief: convert from np.array[float[n,m]] to raisim::Mat<n,m>
|
||||
template<size_t n, size_t m>
|
||||
raisim::Mat<n, m> convert_np_to_mat(py::array_t<double> array) {
|
||||
|
||||
// check dimensions and shape
|
||||
if (array.ndim() != 2) {
|
||||
std::ostringstream s;
|
||||
s << "error: expecting the given array to have a dimension of 2, but got instead a dimension of "
|
||||
<< array.ndim() << ".";
|
||||
throw std::domain_error(s.str());
|
||||
}
|
||||
if ((array.shape(0) != n) || (array.shape(1) != m)) {
|
||||
std::ostringstream s;
|
||||
s << "error: expecting the given array to have the following shape (" << n << ", " << m
|
||||
<< "), but got instead the shape ("<< array.shape(0) << ", " << array.shape(1) << ").";
|
||||
throw std::domain_error(s.str());
|
||||
}
|
||||
|
||||
// create raisim matrix
|
||||
raisim::Mat<n, m> mat;
|
||||
|
||||
// copy the data
|
||||
for (size_t i=0; i<n; i++)
|
||||
for (size_t j=0; j<m; j++)
|
||||
mat[i, j] = *array.data(i, j);
|
||||
|
||||
// return matrix
|
||||
return mat;
|
||||
}
|
||||
|
||||
|
||||
/// \brief: convert from raisim::VecDyn to np.array[float64[n]]
|
||||
py::array_t<double> convert_vecdyn_to_np(const raisim::VecDyn &vec);
|
||||
|
||||
|
||||
/// \brief: convert from np.array[float[n]] to raisim::VecDyn
|
||||
raisim::VecDyn convert_np_to_vecdyn(py::array_t<double> array);
|
||||
|
||||
|
||||
/// \brief: convert from raisim::MatDyn to np.array[float64[n,m]]
|
||||
py::array_t<double> convert_matdyn_to_np(const raisim::MatDyn &mat);
|
||||
|
||||
|
||||
/// \brief: convert from np.array[float[n,m]] to raisim::MatDyn
|
||||
raisim::MatDyn convert_np_to_matdyn(py::array_t<double> array);
|
||||
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,90 @@
|
||||
/**
|
||||
* Python wrappers for raisim.object.ArticulatedSystem using pybind11.
|
||||
*
|
||||
* Copyright (c) 2019, Brian Delhaisse <briandelhaisse@gmail.com>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
#include <pybind11/pybind11.h>
|
||||
#include <pybind11/stl.h> // automatic conversion between std::vector, std::list, etc to Python list/tuples/dict
|
||||
#include <pybind11/eigen.h> // automatic conversion between Eigen data types to Numpy data types
|
||||
|
||||
#include "raisim/math.hpp" // contains the definitions of Vec, Mat, etc.
|
||||
#include "raisim/World.hpp"
|
||||
|
||||
namespace py = pybind11;
|
||||
using namespace raisim;
|
||||
|
||||
|
||||
void init_articulated_system(py::module &m) {
|
||||
|
||||
|
||||
/****************/
|
||||
/* LoadFromMJCF */
|
||||
/****************/
|
||||
// py::class_<raisim::mjcf::LoadFromMJCF>(m, "LoadFromMJCF", "Load from MJCF file.");
|
||||
|
||||
|
||||
/*****************/
|
||||
/* LoadFromURDF2 */
|
||||
/*****************/
|
||||
// py::class_<raisim::urdf::LoadFromURDF2>(m, "LoadFromURDF2", "Load from URDF file.");
|
||||
|
||||
|
||||
/***************/
|
||||
/* ControlMode */
|
||||
/***************/
|
||||
py::enum_<raisim::ControlMode::Type>(m, "Type", py::arithmetic())
|
||||
.value("FORCE_AND_TORQUE", raisim::ControlMode::Type::FORCE_AND_TORQUE)
|
||||
.value("PD_PLUS_FEEDFORWARD_TORQUE", raisim::ControlMode::Type::PD_PLUS_FEEDFORWARD_TORQUE)
|
||||
.value("VELOCITY_PLUS_FEEDFORWARD_TORQUE", raisim::ControlMode::Type::VELOCITY_PLUS_FEEDFORWARD_TORQUE);
|
||||
|
||||
|
||||
/***************************/
|
||||
/* ArticulatedSystemOption */
|
||||
/***************************/
|
||||
py::class_<raisim::ArticulatedSystemOption>(m, "ArticulatedSystemOption", "Articulated System Option.")
|
||||
.def_readwrite("do_not_collide_with_parent", &raisim::ArticulatedSystemOption::doNotCollideWithParent);
|
||||
|
||||
|
||||
/*********************/
|
||||
/* ArticulatedSystem */
|
||||
/*********************/
|
||||
py::class_<raisim::ArticulatedSystem, raisim::Object> system(m, "ArticulatedSystem", "Raisim Articulated System.");
|
||||
|
||||
system.def(py::init<>(), "Initialize the Articulated System.")
|
||||
.def(py::init<const std::string &, const std::string &, std::vector<std::string>, raisim::ArticulatedSystemOption>(),
|
||||
"Initialize the Articulated System." ) // TODO: finish the doc
|
||||
.def("get_generalized_coordinate", [](raisim::ArticulatedSystem &self) {
|
||||
return ;
|
||||
})
|
||||
.def("update_kinematics", &raisim::ArticulatedSystem::updateKinematics, R"mydelimiter(
|
||||
unnecessary to call this function if you are simulating your system. `integrate1` calls this function Call
|
||||
this function if you want to get kinematic properties but you don't want to integrate.
|
||||
)mydelimiter")
|
||||
;
|
||||
|
||||
py::enum_<raisim::ArticulatedSystem::Frame>(system, "Frame")
|
||||
.value("WORLD_FRAME", raisim::ArticulatedSystem::Frame::WORLD_FRAME)
|
||||
.value("PARENT_FRAME", raisim::ArticulatedSystem::Frame::PARENT_FRAME)
|
||||
.value("BODY_FRAME", raisim::ArticulatedSystem::Frame::BODY_FRAME);
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,225 @@
|
||||
/**
|
||||
* Python wrappers for raisim.constraints using pybind11.
|
||||
*
|
||||
* Copyright (c) 2019, Brian Delhaisse <briandelhaisse@gmail.com>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
#include <pybind11/pybind11.h>
|
||||
#include <pybind11/stl.h> // automatic conversion between std::vector, std::list, etc to Python list/tuples/dict
|
||||
#include <pybind11/eigen.h> // automatic conversion between Eigen data types to Numpy data types
|
||||
|
||||
#include "raisim/math.hpp" // contains the definitions of Vec, Mat, etc.
|
||||
#include "raisim/object/Object.hpp"
|
||||
#include "raisim/constraints/Constraints.hpp"
|
||||
#include "raisim/constraints/Wire.hpp"
|
||||
#include "raisim/constraints/StiffWire.hpp"
|
||||
#include "raisim/constraints/CompliantWire.hpp"
|
||||
|
||||
#include "converter.hpp" // contains code that allows to convert between the Vec, Mat to numpy arrays.
|
||||
|
||||
namespace py = pybind11;
|
||||
using namespace raisim;
|
||||
|
||||
|
||||
void init_constraints(py::module &m) {
|
||||
|
||||
|
||||
// create submodule
|
||||
py::module constraints_module = m.def_submodule("constraints", "RaiSim contact submodule.");
|
||||
|
||||
|
||||
/**************/
|
||||
/* Constraint */
|
||||
/**************/
|
||||
py::class_<raisim::Constraints>(constraints_module, "Constraints", "Raisim Constraints from which all other constraints inherit from.");
|
||||
|
||||
|
||||
//
|
||||
// /********/
|
||||
// /* Wire */
|
||||
// /********/
|
||||
// py::class_<raisim::Wire>(constraints_module, "Wire", "Raisim Wire constraint class; it creates a wire constraint between 2 bodies.")
|
||||
// .def("__init__", [](raisim::Wire &self, Object &object1, size_t local_idx1, py::array_t<double> pos_body1,
|
||||
// Object &object2, size_t local_idx2, py::array_t<double> pos_body2, double length)
|
||||
// {
|
||||
// // convert the arrays to Vec<3>
|
||||
// raisim::Vec<3> pos1 = convert_np_to_vec<3>(pos_body1);
|
||||
// raisim::Vec<3> pos2 = convert_np_to_vec<3>(pos_body2);
|
||||
//
|
||||
// // instantiate the class
|
||||
// new (&self) raisim::Wire(&object1, local_idx1, pos1, &object2, local_idx2, pos2, length);
|
||||
// },
|
||||
// "Instantiate the wire constraint class.\n\n"
|
||||
// "Args:\n"
|
||||
// " object1 (Object): first object/body instance.\n"
|
||||
// " local_idx1 (int): local index of the first object/body.\n"
|
||||
// " pos_body1 (np.array[float[3]]): position of the constraint on the first body.\n"
|
||||
// " object2 (Object): second object/body instance.\n"
|
||||
// " local_idx2 (int): local index of the second object/body.\n"
|
||||
// " pos_body2 (np.array[float[3]]): position of the constraint on the second body.\n"
|
||||
// " length (float): length of the wire constraint.")
|
||||
//
|
||||
//
|
||||
// .def("update", &raisim::Wire::update, "update internal variables (called by `integrate1()`).")
|
||||
//
|
||||
//
|
||||
// .def("get_length", &raisim::Wire::getLength, R"mydelimiter(
|
||||
// Get the length of the wire constraint.
|
||||
//
|
||||
// Returns:
|
||||
// float: length of the wire constraint.
|
||||
// )mydelimiter")
|
||||
//
|
||||
//
|
||||
// .def("get_p1", [](raisim::Wire &self) {
|
||||
// Vec<3> p1 = self.getP1();
|
||||
// return convert_vec_to_np(p1);
|
||||
// }, R"mydelimiter(
|
||||
// Return the first attachment point in the World frame.
|
||||
//
|
||||
// Returns:
|
||||
// np.array[float[3]]: first point position expressed in the world frame.
|
||||
// )mydelimiter")
|
||||
//
|
||||
//
|
||||
// .def("get_p2", [](raisim::Wire &self) {
|
||||
// Vec<3> p2 = self.getP2();
|
||||
// return convert_vec_to_np(p2);
|
||||
// }, R"mydelimiter(
|
||||
// Return the second attachment point in the World frame.
|
||||
//
|
||||
// Returns:
|
||||
// np.array[float[3]]: second point position expressed in the world frame.
|
||||
// )mydelimiter")
|
||||
//
|
||||
//
|
||||
// .def("get_body1", &raisim::Wire::getBody1, R"mydelimiter(
|
||||
// Return the first object to which the wire is attached.
|
||||
//
|
||||
// Returns:
|
||||
// Object: first object.
|
||||
// )mydelimiter")
|
||||
//
|
||||
//
|
||||
// .def("get_body2", &raisim::Wire::getBody2, R"mydelimiter(
|
||||
// Return the second object to which the wire is attached.
|
||||
//
|
||||
// Returns:
|
||||
// Object: second object.
|
||||
// )mydelimiter")
|
||||
//
|
||||
//
|
||||
// .def("get_normal", [](raisim::Wire &self) {
|
||||
// Vec<3> normal = self.getNorm();
|
||||
// return convert_vec_to_np(normal);
|
||||
// }, R"mydelimiter(
|
||||
// Return the direction of the normal (i.e., p2-p1 normalized)
|
||||
//
|
||||
// Returns:
|
||||
// np.array[float[3]]: direction of the normal.
|
||||
// )mydelimiter")
|
||||
//
|
||||
//
|
||||
// .def("get_local_idx1", &raisim::Wire::getLocalIdx1, R"mydelimiter(
|
||||
// Return the local index of object1.
|
||||
//
|
||||
// Returns:
|
||||
// int: local index of object1.
|
||||
// )mydelimiter")
|
||||
//
|
||||
//
|
||||
// .def("get_local_idx2", &raisim::Wire::getLocalIdx2, R"mydelimiter(
|
||||
// Return the local index of object2.
|
||||
//
|
||||
// Returns:
|
||||
// int: local index of object2.
|
||||
// )mydelimiter")
|
||||
//
|
||||
//
|
||||
// .def("get_stretch", &raisim::Wire::getStretch, R"mydelimiter(
|
||||
// Return the stretch length (i.e., constraint violation).
|
||||
//
|
||||
// Returns:
|
||||
// float: stretch length.
|
||||
// )mydelimiter")
|
||||
//
|
||||
//
|
||||
// .def_property("name", &raisim::Wire::getName, &raisim::Object::setName)
|
||||
// .def("get_name", &raisim::Wire::getName, "Get the wire constraint's name.")
|
||||
// .def("set_name", &raisim::Wire::setName, "Set the wire constraint's name.", py::arg("name"))
|
||||
// .def_readwrite("is_active", &raisim::Wire::isActive)
|
||||
// ;
|
||||
//
|
||||
//
|
||||
// /*************/
|
||||
// /* StiffWire */
|
||||
// /*************/
|
||||
//
|
||||
// py::class_<raisim::StiffWire>(constraints_module, "StiffWire", "Raisim StiffWire constraint class; it creates a stiff wire constraint between 2 bodies.")
|
||||
// .def("__init__", [](raisim::StiffWire &self, Object &object1, size_t local_idx1, py::array_t<double> pos_body1,
|
||||
// Object &object2, size_t local_idx2, py::array_t<double> pos_body2, double length)
|
||||
// {
|
||||
// // convert the arrays to Vec<3>
|
||||
// raisim::Vec<3> pos1 = convert_np_to_vec<3>(pos_body1);
|
||||
// raisim::Vec<3> pos2 = convert_np_to_vec<3>(pos_body2);
|
||||
//
|
||||
// // instantiate the class
|
||||
// new (&self) raisim::StiffWire(&object1, local_idx1, pos1, &object2, local_idx2, pos2, length);
|
||||
// },
|
||||
// "Instantiate the stiff wire constraint class.\n\n"
|
||||
// "Args:\n"
|
||||
// " object1 (Object): first object/body instance.\n"
|
||||
// " local_idx1 (int): local index of the first object/body.\n"
|
||||
// " pos_body1 (np.array[float[3]]): position of the constraint on the first body.\n"
|
||||
// " object2 (Object): second object/body instance.\n"
|
||||
// " local_idx2 (int): local index of the second object/body.\n"
|
||||
// " pos_body2 (np.array[float[3]]): position of the constraint on the second body.\n"
|
||||
// " length (float): length of the wire constraint.");
|
||||
//
|
||||
//
|
||||
// /*****************/
|
||||
// /* CompliantWire */
|
||||
// /*****************/
|
||||
//
|
||||
// py::class_<raisim::CompliantWire>(constraints_module, "CompliantWire", "Raisim Compliant Wire constraint class; it creates a compliant wire constraint between 2 bodies.")
|
||||
// .def("__init__", [](raisim::CompliantWire &self, Object &object1, size_t local_idx1, py::array_t<double> pos_body1,
|
||||
// Object &object2, size_t local_idx2, py::array_t<double> pos_body2, double length, double stiffness)
|
||||
// {
|
||||
// // convert the arrays to Vec<3>
|
||||
// raisim::Vec<3> pos1 = convert_np_to_vec<3>(pos_body1);
|
||||
// raisim::Vec<3> pos2 = convert_np_to_vec<3>(pos_body2);
|
||||
//
|
||||
// // instantiate the class
|
||||
// new (&self) raisim::CompliantWire(&object1, local_idx1, pos1, &object2, local_idx2, pos2, length, stiffness);
|
||||
// },
|
||||
// "Instantiate the compliant wire constraint class.\n\n"
|
||||
// "Args:\n"
|
||||
// " object1 (Object): first object/body instance.\n"
|
||||
// " local_idx1 (int): local index of the first object/body.\n"
|
||||
// " pos_body1 (np.array[float[3]]): position of the constraint on the first body.\n"
|
||||
// " object2 (Object): second object/body instance.\n"
|
||||
// " local_idx2 (int): local index of the second object/body.\n"
|
||||
// " pos_body2 (np.array[float[3]]): position of the constraint on the second body.\n"
|
||||
// " length (float): length of the wire constraint.\n"
|
||||
// " stiffness (float): stiffness of the wire.")
|
||||
// .def("apply_tension", &raisim::CompliantWire::applyTension, "Apply a tension in the compliant wire.")
|
||||
|
||||
}
|
||||
@@ -0,0 +1,249 @@
|
||||
/**
|
||||
* Python wrappers for raisim.contact using pybind11.
|
||||
*
|
||||
* Copyright (c) 2019, Brian Delhaisse <briandelhaisse@gmail.com>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
#include <pybind11/pybind11.h>
|
||||
#include <pybind11/stl.h> // automatic conversion between std::vector, std::list, etc to Python list/tuples/dict
|
||||
#include <pybind11/eigen.h> // automatic conversion between Eigen data types to Numpy data types
|
||||
|
||||
#include "raisim/math.hpp" // contains the definitions of Vec, Mat, etc.
|
||||
#include "raisim/contact/Contact.hpp"
|
||||
#include "raisim/contact/BisectionContactSolver.hpp"
|
||||
#include "raisim/contact/PerObjectContactList.hpp"
|
||||
|
||||
#include "converter.hpp" // contains code that allows to convert between the Vec, Mat to numpy arrays.
|
||||
|
||||
namespace py = pybind11;
|
||||
using namespace raisim;
|
||||
|
||||
|
||||
void init_contact(py::module &m) {
|
||||
|
||||
|
||||
// create submodule
|
||||
py::module contact_module = m.def_submodule("contact", "RaiSim contact submodule.");
|
||||
|
||||
|
||||
/*****************/
|
||||
/* Contact class */
|
||||
/*****************/
|
||||
py::class_<raisim::contact::Contact>(contact_module, "Contact", "Raisim Contact.")
|
||||
.def("__init__", [](raisim::contact::Contact &self, py::array_t<double> position, py::array_t<double> normal,
|
||||
bool objectA, size_t contact_problem_index, size_t contact_index_in_object, size_t pair_object_index,
|
||||
BodyType pair_object_body_type, size_t pair_contact_index_in_pair_object, size_t local_body_index,
|
||||
double depth)
|
||||
{
|
||||
// convert the arrays to Vec<3>
|
||||
raisim::Vec<3> pos = convert_np_to_vec<3>(position);
|
||||
raisim::Vec<3> norm = convert_np_to_vec<3>(normal);
|
||||
|
||||
// instantiate the class
|
||||
new (&self) raisim::contact::Contact(pos, norm, objectA, contact_problem_index, contact_index_in_object,
|
||||
pair_object_index, pair_object_body_type, pair_contact_index_in_pair_object, local_body_index, depth);
|
||||
},
|
||||
"Instantiate the contact class.\n\n"
|
||||
"Args:\n"
|
||||
" position (np.array[float[3]]): position vector.\n"
|
||||
" normal (np.array[float[3]]): normal vector.\n"
|
||||
" objectA (bool): True if object A.\n"
|
||||
" contact_problem_index (int): contact problem index.\n"
|
||||
" contact_index_in_object (int): contact index in object (an object can be in contact at multiple points).\n"
|
||||
" pair_object_index (int): pair object index.\n"
|
||||
" pair_object_index (BodyType): pair object body type between {STATIC, KINEMATIC, DYNAMIC}.\n"
|
||||
" pair_contact_index_in_pair_object (int): pair contact index in pair object.\n"
|
||||
" local_body_index (int): local body index."
|
||||
" depth (float): depth of the contact.")
|
||||
|
||||
|
||||
.def("get_position", [](raisim::contact::Contact &self) {
|
||||
Vec<3> position = self.getPosition();
|
||||
return convert_vec_to_np(position);
|
||||
}, R"mydelimiter(
|
||||
Get the contact position.
|
||||
|
||||
Returns:
|
||||
np.array[float[3]]: contact position in the world.
|
||||
)mydelimiter")
|
||||
|
||||
|
||||
.def("get_normal", [](raisim::contact::Contact &self) {
|
||||
Vec<3> normal = self.getNormal();
|
||||
return convert_vec_to_np(normal);
|
||||
}, R"mydelimiter(
|
||||
Get the contact normal.
|
||||
|
||||
Returns:
|
||||
np.array[float[3]]: contact normal in the world.
|
||||
)mydelimiter")
|
||||
|
||||
|
||||
.def("get_contact_frame", [](raisim::contact::Contact &self) {
|
||||
Mat<3, 3> frame = self.getContactFrame();
|
||||
return convert_mat_to_np(frame);
|
||||
}, R"mydelimiter(
|
||||
Get the contact frame.
|
||||
|
||||
Returns:
|
||||
np.array[float[3, 3]]: contact frame.
|
||||
)mydelimiter")
|
||||
|
||||
|
||||
.def("get_index_contact_problem", &raisim::contact::Contact::getIndexContactProblem, R"mydelimiter(
|
||||
Get the index contact problem.
|
||||
|
||||
Returns:
|
||||
int: index.
|
||||
)mydelimiter")
|
||||
|
||||
|
||||
.def("get_pair_object_index", &raisim::contact::Contact::getPairObjectIndex, R"mydelimiter(
|
||||
Get the pair object index.
|
||||
|
||||
Returns:
|
||||
int: index.
|
||||
)mydelimiter")
|
||||
|
||||
|
||||
.def("get_pair_contact_index_in_pair_object", &raisim::contact::Contact::getPairContactIndexInPairObject, R"mydelimiter(
|
||||
Get the pair contact index in pair objects.
|
||||
|
||||
Returns:
|
||||
int: index.
|
||||
)mydelimiter")
|
||||
|
||||
|
||||
.def("get_impulse", [](raisim::contact::Contact &self) {
|
||||
Vec<3> *impulse = self.getImpulse();
|
||||
return convert_vec_to_np(*impulse);
|
||||
}, R"mydelimiter(
|
||||
Get the impulse.
|
||||
|
||||
Returns:
|
||||
np.array[float[3]]: impulse.
|
||||
)mydelimiter")
|
||||
|
||||
|
||||
.def("is_objectA", &raisim::contact::Contact::isObjectA, R"mydelimiter(
|
||||
Check if it is object A.
|
||||
|
||||
Returns:
|
||||
bool: True if object A is in contact.
|
||||
)mydelimiter")
|
||||
|
||||
|
||||
.def("get_pair_object_body_type", &raisim::contact::Contact::getPairObjectBodyType, R"mydelimiter(
|
||||
Get the pair object body type.
|
||||
|
||||
Returns:
|
||||
raisim.BodyType: the body type (STATIC, KINEMATIC, DYNAMIC)
|
||||
)mydelimiter")
|
||||
|
||||
|
||||
.def("set_impulse", [](raisim::contact::Contact &self, py::array_t<double> impulse) {
|
||||
Vec<3> impulse_ = convert_np_to_vec<3>(impulse);
|
||||
self.setImpulse(&impulse_);
|
||||
}, R"mydelimiter(
|
||||
Set the impulse.
|
||||
|
||||
Args:
|
||||
np.array[float[3]]: impulse.
|
||||
)mydelimiter",
|
||||
py::arg("impulse"))
|
||||
|
||||
|
||||
.def("set_inverse_inertia", [](raisim::contact::Contact &self, py::array_t<double> inverse_inertia) {
|
||||
Mat<3, 3> I_ = convert_np_to_mat<3, 3>(inverse_inertia);
|
||||
self.setInvInertia(&I_);
|
||||
}, R"mydelimiter(
|
||||
Set the inverse of the inertia matrix.
|
||||
|
||||
Args:
|
||||
np.array[float[3,3]]: inverse of the inertia matrix.
|
||||
)mydelimiter",
|
||||
py::arg("inverse_inertia"))
|
||||
|
||||
|
||||
.def("get_inverse_inertia", [](raisim::contact::Contact &self) {
|
||||
const Mat<3, 3> *I_ = self.getInvInertia();
|
||||
return convert_mat_to_np(*I_);
|
||||
}, R"mydelimiter(
|
||||
Get the inverse inertia matrix.
|
||||
|
||||
Returns:
|
||||
np.array[float[3,3]]: inverse of the inertia matrix.
|
||||
)mydelimiter")
|
||||
|
||||
|
||||
.def("get_local_body_index", &raisim::contact::Contact::getlocalBodyIndex, R"mydelimiter(
|
||||
Get local body index.
|
||||
|
||||
Returns:
|
||||
int: local body index.
|
||||
)mydelimiter")
|
||||
|
||||
|
||||
.def("get_depth", &raisim::contact::Contact::getDepth, R"mydelimiter(
|
||||
Get the depth.
|
||||
|
||||
Returns:
|
||||
float: depth.
|
||||
)mydelimiter")
|
||||
|
||||
|
||||
.def("is_self_collision", &raisim::contact::Contact::isSelfCollision, R"mydelimiter(
|
||||
Return True if self-collision is enabled.
|
||||
|
||||
Returns:
|
||||
bool: True if self-collision is enabled.
|
||||
)mydelimiter")
|
||||
|
||||
|
||||
.def("set_self_collision", &raisim::contact::Contact::setSelfCollision, "Enable self-collision.")
|
||||
|
||||
|
||||
.def("skip", &raisim::contact::Contact::skip, R"mydelimiter(
|
||||
Return True if we contact is skipped.
|
||||
|
||||
Returns:
|
||||
bool: True if the contact is skipped.
|
||||
)mydelimiter")
|
||||
|
||||
|
||||
.def("set_skip", &raisim::contact::Contact::setSkip, "Skip this contact.");
|
||||
|
||||
|
||||
/**************************/
|
||||
/* BisectionContactSolver */
|
||||
/**************************/
|
||||
|
||||
py::class_<raisim::contact::Single3DContactProblem>(contact_module, "Single3DContactProblem", "Raisim single 3D contact problem.")
|
||||
.def(py::init<>(), "Initialize the single 3D contact problem.")
|
||||
.def(py::init<const MaterialPairProperties&, double, double, double, double>())
|
||||
.def("check_rank", &raisim::contact::Single3DContactProblem::checkRank)
|
||||
;
|
||||
|
||||
/************************/
|
||||
/* PerObjectContactList */
|
||||
/************************/
|
||||
|
||||
}
|
||||
@@ -0,0 +1,106 @@
|
||||
/**
|
||||
* Type converters used to convert between different data types.
|
||||
*
|
||||
* Copyright (c) 2019, Brian Delhaisse <briandelhaisse@gmail.com>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "converter.hpp"
|
||||
|
||||
namespace py = pybind11;
|
||||
|
||||
|
||||
/// \brief: convert from raisim::VecDyn to np.array[float64[n]]
|
||||
py::array_t<double> convert_vecdyn_to_np(const raisim::VecDyn &vec) {
|
||||
const double *ptr = vec.ptr(); // get data pointer
|
||||
size_t n = vec.n; // get dimension
|
||||
|
||||
// return np.array[float64[n,m]]
|
||||
return py::array_t<double>(
|
||||
{n}, // shape
|
||||
{sizeof(double)}, // C-style contiguous strides for double (double=8bytes)
|
||||
ptr);
|
||||
// vec); // numpy array references this parent
|
||||
}
|
||||
|
||||
|
||||
/// \brief: convert from np.array[float[n]] to raisim::VecDyn
|
||||
raisim::VecDyn convert_np_to_vecdyn(py::array_t<double> array) {
|
||||
|
||||
size_t size = array.size();
|
||||
|
||||
// reshape if necessary
|
||||
if (array.ndim() > 1)
|
||||
array.resize({size});
|
||||
|
||||
// create raisim dynamic vector
|
||||
raisim::VecDyn vec(size);
|
||||
|
||||
// copy the data
|
||||
for(size_t i=0; i<size; i++) {
|
||||
vec[i] = *array.data(i);
|
||||
}
|
||||
|
||||
// return vector
|
||||
return vec;
|
||||
}
|
||||
|
||||
|
||||
/// \brief: convert from raisim::MatDyn to np.array[float64[n,m]]
|
||||
py::array_t<double> convert_matdyn_to_np(const raisim::MatDyn &mat) {
|
||||
const double *ptr = mat.ptr(); // get data pointer
|
||||
size_t n = mat.n;
|
||||
size_t m = mat.m;
|
||||
|
||||
// return np.array[float64[n,m]]
|
||||
return py::array_t<double>(
|
||||
{n, m}, // shape
|
||||
{sizeof(double), sizeof(double)}, // C-style contiguous strides for double (double=8bytes)
|
||||
ptr);
|
||||
// mat); // numpy array references this parent
|
||||
}
|
||||
|
||||
|
||||
/// \brief: convert from np.array[float[n,m]] to raisim::MatDyn
|
||||
raisim::MatDyn convert_np_to_matdyn(py::array_t<double> array) {
|
||||
|
||||
// check dimensions and shape
|
||||
if (array.ndim() != 2) {
|
||||
std::ostringstream s;
|
||||
s << "error: expecting the given array to have a dimension of 2, but got instead a dimension of "
|
||||
<< array.ndim() << ".";
|
||||
throw std::domain_error(s.str());
|
||||
}
|
||||
|
||||
// get the number of rows and columns
|
||||
size_t nrows = array.shape(0);
|
||||
size_t ncols = array.shape(1);
|
||||
|
||||
// create raisim matrix
|
||||
raisim::MatDyn mat(nrows, ncols);
|
||||
|
||||
// copy the data
|
||||
for (size_t i=0; i<nrows; i++)
|
||||
for (size_t j=0; j<ncols; j++)
|
||||
mat[i, j] = *array.data(i, j);
|
||||
|
||||
// return matrix
|
||||
return mat;
|
||||
}
|
||||
@@ -0,0 +1,94 @@
|
||||
/**
|
||||
* Python wrappers for raisim.object using pybind11.
|
||||
*
|
||||
* Copyright (c) 2019, Brian Delhaisse <briandelhaisse@gmail.com>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
#include <pybind11/pybind11.h>
|
||||
#include <pybind11/stl.h> // automatic conversion between std::vector, std::list, etc to Python list/tuples/dict
|
||||
#include <pybind11/eigen.h> // automatic conversion between Eigen data types to Numpy data types
|
||||
|
||||
#include "raisim/object/Object.hpp"
|
||||
|
||||
namespace py = pybind11;
|
||||
using namespace raisim;
|
||||
|
||||
|
||||
void init_single_bodies(py::module &);
|
||||
void init_articulated_system(py::module &);
|
||||
void init_terrain(py::module &);
|
||||
|
||||
|
||||
void init_object(py::module &m) {
|
||||
|
||||
// create submodule
|
||||
py::module object_module = m.def_submodule("object", "RaiSim contact submodule.");
|
||||
|
||||
|
||||
/**************/
|
||||
/* ObjectType */
|
||||
/**************/
|
||||
// object type enum (from include/raisim/configure.hpp)
|
||||
py::enum_<raisim::ObjectType>(object_module, "ObjectType", py::arithmetic())
|
||||
.value("SPHERE", raisim::ObjectType::SPHERE)
|
||||
.value("BOX", raisim::ObjectType::BOX)
|
||||
.value("CYLINDER", raisim::ObjectType::CYLINDER)
|
||||
.value("CONE", raisim::ObjectType::CONE)
|
||||
.value("CAPSULE", raisim::ObjectType::CAPSULE)
|
||||
.value("MESH", raisim::ObjectType::MESH)
|
||||
.value("HALFSPACE", raisim::ObjectType::HALFSPACE)
|
||||
.value("COMPOUND", raisim::ObjectType::COMPOUND)
|
||||
.value("HEIGHTMAP", raisim::ObjectType::HEIGHTMAP)
|
||||
.value("ARTICULATED_SYSTEM", raisim::ObjectType::ARTICULATED_SYSTEM);
|
||||
|
||||
|
||||
/************/
|
||||
/* BodyType */
|
||||
/************/
|
||||
// body type enum (from include/raisim/configure.hpp)
|
||||
py::enum_<raisim::BodyType>(object_module, "BodyType", py::arithmetic())
|
||||
.value("STATIC", raisim::BodyType::STATIC)
|
||||
.value("KINEMATIC", raisim::BodyType::KINEMATIC)
|
||||
.value("DYNAMIC", raisim::BodyType::DYNAMIC);
|
||||
|
||||
|
||||
/**********/
|
||||
/* Object */
|
||||
/**********/
|
||||
py::class_<raisim::Object>(object_module, "Object", "Raisim Object from which all other objects/bodies inherit from.")
|
||||
.def_property("name", &raisim::Object::getName, &raisim::Object::setName)
|
||||
.def("get_name", &raisim::Object::getName, "Get the object's name.")
|
||||
.def("set_name", &raisim::Object::setName, "Set the object's name.", py::arg("name"))
|
||||
.def("clear_per_object_contact", &raisim::Object::clearPerObjectContact)
|
||||
.def("add_contact_to_per_object_contact", &raisim::Object::addContactToPerObjectContact)
|
||||
;
|
||||
|
||||
|
||||
// raisim.object.singleBodies
|
||||
init_single_bodies(object_module);
|
||||
|
||||
// raisim.object.ArticulatedSystem
|
||||
init_articulated_system(object_module);
|
||||
|
||||
// raisim.object.terrain
|
||||
init_terrain(object_module);
|
||||
|
||||
}
|
||||
@@ -0,0 +1,309 @@
|
||||
/**
|
||||
* Python wrappers for RaiSim using pybind11.
|
||||
*
|
||||
* Copyright (c) 2019, Brian Delhaisse <briandelhaisse@gmail.com>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
#include <pybind11/pybind11.h>
|
||||
#include <pybind11/stl.h> // automatic conversion between std::vector, std::list, etc to Python list/tuples/dict
|
||||
#include <pybind11/eigen.h> // automatic conversion between Eigen data types to Numpy data types
|
||||
|
||||
#include <iostream>
|
||||
|
||||
#include "raisim/math.hpp" // contains the definitions of Vec, Mat, etc.
|
||||
#include "raisim/World.hpp"
|
||||
#include "raisim/RaisimServer.hpp"
|
||||
#include "raisim/OgreVis.hpp"
|
||||
//#include "visualizer/raisimKeyboardCallback.hpp"
|
||||
//#include "visualizer/helper.hpp"
|
||||
//#include "visualizer/guiState.hpp"
|
||||
//#include "visualizer/raisimBasicImguiPanel.hpp"
|
||||
|
||||
#include "converter.hpp" // contains code that allows to convert between the Vec, Mat to numpy arrays.
|
||||
|
||||
namespace py = pybind11;
|
||||
using namespace raisim;
|
||||
|
||||
|
||||
void init_object(py::module &);
|
||||
void init_constraints(py::module &);
|
||||
void init_contact(py::module &);
|
||||
// void init_visualizer(py::module &);
|
||||
|
||||
|
||||
// The PYBIND11_MODULE() macro creates a function that will be called when an import statement is issued from within
|
||||
// Python. In the following, "raisim" is the module name, "m" is a variable of type py::module which is the main
|
||||
// interface for creating bindings. The method module::def() generates binding code that exposes the C++ function
|
||||
// to Python.
|
||||
PYBIND11_MODULE(raisimpy, m) {
|
||||
|
||||
m.doc() = "Python wrappers for the RaiSim library and visualizer."; // docstring for the module
|
||||
|
||||
|
||||
/*************/
|
||||
/* Materials */
|
||||
/*************/
|
||||
py::class_<raisim::MaterialPairProperties>(m, "MaterialPairProperties", "Raisim Material Pair Properties (friction and restitution).")
|
||||
.def(py::init<>(), "Initialize the material pair properties.")
|
||||
.def(py::init<double, double, double>(),
|
||||
"Initialize the material pair properties.\n\n"
|
||||
"Args:\n"
|
||||
" friction (float): coefficient of friction.\n"
|
||||
" restitution (float): coefficient of restitution.\n"
|
||||
" threshold (float): restitution threshold.",
|
||||
py::arg("friction"), py::arg("restitution"), py::arg("threshold"));
|
||||
|
||||
|
||||
py::class_<raisim::MaterialManager>(m, "MaterialManager", "Raisim Material Manager.")
|
||||
.def(py::init<>(), "Initialize the material pair manager.")
|
||||
.def(py::init<const std::string>(),
|
||||
"Initialize the material manager by uploading the material data from a file.\n\n"
|
||||
"Args:\n"
|
||||
" xml_file (float): xml file.",
|
||||
py::arg("xml_file"))
|
||||
.def("set_material_pair_properties", &raisim::MaterialManager::setMaterialPairProp, R"mydelimiter(
|
||||
Set the material pair properties (friction and restitution).
|
||||
|
||||
Args:
|
||||
material1 (str): first material.
|
||||
material2 (str): second material.
|
||||
friction (float): coefficient of friction.
|
||||
restitution (float): coefficient of restitution.
|
||||
threshold (float): restitution threshold.
|
||||
)mydelimiter",
|
||||
py::arg("material1"), py::arg("material2"), py::arg("friction"), py::arg("restitution"), py::arg("threshold"))
|
||||
.def("get_material_pair_properties", &raisim::MaterialManager::getMaterialPairProp, R"mydelimiter(
|
||||
Get the material pair properties (friction and restitution).
|
||||
|
||||
Args:
|
||||
material1 (str): first material.
|
||||
material2 (str): second material.
|
||||
|
||||
Returns:
|
||||
MaterialPairProperties: material pair properties (friction, restitution, and restitution threshold).
|
||||
)mydelimiter",
|
||||
py::arg("material1"), py::arg("material2"))
|
||||
.def("set_default_material_properties", &raisim::MaterialManager::setDefaultMaterialProperties, R"mydelimiter(
|
||||
Set the default material properties.
|
||||
|
||||
Args:
|
||||
friction (float): coefficient of friction.
|
||||
restitution (float): coefficient of restitution.
|
||||
threshold (float): restitution threshold.
|
||||
)mydelimiter",
|
||||
py::arg("friction"), py::arg("restitution"), py::arg("threshold"))
|
||||
;
|
||||
|
||||
|
||||
/******************/
|
||||
/* raisim.contact */
|
||||
/******************/
|
||||
init_contact(m);
|
||||
|
||||
/*****************/
|
||||
/* raisim.object */
|
||||
/*****************/
|
||||
init_object(m); // define primitive shapes and articulated systems)
|
||||
|
||||
/*********************/
|
||||
/* raisim.constraint */
|
||||
/*********************/
|
||||
init_constraints(m);
|
||||
|
||||
/*********/
|
||||
/* World */
|
||||
/*********/
|
||||
py::class_<raisim::World>(m, "World", "Raisim world.", py::dynamic_attr()) // enable dynamic attributes for C++ class in Python
|
||||
.def(py::init<>(), "Initialize the World.")
|
||||
.def(py::init<const std::string &>(), "Initialize the World from the given config file.", py::arg("configFile"))
|
||||
.def("set_time_step", &raisim::World::setTimeStep, R"mydelimiter(
|
||||
Set the given time step `dt` in the simulator.
|
||||
|
||||
Args:
|
||||
dt (float): time step to be set in the simulator.
|
||||
)mydelimiter",
|
||||
py::arg("dt"))
|
||||
.def("get_time_step", &raisim::World::getTimeStep, R"mydelimiter(
|
||||
Get the current time step that has been set in the simulator.
|
||||
|
||||
Returns:
|
||||
float: time step.
|
||||
)mydelimiter")
|
||||
|
||||
// .def("add_sphere", &raisim::World::addSphere, R"mydelimiter(
|
||||
// Add dynamically a sphere into the world.
|
||||
//
|
||||
// Args:
|
||||
// radius (float): radius of the sphere.
|
||||
// mass (float): mass of the sphere.
|
||||
// material (str): material to be applied to the sphere.
|
||||
// collision_group (unsigned long): collision group.
|
||||
// collision_mask (unsigned long): collision mask.
|
||||
// Returns:
|
||||
// Sphere: the sphere instance.
|
||||
// )mydelimiter",
|
||||
// py::arg("radius"), py::arg("mass"), py::arg("material") = "default", py::arg("collision_group") = 1, py::arg("collision_mask") = CollisionGroup(-1))
|
||||
// .def("add_box", &raisim::World::addBox, R"mydelimiter(
|
||||
// Add dynamically a box into the world.
|
||||
//
|
||||
// Args:
|
||||
// x (float): length along the x axis.
|
||||
// y (float): length along the y axis.
|
||||
// z (float): length along the z axis.
|
||||
// mass (float): mass of the box.
|
||||
// material (str): material to be applied to the box.
|
||||
// collision_group (unsigned long): collision group.
|
||||
// collision_mask (unsigned long): collision mask.
|
||||
// Returns:
|
||||
// Box: the box instance.
|
||||
// )mydelimiter",
|
||||
// py::arg("x"), py::arg("y"), py::arg("z"), py::arg("mass"), py::arg("material") = "default", py::arg("collision_group") = 1, py::arg("collision_mask") = CollisionGroup(-1))
|
||||
// .def("add_cylinder", &raisim::World::addCylinder, R"mydelimiter(
|
||||
// Add dynamically a cylinder into the world.
|
||||
//
|
||||
// Args:
|
||||
// radius (float): radius of the cylinder.
|
||||
// height (float): height of the cylinder.
|
||||
// mass (float): mass of the cylinder.
|
||||
// material (str): material to be applied to the cylinder.
|
||||
// collision_group (unsigned long): collision group.
|
||||
// collision_mask (unsigned long): collision mask.
|
||||
// Returns:
|
||||
// Cylinder: the cylinder instance.
|
||||
// )mydelimiter",
|
||||
// py::arg("radius"), py::arg("height"), py::arg("mass"), py::arg("material") = "default", py::arg("collision_group") = 1, py::arg("collision_mask") = CollisionGroup(-1))
|
||||
// .def("add_cone", &raisim::World::addCone, R"mydelimiter(
|
||||
// Add dynamically a cone into the world.
|
||||
//
|
||||
// Args:
|
||||
// radius (float): radius of the cone.
|
||||
// height (float): height of the cone.
|
||||
// mass (float): mass of the cone.
|
||||
// material (str): material to be applied to the cone.
|
||||
// collision_group (unsigned long): collision group.
|
||||
// collision_mask (unsigned long): collision mask.
|
||||
// Returns:
|
||||
// Cone: the cone instance.
|
||||
// )mydelimiter",
|
||||
// py::arg("radius"), py::arg("height"), py::arg("mass"), py::arg("material") = "default", py::arg("collision_group") = 1, py::arg("collision_mask") = CollisionGroup(-1))
|
||||
// .def("add_capsule", &raisim::World::addCapsule, R"mydelimiter(
|
||||
// Add dynamically a capsule into the world.
|
||||
//
|
||||
// Args:
|
||||
// radius (float): radius of the capsule.
|
||||
// height (float): height of the capsule.
|
||||
// mass (float): mass of the capsule.
|
||||
// material (str): material to be applied to the capsule.
|
||||
// collision_group (unsigned long): collision group.
|
||||
// collision_mask (unsigned long): collision mask.
|
||||
// Returns:
|
||||
// Capsule: the capsule instance.
|
||||
// )mydelimiter",
|
||||
// py::arg("radius"), py::arg("height"), py::arg("mass"), py::arg("material") = "default", py::arg("collision_group") = 1, py::arg("collision_mask") = CollisionGroup(-1))
|
||||
// .def("add_ground", &raisim::World::addGround, R"mydelimiter(
|
||||
// Add dynamically a ground into the world.
|
||||
//
|
||||
// Args:
|
||||
// height (float): height of the ground.
|
||||
// material (str): material to be applied to the ground.
|
||||
// collision_mask (unsigned long): collision mask.
|
||||
// Returns:
|
||||
// Ground: the ground instance.
|
||||
// )mydelimiter",
|
||||
// py::arg("height"), py::arg("material") = "default", py::arg("collision_mask") = CollisionGroup(-1))
|
||||
|
||||
// .def("add_heightmap", &raisim::World::, R"mydelimiter(
|
||||
// Add dynamically a ground into the world.
|
||||
//
|
||||
// Args:
|
||||
// height (float): height of the ground.
|
||||
// material (str): material to be applied to the ground.
|
||||
// collision_mask (unsigned long): collision mask.
|
||||
// Returns:
|
||||
// Ground: the ground instance.
|
||||
// )mydelimiter",
|
||||
// py::arg("height"), py::arg("material") = "default", py::arg("collision_mask") = CollisionGroup(-1))
|
||||
|
||||
|
||||
.def("integrate", &raisim::World::integrate, "this function is simply calling both `integrate1()` and `integrate2()` one-by-one.")
|
||||
.def("integrate1", &raisim::World::integrate1, R"mydelimiter(
|
||||
It performs:
|
||||
1. deletion contacts from previous time step
|
||||
2. collision detection
|
||||
3. register contacts to each body
|
||||
4. calls `preContactSolverUpdate1()` of each object
|
||||
)mydelimiter")
|
||||
.def("integrate2", &raisim::World::integrate2, R"mydelimiter(
|
||||
It performs
|
||||
1. calls `preContactSolverUpdate2()` of each body
|
||||
2. run collision solver
|
||||
3. calls `integrate` method of each object
|
||||
)mydelimiter")
|
||||
.def("get_gravity", [](raisim::World &world) {
|
||||
Vec<3> gravity = world.getGravity();
|
||||
return convert_vec_to_np(gravity);
|
||||
}, R"mydelimiter(
|
||||
Get the gravity vector from the world.
|
||||
|
||||
Returns:
|
||||
np.array[float[3]]: gravity vector.
|
||||
)mydelimiter")
|
||||
.def("set_gravity", [](raisim::World &world, py::array_t<double> array) {
|
||||
raisim::Vec<3> gravity = convert_np_to_vec<3>(array);
|
||||
world.setGravity(gravity);
|
||||
}, R"mydelimiter(
|
||||
Set the gravity vector in the world.
|
||||
|
||||
Args:
|
||||
np.array[float[3]]: gravity vector.
|
||||
)mydelimiter", py::arg("gravity"))
|
||||
.def("set_erp", &raisim::World::setERP, "Set the error reduction parameter (ERP).", py::arg("erp"), py::arg("erp2")=0)
|
||||
.def("set_contact_solver_parameters", &raisim::World::setContactSolverParam, R"mydelimiter(
|
||||
Set contact solver parameters.
|
||||
|
||||
Args:
|
||||
alpha_init (float): alpha init.
|
||||
alpha_min (float): alpha minimum.
|
||||
alpha_decay (float): alpha decay.
|
||||
max_iters (float): maximum number of iterations.
|
||||
threshold (float): threshold.
|
||||
)mydelimiter",
|
||||
py::arg("alpha_init"), py::arg("alpha_min"), py::arg("alpha_decay"), py::arg("max_iters"), py::arg("threshold"))
|
||||
.def("get_world_time", &raisim::World::getWorldTime, R"mydelimiter(
|
||||
Return the total integrated time (which is updated at every `integrate2()`` call).
|
||||
|
||||
Returns:
|
||||
float: world time.
|
||||
)mydelimiter")
|
||||
.def("set_world_time", &raisim::World::setWorldTime, R"mydelimiter(
|
||||
Set the world time.
|
||||
|
||||
Args:
|
||||
time (float): world time
|
||||
)mydelimiter", py::arg("time"))
|
||||
;
|
||||
|
||||
// visualizer class
|
||||
// py::class_<raisim::OgreVis, std::unique_ptr<raisim::Ogrevis, py::nodelete>>(m, "Visualizer", "Ogre visualizer for Raisim.")
|
||||
// .def(py::init(&raisim::OgreVis::get), "Create Ogre visualizer instance (singleton).", py::return_value_policy::reference)
|
||||
// .def("get", &raisim::OgreVis::get, "Get the single Ogre visualizer instance (singleton).")
|
||||
// .def();
|
||||
}
|
||||
@@ -0,0 +1,272 @@
|
||||
/**
|
||||
* Python wrappers for raisim.object using pybind11.
|
||||
*
|
||||
* Copyright (c) 2019, Brian Delhaisse <briandelhaisse@gmail.com>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
#include <pybind11/pybind11.h>
|
||||
#include <pybind11/stl.h> // automatic conversion between std::vector, std::list, etc to Python list/tuples/dict
|
||||
#include <pybind11/eigen.h> // automatic conversion between Eigen data types to Numpy data types
|
||||
//#include <pybind11/numpy.h> // numpy types
|
||||
|
||||
#include "raisim/math.hpp" // contains the definitions of Vec, Mat, etc.
|
||||
#include "raisim/object/singleBodies/Box.hpp"
|
||||
#include "raisim/object/singleBodies/Capsule.hpp"
|
||||
#include "raisim/object/singleBodies/Compound.hpp"
|
||||
#include "raisim/object/singleBodies/Cone.hpp"
|
||||
#include "raisim/object/singleBodies/Cylinder.hpp"
|
||||
#include "raisim/object/singleBodies/Mesh.hpp"
|
||||
#include "raisim/object/singleBodies/SingleBodyObject.hpp"
|
||||
#include "raisim/object/singleBodies/Sphere.hpp"
|
||||
|
||||
#include "converter.hpp" // contains code that allows to convert between the Vec, Mat to numpy arrays.
|
||||
|
||||
namespace py = pybind11;
|
||||
using namespace raisim;
|
||||
|
||||
|
||||
void init_single_bodies(py::module &m) {
|
||||
|
||||
/********************/
|
||||
/* SingleBodyObject */
|
||||
/********************/
|
||||
py::class_<raisim::SingleBodyObject, raisim::Object>(m, "SingleBodyObject", "Raisim Single Object from which all single objects/bodies (such as box, sphere, etc) inherit from.")
|
||||
.def(py::init<raisim::ObjectType>(), "Initialize the Object.", py::arg("object_type"))
|
||||
.def("get_position", &raisim::SingleBodyObject::getPosition, R"mydelimiter(
|
||||
Get the body's position with respect to the world frame.
|
||||
|
||||
Returns:
|
||||
np.array[float[3]]: position in the world frame.
|
||||
)mydelimiter")
|
||||
.def("get_com_position", &raisim::SingleBodyObject::getComPosition, R"mydelimiter(
|
||||
Get the body's center of mass position with respect to the world frame.
|
||||
|
||||
Returns:
|
||||
np.array[float[3]]: center of mass position in the world frame.
|
||||
)mydelimiter")
|
||||
.def("get_linear_velocity", &raisim::SingleBodyObject::getLinearVelocity, R"mydelimiter(
|
||||
Get the body's linear velocity with respect to the world frame.
|
||||
|
||||
Returns:
|
||||
np.array[float[3]]: linear velocity in the world frame.
|
||||
)mydelimiter")
|
||||
.def("get_angular_velocity", &raisim::SingleBodyObject::getAngularVelocity, R"mydelimiter(
|
||||
Get the body's angular velocity position with respect to the world frame.
|
||||
|
||||
Returns:
|
||||
np.array[float[3]]: angular velocity in the world frame.
|
||||
)mydelimiter")
|
||||
.def("get_quaternion", py::overload_cast<>(&raisim::SingleBodyObject::getQuaternion), R"mydelimiter(
|
||||
Get the body's orientation (expressed as a quaternion [w,x,y,z]) with respect to the world frame.
|
||||
|
||||
Returns:
|
||||
np.array[float[4]]: quaternion [w,x,y,z].
|
||||
)mydelimiter")
|
||||
.def("get_rotation_matrix", py::overload_cast<>(&raisim::SingleBodyObject::getRotationMatrix), R"mydelimiter(
|
||||
Get the body's orientation (expressed as a rotation matrix) with respect to the world frame.
|
||||
|
||||
Returns:
|
||||
np.array[float[3,3]]: rotation matrix.
|
||||
)mydelimiter")
|
||||
.def("get_kinetic_energy", &raisim::SingleBodyObject::getKineticEnergy, R"mydelimiter(
|
||||
Get the body's kinetic energy.
|
||||
|
||||
Returns:
|
||||
float: kinetic energy.
|
||||
)mydelimiter")
|
||||
.def("get_potential_energy", &raisim::SingleBodyObject::getPotentialEnergy, R"mydelimiter(
|
||||
Get the body's potential energy.
|
||||
|
||||
Returns:
|
||||
float: potential energy.
|
||||
)mydelimiter")
|
||||
.def("get_energy", &raisim::SingleBodyObject::getEnergy, R"mydelimiter(
|
||||
Get the body's total energy.
|
||||
|
||||
Returns:
|
||||
float: total energy.
|
||||
)mydelimiter")
|
||||
.def("get_linear_momentum", &raisim::SingleBodyObject::getLinearMomentum, R"mydelimiter(
|
||||
Get the body's linear momentum.
|
||||
|
||||
Returns:
|
||||
np.array[float[3]]: linear momentum.
|
||||
)mydelimiter")
|
||||
.def("get_mass", &raisim::SingleBodyObject::getMass, R"mydelimiter(
|
||||
Get the body's mass.
|
||||
|
||||
Returns:
|
||||
float: mass (kg).
|
||||
)mydelimiter")
|
||||
.def("get_world_inertia_matrix", &raisim::SingleBodyObject::getInertiaMatrix_W, R"mydelimiter(
|
||||
Get the body's inertia matrix expressed in the world frame.
|
||||
|
||||
Returns:
|
||||
np.array[float[3,3]]: world inertia matrix.
|
||||
)mydelimiter")
|
||||
.def("get_body_inertia_matrix", &raisim::SingleBodyObject::getInertiaMatrix_B, R"mydelimiter(
|
||||
Get the body's inertia matrix expressed in the body frame.
|
||||
|
||||
Returns:
|
||||
np.array[float[3,3]]: body inertia matrix.
|
||||
)mydelimiter")
|
||||
.def("get_object_type", &raisim::SingleBodyObject::getObjectType, R"mydelimiter(
|
||||
Get the body's type.
|
||||
|
||||
Returns:
|
||||
raisim.ObjectType: object type (BOX, CYLINDER, CAPSULE, CONE, SPHERE, etc.)
|
||||
)mydelimiter")
|
||||
;
|
||||
|
||||
|
||||
/*******/
|
||||
/* Box */
|
||||
/*******/
|
||||
py::class_<raisim::Box, raisim::SingleBodyObject>(m, "Box", "Raisim Box.")
|
||||
.def(py::init<double, double, double, double>(),
|
||||
"Initialize a box.\n\n"
|
||||
"Args:\n"
|
||||
" x (float): length along the x axis.\n"
|
||||
" y (float): length along the y axis.\n"
|
||||
" z (float): length along the z axis.\n"
|
||||
" mass (float): mass of the box.",
|
||||
py::arg("x"), py::arg("y"), py::arg("z"), py::arg("mass"))
|
||||
.def("get_dimensions", [](raisim::Box &box) {
|
||||
Vec<3> dimensions = box.getDim();
|
||||
return convert_vec_to_np(dimensions);
|
||||
}, R"mydelimiter(
|
||||
Get the box's dimensions.
|
||||
|
||||
Returns:
|
||||
tuple[float[3]]: dimensions along each axis.
|
||||
)mydelimiter");
|
||||
|
||||
|
||||
/***********/
|
||||
/* Capsule */
|
||||
/***********/
|
||||
py::class_<raisim::Capsule, raisim::SingleBodyObject>(m, "Capsule", "Raisim Capsule.")
|
||||
.def(py::init<double, double, double>(),
|
||||
"Initialize a capsule.\n\n"
|
||||
"Args:\n"
|
||||
" radius (float): radius of the capsule.\n"
|
||||
" height (float): height of the capsule.\n"
|
||||
" mass (float): mass of the capsule.",
|
||||
py::arg("radius"), py::arg("height"), py::arg("mass"))
|
||||
.def("get_radius", &raisim::Capsule::getRadius, R"mydelimiter(
|
||||
Get the capsule's radius.
|
||||
|
||||
Returns:
|
||||
float: radius of the capsule.
|
||||
)mydelimiter")
|
||||
.def("get_height", &raisim::Capsule::getHeight, R"mydelimiter(
|
||||
Get the capsule's height.
|
||||
|
||||
Returns:
|
||||
float: height of the capsule.
|
||||
)mydelimiter");
|
||||
|
||||
|
||||
/************/
|
||||
/* Compound */
|
||||
/************/
|
||||
|
||||
|
||||
/********/
|
||||
/* Cone */
|
||||
/********/
|
||||
py::class_<raisim::Cone, raisim::SingleBodyObject>(m, "Cone", "Raisim Cone.")
|
||||
.def(py::init<double, double, double>(),
|
||||
"Initialize a cone.\n\n"
|
||||
"Args:\n"
|
||||
" radius (float): radius of the cone.\n"
|
||||
" height (float): height of the cone.\n"
|
||||
" mass (float): mass of the cone.",
|
||||
py::arg("radius"), py::arg("height"), py::arg("mass"))
|
||||
.def("get_radius", &raisim::Cone::getRadius, R"mydelimiter(
|
||||
Get the cone's radius.
|
||||
|
||||
Returns:
|
||||
float: radius of the cone.
|
||||
)mydelimiter")
|
||||
.def("get_height", &raisim::Cone::getHeight, R"mydelimiter(
|
||||
Get the cone's height.
|
||||
|
||||
Returns:
|
||||
float: height of the cone.
|
||||
)mydelimiter");
|
||||
|
||||
|
||||
/************/
|
||||
/* Cylinder */
|
||||
/************/
|
||||
py::class_<raisim::Cylinder, raisim::SingleBodyObject>(m, "Cylinder", "Raisim Cylinder.")
|
||||
.def(py::init<double, double, double>(),
|
||||
"Initialize a cylinder.\n\n"
|
||||
"Args:\n"
|
||||
" radius (float): radius of the cylinder.\n"
|
||||
" height (float): height of the cylinder.\n"
|
||||
" mass (float): mass of the cylinder.",
|
||||
py::arg("radius"), py::arg("height"), py::arg("mass"))
|
||||
.def("get_radius", &raisim::Cylinder::getRadius, R"mydelimiter(
|
||||
Get the cylinder's radius.
|
||||
|
||||
Returns:
|
||||
float: radius of the cylinder.
|
||||
)mydelimiter")
|
||||
.def("get_height", &raisim::Cylinder::getHeight, R"mydelimiter(
|
||||
Get the cylinder's height.
|
||||
|
||||
Returns:
|
||||
float: height of the cylinder.
|
||||
)mydelimiter");
|
||||
|
||||
|
||||
/********/
|
||||
/* Mesh */
|
||||
/********/
|
||||
// py::class_<raisim::Mesh, raisim::SingleBodyObject>(m, "Mesh", "Raisim Mesh.")
|
||||
// .def(py::init<const std::string&, dSpaceID>(),
|
||||
// "Initialize a Mesh.\n\n"
|
||||
// "Args:\n"
|
||||
// " filename (str): path to the mesh file.\n"
|
||||
// " space (dSpaceID): space.",
|
||||
// py::arg("filename"), py::arg("space"));
|
||||
|
||||
|
||||
/**********/
|
||||
/* Sphere */
|
||||
/**********/
|
||||
py::class_<raisim::Sphere, raisim::SingleBodyObject>(m, "Sphere", "Raisim Sphere.")
|
||||
.def(py::init<double, double>(),
|
||||
"Initialize a sphere.\n\n"
|
||||
"Args:\n"
|
||||
" radius (float): radius of the sphere.\n"
|
||||
" mass (float): mass of the sphere.",
|
||||
py::arg("radius"), py::arg("mass"))
|
||||
.def("get_radius", &raisim::Sphere::getRadius, R"mydelimiter(
|
||||
Get the sphere's radius.
|
||||
|
||||
Returns:
|
||||
float: radius of the sphere.
|
||||
)mydelimiter");
|
||||
|
||||
}
|
||||
@@ -0,0 +1,44 @@
|
||||
/**
|
||||
* Python wrappers for raisim.object.terrain using pybind11.
|
||||
*
|
||||
* Copyright (c) 2019, Brian Delhaisse <briandelhaisse@gmail.com>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
#include <pybind11/pybind11.h>
|
||||
#include <pybind11/stl.h> // automatic conversion between std::vector, std::list, etc to Python list/tuples/dict
|
||||
#include <pybind11/eigen.h> // automatic conversion between Eigen data types to Numpy data types
|
||||
|
||||
#include "raisim/math.hpp" // contains the definitions of Vec, Mat, etc.
|
||||
#include "raisim/object/terrain/Ground.hpp"
|
||||
#include "raisim/object/terrain/HeightMap.hpp"
|
||||
|
||||
namespace py = pybind11;
|
||||
using namespace raisim;
|
||||
|
||||
|
||||
void init_terrain(py::module &m) {
|
||||
|
||||
// ground class
|
||||
|
||||
// heightmap class
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,48 @@
|
||||
/**
|
||||
* Python wrappers for raisimOgre using pybind11.
|
||||
*
|
||||
* Copyright (c) 2019, Brian Delhaisse <briandelhaisse@gmail.com>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
#include <pybind11/pybind11.h>
|
||||
#include <pybind11/stl.h> // automatic conversion between std::vector, std::list, etc to Python list/tuples/dict
|
||||
#include <pybind11/eigen.h> // automatic conversion between Eigen data types to Numpy data types
|
||||
|
||||
#include <iostream>
|
||||
|
||||
#include "raisim/math.hpp" // contains the definitions of Vec, Mat, etc.
|
||||
#include "raisim/World.hpp"
|
||||
#include "raisim/RaisimServer.hpp"
|
||||
#include "raisim/OgreVis.hpp"
|
||||
//#include "visualizer/raisimKeyboardCallback.hpp"
|
||||
//#include "visualizer/helper.hpp"
|
||||
//#include "visualizer/guiState.hpp"
|
||||
//#include "visualizer/raisimBasicImguiPanel.hpp"
|
||||
|
||||
|
||||
namespace py = pybind11;
|
||||
using namespace raisim;
|
||||
|
||||
|
||||
void init_visualizer(py::module &m) {
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
import numpy as np
|
||||
import raisimpy as raisim
|
||||
|
||||
world = raisim.World()
|
||||
print("gravity: ", world.get_gravity())
|
||||
print("set gravity to: np.array([0.,1.,2.])")
|
||||
world.set_gravity(np.array([0.,1.,2.]))
|
||||
print("gravity: ", world.get_gravity())
|
||||
print("set gravity to: np.array([0.,-1.,-2.]).reshape(-1,1)")
|
||||
world.set_gravity(np.array([0.,-1.,-2.]).reshape(-1,1))
|
||||
print("gravity: ", world.get_gravity())
|
||||
print("set gravity to: np.array([0.,1.,2.]).reshape(1,-1)")
|
||||
world.set_gravity(np.array([0.,1.,2.]).reshape(1,-1))
|
||||
print("gravity: ", world.get_gravity())
|
||||
print("set gravity to: range(3,6)")
|
||||
world.set_gravity(range(3,6))
|
||||
print("gravity: ", world.get_gravity())
|
||||
|
||||
print("set gravity to: range(3,7)")
|
||||
world.set_gravity(range(3,7))
|
||||
|
||||
Reference in New Issue
Block a user