diff --git a/CMakeLists.txt b/CMakeLists.txt
index 13557e75d3051924c04beaadd4dc231d81b36207..62ad671b468ebbc1750c2f7a1f4d6a811c527cf3 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -180,6 +180,7 @@ SET(${PROJECT_NAME}_PYTHON_HEADERS
 
 IF(HPP_FCL_FOUND)
   LIST(APPEND ${PROJECT_NAME}_PYTHON_HEADERS
+      python/geometry-object.hpp
       python/geometry-model.hpp
       python/geometry-data.hpp
     )
diff --git a/src/algorithm/collisions.hpp b/src/algorithm/collisions.hpp
index cb37daad83ff5e5b5552ba98d90946f3121896ae..31a825b52ca6f70bf262d8887325c0381534d400 100644
--- a/src/algorithm/collisions.hpp
+++ b/src/algorithm/collisions.hpp
@@ -29,7 +29,7 @@ namespace se3
 
 
   ///
-  /// \brief Apply a forward kinematics and update the placement of the collision objects.
+  /// \brief Apply a forward kinematics and update the placement of the geometry objects (both collision's and visual's one).
   ///
   /// \param[in] model The model structure of the rigid body system.
   /// \param[in] data The data structure of the rigid body system.
@@ -45,7 +45,7 @@ namespace se3
                                        );
   
   ///
-  /// \brief Update the placement of the collision objects according to the current joint placements contained in data.
+  /// \brief Update the placement of the geometry objects according to the current joint placements contained in data. (both collision's and visual's one)
   ///
   /// \param[in] model The model structure of the rigid body system.
   /// \param[in] data The data structure of the rigid body system.
@@ -102,11 +102,16 @@ namespace se3
                                        GeometryData & data_geom
                                        )
   {
-    for (GeometryData::GeomIndex i=0; i < (GeometryData::GeomIndex) data_geom.model_geom.ngeom; ++i)
+    for (GeometryData::GeomIndex i=0; i < (GeometryData::GeomIndex) data_geom.model_geom.ncollisions; ++i)
     {
-      const Model::JointIndex & parent = model_geom.geom_parents[i];
-      data_geom.oMg[i] =  (data.oMi[parent] * model_geom.geometryPlacement[i]);
-      data_geom.oMg_fcl[i] =  toFclTransform3f(data_geom.oMg[i]);
+      const Model::JointIndex & parent = model_geom.collision_objects[i].parent;
+      data_geom.oMg_collisions[i] =  (data.oMi[parent] * model_geom.collision_objects[i].placement);
+      data_geom.oMg_fcl_collisions[i] =  toFclTransform3f(data_geom.oMg_collisions[i]);
+    }
+    for (GeometryData::GeomIndex i=0; i < (GeometryData::GeomIndex) data_geom.model_geom.nvisuals; ++i)
+    {
+      const Model::JointIndex & parent = model_geom.visual_objects[i].parent;
+      data_geom.oMg_visuals[i] =  (data.oMi[parent] * model_geom.visual_objects[i].placement);
     }
   }
   
diff --git a/src/multibody/geometry.hpp b/src/multibody/geometry.hpp
index ebe9444549553667a60ce0dbefa709ddadf1a0e9..ef5349e9fe6bc24d594c1cb977410adf92675d30 100644
--- a/src/multibody/geometry.hpp
+++ b/src/multibody/geometry.hpp
@@ -156,7 +156,83 @@ namespace se3
     GeomIndex object2;
 
   }; // struct CollisionResult
+
+enum GeometryType
+{
+  VISUAL,
+  COLLISION,
+  NONE
+};
+
+struct GeometryObject
+{
+  typedef Model::Index Index;
+  typedef Model::JointIndex JointIndex;
+  typedef Model::GeomIndex GeomIndex;
+
+  /// \brief Type of the GeometryObject. Cann be VISUAL, COLLISION, or NONE (cf GeometryType enumeration)
+  GeometryType type;
+
+  /// \brief Name of the geometry object
+  std::string name;
+
+  /// \brief Index of the parent joint
+  JointIndex parent;
+
+  /// \brief The actual cloud of points representing the collision mesh of the object
+  fcl::CollisionObject collision_object;
+
+  /// \brief Position of geometry object in parent joint's frame
+  SE3 placement;
+
+  /// \brief Absolute path to the mesh file
+  std::string mesh_path;
+
+
+  GeometryObject(const GeometryType type, const std::string & name, const JointIndex parent, const fcl::CollisionObject & collision,
+                 const SE3 & placement, const std::string & mesh_path)
+                : type(type)
+                , name(name)
+                , parent(parent)
+                , collision_object(collision)
+                , placement(placement)
+                , mesh_path(mesh_path)
+  {}
+
+  GeometryObject & operator=(const GeometryObject & other)
+  {
+    type = other.type;
+    name = other.name;
+    parent = other.parent;
+    collision_object = other.collision_object;
+    placement = other.placement;
+    mesh_path = other.mesh_path;
+    return *this;
+  }
+
+};
   
+  inline bool operator==(const GeometryObject & lhs, const GeometryObject & rhs)
+  {
+    return (lhs.type == rhs.type && lhs.name == rhs.name
+                               && lhs.parent == rhs.parent
+                               // && lhs.collision_object == rhs.collision_object
+                               && lhs.placement == rhs.placement
+                               && lhs.mesh_path ==  rhs.mesh_path
+                               );
+  }
+
+  inline std::ostream & operator<< (std::ostream & os, const GeometryObject & geom_object)
+  {
+    os  << "Type: \t" << geom_object.type
+        << "Name: \t" << geom_object.name
+        << "Parent ID: \t" << geom_object.parent
+        // << "collision object: \t" << geom_object.collision_object
+        << "Position in parent frame: \t" << geom_object.placement
+        << "Absolute path to mesh file: \t" << geom_object.mesh_path
+        << std::endl;
+    return os;
+  }
 
   struct GeometryModel
   {
@@ -166,35 +242,140 @@ namespace se3
     
     typedef std::list<GeomIndex> GeomIndexList;
 
+    /// \brief A const reference to the reference model.
     const se3::Model & model;
-    Index ngeom;
-    std::vector<fcl::CollisionObject> collision_objects;
-    std::vector<std::string> geom_names;
-    std::vector<JointIndex> geom_parents;                          // Joint parent of body <i>, denoted <li> (li==parents[i])
-    std::vector<SE3> geometryPlacement;                       // Position of geometry object in parent joint's frame
+
+    /// \brief The number of GeometryObjects that are of type COLLISION
+    Index ncollisions;
+
+    /// \brief The number of GeometryObjects that are of type visuals
+    Index nvisuals;
+
+    /// \brief Vector of GeometryObjects used for collision computations
+    std::vector<GeometryObject> collision_objects;
+
+    /// \brief Vector of GeometryObjects used for visualisation
+    std::vector<GeometryObject> visual_objects;
     
-    std::map < JointIndex, GeomIndexList >  innerObjects;       // Associate a list of CollisionObjects to a given joint Id
-    std::map < JointIndex, GeomIndexList >  outerObjects;       // Associate a list of CollisionObjects to a given joint Id
+    /// \brief A list of associated collision GeometryObjects to a given joint Id.
+    ///        Inner objects can be seen as geometry objects that directly move when the associated joint moves
+    std::map < JointIndex, GeomIndexList >  innerObjects;
+
+    /// \brief A list of associated collision GeometryObjects to a given joint Id
+    ///        Outer objects can be seen as geometry objects that may often be obstacles to the Inner objects of given joint
+    std::map < JointIndex, GeomIndexList >  outerObjects;
 
     GeometryModel(const se3::Model & model)
       : model(model)
-      , ngeom(0)
+      , ncollisions(0)
+      , nvisuals(0)
       , collision_objects()
-      , geom_names(0)
-      , geom_parents(0)
-      , geometryPlacement(0)
+      , visual_objects()
       , innerObjects()
       , outerObjects()
     {}
 
     ~GeometryModel() {};
 
-    GeomIndex addGeomObject(const JointIndex parent, const fcl::CollisionObject & co, const SE3 & placement, const std::string & geoName = "");
-    GeomIndex getGeomId(const std::string & name) const;
-    bool existGeomName(const std::string & name) const;
-    const std::string & getGeomName(const GeomIndex index) const;
 
+    /**
+     * @brief      Add a geometry object whose type is COLLISION to a GeometryModel
+     *
+     * @param[in]  parent     Index of the parent joint
+     * @param[in]  co         The actual fcl CollisionObject
+     * @param[in]  placement  The relative placement regarding to the parent frame
+     * @param[in]  geom_name  The name of the Geometry Object
+     * @param[in]  mesh_path  The absolute path to the mesh
+     *
+     * @return     The index of the new added GeometryObject in collision_objects
+     */
+    GeomIndex addCollisionObject(const JointIndex parent, const fcl::CollisionObject & co,
+                                 const SE3 & placement, const std::string & geom_name = "",
+                                 const std::string & mesh_path = "");
+    
+    /**
+     * @brief      Add a geometry object whose type is VISUAL to a GeometryModel
+     *
+     * @param[in]  parent     Index of the parent joint
+     * @param[in]  co         The actual fcl CollisionObject
+     * @param[in]  placement  The relative placement regarding to the parent frame
+     * @param[in]  geom_name  The name of the Geometry Object
+     * @param[in]  mesh_path  The absolute path to the mesh
+     *
+     * @return     The index of the new added GeometryObject in visual_objects
+     */
+    GeomIndex addVisualObject(const JointIndex parent, const fcl::CollisionObject & co,
+                              const SE3 & placement, const std::string & geom_name = "",
+                              const std::string & mesh_path = "");
+
+    /**
+     * @brief      Return the index of a GeometryObject of type COLLISION given by its name.
+     *
+     * @param[in]  name  Name of the GeometryObject
+     *
+     * @return     Index of the corresponding GeometryObject
+     */
+    GeomIndex getCollisionId(const std::string & name) const;
+    
+    /**
+     * @brief      Return the index of a GeometryObject of type VISUAL given by its name.
+     *
+     * @param[in]  name  Name of the GeometryObject
+     *
+     * @return     Index of the corresponding GeometryObject
+     */
+    GeomIndex getVisualId(const std::string & name) const;
+    
+    /**
+     * @brief      Check if a GeometryObject of type COLLISION given by its name exists.
+     *
+     * @param[in]  name  Name of the GeometryObject
+     *
+     * @return     True if the GeometryObject exists in the collision_objects.
+     */
+    bool existCollisionName(const std::string & name) const;
+    
+    /**
+     * @brief      Check if a GeometryObject of type VISUAL given by its name exists.
+     *
+     * @param[in]  name  Name of the GeometryObject
+     *
+     * @return     True if the GeometryObject exists in the visual_objects.
+     */
+    bool existVisualName(const std::string & name) const;
+
+    /**
+     * @brief      Get the name of a GeometryObject of type COLLISION given by its index.
+     *
+     * @param[in]  index  Index of the GeometryObject
+     *
+     * @return     Name of the GeometryObject
+     */
+    const std::string & getCollisionName(const GeomIndex index) const;
+    
+    /**
+     * @brief      Get the name of a GeometryObject of type VISUAL given by its index.
+     *
+     * @param[in]  index  Index of the GeometryObject
+     *
+     * @return     Name of the GeometryObject
+     */
+    const std::string & getVisualName(const GeomIndex index) const;
+
+    /**
+     * @brief      Associate a GeometryObject of type COLLISION to a joint's inner objects list
+     *
+     * @param[in]  joint         Index of the joint
+     * @param[in]  inner_object  Index of the GeometryObject that will be an inner object
+     */
     void addInnerObject(const JointIndex joint, const GeomIndex inner_object);
+    
+    /**
+     * @brief      Associate a GeometryObject of type COLLISION to a joint's outer objects list
+     *
+     * @param[in]  joint         Index of the joint
+     * @param[in]  inner_object  Index of the GeometryObject that will be an outer object
+     */
     void addOutterObject(const JointIndex joint, const GeomIndex outer_object);
 
     friend std::ostream& operator<<(std::ostream & os, const GeometryModel & model_geom);
@@ -220,17 +401,21 @@ namespace se3
     const GeometryModel & model_geom;
 
     ///
-    /// \brief Vector gathering the SE3 placements of the geometries relative to the world.
+    /// \brief Vector gathering the SE3 placements of the collision objects relative to the world.
     ///        See updateGeometryPlacements to update the placements.
     ///
-    std::vector<se3::SE3> oMg;
-    
+    std::vector<se3::SE3> oMg_collisions;
+
+    ///
+    /// \brief Vector gathering the SE3 placements of the visual objects relative to the world.
+    ///        See updateGeometryPlacements to update the placements.
+    ///
+    std::vector<se3::SE3> oMg_visuals;
     ///
     /// \brief Same as oMg but using fcl::Transform3f to store placement.
     ///        This pre-allocation avoids dynamic allocation during collision checking or distance computations.
     ///
-    std::vector<fcl::Transform3f> oMg_fcl;
-
+    std::vector<fcl::Transform3f> oMg_fcl_collisions;
     ///
     /// \brief Vector of collision pairs.
     ///        See addCollisionPair, removeCollisionPair to fill or remove elements in the vector.
@@ -255,14 +440,15 @@ namespace se3
     GeometryData(const Data & data, const GeometryModel & model_geom)
         : data_ref(data)
         , model_geom(model_geom)
-        , oMg(model_geom.ngeom)
-        , oMg_fcl(model_geom.ngeom)
+        , oMg_collisions(model_geom.ncollisions)
+        , oMg_visuals(model_geom.nvisuals)
+        , oMg_fcl_collisions(model_geom.ncollisions)
         , collision_pairs()
         , nCollisionPairs(0)
         , distance_results()
         , collision_results()
     {
-      const std::size_t num_max_collision_pairs = (model_geom.ngeom * (model_geom.ngeom-1))/2;
+      const std::size_t num_max_collision_pairs = (model_geom.ncollisions * (model_geom.ncollisions-1))/2;
       collision_pairs.reserve(num_max_collision_pairs);
       distance_results.resize(num_max_collision_pairs, DistanceResult( fcl::DistanceResult(), 0, 0) );
       collision_results.resize(num_max_collision_pairs, CollisionResult( fcl::CollisionResult(), 0, 0));
diff --git a/src/multibody/geometry.hxx b/src/multibody/geometry.hxx
index b325d6c65e858c7b70b1d767c036f098a08708e2..5c4cd8c6ea41097d0d01a97e7898a7cbe8277ad0 100644
--- a/src/multibody/geometry.hxx
+++ b/src/multibody/geometry.hxx
@@ -42,48 +42,87 @@
 namespace se3
 {
 
-  inline GeometryModel::GeomIndex GeometryModel::addGeomObject(const JointIndex parent,
-                                                               const fcl::CollisionObject & co,
-                                                               const SE3 & placement,
-                                                               const std::string & geoName)
+  GeometryModel::GeomIndex GeometryModel::addCollisionObject(const JointIndex parent,
+                                                             const fcl::CollisionObject & co,
+                                                             const SE3 & placement,
+                                                             const std::string & geom_name,
+                                                             const std::string & mesh_path)
   {
+    Index idx = (Index) (ncollisions ++);
 
-    Index idx = (Index) (ngeom ++);
+    collision_objects.push_back(GeometryObject(COLLISION, geom_name, parent, co,
+                                               placement, mesh_path));
+    addInnerObject(parent, idx);
+    return idx;
+  }
 
+  GeometryModel::GeomIndex GeometryModel::addVisualObject(const JointIndex parent,
+                                                          const fcl::CollisionObject & co,
+                                                          const SE3 & placement,
+                                                          const std::string & geom_name,
+                                                          const std::string & mesh_path)
+  {
 
-    collision_objects    .push_back(co);
-    geom_parents         .push_back(parent);
-    geometryPlacement    .push_back(placement);
-    geom_names           .push_back( (geoName!="")?geoName:random(8));
-    
-    addInnerObject(parent, idx);
+    Index idx = (Index) (nvisuals ++);
 
+    visual_objects.push_back(GeometryObject(VISUAL, geom_name, parent, co,
+                                            placement, mesh_path));
+    
     return idx;
   }
 
-  inline GeometryModel::GeomIndex GeometryModel::getGeomId (const std::string & name) const
+  inline GeometryModel::GeomIndex GeometryModel::getCollisionId(const std::string & name) const
   {
-    std::vector<std::string>::iterator::difference_type
-      res = std::find(geom_names.begin(),geom_names.end(),name) - geom_names.begin();
-    assert( (res<INT_MAX) && "Id superior to int range. Should never happen.");
-    assert( (res>=0)&&(res<(long)collision_objects.size())&&"The joint name you asked does not exist" );
-    return GeomIndex(res);
+
+    std::vector<GeometryObject>::const_iterator it = std::find_if(collision_objects.begin(),
+                                                                  collision_objects.end(),
+                                                                  boost::bind(&GeometryObject::name, _1) == name
+                                                                  );
+    return GeometryModel::GeomIndex(it - collision_objects.begin());
+  }
+
+  inline GeometryModel::GeomIndex GeometryModel::getVisualId(const std::string & name) const
+  {
+
+    std::vector<GeometryObject>::const_iterator it = std::find_if(visual_objects.begin(),
+                                                                  visual_objects.end(),
+                                                                  boost::bind(&GeometryObject::name, _1) == name
+                                                                  );
+    return GeometryModel::GeomIndex(it - visual_objects.begin());
   }
 
-  inline bool GeometryModel::existGeomName (const std::string & name) const
+
+  inline bool GeometryModel::existCollisionName(const std::string & name) const
   {
-    return (geom_names.end() != std::find(geom_names.begin(),geom_names.end(),name));
+    return std::find_if(collision_objects.begin(),
+                        collision_objects.end(),
+                        boost::bind(&GeometryObject::name, _1) == name) != collision_objects.end();
   }
   
-  inline const std::string& GeometryModel::getGeomName (const GeomIndex index) const
+  inline bool GeometryModel::existVisualName(const std::string & name) const
+  {
+    return std::find_if(visual_objects.begin(),
+                        visual_objects.end(),
+                        boost::bind(&GeometryObject::name, _1) == name) != visual_objects.end();
+  }
+
+  inline const std::string& GeometryModel::getCollisionName(const GeomIndex index) const
   {
     assert( index < (GeomIndex)collision_objects.size() );
-    return geom_names[index];
+    return collision_objects[index].name;
+  }
+
+  inline const std::string& GeometryModel::getVisualName(const GeomIndex index) const
+  {
+    assert( index < (GeomIndex)visual_objects.size() );
+    return visual_objects[index].name;
   }
 
-  inline void GeometryModel::addInnerObject (const JointIndex joint_id, const GeomIndex inner_object)
+  inline void GeometryModel::addInnerObject(const JointIndex joint_id, const GeomIndex inner_object)
   {
-    if (std::find(innerObjects[joint_id].begin(), innerObjects[joint_id].end(),inner_object)==innerObjects[joint_id].end())
+    if (std::find(innerObjects[joint_id].begin(),
+                  innerObjects[joint_id].end(),
+                  inner_object) == innerObjects[joint_id].end())
       innerObjects[joint_id].push_back(inner_object);
     else
       std::cout << "inner object already added" << std::endl;
@@ -91,7 +130,9 @@ namespace se3
 
   inline void GeometryModel::addOutterObject (const JointIndex joint, const GeomIndex outer_object)
   {
-    if (std::find(outerObjects[joint].begin(), outerObjects[joint].end(),outer_object)==outerObjects[joint].end())
+    if (std::find(outerObjects[joint].begin(),
+                  outerObjects[joint].end(),
+                  outer_object) == outerObjects[joint].end())
       outerObjects[joint].push_back(outer_object);
     else
       std::cout << "outer object already added" << std::endl;
@@ -99,12 +140,18 @@ namespace se3
 
   inline std::ostream & operator<< (std::ostream & os, const GeometryModel & model_geom)
   {
-    os << "Nb collision objects = " << model_geom.ngeom << std::endl;
+    os << "Nb collision objects = " << model_geom.ncollisions << std::endl;
     
-    for(GeometryModel::Index i=0;i<(GeometryModel::Index)(model_geom.ngeom);++i)
+    for(GeometryModel::Index i=0;i<(GeometryModel::Index)(model_geom.ncollisions);++i)
     {
-      os  << "Collision object " << i << " : " << model_geom.geom_names[i] << ": attached to joint = " << model_geom.geom_parents[i]
-          << "\nwith offset \n" << model_geom.geometryPlacement[i] <<std::endl;
+      os  << model_geom.collision_objects[i] <<std::endl;
+    }
+
+    os << "Nb visual objects = " << model_geom.nvisuals << std::endl;
+    
+    for(GeometryModel::Index i=0;i<(GeometryModel::Index)(model_geom.nvisuals);++i)
+    {
+      os  << model_geom.visual_objects[i] <<std::endl;
     }
 
     return os;
@@ -112,10 +159,11 @@ namespace se3
 
   inline std::ostream & operator<< (std::ostream & os, const GeometryData & data_geom)
   {
-
-    for(GeometryData::Index i=0;i<(GeometryData::Index)(data_geom.model_geom.ngeom);++i)
+    os << "Nb collision pairs = " << data_geom.nCollisionPairs << std::endl;
+    
+    for(GeometryData::Index i=0;i<(GeometryData::Index)(data_geom.nCollisionPairs);++i)
     {
-      os << "collision object in position " << data_geom.oMg[i] << std::endl;
+      os << "collision object in position " << data_geom.collision_pairs[i] << std::endl;
     }
 
     return os;
@@ -124,7 +172,7 @@ namespace se3
   inline void GeometryData::addCollisionPair (const GeomIndex co1, const GeomIndex co2)
   {
     assert ( co1 != co2);
-    assert ( co2 < model_geom.ngeom);
+    assert ( co2 < model_geom.ncollisions);
     CollisionPair_t pair(co1, co2);
     
     addCollisionPair(pair);
@@ -132,7 +180,7 @@ namespace se3
 
   inline void GeometryData::addCollisionPair (const CollisionPair_t & pair)
   {
-    assert(pair.second < model_geom.ngeom);
+    assert(pair.second < model_geom.ncollisions);
     
     if (!existCollisionPair(pair))
     {
@@ -144,16 +192,16 @@ namespace se3
   inline void GeometryData::addAllCollisionPairs()
   {
     removeAllCollisionPairs();
-    collision_pairs.reserve((model_geom.ngeom * (model_geom.ngeom-1))/2);
-    for (Index i = 0; i < model_geom.ngeom; ++i)
-      for (Index j = i+1; j < model_geom.ngeom; ++j)
+    collision_pairs.reserve((model_geom.ncollisions * (model_geom.ncollisions-1))/2);
+    for (Index i = 0; i < model_geom.ncollisions; ++i)
+      for (Index j = i+1; j < model_geom.ncollisions; ++j)
         addCollisionPair(i,j);
   }
   
   inline void GeometryData::removeCollisionPair (const GeomIndex co1, const GeomIndex co2)
   {
     assert(co1 < co2);
-    assert(co2 < model_geom.ngeom);
+    assert(co2 < model_geom.ncollisions);
     assert(existCollisionPair(co1,co2));
 
     removeCollisionPair (CollisionPair_t(co1,co2));
@@ -161,9 +209,11 @@ namespace se3
 
   inline void GeometryData::removeCollisionPair (const CollisionPair_t & pair)
   {
-    assert(pair.second < model_geom.ngeom);
+    assert(pair.second < model_geom.ncollisions);
 
-    CollisionPairsVector_t::iterator it = std::find(collision_pairs.begin(), collision_pairs.end(), pair);
+    CollisionPairsVector_t::iterator it = std::find(collision_pairs.begin(),
+                                                    collision_pairs.end(),
+                                                    pair);
     if (it != collision_pairs.end())
     {
       collision_pairs.erase(it);
@@ -184,8 +234,9 @@ namespace se3
 
   inline bool GeometryData::existCollisionPair (const CollisionPair_t & pair) const
   {
-    return (std::find(collision_pairs.begin(), collision_pairs.end(), pair)
-            != collision_pairs.end());
+    return (std::find(collision_pairs.begin(),
+                      collision_pairs.end(),
+                      pair) != collision_pairs.end());
   }
   
   inline GeometryData::Index GeometryData::findCollisionPair (const GeomIndex co1, const GeomIndex co2) const
@@ -195,7 +246,9 @@ namespace se3
   
   inline GeometryData::Index GeometryData::findCollisionPair (const CollisionPair_t & pair) const
   {
-    CollisionPairsVector_t::const_iterator it = std::find(collision_pairs.begin(), collision_pairs.end(), pair);
+    CollisionPairsVector_t::const_iterator it = std::find(collision_pairs.begin(),
+                                                          collision_pairs.end(),
+                                                          pair);
     
     return (Index) distance(collision_pairs.begin(), it);
   }
@@ -237,8 +290,8 @@ namespace se3
     fcl::CollisionRequest collisionRequest (1, false, false, 1, false, true, fcl::GST_INDEP);
     fcl::CollisionResult collisionResult;
 
-    fcl::collide (model_geom.collision_objects[co1].collisionGeometry().get(), oMg_fcl[co1],
-                  model_geom.collision_objects[co2].collisionGeometry().get(), oMg_fcl[co2],
+    fcl::collide (model_geom.collision_objects[co1].collision_object.collisionGeometry().get(), oMg_fcl_collisions[co1],
+                  model_geom.collision_objects[co2].collision_object.collisionGeometry().get(), oMg_fcl_collisions[co2],
                   collisionRequest, collisionResult);
 
     return CollisionResult (collisionResult, co1, co2);
@@ -275,8 +328,8 @@ namespace se3
     
     fcl::DistanceRequest distanceRequest (true, 0, 0, fcl::GST_INDEP);
     fcl::DistanceResult result;
-    fcl::distance ( model_geom.collision_objects[co1].collisionGeometry().get(), oMg_fcl[co1],
-                    model_geom.collision_objects[co2].collisionGeometry().get(), oMg_fcl[co2],
+    fcl::distance ( model_geom.collision_objects[co1].collision_object.collisionGeometry().get(), oMg_fcl_collisions[co1],
+                    model_geom.collision_objects[co2].collision_object.collisionGeometry().get(), oMg_fcl_collisions[co2],
                     distanceRequest, result);
     
     return DistanceResult (result, co1, co2);
diff --git a/src/multibody/parser/urdf-with-geometry.hpp b/src/multibody/parser/urdf-with-geometry.hpp
index 78449501104535bba7191db94728b4dd8fbfddc8..d0aecf24853972277feb0c36b089d7f23bb0856e 100644
--- a/src/multibody/parser/urdf-with-geometry.hpp
+++ b/src/multibody/parser/urdf-with-geometry.hpp
@@ -35,15 +35,18 @@ namespace se3
 
 
     /**
-     * @brief      Get a CollisionObject from an urdf link, searching
+     * @brief      Get a fcl::CollisionObject from an urdf geometry, searching
      *             for it in specified package directories
      *
-     * @param[in]  link          The input urdf link
-     * @param[in]  package_dirs  A vector containing the different directories where to search for packages
+     * @param[in]  urdf_geometry  The input urdf geometry
+     * @param[in]  package_dirs   A vector containing the different directories where to search for packages
+     * @param[out] mesh_path      The Absolute path of the mesh currently read
      *
-     * @return     The mesh converted as a fcl::CollisionObject
+     * @return     The geometry converted as a fcl::CollisionObject
      */
-    inline fcl::CollisionObject retrieveCollisionGeometry (const ::urdf::LinkConstPtr & link, const std::vector < std::string > & package_dirs);
+    inline fcl::CollisionObject retrieveCollisionGeometry(const boost::shared_ptr < ::urdf::Geometry > urdf_geometry,
+                                                          const std::vector < std::string > & package_dirs,
+                                                          std::string & mesh_path);
 
     
     /**
diff --git a/src/multibody/parser/urdf-with-geometry.hxx b/src/multibody/parser/urdf-with-geometry.hxx
index ca12a540dfc4cf0a6f9cbbae78098110429095ac..900b94e8db688d6c55dac12e1cafd84c089b1bbb 100644
--- a/src/multibody/parser/urdf-with-geometry.hxx
+++ b/src/multibody/parser/urdf-with-geometry.hxx
@@ -31,33 +31,35 @@ namespace se3
   namespace urdf
   {
     
-    inline fcl::CollisionObject retrieveCollisionGeometry (const ::urdf::LinkConstPtr & link, const std::vector < std::string > & package_dirs)
+    inline fcl::CollisionObject retrieveCollisionGeometry(const boost::shared_ptr < ::urdf::Geometry> urdf_geometry,
+                                                          const std::vector < std::string > & package_dirs,
+                                                          std::string & mesh_path)
     {
-      boost::shared_ptr < ::urdf::Collision> collision = link->collision;
       boost::shared_ptr < fcl::CollisionGeometry > geometry;
 
       // Handle the case where collision geometry is a mesh
-      if (collision->geometry->type == ::urdf::Geometry::MESH)
+      if (urdf_geometry->type == ::urdf::Geometry::MESH)
       {
-        boost::shared_ptr < ::urdf::Mesh> collisionGeometry = boost::dynamic_pointer_cast< ::urdf::Mesh> (collision->geometry);
+        boost::shared_ptr < ::urdf::Mesh> collisionGeometry = boost::dynamic_pointer_cast< ::urdf::Mesh> (urdf_geometry);
         std::string collisionFilename = collisionGeometry->filename;
 
-        std::string full_path = convertURDFMeshPathToAbsolutePath(collisionFilename, package_dirs);
+        mesh_path = convertURDFMeshPathToAbsolutePath(collisionFilename, package_dirs);
 
         ::urdf::Vector3 scale = collisionGeometry->scale;
 
         // Create FCL mesh by parsing Collada file.
         Polyhedron_ptr polyhedron (new PolyhedronType);
 
-        loadPolyhedronFromResource (full_path, scale, polyhedron);
+        loadPolyhedronFromResource (mesh_path, scale, polyhedron);
         geometry = polyhedron;
       }
 
       // Handle the case where collision geometry is a cylinder
       // Use FCL capsules for cylinders
-      else if (collision->geometry->type == ::urdf::Geometry::CYLINDER)
+      else if (urdf_geometry->type == ::urdf::Geometry::CYLINDER)
       {
-        boost::shared_ptr < ::urdf::Cylinder> collisionGeometry = boost::dynamic_pointer_cast< ::urdf::Cylinder> (collision->geometry);
+        mesh_path = "CYLINDER";
+        boost::shared_ptr < ::urdf::Cylinder> collisionGeometry = boost::dynamic_pointer_cast< ::urdf::Cylinder> (urdf_geometry);
   
         double radius = collisionGeometry->radius;
         double length = collisionGeometry->length;
@@ -66,9 +68,10 @@ namespace se3
         geometry = boost::shared_ptr < fcl::CollisionGeometry >(new fcl::Capsule (radius, length));
       }
       // Handle the case where collision geometry is a box.
-      else if (collision->geometry->type == ::urdf::Geometry::BOX) 
+      else if (urdf_geometry->type == ::urdf::Geometry::BOX) 
       {
-        boost::shared_ptr < ::urdf::Box> collisionGeometry = boost::dynamic_pointer_cast< ::urdf::Box> (collision->geometry);
+        mesh_path = "BOX";
+        boost::shared_ptr < ::urdf::Box> collisionGeometry = boost::dynamic_pointer_cast< ::urdf::Box> (urdf_geometry);
   
         double x = collisionGeometry->dim.x;
         double y = collisionGeometry->dim.y;
@@ -77,9 +80,10 @@ namespace se3
         geometry = boost::shared_ptr < fcl::CollisionGeometry > (new fcl::Box (x, y, z));
       }
       // Handle the case where collision geometry is a sphere.
-      else if (collision->geometry->type == ::urdf::Geometry::SPHERE)
+      else if (urdf_geometry->type == ::urdf::Geometry::SPHERE)
       {
-        boost::shared_ptr < ::urdf::Sphere> collisionGeometry = boost::dynamic_pointer_cast< ::urdf::Sphere> (collision->geometry);
+        mesh_path = "SPHERE";
+        boost::shared_ptr < ::urdf::Sphere> collisionGeometry = boost::dynamic_pointer_cast< ::urdf::Sphere> (urdf_geometry);
 
         double radius = collisionGeometry->radius;
 
@@ -103,25 +107,48 @@ namespace se3
                                  const std::vector<std::string> & package_dirs) throw (std::invalid_argument)
     {
 
+      std::string mesh_path = "";
+      
+      std::string link_name = link->name;
       // start with first link that is not empty
       if(link->collision)
       {
-
-
         assert(link->getParent()!=NULL);
+        if (link->getParent() == NULL)
+        {
+          const std::string exception_message (link->name + " - joint information missing.");
+          throw std::invalid_argument(exception_message);
+        }
+        
+        for (std::vector< boost::shared_ptr< ::urdf::Collision> >::const_iterator i = link->collision_array.begin();i != link->collision_array.end(); ++i)
+        {
+          fcl::CollisionObject collision_object = retrieveCollisionGeometry((*i)->geometry, package_dirs, mesh_path);
+          SE3 geomPlacement = convertFromUrdf((*i)->origin);
+          std::string collision_object_name = (*i)->name ;
+          geom_model.addCollisionObject(model.parents[model.getBodyId(link_name)], collision_object, geomPlacement, collision_object_name, mesh_path); 
+          
+        }
+      } // if(link->collision)
 
-        fcl::CollisionObject collision_object = retrieveCollisionGeometry(link, package_dirs);
-        SE3 geomPlacement = convertFromUrdf(link->collision->origin);
-        std::string collision_object_name = link->name ;
-        geom_model.addGeomObject(model.parents[model.getBodyId(collision_object_name)], collision_object, geomPlacement, collision_object_name);     
-
+      if(link->visual)
+      {
+        assert(link->getParent()!=NULL);
         if (link->getParent() == NULL)
         {
           const std::string exception_message (link->name + " - joint information missing.");
           throw std::invalid_argument(exception_message);
         }
+        
+        for (std::vector< boost::shared_ptr< ::urdf::Visual> >::const_iterator i = link->visual_array.begin(); i != link->visual_array.end(); ++i)
+        {
+          fcl::CollisionObject visual_object = retrieveCollisionGeometry((*i)->geometry, package_dirs, mesh_path);
+          SE3 geomPlacement = convertFromUrdf((*i)->origin);
+          std::string visual_object_name = (*i)->name ;
+          geom_model.addVisualObject(model.parents[model.getBodyId(link_name)], visual_object, geomPlacement, visual_object_name, mesh_path); 
+          
+        }
+      } // if(link->visual)
 
-      } // if(link->collision)
       
       BOOST_FOREACH(::urdf::LinkConstPtr child,link->child_links)
       {
diff --git a/src/python/geometry-data.hpp b/src/python/geometry-data.hpp
index 1e1478711e2ff1dc92bf698657c1c35ca5d03b0f..876e87487af1d70171795928b65c30a850d888f1 100644
--- a/src/python/geometry-data.hpp
+++ b/src/python/geometry-data.hpp
@@ -94,10 +94,14 @@ namespace se3
         
         .add_property("nCollisionPairs", &GeometryDataPythonVisitor::nCollisionPairs)
         
-        .add_property("oMg",
-                      bp::make_function(&GeometryDataPythonVisitor::oMg,
+        .add_property("oMg_collisions",
+                      bp::make_function(&GeometryDataPythonVisitor::oMg_collisions,
                                         bp::return_internal_reference<>()),
                       "Vector of collision objects placement relative to the world.")
+        .add_property("oMg_visuals",
+                      bp::make_function(&GeometryDataPythonVisitor::oMg_visuals,
+                                        bp::return_internal_reference<>()),
+                      "Vector of visual objects placement relative to the world.")
         .add_property("collision_pairs",
                       bp::make_function(&GeometryDataPythonVisitor::collision_pairs,
                                         bp::return_internal_reference<>()),
@@ -165,7 +169,8 @@ namespace se3
 
       static Index nCollisionPairs(const GeometryDataHandler & m ) { return m->nCollisionPairs; }
       
-      static std::vector<SE3> & oMg(GeometryDataHandler & m) { return m->oMg; }
+      static std::vector<SE3> & oMg_collisions(GeometryDataHandler & m) { return m->oMg_collisions; }
+      static std::vector<SE3> & oMg_visuals(GeometryDataHandler & m) { return m->oMg_visuals; }
       static std::vector<CollisionPair_t> & collision_pairs( GeometryDataHandler & m ) { return m->collision_pairs; }
       static std::vector<DistanceResult> & distance_results( GeometryDataHandler & m ) { return m->distance_results; }
       static std::vector<CollisionResult> & collision_results( GeometryDataHandler & m ) { return m->collision_results; }
diff --git a/src/python/geometry-model.hpp b/src/python/geometry-model.hpp
index 47a16206046004c478523c319ff9e5c82825ff53..fb4c7d44bf2a62fbd7cf3b278589e3f9bf6c64ca 100644
--- a/src/python/geometry-model.hpp
+++ b/src/python/geometry-model.hpp
@@ -63,20 +63,23 @@ namespace se3
       void visit(PyClass& cl) const 
       {
 	cl
-    .add_property("ngeom", &GeometryModelPythonVisitor::ngeom)
-
-    .def("getGeomId",&GeometryModelPythonVisitor::getGeomId)
-
-    .add_property("geometryPlacement",
-      bp::make_function(&GeometryModelPythonVisitor::geometryPlacement,
+    .add_property("ncollisions", &GeometryModelPythonVisitor::ncollisions)
+    .add_property("nvisuals", &GeometryModelPythonVisitor::nvisuals)
+
+    .def("getCollisionId",&GeometryModelPythonVisitor::getCollisionId)
+    .def("getVisualId",&GeometryModelPythonVisitor::getVisualId)
+    .def("existCollisionName",&GeometryModelPythonVisitor::existCollisionName)
+    .def("existVisualName",&GeometryModelPythonVisitor::existVisualName)
+    .def("getCollisionName",&GeometryModelPythonVisitor::getCollisionName)
+    .def("getVisualName",&GeometryModelPythonVisitor::getVisualName)
+    .add_property("collision_objects",
+      bp::make_function(&GeometryModelPythonVisitor::collision_objects,
             bp::return_internal_reference<>())  )
-    .add_property("geom_parents", 
-      bp::make_function(&GeometryModelPythonVisitor::geom_parents,
-            bp::return_internal_reference<>())  )
-    .add_property("geom_names",
-      bp::make_function(&GeometryModelPythonVisitor::geom_names,
+    .add_property("visual_objects",
+      bp::make_function(&GeometryModelPythonVisitor::visual_objects,
             bp::return_internal_reference<>())  )
 
+
     .def("__str__",&GeometryModelPythonVisitor::toString)
 
 	  .def("BuildGeometryModel",&GeometryModelPythonVisitor::maker_default)
@@ -84,14 +87,26 @@ namespace se3
 	  ;
       }
 
-      static GeometryModel::Index ngeom( GeometryModelHandler & m ) { return m->ngeom; }
+      static GeometryModel::Index ncollisions( GeometryModelHandler & m ) { return m->ncollisions; }
+      static GeometryModel::Index nvisuals( GeometryModelHandler & m ) { return m->nvisuals; }
 
-      static Model::GeomIndex getGeomId( const GeometryModelHandler & gmodelPtr, const std::string & name )
-      { return  gmodelPtr->getGeomId(name); }
+      static std::vector<GeometryObject> & collision_objects( GeometryModelHandler & m ) { return m->collision_objects; }
+      static std::vector<GeometryObject> & visual_objects( GeometryModelHandler & m ) { return m->visual_objects; }
       
-      static std::vector<SE3> & geometryPlacement( GeometryModelHandler & m ) { return m->geometryPlacement; }
-      static std::vector<Model::JointIndex> & geom_parents( GeometryModelHandler & m ) { return m->geom_parents; }
-      static std::vector<std::string> & geom_names ( GeometryModelHandler & m ) { return m->geom_names; }
+      static Model::GeomIndex getCollisionId( const GeometryModelHandler & gmodelPtr, const std::string & name )
+      { return  gmodelPtr->getCollisionId(name); }
+      static Model::GeomIndex getVisualId( const GeometryModelHandler & gmodelPtr, const std::string & name )
+      { return  gmodelPtr->getVisualId(name); }
+      static bool existCollisionName(const GeometryModelHandler & gmodelPtr, const std::string & name)
+      { return gmodelPtr->existCollisionName(name);}
+      static bool existVisualName(const GeometryModelHandler & gmodelPtr, const std::string & name)
+      { return gmodelPtr->existVisualName(name);}
+      static std::string getCollisionName(const GeometryModelHandler & gmodelPtr, const GeomIndex index)
+      { return gmodelPtr->getCollisionName(index);}
+      static std::string getVisualName(const GeometryModelHandler & gmodelPtr, const GeomIndex index)
+      { return gmodelPtr->getVisualName(index);}
+      // static std::vector<Model::JointIndex> & geom_parents( GeometryModelHandler & m ) { return m->geom_parents; }
+      // static std::vector<std::string> & geom_names ( GeometryModelHandler & m ) { return m->geom_names; }
 
       
 
diff --git a/src/python/geometry-object.hpp b/src/python/geometry-object.hpp
new file mode 100644
index 0000000000000000000000000000000000000000..1cf84df10d8c9b49049e799e45a613178c841870
--- /dev/null
+++ b/src/python/geometry-object.hpp
@@ -0,0 +1,95 @@
+//
+// Copyright (c) 2016 CNRS
+//
+// This file is part of Pinocchio
+// Pinocchio is free software: you can redistribute it
+// and/or modify it under the terms of the GNU Lesser General Public
+// License as published by the Free Software Foundation, either version
+// 3 of the License, or (at your option) any later version.
+//
+// Pinocchio is distributed in the hope that it will be
+// useful, but WITHOUT ANY WARRANTY; without even the implied warranty
+// of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// General Lesser Public License for more details. You should have
+// received a copy of the GNU Lesser General Public License along with
+// Pinocchio If not, see
+// <http://www.gnu.org/licenses/>.
+
+#ifndef __se3_python_geometry_object_hpp__
+#define __se3_python_geometry_object_hpp__
+
+#include <eigenpy/exception.hpp>
+#include <eigenpy/eigenpy.hpp>
+
+#include <boost/python/suite/indexing/vector_indexing_suite.hpp>
+
+#include "pinocchio/multibody/model.hpp"
+#include "pinocchio/multibody/geometry.hpp"
+
+
+namespace se3
+{
+  namespace python
+  {
+    namespace bp = boost::python;
+
+    struct GeometryObjectPythonVisitor
+      : public boost::python::def_visitor< GeometryObjectPythonVisitor >
+    {
+      typedef eigenpy::UnalignedEquivalent<SE3>::type SE3_fx;
+      typedef Model::Index Index;
+      typedef Model::JointIndex JointIndex;
+      typedef Model::FrameIndex FrameIndex;
+
+    public:
+
+      static PyObject* convert(Frame const& f)
+      {
+        return boost::python::incref(boost::python::object(f).ptr());
+      }
+
+      template<class PyClass>
+      void visit(PyClass& cl) const 
+      {
+        cl
+          .add_property("name", &GeometryObjectPythonVisitor::getName, &GeometryObjectPythonVisitor::setName)
+          .add_property("parent_id", &GeometryObjectPythonVisitor::getParentId, &GeometryObjectPythonVisitor::setParentId)
+          .add_property("placement", &GeometryObjectPythonVisitor::getPlacementWrtParentJoint, &GeometryObjectPythonVisitor::setMeshPath)
+          .add_property("mesh_path", &GeometryObjectPythonVisitor::getMeshPath, &GeometryObjectPythonVisitor::setMeshPath)
+          ;
+      }
+
+
+      static std::string getName( const GeometryObject & self) { return self.name; }
+      static void setName(GeometryObject & self, const std::string & name) { self.name = name; }
+      static JointIndex getParentId( const GeometryObject & self) { return self.parent; }
+      static void setParentId(GeometryObject & self, const JointIndex parent) { self.parent = parent; }
+      static SE3_fx getPlacementWrtParentJoint( const GeometryObject & self) { return self.placement; }
+      static void setPlacementWrtParentJoint(GeometryObject & self, const SE3_fx & placement) { self.placement = placement; }
+      static std::string getMeshPath( const GeometryObject & self) { return self.mesh_path; }
+      static void setMeshPath(GeometryObject & self, const std::string & mesh_path) { self.mesh_path = mesh_path; }
+
+      static void expose()
+      {
+        bp::class_<GeometryObject>("GeometryObject",
+                           "A wrapper on a collision geometry including its parent joint, placement in parent frame.\n\n",
+	                         bp::no_init
+                         )
+	                       .def(GeometryObjectPythonVisitor())
+	                       ;
+    
+        // bp::to_python_converter< GeometryObject,GeometryObjectPythonVisitor >();
+
+        bp::class_< std::vector<GeometryObject> >("StdVec_GeometryObject")
+        .def(bp::vector_indexing_suite< std::vector<GeometryObject> >());
+      }
+
+
+    };
+    
+
+  } // namespace python
+} // namespace se3
+
+#endif // ifndef __se3_python_geometry_object_hpp__
+
diff --git a/src/python/python.cpp b/src/python/python.cpp
index ee1bee3ed76ec3705e6d71d9c1c0b00e602d40b7..efff5180b11cc8c6d64733a555fd1e77e6caac02 100644
--- a/src/python/python.cpp
+++ b/src/python/python.cpp
@@ -32,6 +32,7 @@
 #include "pinocchio/python/explog.hpp"
 
 #ifdef WITH_HPP_FCL
+#include "pinocchio/python/geometry-object.hpp"
 #include "pinocchio/python/geometry-model.hpp"
 #include "pinocchio/python/geometry-data.hpp"
 #endif
@@ -69,7 +70,8 @@ namespace se3
       FramePythonVisitor::expose();
       ModelPythonVisitor::expose();
       DataPythonVisitor::expose();
-#ifdef WITH_HPP_FCL      
+#ifdef WITH_HPP_FCL
+      GeometryObjectPythonVisitor::expose();      
       CollisionPairPythonVisitor::expose();
       GeometryModelPythonVisitor::expose();
       GeometryDataPythonVisitor::expose();
diff --git a/unittest/geom.cpp b/unittest/geom.cpp
index 133f53ee4faeee4aa0d36102772e4fd99b8a6b76..7ad9de83f34904ef56b93d0ff1c80eea1830e23a 100644
--- a/unittest/geom.cpp
+++ b/unittest/geom.cpp
@@ -129,12 +129,12 @@ struct Distance_t
 #endif
 std::ostream& operator<<(std::ostream& os, const std::pair < se3::Model, se3::GeometryModel >& robot)
 {
-  os << "Nb collision objects = " << robot.second.ngeom << std::endl;
+  os << "Nb collision objects = " << robot.second.ncollisions << std::endl;
   
-  for(se3::GeometryModel::Index i=0;i<(se3::GeometryModel::Index)(robot.second.ngeom);++i)
+  for(se3::GeometryModel::Index i=0;i<(se3::GeometryModel::Index)(robot.second.ncollisions);++i)
   {
-    os  << "Object n " << i << " : " << robot.second.geom_names[i] << ": attached to joint = " << robot.second.geom_parents[i]
-        << "=" << robot.first.getJointName(robot.second.geom_parents[i]) << std::endl;
+    os  << "Object n " << i << " : " << robot.second.collision_objects[i].name << ": attached to joint = " << robot.second.collision_objects[i].parent
+        << "=" << robot.first.getJointName(robot.second.collision_objects[i].parent) << std::endl;
   }
   return os;
 } 
@@ -156,11 +156,11 @@ BOOST_AUTO_TEST_CASE ( simple_boxes )
   
   boost::shared_ptr<fcl::Box> Sample(new fcl::Box(1));
   fcl::CollisionObject box1(Sample, fcl::Transform3f());
-  model_geom.addGeomObject(model.getJointId("planar1_joint"),box1, SE3::Identity(),  "ff1_collision_object");
+  model_geom.addCollisionObject(model.getJointId("planar1_joint"),box1, SE3::Identity(),  "ff1_collision_object", "");
   
   boost::shared_ptr<fcl::Box> Sample2(new fcl::Box(1));
   fcl::CollisionObject box2(Sample, fcl::Transform3f());
-  model_geom.addGeomObject(model.getJointId("planar2_joint"),box2, SE3::Identity(),  "ff2_collision_object");
+  model_geom.addCollisionObject(model.getJointId("planar2_joint"),box2, SE3::Identity(),  "ff2_collision_object", "");
 
   se3::Data data(model);
   se3::GeometryData data_geom(data, model_geom);
@@ -448,9 +448,9 @@ JointPositionsMap_t fillPinocchioJointPositions(const se3::Data & data)
 GeometryPositionsMap_t fillPinocchioGeometryPositions(const se3::GeometryData & data_geom)
 {
   GeometryPositionsMap_t result;
-  for (std::size_t i = 0; i < data_geom.model_geom.ngeom ; ++i)
+  for (std::size_t i = 0; i < data_geom.model_geom.ncollisions ; ++i)
   {
-    result[data_geom.model_geom.getGeomName(i)] = data_geom.oMg[i];
+    result[data_geom.model_geom.getCollisionName(i)] = data_geom.oMg_collisions[i];
   }
   return result;
 }