diff --git a/std-map.hpp b/std-map.hpp
new file mode 100644
index 0000000000000000000000000000000000000000..c5a5340f5e0166acb91ed2273ee8d81338f1ed18
--- /dev/null
+++ b/std-map.hpp
@@ -0,0 +1,77 @@
+//
+// Copyright (c) 2020 INRIA
+//
+
+#ifndef __pinocchio_python_utils_map_hpp__
+#define __pinocchio_python_utils_map_hpp__
+
+#include <boost/python/suite/indexing/map_indexing_suite.hpp>
+
+namespace pinocchio
+{
+  namespace python
+  {
+    namespace details
+    {
+      template<typename Container>
+      struct overload_base_get_item_for_std_map
+      : public boost::python::def_visitor< overload_base_get_item_for_std_map<Container> >
+      {
+        typedef typename Container::value_type value_type;
+        typedef typename Container::value_type::second_type data_type;
+        typedef typename Container::key_type key_type;
+        typedef typename Container::key_type index_type;
+        
+        template <class Class>
+        void visit(Class& cl) const
+        {
+          cl
+          .def("__getitem__", &base_get_item);
+        }
+        
+      private:
+        
+        static boost::python::object
+        base_get_item(boost::python::back_reference<Container&> container, PyObject* i_)
+        {
+          namespace bp = ::boost::python;
+
+          index_type idx = convert_index(container.get(), i_);
+          typename Container::iterator i = container.get().find(idx);
+          if (i == container.get().end())
+          {
+              PyErr_SetString(PyExc_KeyError, "Invalid key");
+              bp::throw_error_already_set();
+          }
+          
+          typename bp::to_python_indirect<data_type&,bp::detail::make_reference_holder> convert;
+          return bp::object(bp::handle<>(convert(i->second)));
+        }
+        
+        static index_type
+        convert_index(Container& /*container*/, PyObject* i_)
+        {
+          namespace bp = ::boost::python;
+          bp::extract<key_type const&> i(i_);
+          if (i.check())
+          {
+            return i();
+          }
+          else
+          {
+            bp::extract<key_type> i(i_);
+            if (i.check())
+              return i();
+          }
+          
+          PyErr_SetString(PyExc_TypeError, "Invalid index type");
+          bp::throw_error_already_set();
+          return index_type();
+        }
+      };
+      
+    }
+  }
+}
+
+#endif // ifndef __pinocchio_python_utils_map_hpp__
diff --git a/std-vector.hpp b/std-vector.hpp
new file mode 100644
index 0000000000000000000000000000000000000000..c441268059931f255f7247d619b1ae6289bb7a9e
--- /dev/null
+++ b/std-vector.hpp
@@ -0,0 +1,374 @@
+//
+// Copyright (c) 2016-2022 CNRS INRIA
+//
+
+#ifndef __pinocchio_python_utils_std_vector_hpp__
+#define __pinocchio_python_utils_std_vector_hpp__
+
+#include <boost/python.hpp>
+#include <boost/python/stl_iterator.hpp>
+#include <boost/python/suite/indexing/vector_indexing_suite.hpp>
+#include <boost/mpl/if.hpp>
+
+#include <string>
+#include <vector>
+#include <iterator>
+
+#include "pinocchio/bindings/python/utils/pickle-vector.hpp"
+#include "pinocchio/bindings/python/utils/registration.hpp"
+#include "pinocchio/bindings/python/utils/copyable.hpp"
+
+namespace pinocchio
+{
+  namespace python
+  {
+    // Forward declaration
+    template<typename vector_type, bool NoProxy = false>
+    struct StdContainerFromPythonList;
+  
+    // Forward declaration
+    template<typename vector_type, bool NoProxy = false>
+    struct StdContainerFromPythonList;
+  
+    namespace details
+    {
+    
+      /// \brief Check if a PyObject can be converted to an std::vector<T>.
+      template<typename T>
+      bool from_python_list(PyObject * obj_ptr,T *)
+      {
+        namespace bp = ::boost::python;
+        
+        // Check if it is a list
+        if(!PyList_Check(obj_ptr)) return false;
+        
+        // Retrieve the underlying list
+        bp::object bp_obj(bp::handle<>(bp::borrowed(obj_ptr)));
+        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(bp::ssize_t k = 0; k < list_size; ++k)
+        {
+          bp::extract<T> elt(bp_list[k]);
+          if(!elt.check()) return false;
+        }
+        
+        return true;
+      }
+    
+      template<typename vector_type, bool NoProxy>
+      struct build_list
+      {
+        static ::boost::python::list run(vector_type & vec)
+        {
+          namespace bp = ::boost::python;
+          
+          bp::list bp_list;
+          for(size_t k = 0; k < vec.size(); ++k)
+          {
+            bp_list.append(boost::ref(vec[k]));
+          }
+          return bp_list;
+        }
+      };
+    
+      template<typename vector_type>
+      struct build_list<vector_type,true>
+      {
+        static ::boost::python::list run(vector_type & vec)
+        {
+          namespace bp = ::boost::python;
+          
+          typedef bp::iterator<vector_type> iterator;
+          return bp::list(iterator()(vec));
+        }
+      };
+    } // namespace details
+}} // namespace pinocchio::python
+
+namespace boost { namespace python { namespace converter {
+
+  template<typename Type, class Allocator>
+  struct reference_arg_from_python<std::vector<Type,Allocator> &>
+  : arg_lvalue_from_python_base
+  {
+    typedef std::vector<Type,Allocator> vector_type;
+    typedef vector_type & ref_vector_type;
+    typedef ref_vector_type result_type;
+    
+    reference_arg_from_python(PyObject* py_obj)
+    : arg_lvalue_from_python_base(converter::get_lvalue_from_python(py_obj,
+                                                                    registered<vector_type>::converters))
+    , m_data(NULL)
+    , m_source(py_obj)
+    , vec_ptr(NULL)
+    {
+      if(result() != 0) // we have found a lvalue converter
+        return;
+      
+      // Check if py_obj is a py_list, which can then be converted to an std::vector
+      bool is_convertible = ::pinocchio::python::details::from_python_list(py_obj,(Type*)(0));
+      if(!is_convertible)
+        return;
+      
+      typedef ::pinocchio::python::StdContainerFromPythonList<vector_type> Constructor;
+      Constructor::construct(py_obj,&m_data.stage1);
+      
+      void * & m_result = const_cast<void * &>(result());
+      m_result = m_data.stage1.convertible;
+      vec_ptr = reinterpret_cast<vector_type*>(m_data.storage.bytes);
+    }
+    
+    result_type operator()() const
+    {
+      return ::boost::python::detail::void_ptr_to_reference(result(),
+                                                            (result_type(*)())0);
+    }
+    
+    ~reference_arg_from_python()
+    {
+      if(m_data.stage1.convertible == m_data.storage.bytes)
+      {
+        // Copy back the reference
+        const vector_type & vec = *vec_ptr;
+        list bp_list(handle<>(borrowed(m_source)));
+        for(size_t i = 0; i < vec.size(); ++i)
+        {
+          Type & elt = extract<Type &>(bp_list[i]);
+          elt = vec[i];
+        }
+      }
+    }
+      
+   private:
+    rvalue_from_python_data<ref_vector_type> m_data;
+    PyObject* m_source;
+    vector_type * vec_ptr;
+  };
+
+}}} // boost::python::converter
+
+namespace pinocchio
+{
+  namespace python
+  {
+    
+    ///
+    /// \brief Register the conversion from a Python list to a std::vector
+    ///
+    /// \tparam vector_type A std container (e.g. std::vector or std::list)
+    ///
+    template<typename vector_type, bool NoProxy>
+    struct StdContainerFromPythonList
+    {
+      typedef typename vector_type::value_type T;
+      typedef typename vector_type::allocator_type Allocator;
+      
+      /// \brief Check if obj_ptr can be converted
+      static void* convertible(PyObject* obj_ptr)
+      {
+        namespace bp = boost::python;
+        
+        // Check if it is a list
+        if(!PyList_Check(obj_ptr)) return 0;
+        
+        // Retrieve the underlying list
+        bp::object bp_obj(bp::handle<>(bp::borrowed(obj_ptr)));
+        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(bp::ssize_t k = 0; k < list_size; ++k)
+        {
+          bp::extract<T> elt(bp_list[k]);
+          if(!elt.check()) return 0;
+        }
+        
+        return obj_ptr;
+      }
+      
+      /// \brief Allocate the std::vector and fill it with the element contained in the list
+      static void construct(PyObject* obj_ptr,
+                            boost::python::converter::rvalue_from_python_stage1_data * memory)
+      {
+        namespace bp = boost::python;
+        
+        // Extract the list
+        bp::object bp_obj(bp::handle<>(bp::borrowed(obj_ptr)));
+        bp::list bp_list(bp_obj);
+        
+        void * storage = reinterpret_cast< bp::converter::rvalue_from_python_storage<vector_type>*>
+        (reinterpret_cast<void*>(memory))->storage.bytes;
+        
+        typedef bp::stl_input_iterator<T> iterator;
+        
+        // Build the std::vector
+        new (storage) vector_type(iterator(bp_list),
+                                  iterator());
+        
+        // Validate the construction
+        memory->convertible = storage;
+      }
+      
+      static void register_converter()
+      {
+        ::boost::python::converter::registry::push_back(&convertible,
+                                                        &construct,
+                                                        ::boost::python::type_id<vector_type>());
+      }
+      
+      static ::boost::python::list tolist(vector_type & self)
+      {
+        return details::build_list<vector_type,NoProxy>::run(self);
+      }
+    };
+  
+    namespace internal
+    {
+    
+//    template<typename T> struct has_operator_equal;
+      template<typename T>
+      struct has_operator_equal :
+      boost::mpl::if_<typename boost::is_base_of<NumericalBase<T>,T>::type,has_operator_equal< NumericalBase<T> >,
+      typename boost::mpl::if_<typename boost::is_base_of<Eigen::EigenBase<T>,T>::type,has_operator_equal< Eigen::EigenBase<T> >,
+      boost::true_type>::type >
+      {};
+    
+    
+      template<typename T, class A>
+      struct has_operator_equal< std::vector<T,A> > : has_operator_equal<T>
+      {};
+    
+      template<>
+      struct has_operator_equal<bool> : boost::true_type
+      {};
+    
+      template<typename EigenObject>
+      struct has_operator_equal< Eigen::EigenBase<EigenObject> > : has_operator_equal<typename EigenObject::Scalar>
+      {};
+  
+      template<typename Derived>
+      struct has_operator_equal< NumericalBase<Derived> > : has_operator_equal<typename NumericalBase<Derived>::Scalar>
+      {};
+    
+      template<typename T, bool has_operator_equal_value = boost::is_base_of<boost::true_type,has_operator_equal<T> >::value >
+      struct contains_algo;
+    
+      template<typename T>
+      struct contains_algo<T,true>
+      {
+        template<class Container, typename key_type>
+        static bool run(Container & container, key_type const & key)
+        {
+          return std::find(container.begin(), container.end(), key)
+          != container.end();
+        }
+      };
+      
+      template<typename T>
+      struct contains_algo<T,false>
+      {
+        template<class Container, typename key_type>
+        static bool run(Container & container, key_type const & key)
+        {
+          for(size_t k = 0; k < container.size(); ++k)
+          {
+            if(&container[k] == &key)
+              return true;
+          }
+          return false;
+        }
+      };
+    
+      template<class Container, bool NoProxy>
+      struct contains_vector_derived_policies
+      : public ::boost::python::vector_indexing_suite<Container,NoProxy,contains_vector_derived_policies<Container, NoProxy> >
+      {
+        typedef typename Container::value_type key_type;
+        
+        static bool contains(Container & container, key_type const & key)
+        {
+          return contains_algo<key_type>::run(container,key);
+        }
+      };
+    }
+  
+    struct EmptyPythonVisitor
+    : public ::boost::python::def_visitor<EmptyPythonVisitor>
+    {
+      template <class classT>
+      void visit(classT &) const
+      {}
+    };
+    
+    ///
+    /// \brief Expose an std::vector from a type given as template argument.
+    ///
+    /// \tparam T Type to expose as std::vector<T>.
+    /// \tparam Allocator Type for the Allocator in std::vector<T,Allocator>.
+    /// \tparam NoProxy When set to false, the elements will be copied when returned to Python.
+    /// \tparam EnableFromPythonListConverter Enables the conversion from a Python list to a std::vector<T,Allocator>
+    ///
+    /// \sa StdAlignedVectorPythonVisitor
+    ///
+    template<class vector_type, bool NoProxy = false, bool EnableFromPythonListConverter = true>
+    struct StdVectorPythonVisitor
+    : public ::boost::python::vector_indexing_suite<vector_type, NoProxy, internal::contains_vector_derived_policies<vector_type,NoProxy> >
+    , public StdContainerFromPythonList<vector_type,NoProxy>
+    {
+      typedef typename vector_type::value_type value_type;
+      typedef typename vector_type::allocator_type allocator_type;
+      typedef StdContainerFromPythonList<vector_type,NoProxy> FromPythonListConverter;
+      
+      static void expose(const std::string & class_name,
+                         const std::string & doc_string = "")
+      {
+        expose(class_name,doc_string,EmptyPythonVisitor());
+      }
+      
+      template<typename VisitorDerived>
+      static void expose(const std::string & class_name,
+                         const boost::python::def_visitor<VisitorDerived> & visitor)
+      {
+        expose(class_name,"",visitor);
+      }
+      
+      template<typename VisitorDerived>
+      static void expose(const std::string & class_name,
+                         const std::string & doc_string,
+                         const boost::python::def_visitor<VisitorDerived> & visitor)
+      {
+        namespace bp = boost::python;
+        
+        if(!register_symbolic_link_to_registered_type<vector_type>())
+        {
+          bp::class_<vector_type> cl(class_name.c_str(),doc_string.c_str());
+          cl
+          .def(StdVectorPythonVisitor())
+          
+          .def(bp::init<size_t, const value_type &>(bp::args("self","size","value"),"Constructor from a given size and a given value."))
+          .def(bp::init<const vector_type &>(bp::args("self","other"),"Copy constructor"))
+
+          .def("tolist",&FromPythonListConverter::tolist,bp::arg("self"),
+               "Returns the std::vector as a Python list.")
+          .def(visitor)
+          .def("reserve",&vector_type::reserve,(bp::arg("self"),bp::arg("new_cap")),
+               "Increase the capacity of the vector to a value that's greater or equal to new_cap.")
+#ifndef PINOCCHIO_PYTHON_NO_SERIALIZATION
+          .def_pickle(PickleVector<vector_type>())
+#endif
+          .def(CopyableVisitor<vector_type>())
+          ;
+          
+          // Register conversion
+          if(EnableFromPythonListConverter)
+            FromPythonListConverter::register_converter();
+        }
+      }
+    };
+    
+  } // namespace python
+} // namespace pinocchio
+
+#endif // ifndef __pinocchio_python_utils_std_vector_hpp__