Unverified Commit ff7175c3 authored by Guilhem Saurel's avatar Guilhem Saurel Committed by GitHub
Browse files

Merge branch 'devel' into devel

parents 25d9855c 50bdf623
Pipeline #17107 passed with stage
in 7 minutes and 18 seconds
......@@ -19,7 +19,6 @@ IF(NOT INSTALL_PYTHON_INTERFACE_ONLY)
SET(PROJECT_USE_CMAKE_EXPORT TRUE)
ENDIF(NOT INSTALL_PYTHON_INTERFACE_ONLY)
SET(CUSTOM_HEADER_DIR "${PROJECT_NAME}")
SET(CMAKE_CXX_STANDARD 11)
SET(CXX_DISABLE_WERROR TRUE)
SET(DOXYGEN_USE_MATHJAX YES)
......@@ -32,28 +31,25 @@ INCLUDE(cmake/ide.cmake)
# Project definition
COMPUTE_PROJECT_ARGS(PROJECT_ARGS LANGUAGES CXX)
PROJECT(${PROJECT_NAME} ${PROJECT_ARGS})
SET(CMAKE_CXX_STANDARD 11)
CHECK_MINIMAL_CXX_STANDARD(11 ENFORCE)
# Project dependencies
ADD_PROJECT_DEPENDENCY(pinocchio REQUIRED PKG_CONFIG_REQUIRES "pinocchio >= 2.0.0")
ADD_PROJECT_DEPENDENCY(ndcurves 1.0.0 REQUIRED PKG_CONFIG_REQUIRES "ndcurves >= 0.5.1")
ADD_PROJECT_DEPENDENCY(pinocchio REQUIRED)
ADD_PROJECT_DEPENDENCY(ndcurves 1.0.0 REQUIRED)
IF(NOT CURVES_WITH_PINOCCHIO_SUPPORT)
MESSAGE(FATAL_ERROR "you need to use a curves version compiled with pinocchio support")
MESSAGE(FATAL_ERROR "you need to use a ndcurves version compiled with pinocchio support")
ENDIF(NOT CURVES_WITH_PINOCCHIO_SUPPORT)
SET(BOOST_COMPONENTS unit_test_framework serialization)
ADD_PROJECT_DEPENDENCY(Boost REQUIRED COMPONENTS unit_test_framework serialization)
IF(BUILD_PYTHON_INTERFACE)
FINDPYTHON()
STRING(REGEX REPLACE "-" "_" PY_NAME ${CUSTOM_HEADER_DIR})
ADD_PROJECT_DEPENDENCY(eigenpy REQUIRED PKG_CONFIG_REQUIRES "eigenpy >= 1.6.12")
SET(BOOST_COMPONENTS ${BOOST_COMPONENTS} python)
SEARCH_FOR_BOOST_PYTHON(REQUIRED)
ADD_PROJECT_DEPENDENCY(eigenpy REQUIRED)
INCLUDE_DIRECTORIES(SYSTEM ${PYTHON_INCLUDE_DIRS})
STRING(REGEX REPLACE "-" "_" PY_NAME ${PROJECT_NAME})
SET(${PY_NAME}_INSTALL_DIR ${PYTHON_SITELIB}/${PY_NAME})
ENDIF(BUILD_PYTHON_INTERFACE)
SEARCH_FOR_BOOST()
INCLUDE_DIRECTORIES(SYSTEM ${Boost_INCLUDE_DIRS})
# Main Library
......@@ -70,5 +66,3 @@ IF(NOT INSTALL_PYTHON_INTERFACE_ONLY)
ENDIF(NOT INSTALL_PYTHON_INTERFACE_ONLY)
ADD_SUBDIRECTORY(bindings)
ADD_SUBDIRECTORY(unittest)
PKG_CONFIG_APPEND_BOOST_LIBS(serialization)
......@@ -7,13 +7,13 @@
This package is extracted from an original work of Justin Carpentier (jcarpent@laas.fr),
with the goal to simplify the library, make it more generic and remove old dependencies.
This package provide C++ structures with python bindings used to define and store contact phases and contact sequences.
This package provide C++ structures with python bindings used to define and store contact phases and contact sequences.
# Dependencies
* Eigen
* [Pinocchio](https://github.com/stack-of-tasks/pinocchio)
* [Curves](https://github.com/loco-3d/curves)
* [NDCurves](https://github.com/loco-3d/ndcurves)
* [Eigenpy](https://github.com/stack-of-tasks/eigenpy) (Only for python bindings)
# Installation procedure
......@@ -25,7 +25,7 @@ This package is available as binary in [robotpkg/wip](http://robotpkg.openrobots
Install the required dependencies, eg. (choose for python version):
```
sudo apt-get install robotpkg-py35-pinocchio robotpkg-py35-curves
sudo apt-get install robotpkg-py35-pinocchio robotpkg-py3\*-curves
```
Clone the repository and build the package:
......@@ -49,12 +49,11 @@ A Contact Model define the physical properties of a contact. A Contact Patch def
A contact patch define the placement (in SE(3), in the world frame) of a contact between a part of the robot and the environment. It contains a ContactModel.
### Contact Phase
A contact phase is defined by a constant set of contact points.
In the context of bipedal walking, two examples of contact phases are the single and double support phases.
A contact phase store several data, many of which are optional.
A contact phase store several data, many of which are optional.
It store the set of active contacts as a map<String, ContactPatch> with the effector name as Keys:
......@@ -66,17 +65,17 @@ patchRF = ContactPatch(p,0.5) # create a new contact patch at the placement p wi
cp.addContact("right-feet",patchRF)
# check if an effector is in contact:
cp.isEffectorInContact("right-feet")
# access to the contact patch from the effector name:
# access to the contact patch from the effector name:
cp.contactPatch("right-feet")
```
```
A contact phase can be defined in a specific time interval:
A contact phase can be defined in a specific time interval:
```python
cp = ContactPhase()
cp.timeInitial = 1.
cp.timeFinal =3.5
```
```
**Centroidal dynamic data**
......@@ -103,9 +102,9 @@ Optionnaly, a Contact Phase can store data related to the centroidal dynamic. It
point3_t m_L_final;
/// \brief Final angular momentum derivative for this contact phase
point3_t m_dL_final;
```
```
It also store centroidal trajectories, represented with objects from the [Curves](https://github.com/loco-3d/curves) library:
It also store centroidal trajectories, represented with objects from the [NDCurves](https://github.com/loco-3d/ndcurves) library:
```c
......@@ -125,18 +124,18 @@ It also store centroidal trajectories, represented with objects from the [Curves
curve_ptr m_zmp;
/// \brief SE3 trajectory of the root of the robot
curve_SE3_ptr m_root;
```
```
**Wholebody data:**
A Contact Phase can also store data related to the wholebody motion, it store the following initial and final wholebody configuration as public member:
A Contact Phase can also store data related to the wholebody motion, it store the following initial and final wholebody configuration as public member:
```c
/// \brief Initial whole body configuration of this phase
pointX_t m_q_init;
/// \brief Final whole body configuration of this phase
pointX_t m_q_final;
```
```
And the following trajectories:
......@@ -149,7 +148,7 @@ And the following trajectories:
curve_ptr m_ddq;
/// \brief trajectory for the joint torques
curve_ptr m_tau;
```
```
It can also store the contact forces and contact normal forces, in a map<String,curve_ptr> with the effector name as Key:
......@@ -157,14 +156,14 @@ It can also store the contact forces and contact normal forces, in a map<String,
```python
fR = createRandomPiecewisePolynomial(12)
cp.addContactForceTrajectory("right-feet",fR)
# access the trajectory :
# access the trajectory :
cp.contactForce("right-feet")
# contact normal force :
fnR = createRandomPiecewisePolynomial(1)
cp.addContactNormalForceTrajectory("right-feet",fnR)
# access the trajectory :
# access the trajectory :
cp.contactNormalForce("right-feet")
```
```
And the effector trajectory for the swinging limbs, also in a map<String,curve_ptr> with the effector name as Key:
......@@ -179,9 +178,9 @@ end_pose.rotation = Quaternion(sqrt(2.) / 2., sqrt(2.) / 2., 0, 0).normalized().
effL = SE3Curve(init_pose, end_pose, cp.timeInitial,cp.timeFinal)
# add it to the contact phase:
cp.addEffectorTrajectory("left-feet",effL)
# access the trajectory :
# access the trajectory :
cp.effectorTrajectory("left-feet")
```
```
### Contact Sequence
......@@ -189,9 +188,9 @@ As soon as a creation or a rupture of contact point occurs, the contact set is m
The concatenation of contact phases describes what we name a contact sequence, inside which all the contact phases have
their own duration.
A contact sequence is basically a Vector of Contact Phase, with several helper method which can be used to ease the creation of a Contact Sequence.
A contact sequence is basically a Vector of Contact Phase, with several helper method which can be used to ease the creation of a Contact Sequence.
One can either create a Contact sequence with a know number of contact Phase and correctly set the members of the Contact Phases with:
One can either create a Contact sequence with a know number of contact Phase and correctly set the members of the Contact Phases with:
```c
ContactSequence cs = ContactSequence(3);
......@@ -201,11 +200,11 @@ cs.contactPhase(0) = cp0;
// or:
cs.contactPhase(1).m_c_init = Point3_t(1,0,0.7);
cs.contactPhase(1).timeFinal(3.);
// or :
// or :
ContactPhase& cp2 = cs.contactPhase(2);
/* set the contact phase members ... */
```
```
Or simply append new Contact Phase at the end of the current Contact Sequence;
......@@ -214,7 +213,7 @@ ContactSequence cs; // create empty contact sequence
ContactPhase cp0;
/* set the contact phase members ... */
cs.append(cp0);
```
```
**Helper methods to create contact sequence**
......@@ -229,38 +228,28 @@ Several helper methods have been added to the ContactSequence class to ease the
* it create the contact with eeName at the given placement.
* `moveEffectorOf(eeName, transform, durationBreak, durationCreate)` Similar to moveEffectorToPlacement but use a transform from the previous contact placement instead of a new placement.
* `moveEffectorOf(eeName, transform, durationBreak, durationCreate)` Similar to moveEffectorToPlacement but use a transform from the previous contact placement instead of a new placement.
**Helper methods to check a contact sequence**
The ContactSequence class contains several methods to check if the sequence contains some of the optional data, and if they are consistents across all the contact phases.
This methods should be used in order to check if a ContactSequence object given as input to your algorithm have been correctly initialized with all the data that you are going to use in your algorithm.
It may also be used to check if your algorithm output consistent data.
The ContactSequence class contains several methods to check if the sequence contains some of the optional data, and if they are consistents across all the contact phases.
This methods should be used in order to check if a ContactSequence object given as input to your algorithm have been correctly initialized with all the data that you are going to use in your algorithm.
It may also be used to check if your algorithm output consistent data.
Examples of such methods are `haveConsistentContacts` or `haveCentroidalTrajectories` which check that the (c, dc, ddc, L, dL) have been initialized, have the correct duration,
and that each trajectories of one phase correctly end at the same value as it begin in the next phase.
Examples of such methods are `haveConsistentContacts` or `haveCentroidalTrajectories` which check that the (c, dc, ddc, L, dL) have been initialized, have the correct duration,
and that each trajectories of one phase correctly end at the same value as it begin in the next phase.
**Helper methods to access Data**
The ContactSequence class also contains methods for easier access to the data contained in the ContactPhase vector. For example, `phaseAtTime` or `phaseIdAtTime` can be used to access a specific ContactPhase at a given time.
`getAllEffectorsInContact` output all the effector used to create contact during the sequence.
`getAllEffectorsInContact` output all the effector used to create contact during the sequence.
Finally, methods exists to return the complete trajectory along the contact sequence, concatenating the trajectories of each phases (eg. `concatenateCtrajectories` return the complete c(t) trajectory for all the contact sequence).
## Examples
[Examples](examples/README.md) provide several serialized ContactSequence files with descriptions.
[Examples](examples/README.md) provide several serialized ContactSequence files with descriptions.
......@@ -17,7 +17,7 @@ ADD_LIBRARY(${PY_NAME} SHARED ${${PROJECT_NAME}_PYTHON_SOURCES} ${${PROJECT_NAME
ADD_SOURCE_GROUP(${PROJECT_NAME}_PYTHON_SOURCES)
TARGET_LINK_LIBRARIES(${PY_NAME} ${PROJECT_NAME} ${Boost_SERIALIZATION_LIBRARIES} eigenpy::eigenpy)
TARGET_LINK_LIBRARIES(${PY_NAME} ${PROJECT_NAME} eigenpy::eigenpy)
TARGET_LINK_BOOST_PYTHON(${PY_NAME})
SET_TARGET_PROPERTIES(${PY_NAME} PROPERTIES LIBRARY_OUTPUT_DIRECTORY ${PY_NAME} SOVERSION ${PROJECT_VERSION})
......
Subproject commit fb4c22c319ec5320f9a85527eb1a4130954846f5
Subproject commit f9f19535583faa2bb2ff21d97cb33f8ab7624d36
......@@ -24,6 +24,7 @@ SET(${PROJECT_NAME}_SCENARIO_HEADERS
SET(${PROJECT_NAME}_PYTHON_HEADERS
bindings/python/fwd.hpp
bindings/python/geometry/ellipsoid.hpp
bindings/python/geometry/expose-geometry.hpp
bindings/python/geometry/linear-cone.hpp
......
#ifndef __multicontact_api_python_fwd_hpp__
#define __multicontact_api_python_fwd_hpp__
// Silence a warning about a deprecated use of boost bind by boost python
// at least fo boost 1.73 to 1.75
// ref. https://github.com/stack-of-tasks/tsid/issues/128
#define BOOST_BIND_GLOBAL_PLACEHOLDERS
#include <boost/python.hpp>
#undef BOOST_BIND_GLOBAL_PLACEHOLDERS
#endif // ifndef __multicontact_api_python_utils_printable_hpp__
......@@ -5,8 +5,8 @@
#define __multicontact_api_python_geometry_ellipsoid_hpp__
#include <pinocchio/fwd.hpp>
#include <boost/python.hpp>
#include "multicontact-api/bindings/python/fwd.hpp"
#include "multicontact-api/geometry/ellipsoid.hpp"
namespace multicontact_api {
......
......@@ -4,7 +4,7 @@
#ifndef __multicontact_api_python_serialization_archive_hpp__
#define __multicontact_api_python_serialization_archive_hpp__
#include <boost/python.hpp>
#include "multicontact-api/bindings/python/fwd.hpp"
namespace multicontact_api {
namespace python {
......
......@@ -4,7 +4,7 @@
#ifndef __multicontact_api_python_utils_printable_hpp__
#define __multicontact_api_python_utils_printable_hpp__
#include <boost/python.hpp>
#include "multicontact-api/bindings/python/fwd.hpp"
namespace multicontact_api {
namespace python {
......
......@@ -41,7 +41,7 @@ struct Serializable {
public:
/// \brief Loads a Derived object from a text file.
void loadFromText(const std::string& filename) throw(std::invalid_argument) {
void loadFromText(const std::string& filename) {
std::ifstream ifs(filename.c_str());
if (ifs) {
boost::archive::text_iarchive ia(ifs);
......@@ -53,7 +53,7 @@ struct Serializable {
}
/// \brief Saved a Derived object as a text file.
void saveAsText(const std::string& filename) const throw(std::invalid_argument) {
void saveAsText(const std::string& filename) const {
std::ofstream ofs(filename.c_str());
if (ofs) {
boost::archive::text_oarchive oa(ofs);
......@@ -65,7 +65,7 @@ struct Serializable {
}
/// \brief Loads a Derived object from an XML file.
void loadFromXML(const std::string& filename, const std::string& tag_name) throw(std::invalid_argument) {
void loadFromXML(const std::string& filename, const std::string& tag_name) {
assert(!tag_name.empty());
std::ifstream ifs(filename.c_str());
if (ifs) {
......@@ -78,7 +78,7 @@ struct Serializable {
}
/// \brief Saved a Derived object as an XML file.
void saveAsXML(const std::string& filename, const std::string& tag_name) const throw(std::invalid_argument) {
void saveAsXML(const std::string& filename, const std::string& tag_name) const {
assert(!tag_name.empty());
std::ofstream ofs(filename.c_str());
if (ofs) {
......@@ -91,7 +91,7 @@ struct Serializable {
}
/// \brief Loads a Derived object from an binary file.
void loadFromBinary(const std::string& filename) throw(std::invalid_argument) {
void loadFromBinary(const std::string& filename) {
std::ifstream ifs(filename.c_str());
if (ifs) {
boost::archive::binary_iarchive ia(ifs);
......@@ -103,7 +103,7 @@ struct Serializable {
}
/// \brief Saved a Derived object as an binary file.
void saveAsBinary(const std::string& filename) const throw(std::invalid_argument) {
void saveAsBinary(const std::string& filename) const {
std::ofstream ofs(filename.c_str());
if (ofs) {
boost::archive::binary_oarchive oa(ofs);
......
......@@ -11,8 +11,8 @@ SET(${PROJECT_NAME}_TESTS
)
FOREACH(TEST ${${PROJECT_NAME}_TESTS})
ADD_UNIT_TEST(${TEST} ${TEST})
TARGET_LINK_LIBRARIES(${TEST} ${PROJECT_NAME} ${Boost_LIBRARIES})
ADD_UNIT_TEST(${TEST} "${TEST}.cpp")
TARGET_LINK_LIBRARIES(${TEST} ${PROJECT_NAME} Boost::unit_test_framework)
ENDFOREACH(TEST ${${PROJECT_NAME}_TESTS})
TARGET_COMPILE_DEFINITIONS(examples PRIVATE -DTEST_DATA_PATH="${CMAKE_CURRENT_SOURCE_DIR}/../examples/")
......
......@@ -2,7 +2,7 @@ SET(${PROJECT_NAME}_PYTHON_TESTS
trivial
geometry
scenario
serialization_examples
#serialization_examples
)
FOREACH(TEST ${${PROJECT_NAME}_PYTHON_TESTS})
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment