diff --git a/.github/workflows/ros_ci.yml b/.github/workflows/ros_ci.yml
index ff06681c302c473a015c58ae66c82db92a276a9d..6d7e13a7df488e98394b2b9c9c59105c7c2a3f52 100644
--- a/.github/workflows/ros_ci.yml
+++ b/.github/workflows/ros_ci.yml
@@ -12,10 +12,13 @@ jobs:
       matrix:
         env:
           - {ROS_DISTRO: melodic}
-          - {ROS_DISTRO: noetic}
+          - {ROS_DISTRO: noetic, BUILDER: catkin_tools}
+          - {ROS_DISTRO: foxy}
+          - {ROS_DISTRO: galactic}
+          - {ROS_DISTRO: foxy, PRERELEASE: true}
+          - {ROS_DISTRO: galactic, PRERELEASE: true}
     env:
       CCACHE_DIR: /github/home/.ccache # Enable ccache
-      BUILDER: catkin_tools
     runs-on: ubuntu-latest
     steps:
       - uses: actions/checkout@v2
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 765d2abf15d3488b895c288cf23d7ab69ad1e21d..95632c47321b8561ebfc6d78a209a1894d7454a1 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -230,6 +230,9 @@ ADD_SOURCE_GROUP(${PROJECT_NAME}_SOURCES)
 
 # Install package for ROS
 install(FILES package.xml DESTINATION share/eigenpy)
+# Allows Colcon to find non-Ament packages when using workspace underlays
+file(WRITE ${CMAKE_CURRENT_BINARY_DIR}/share/ament_index/resource_index/packages/${PROJECT_NAME} "")
+install(FILES ${CMAKE_CURRENT_BINARY_DIR}/share/ament_index/resource_index/packages/${PROJECT_NAME} DESTINATION share/ament_index/resource_index/packages)
 
 # ----------------------------------------------------
 # --- PYTHON LIBRARY ---------------------------------
diff --git a/cmake b/cmake
index b0aa0ff9377c953340aeb037297003df04d6185f..b0a77e2ead3f8dbb201b05e42048bb1cfc6a518e 160000
--- a/cmake
+++ b/cmake
@@ -1 +1 @@
-Subproject commit b0aa0ff9377c953340aeb037297003df04d6185f
+Subproject commit b0a77e2ead3f8dbb201b05e42048bb1cfc6a518e
diff --git a/include/eigenpy/quaternion.hpp b/include/eigenpy/quaternion.hpp
index 1f824eced7d5beafa4ff044ebb8e978fc3fedc7a..7e00edfa3bc5b6602d4710270ec0bd17d2a77cdf 100644
--- a/include/eigenpy/quaternion.hpp
+++ b/include/eigenpy/quaternion.hpp
@@ -275,7 +275,7 @@ namespace eigenpy
       return new Quaternion;
     }
     
-    static Quaternion* FromOneVector(const Vector4& v)
+    static Quaternion* FromOneVector(const Eigen::Ref<Vector4> v)
     {
       Quaternion* q(new Quaternion(v[3],v[0],v[1],v[2]));
       return q;
diff --git a/include/eigenpy/user-type.hpp b/include/eigenpy/user-type.hpp
index ed49ceb21fc10c72b29dd31ea015f6c1f1719fe1..cbe0c05d285ad0dd972f6c28b3fb4035582c3de9 100644
--- a/include/eigenpy/user-type.hpp
+++ b/include/eigenpy/user-type.hpp
@@ -1,5 +1,5 @@
 //
-// Copyright (c) 2020-2021 INRIA
+// Copyright (c) 2020-2022 INRIA
 //
 
 #ifndef __eigenpy_user_type_hpp__
@@ -19,14 +19,18 @@ namespace eigenpy
   {
     static To run(const From & from)
     {
-      return (To)from;
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wconversion"
+#pragma GCC diagnostic ignored "-Wfloat-conversion"
+      return static_cast<To>(from);
+#pragma GCC diagnostic pop
     }
-    
+
   };
 
   namespace internal
   {
-  
+
     template<typename From, typename To>
     static void cast(void * from_, void * to_, npy_intp n, void * /*fromarr*/, void * /*toarr*/)
     {
@@ -38,7 +42,7 @@ namespace eigenpy
         to[i] = eigenpy::cast<From,To>::run(from[i]);
       }
     }
-  
+
     template<typename T, int type_code = NumpyEquivalentType<T>::type_code>
     struct SpecialMethods
     {
@@ -54,7 +58,7 @@ namespace eigenpy
       inline static int fillwithscalar(void* buffer_, npy_intp length,
                                        void* value, void* arr);
     };
-  
+
     template<typename T>
     struct OffsetOf
     {
@@ -63,10 +67,10 @@ namespace eigenpy
         char c;
         T v;
       };
-      
+
       enum { value = offsetof(Data, v) };
     };
-  
+
     template<typename T>
     struct SpecialMethods<T,NPY_USERDEF>
     {
@@ -79,7 +83,7 @@ namespace eigenpy
           T & t2 = *static_cast<T*>(src);
           t1 = t2;
         }
-          
+
         if(swap)
         {
           T & t1 = *static_cast<T*>(dst);
@@ -112,14 +116,14 @@ namespace eigenpy
       ///        pointed to by data. This function deals with “misbehaved” arrays.
       ///        If successful, a zero is returned, otherwise, a negative one is returned
       ///        (and a Python error set).
-      
+
       /// \param[in] src_obj  Pointer to the location of the python object
       /// \param[in] dest_ptr Pointer to the location in the array where the source object should be saved.
       /// \param[in] array Pointer to the location of the array
       ///
       /// \returns int Success(0) or Failure(-1)
       ///
-      
+
       inline static int setitem(PyObject * src_obj, void * dest_ptr, void * array)
       {
 //        std::cout << "setitem" << std::endl;
@@ -132,7 +136,7 @@ namespace eigenpy
         PyArray_Descr * descr = PyArray_DTYPE(py_array);
         PyTypeObject * array_scalar_type = descr->typeobj;
         PyTypeObject * src_obj_type = Py_TYPE(src_obj);
-        
+
         if(array_scalar_type != src_obj_type)
         {
           std::stringstream ss;
@@ -141,7 +145,7 @@ namespace eigenpy
           eigenpy::Exception(ss.str());
           return -1;
         }
-        
+
         bp::extract<T&> extract_src_obj(src_obj);
         if(!extract_src_obj.check())
         {
@@ -151,25 +155,25 @@ namespace eigenpy
           eigenpy::Exception(ss.str());
           return -1;
         }
-        
+
         const T & src = extract_src_obj();
         T & dest = *static_cast<T*>(dest_ptr);
         dest = src;
 
         return 0;
       }
-      
+
       inline static void copyswapn(void * dst, long dstride, void * src, long sstride,
                                    long n, int swap, void * array)
       {
 //        std::cout << "copyswapn" << std::endl;
-        
+
         char *dstptr = static_cast<char*>(dst);
         char *srcptr = static_cast<char*>(src);
-        
+
         PyArrayObject * py_array = static_cast<PyArrayObject *>(array);
         PyArray_CopySwapFunc * copyswap = PyArray_DESCR(py_array)->f->copyswap;
-        
+
         for (npy_intp i = 0; i < n; i++)
         {
           copyswap(dstptr, srcptr, swap, array);
@@ -177,7 +181,7 @@ namespace eigenpy
           srcptr += sstride;
         }
       }
-      
+
       inline static npy_bool nonzero(void * ip, void * array)
       {
 //        std::cout << "nonzero" << std::endl;
@@ -196,7 +200,7 @@ namespace eigenpy
           return (npy_bool)(tmp_value != ZeroValue);
         }
       }
-      
+
       inline static void dotfunc(void * ip0_, npy_intp is0, void * ip1_, npy_intp is1,
                                  void * op, npy_intp n, void * /*arr*/)
       {
@@ -206,13 +210,13 @@ namespace eigenpy
         typedef const Eigen::Map<const VectorT,0,InputStride> ConstMapType;
 
         ConstMapType
-        v0(static_cast<T*>(ip0_),n,InputStride(is0/sizeof(T))),
-        v1(static_cast<T*>(ip1_),n,InputStride(is1/sizeof(T)));
-        
+        v0(static_cast<T*>(ip0_),n,InputStride(is0/(Eigen::DenseIndex)sizeof(T))),
+        v1(static_cast<T*>(ip1_),n,InputStride(is1/(Eigen::DenseIndex)sizeof(T)));
+
         *static_cast<T*>(op) = v0.dot(v1);
       }
-      
-      
+
+
       inline static int fillwithscalar(void* buffer_, npy_intp length,
                                        void* value, void* /*arr*/)
       {
@@ -225,8 +229,8 @@ namespace eigenpy
         }
         return 0;
       }
-      
-      
+
+
       static int fill(void* data_, npy_intp length, void* /*arr*/)
       {
 //        std::cout << "fillwithscalar" << std::endl;
@@ -240,10 +244,10 @@ namespace eigenpy
         }
         return 0;
       }
-      
+
 
     };  //     struct SpecialMethods<T,NPY_USERDEF>
-  
+
   } // namespace internal
 
 
@@ -252,17 +256,17 @@ namespace eigenpy
   {
     PyArray_Descr* from_array_descr = Register::getPyArrayDescr<From>();
 //    int from_typenum = Register::getTypeCode<From>();
-    
+
 //    PyTypeObject * to_py_type = Register::getPyType<To>();
     int to_typenum = Register::getTypeCode<To>();
     assert(to_typenum >= 0 && "to_typenum is not valid");
     assert(from_array_descr != NULL && "from_array_descr is not valid");
-    
+
     std::cout << "From: " << bp::type_info(typeid(From)).name() << " " << Register::getTypeCode<From>()
     << " to: " << bp::type_info(typeid(To)).name() << " " << Register::getTypeCode<To>()
     << "\n to_typenum: " << to_typenum
     << std::endl;
-    
+
     if(call_PyArray_RegisterCastFunc(from_array_descr,
                                      to_typenum,
                                      static_cast<PyArray_VectorUnaryFunc *>(&eigenpy::internal::cast<From,To>)) < 0)
@@ -277,7 +281,7 @@ namespace eigenpy
       eigenpy::Exception(ss.str());
       return false;
     }
-    
+
     if (safe && call_PyArray_RegisterCanCast(from_array_descr,
                                              to_typenum,
                                              NPY_NOSCALAR) < 0)
@@ -292,7 +296,7 @@ namespace eigenpy
       eigenpy::Exception(ss.str());
       return false;
     }
-    
+
     return true;
   }
 
@@ -307,17 +311,17 @@ namespace eigenpy
     bp::type_info type = bp::type_id<T>();
     const bp::converter::registration* registration =
       bp::converter::registry::query(type);
-    
+
     // If the class is not registered, return None.
     if (!registration) {
       //std::cerr<<"Class Not Registered. Returning Empty."<<std::endl;
       return bp::object();
     }
-    
+
     bp::handle<PyTypeObject> handle(bp::borrowed(registration->get_class_object()));
     return bp::object(handle);
   }
-  
+
   template<typename Scalar>
   int registerNewType(PyTypeObject * py_type_ptr = NULL)
   {
@@ -325,16 +329,16 @@ namespace eigenpy
     // In this case, the registration is not required.
     if(isNumpyNativeType<Scalar>())
       return NumpyEquivalentType<Scalar>::type_code;
-    
+
     // Retrieve the registered type for the current Scalar
     if(py_type_ptr == NULL)
     { // retrive the type from Boost.Python
       py_type_ptr = Register::getPyType<Scalar>();
     }
-    
+
     if(Register::isRegistered(py_type_ptr))
       return Register::getTypeCode(py_type_ptr); // the type is already registered
-    
+
     PyArray_GetItemFunc * getitem = &internal::SpecialMethods<Scalar>::getitem;
     PyArray_SetItemFunc * setitem = &internal::SpecialMethods<Scalar>::setitem;
     PyArray_NonzeroFunc * nonzero = &internal::SpecialMethods<Scalar>::nonzero;
@@ -343,7 +347,7 @@ namespace eigenpy
     PyArray_DotFunc * dotfunc = &internal::SpecialMethods<Scalar>::dotfunc;
     PyArray_FillFunc * fill = &internal::SpecialMethods<Scalar>::fill;
     PyArray_FillWithScalarFunc * fillwithscalar = &internal::SpecialMethods<Scalar>::fillwithscalar;
-    
+
     int code = Register::registerNewType(py_type_ptr,
                                          &typeid(Scalar),
                                          sizeof(Scalar),
@@ -353,13 +357,13 @@ namespace eigenpy
                                          dotfunc,
                                          fill,
                                          fillwithscalar);
-    
+
     call_PyArray_RegisterCanCast(call_PyArray_DescrFromType(NPY_OBJECT),
                                  code, NPY_NOSCALAR);
-    
+
     return code;
   }
-  
+
 } // namespace eigenpy
 
 #endif // __eigenpy_user_type_hpp__
diff --git a/package.xml b/package.xml
index 8454baff87311951e4f7809b31de02037091646a..13171594d921949b16ce2db2cb2362484113df6a 100644
--- a/package.xml
+++ b/package.xml
@@ -13,9 +13,10 @@
 
   <build_depend>git</build_depend>
   <build_depend>doxygen</build_depend>
-  <!-- The following tags are recommended by REP-136 -->
+
+  <!-- The following tag is recommended by REP-136 -->
   <exec_depend condition="$ROS_VERSION == 1">catkin</exec_depend>
-  <exec_depend condition="$ROS_VERSION == 2">ament_cmake</exec_depend>
+
   <depend condition="$ROS_PYTHON_VERSION == 2">python</depend>
   <depend condition="$ROS_PYTHON_VERSION == 3">python3</depend>
   <depend condition="$ROS_PYTHON_VERSION == 2">python-numpy</depend>