Unverified Commit 8c5b40ea authored by Carlos Mastalli's avatar Carlos Mastalli Committed by GitHub
Browse files

Merge pull request #1025 from wxmerkt/hotfix/fix-compilation-with-clang

ContactModel1D: Fix compilation with LLVM, fix unittests with clang
parents 43502019 c60c9a26
Pipeline #17275 passed with stage
in 42 minutes and 22 seconds
......@@ -19,6 +19,8 @@ TARGET_LINK_BOOST_PYTHON(${PROJECT_NAME}_pywrap)
# BOOST_PYTHON_MEMBER_FUNCTION_OVERLOADS spews conversion warnings from int to long unsigned int.
# Unfortunately, using literals does not work in a macro. As such, this turns them off for the entire wrapper:
TARGET_COMPILE_OPTIONS(${PROJECT_NAME}_pywrap PRIVATE "-Wno-conversion")
# We are also exposing deprecated declarations until they are removed. Ignore the errors for the wrapper:
TARGET_COMPILE_OPTIONS(${PROJECT_NAME}_pywrap PRIVATE "-Wno-deprecated-declarations")
IF(UNIX AND NOT APPLE)
SET_TARGET_PROPERTIES(${PROJECT_NAME}_pywrap PROPERTIES INSTALL_RPATH "\$ORIGIN/../../..")
......
......@@ -10,7 +10,6 @@
#define BINDINGS_PYTHON_CROCODDYL_CORE_COST_BASE_HPP_
#include "crocoddyl/core/cost-base.hpp"
#include "crocoddyl/core/utils/to-string.hpp"
#include "crocoddyl/core/utils/exception.hpp"
namespace crocoddyl {
......
......@@ -9,6 +9,7 @@
#include "python/crocoddyl/fwd.hpp"
#include "crocoddyl/core/utils/version.hpp"
#include "python/crocoddyl/utils/vector-converter.hpp"
#include "python/crocoddyl/utils/set-converter.hpp"
namespace crocoddyl {
namespace python {
......@@ -41,6 +42,9 @@ BOOST_PYTHON_MODULE(libcrocoddyl_pywrap) {
StdVectorPythonVisitor<MatrixX, std::allocator<MatrixX>, true>::expose("StdVec_MatrixX");
StdVectorPythonVisitor<RowMatrixX, std::allocator<RowMatrixX>, true>::expose("StdVec_RowMatrixX");
// Register converters between std::set and Python set
StdSetPythonVisitor<std::string, std::less<std::string>, std::allocator<std::string>, true>::expose("StdSet_String");
exposeCore();
exposeMultibody();
}
......
///////////////////////////////////////////////////////////////////////////////
// BSD 3-Clause License
//
// Copyright (C) 2019-2021, LAAS-CNRS, University of Edinburgh
// Copyright (C) 2019-2022, LAAS-CNRS, University of Edinburgh, University of Oxford
// Copyright note valid unless otherwise stated in individual files.
// All rights reserved.
///////////////////////////////////////////////////////////////////////////////
......@@ -12,9 +12,11 @@
#include <utility>
#include <string>
#include "python/crocoddyl/multibody/multibody.hpp"
#include "python/crocoddyl/utils/set-converter.hpp"
#include "python/crocoddyl/utils/map-converter.hpp"
#include "crocoddyl/multibody/contacts/multiple-contacts.hpp"
#include "python/crocoddyl/utils/printable.hpp"
#include "python/crocoddyl/utils/deprecate.hpp"
namespace crocoddyl {
namespace python {
......@@ -22,20 +24,23 @@ namespace python {
BOOST_PYTHON_MEMBER_FUNCTION_OVERLOADS(ContactModelMultiple_addContact_wrap, ContactModelMultiple::addContact, 2, 3)
void exposeContactMultiple() {
#pragma GCC diagnostic push // TODO: Remove once the deprecated signature has been removed in a future release
#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
// Register custom converters between std::map and Python dict
typedef boost::shared_ptr<ContactItem> ContactItemPtr;
typedef boost::shared_ptr<ContactDataAbstract> ContactDataPtr;
StdMapPythonVisitor<std::string, ContactItemPtr, std::less<std::string>,
std::allocator<std::pair<const std::string, ContactItemPtr> >,
std::allocator<std::pair<const std::string, ContactItemPtr>>,
true>::expose("StdMap_ContactItem");
StdMapPythonVisitor<std::string, ContactDataPtr, std::less<std::string>,
std::allocator<std::pair<const std::string, ContactDataPtr> >,
std::allocator<std::pair<const std::string, ContactDataPtr>>,
true>::expose("StdMap_ContactData");
bp::register_ptr_to_python<boost::shared_ptr<ContactItem> >();
bp::register_ptr_to_python<boost::shared_ptr<ContactItem>>();
bp::class_<ContactItem>("ContactItem", "Describe a contact item.\n\n",
bp::init<std::string, boost::shared_ptr<ContactModelAbstract>, bp::optional<bool> >(
bp::init<std::string, boost::shared_ptr<ContactModelAbstract>, bp::optional<bool>>(
bp::args("self", "name", "contact", "active"),
"Initialize the contact item.\n\n"
":param name: contact name\n"
......@@ -47,10 +52,10 @@ void exposeContactMultiple() {
.def_readwrite("active", &ContactItem::active, "contact status")
.def(PrintableVisitor<ContactItem>());
bp::register_ptr_to_python<boost::shared_ptr<ContactModelMultiple> >();
bp::register_ptr_to_python<boost::shared_ptr<ContactModelMultiple>>();
bp::class_<ContactModelMultiple>("ContactModelMultiple",
bp::init<boost::shared_ptr<StateMultibody>, bp::optional<std::size_t> >(
bp::init<boost::shared_ptr<StateMultibody>, bp::optional<std::size_t>>(
bp::args("self", "state", "nu"),
"Initialize the multiple contact model.\n\n"
":param state: state of the multibody system\n"
......@@ -114,20 +119,30 @@ void exposeContactMultiple() {
.add_property("nc_total", bp::make_function(&ContactModelMultiple::get_nc_total),
"dimension of the total contact vector")
.add_property("nu", bp::make_function(&ContactModelMultiple::get_nu), "dimension of control vector")
.add_property("active",
bp::make_function(&ContactModelMultiple::get_active,
deprecated<bp::return_value_policy<bp::return_by_value>>(
"Deprecated. Use property active_set")),
"list of names of active contact items")
.add_property("inactive",
bp::make_function(&ContactModelMultiple::get_inactive,
deprecated<bp::return_value_policy<bp::return_by_value>>(
"Deprecated. Use property inactive_set")),
"list of names of inactive contact items")
.add_property(
"active",
bp::make_function(&ContactModelMultiple::get_active, bp::return_value_policy<bp::return_by_value>()),
"name of active contact items")
"active_set",
bp::make_function(&ContactModelMultiple::get_active_set, bp::return_value_policy<bp::return_by_value>()),
"set of names of active contact items")
.add_property(
"inactive",
bp::make_function(&ContactModelMultiple::get_inactive, bp::return_value_policy<bp::return_by_value>()),
"name of inactive contact items")
"inactive_set",
bp::make_function(&ContactModelMultiple::get_inactive_set, bp::return_value_policy<bp::return_by_value>()),
"set of names of inactive contact items")
.def("getContactStatus", &ContactModelMultiple::getContactStatus, bp::args("self", "name"),
"Return the contact status of a given contact name.\n\n"
":param name: contact name")
.def(PrintableVisitor<ContactModelMultiple>());
bp::register_ptr_to_python<boost::shared_ptr<ContactDataMultiple> >();
bp::register_ptr_to_python<boost::shared_ptr<ContactDataMultiple>>();
bp::class_<ContactDataMultiple>(
"ContactDataMultiple", "Data class for multiple contacts.\n\n",
......@@ -135,7 +150,7 @@ void exposeContactMultiple() {
bp::args("self", "model", "data"),
"Create multicontact data.\n\n"
":param model: multicontact model\n"
":param data: Pinocchio data")[bp::with_custodian_and_ward<1, 2, bp::with_custodian_and_ward<1, 3> >()])
":param data: Pinocchio data")[bp::with_custodian_and_ward<1, 2, bp::with_custodian_and_ward<1, 3>>()])
.add_property("Jc", bp::make_getter(&ContactDataMultiple::Jc, bp::return_internal_reference<>()),
bp::make_setter(&ContactDataMultiple::Jc),
"contact Jacobian in frame coordinate (memory defined for active and inactive contacts)")
......@@ -158,6 +173,8 @@ void exposeContactMultiple() {
bp::make_getter(&ContactDataMultiple::contacts, bp::return_value_policy<bp::return_by_value>()),
"stack of contacts data")
.def_readwrite("fext", &ContactDataMultiple::fext, "external spatial forces in join coordinates");
#pragma GCC diagnostic pop
}
} // namespace python
......
......@@ -10,7 +10,6 @@
#ifndef BINDINGS_PYTHON_CROCODDYL_UTILS_MAP_CONVERTER_HPP_
#define BINDINGS_PYTHON_CROCODDYL_UTILS_MAP_CONVERTER_HPP_
#include <Eigen/Dense>
#include <map>
#include <boost/python/stl_iterator.hpp>
#include <boost/python/to_python_converter.hpp>
......@@ -49,8 +48,6 @@ struct dict_to_map {
/// Check if conversion is possible
static void* convertible(PyObject* object) {
namespace python = boost::python;
// Check if it is a list
if (!PyObject_GetIter(object)) return 0;
return object;
......@@ -58,14 +55,13 @@ struct dict_to_map {
/// Perform the conversion
static void construct(PyObject* object, boost::python::converter::rvalue_from_python_stage1_data* data) {
namespace python = boost::python;
// convert the PyObject pointed to by `object` to a boost::python::dict
python::handle<> handle(python::borrowed(object)); // "smart ptr"
python::dict dict(handle);
bp::handle<> handle(bp::borrowed(object)); // "smart ptr"
bp::dict dict(handle);
// get a pointer to memory into which we construct the map
// this is provided by the Python runtime
typedef python::converter::rvalue_from_python_storage<Container> storage_type;
typedef bp::converter::rvalue_from_python_storage<Container> storage_type;
void* storage = reinterpret_cast<storage_type*>(data)->storage.bytes;
// placement-new allocate the result
......@@ -73,24 +69,24 @@ struct dict_to_map {
// iterate over the dictionary `dict`, fill up the map `map`
Container& map(*(static_cast<Container*>(storage)));
python::list keys(dict.keys());
int keycount(static_cast<int>(python::len(keys)));
bp::list keys(dict.keys());
int keycount(static_cast<int>(bp::len(keys)));
for (int i = 0; i < keycount; ++i) {
// get the key
python::object keyobj(keys[i]);
python::extract<typename Container::key_type> keyproxy(keyobj);
bp::object keyobj(keys[i]);
bp::extract<typename Container::key_type> keyproxy(keyobj);
if (!keyproxy.check()) {
PyErr_SetString(PyExc_KeyError, "Bad key type");
python::throw_error_already_set();
bp::throw_error_already_set();
}
typename Container::key_type key = keyproxy();
// get the corresponding value
python::object valobj(dict[keyobj]);
python::extract<typename Container::mapped_type> valproxy(valobj);
bp::object valobj(dict[keyobj]);
bp::extract<typename Container::mapped_type> valproxy(valobj);
if (!valproxy.check()) {
PyErr_SetString(PyExc_ValueError, "Bad value type");
python::throw_error_already_set();
bp::throw_error_already_set();
}
typename Container::mapped_type val = valproxy();
map[key] = val;
......@@ -101,8 +97,7 @@ struct dict_to_map {
}
static boost::python::dict todict(Container& self) {
namespace python = boost::python;
python::dict dict;
bp::dict dict;
typename Container::const_iterator it;
for (it = self.begin(); it != self.end(); ++it) {
dict.setdefault(it->first, it->second);
......
///////////////////////////////////////////////////////////////////////////////
// BSD 3-Clause License
//
// Copyright (C) 2022, University of Oxford
// Copyright (C) 2019-2020, LAAS-CNRS, University of Edinburgh
// Copyright (C) 2020, INRIA
// Copyright note valid unless otherwise stated in individual files.
// All rights reserved.
///////////////////////////////////////////////////////////////////////////////
#ifndef BINDINGS_PYTHON_CROCODDYL_UTILS_SET_CONVERTER_HPP_
#define BINDINGS_PYTHON_CROCODDYL_UTILS_SET_CONVERTER_HPP_
#include <set>
#include <boost/python/stl_iterator.hpp>
#include <boost/python/to_python_converter.hpp>
#include <boost/python/suite/indexing/indexing_suite.hpp>
#include <iostream>
namespace crocoddyl {
namespace python {
namespace bp = boost::python;
/**
* @brief Create a pickle interface for the std::set
*
* @param[in] Container Set type to be pickled
* \sa Pickle
*/
template <typename Container>
struct PickleSet : boost::python::pickle_suite {
static boost::python::tuple getinitargs(const Container&) { return boost::python::make_tuple(); }
static boost::python::tuple getstate(boost::python::object op) {
bp::list list;
const Container& ret = boost::python::extract<const Container&>(op);
for (const auto& it : ret) {
list.append(it);
}
return boost::python::make_tuple(list);
}
static void setstate(boost::python::object op, boost::python::tuple tup) {
Container& o = boost::python::extract<Container&>(op)();
boost::python::stl_input_iterator<typename Container::value_type> begin(tup[0]), end;
o.insert(begin, end);
}
};
/** @brief Type that allows for registration of conversions from python iterable types. */
template <typename Container>
struct set_to_set {
/** @note Registers converter from a python iterable type to the provided type. */
static void register_converter() {
boost::python::converter::registry::push_back(&set_to_set::convertible, &set_to_set::construct,
boost::python::type_id<Container>());
}
/** @brief Check if PyObject is iterable. */
static void* convertible(PyObject* object) {
// Check if it is a set
if (!PySet_Check(object)) return 0;
PyObject* iter = PyObject_GetIter(object);
PyObject* item;
while ((item = PyIter_Next(iter))) {
bp::extract<typename Container::value_type> elt(iter);
// Py_DECREF(item);
if (!elt.check()) return 0;
}
Py_DECREF(iter);
return object;
}
/** @brief Convert iterable PyObject to C++ container type.
*
* Container Concept requirements:
* * Container::value_type is CopyConstructable.
*/
static void construct(PyObject* object, boost::python::converter::rvalue_from_python_stage1_data* data) {
// Object is a borrowed reference, so create a handle indicting it is
// borrowed for proper reference counting.
bp::handle<> handle(bp::borrowed(object));
// Obtain a handle to the memory block that the converter has allocated
// for the C++ type.
typedef bp::converter::rvalue_from_python_storage<Container> storage_type;
void* storage = reinterpret_cast<storage_type*>(data)->storage.bytes;
typedef bp::stl_input_iterator<typename Container::value_type> iterator;
// Allocate the C++ type into the converter's memory block, and assign
// its handle to the converter's convertible variable. The C++
// container is populated by passing the begin and end iterators of
// the python object to the container's constructor.
new (storage) Container(iterator(bp::object(handle)), // begin
iterator()); // end
data->convertible = storage;
}
static boost::python::object toset(Container& self) {
PyObject* set = PySet_New(NULL);
for (auto it = self.begin(); it != self.end(); ++it) {
PySet_Add(set, bp::object(*it).ptr());
}
return bp::object(bp::handle<>(set));
}
};
/**
* @brief Expose an std::set from a type given as template argument.
*
* @param[in] T Type to expose as std::set<T>.
* @param[in] Compare Type for the comparison function in
* std::set<T,Compare,Allocator>.
* @param[in] Allocator Type for the Allocator in
* std::set<T,Compare,Allocator>.
* @param[in] NoProxy When set to false, the elements will be copied when
* returned to Python.
*/
template <class T, class Compare = std::less<T>, class Allocator = std::allocator<T>, bool NoProxy = false>
struct StdSetPythonVisitor : public set_to_set<std::set<T, Compare, Allocator>> {
typedef std::set<T, Compare, Allocator> Container;
typedef set_to_set<Container> FromPythonSetConverter;
static void expose(const std::string& class_name, const std::string& doc_string = "") {
namespace bp = boost::python;
bp::class_<Container>(class_name.c_str(), doc_string.c_str())
// .def(StdSetPythonVisitor()); // TODO: Needs an indexing_suite for
// set
.def("toset", &FromPythonSetConverter::toset, bp::arg("self"), "Returns the std::set as a Python set.")
.def_pickle(PickleSet<Container>());
// Register conversion
FromPythonSetConverter::register_converter();
}
};
} // namespace python
} // namespace crocoddyl
#endif // BINDINGS_PYTHON_CROCODDYL_UTILS_SET_CONVERTER_HPP_
......@@ -10,7 +10,6 @@
#ifndef BINDINGS_PYTHON_CROCODDYL_UTILS_VECTOR_CONVERTER_HPP_
#define BINDINGS_PYTHON_CROCODDYL_UTILS_VECTOR_CONVERTER_HPP_
#include <Eigen/Dense>
#include <vector>
#include <boost/python/stl_iterator.hpp>
#include <boost/python/to_python_converter.hpp>
......@@ -51,19 +50,17 @@ struct list_to_vector {
/** @brief Check if PyObject is iterable. */
static void* convertible(PyObject* object) {
namespace python = boost::python;
// Check if it is a list
if (!PyList_Check(object)) return 0;
// Retrieve the underlying list
bp::object bp_obj(bp::handle<>(bp::borrowed(object)));
python::list bp_list(bp_obj);
python::ssize_t list_size = python::len(bp_list);
bp::list bp_list(bp_obj);
bp::ssize_t list_size = bp::len(bp_list);
// Check if all the elements contained in the current vector is of type T
for (python::ssize_t k = 0; k < list_size; ++k) {
python::extract<typename Container::value_type> elt(bp_list[k]);
for (bp::ssize_t k = 0; k < list_size; ++k) {
bp::extract<typename Container::value_type> elt(bp_list[k]);
if (!elt.check()) return 0;
}
return object;
......@@ -77,31 +74,29 @@ struct list_to_vector {
* i.e. Container(begin, end)
*/
static void construct(PyObject* object, boost::python::converter::rvalue_from_python_stage1_data* data) {
namespace python = boost::python;
// Object is a borrowed reference, so create a handle indicting it is
// borrowed for proper reference counting.
python::handle<> handle(python::borrowed(object));
bp::handle<> handle(bp::borrowed(object));
// Obtain a handle to the memory block that the converter has allocated
// for the C++ type.
typedef python::converter::rvalue_from_python_storage<Container> storage_type;
typedef bp::converter::rvalue_from_python_storage<Container> storage_type;
void* storage = reinterpret_cast<storage_type*>(data)->storage.bytes;
typedef python::stl_input_iterator<typename Container::value_type> iterator;
typedef bp::stl_input_iterator<typename Container::value_type> iterator;
// Allocate the C++ type into the converter's memory block, and assign
// its handle to the converter's convertible variable. The C++
// container is populated by passing the begin and end iterators of
// the python object to the container's constructor.
new (storage) Container(iterator(python::object(handle)), // begin
iterator()); // end
new (storage) Container(iterator(bp::object(handle)), // begin
iterator()); // end
data->convertible = storage;
}
static boost::python::list tolist(Container& self) {
namespace python = boost::python;
typedef python::iterator<Container> iterator;
python::list list(iterator()(self));
typedef bp::iterator<Container> iterator;
bp::list list(iterator()(self));
return list;
}
};
......
......@@ -16,7 +16,6 @@
#include "crocoddyl/core/fwd.hpp"
#include "crocoddyl/core/state-base.hpp"
#include "crocoddyl/core/utils/math.hpp"
#include "crocoddyl/core/utils/to-string.hpp"
namespace crocoddyl {
......
......@@ -16,7 +16,6 @@
#include "crocoddyl/core/fwd.hpp"
#include "crocoddyl/core/mathbase.hpp"
#include "crocoddyl/core/utils/to-string.hpp"
namespace crocoddyl {
......
......@@ -16,7 +16,6 @@
#include "crocoddyl/core/fwd.hpp"
#include "crocoddyl/core/mathbase.hpp"
#include "crocoddyl/core/state-base.hpp"
#include "crocoddyl/core/utils/to-string.hpp"
#include "crocoddyl/core/utils/exception.hpp"
namespace crocoddyl {
......
......@@ -32,7 +32,7 @@ void CostModelSumTpl<Scalar>::addCost(const std::string& name, boost::shared_ptr
std::pair<typename CostModelContainer::iterator, bool> ret =
costs_.insert(std::make_pair(name, boost::make_shared<CostItem>(name, cost, weight, active)));
if (ret.second == false) {
std::cout << "Warning: we couldn't add the " << name << " cost item, it already existed." << std::endl;
std::cerr << "Warning: we couldn't add the " << name << " cost item, it already existed." << std::endl;
} else if (active) {
nr_ += cost->get_activation()->get_nr();
nr_total_ += cost->get_activation()->get_nr();
......@@ -57,7 +57,7 @@ void CostModelSumTpl<Scalar>::removeCost(const std::string& name) {
active_.erase(std::remove(active_.begin(), active_.end(), name), active_.end());
inactive_.erase(std::remove(inactive_.begin(), inactive_.end(), name), inactive_.end());
} else {
std::cout << "Warning: we couldn't remove the " << name << " cost item, it doesn't exist." << std::endl;
std::cerr << "Warning: we couldn't remove the " << name << " cost item, it doesn't exist." << std::endl;
}
}
......@@ -80,7 +80,7 @@ void CostModelSumTpl<Scalar>::changeCostStatus(const std::string& name, const bo
}
it->second->active = active;
} else {
std::cout << "Warning: we couldn't change the status of the " << name << " cost item, it doesn't exist."
std::cerr << "Warning: we couldn't change the status of the " << name << " cost item, it doesn't exist."
<< std::endl;
}
}
......@@ -264,7 +264,7 @@ bool CostModelSumTpl<Scalar>::getCostStatus(const std::string& name) const {
if (it != costs_.end()) {
return it->second->active;
} else {
std::cout << "Warning: we couldn't get the status of the " << name << " cost item, it doesn't exist." << std::endl;
std::cerr << "Warning: we couldn't get the status of the " << name << " cost item, it doesn't exist." << std::endl;
return false;
}
}
......
......@@ -15,7 +15,6 @@
#include "crocoddyl/core/fwd.hpp"
#include "crocoddyl/core/state-base.hpp"
#include "crocoddyl/core/utils/to-string.hpp"
#include "crocoddyl/core/utils/math.hpp"
namespace crocoddyl {
......
......@@ -14,7 +14,6 @@
#include "crocoddyl/core/fwd.hpp"
#include "crocoddyl/core/utils/exception.hpp"
#include "crocoddyl/core/action-base.hpp"
#include "crocoddyl/core/utils/to-string.hpp"
#include "crocoddyl/core/utils/deprecate.hpp"
namespace crocoddyl {
......
......@@ -12,13 +12,7 @@
#include <exception>
#include <sstream>
#include "crocoddyl/core/utils/to-string.hpp"
#if __cplusplus >= 201103L // We are using C++11 or a later version
#define NOEXCEPT noexcept
#else
#define NOEXCEPT throw()
#endif
#define throw_pretty(m) \
{ \
......
///////////////////////////////////////////////////////////////////////////////
// BSD 3-Clause License
//
// Copyright (C) 2019-2020, University of Edinburgh
// Copyright note valid unless otherwise stated in individual files.
// All rights reserved.
///////////////////////////////////////////////////////////////////////////////
#if __cplusplus < 201103L
#ifndef CROCODDYL_CORE_UTILS_TO_STRING_HPP_
#define CROCODDYL_CORE_UTILS_TO_STRING_HPP_
#include <sstream>
namespace std {
template <typename T>
std::string to_string(T number) {
std::ostringstream ss;
ss << number;
return ss.str();
}
} // namespace std
#endif // CROCODDYL_CORE_UTILS_TO_STRING_HPP_
#endif // __cplusplus__ >= 201103L
......@@ -13,7 +13,6 @@
#include "crocoddyl/core/mathbase.hpp"
#include "crocoddyl/multibody/states/multibody.hpp"
#include "crocoddyl/multibody/force-base.hpp"
#include "crocoddyl/core/utils/to-string.hpp"
namespace crocoddyl {
......
......@@ -34,7 +34,7 @@ void ContactModel1DTpl<Scalar>::calc(const boost::shared_ptr<ContactDataAbstract
d->v = pinocchio::getFrameVelocity(*state_->get_pinocchio().get(), *d->pinocchio, id_);
d->a = pinocchio::getFrameAcceleration(*state_->get_pinocchio().get(), *d->pinocchio, id_);
d->Jc.template row(0) = d->fJf.template row(2);
d->Jc.row(0) = d->fJf.row(2);