diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml
new file mode 100644
index 0000000000000000000000000000000000000000..f50e95d01d590d8ac7a7680328c64cee74e0a198
--- /dev/null
+++ b/.gitlab-ci.yml
@@ -0,0 +1,54 @@
+variables:
+  GIT_SUBMODULE_STRATEGY: "recursive"
+  GIT_DEPTH: "3"
+  CCACHE_BASEDIR: "${CI_PROJECT_DIR}"
+  CCACHE_DIR: "${CI_PROJECT_DIR}/ccache"
+
+cache:
+  paths:
+    - ccache
+
+.robotpkg-dynamic-graph-bridge-v3: &robotpkg-dynamic-graph-bridge-v3
+  except:
+    - gh-pages
+  script:
+    - mkdir -p ccache
+    - cd /root/robotpkg/wip/dynamic-graph-bridge-v3
+    - git pull
+    - make checkout MASTER_REPOSITORY="dir ${CI_PROJECT_DIR}"
+    - make install
+    - cd work.$(hostname)/$(make show-var VARNAME=DISTNAME)
+    - make test
+
+robotpkg-dynamic-graph-bridge-v3-14.04-release:
+  <<: *robotpkg-dynamic-graph-bridge-v3
+  image: eur0c.laas.fr:5000/stack-of-tasks/dynamic_graph_bridge/dynamic-graph-bridge-v3:14.04
+
+robotpkg-dynamic-graph-bridge-v3-16.04-release:
+  <<: *robotpkg-dynamic-graph-bridge-v3
+  image: eur0c.laas.fr:5000/stack-of-tasks/dynamic_graph_bridge/dynamic-graph-bridge-v3:16.04
+
+robotpkg-dynamic-graph-bridge-v3-18.04-release:
+  <<: *robotpkg-dynamic-graph-bridge-v3
+  image: eur0c.laas.fr:5000/stack-of-tasks/dynamic_graph_bridge/dynamic-graph-bridge-v3:18.04
+  allow_failure: true
+
+doc-coverage:
+  <<: *robotpkg-dynamic-graph-bridge-v3
+  image: eur0c.laas.fr:5000/stack-of-tasks/dynamic_graph_bridge/dynamic-graph-bridge-v3:16.04
+  before_script:
+    - echo -e 'CXXFLAGS+= --coverage\nLDFLAGS+= --coverage\nPKG_DEFAULT_OPTIONS= debug' >> /opt/openrobots/etc/robotpkg.conf
+  after_script:
+    - cd /root/robotpkg/wip/dynamic-graph-bridge-v3
+    - cd work.$(hostname)/$(make show-var VARNAME=DISTNAME)
+    - make doc
+    - mv doc/doxygen-html ${CI_PROJECT_DIR}
+    - mkdir -p ${CI_PROJECT_DIR}/coverage/
+    - gcovr -r .
+    - gcovr -r . --html --html-details -o ${CI_PROJECT_DIR}/coverage/index.html
+  artifacts:
+    expire_in: 1 day
+    paths:
+      - doxygen-html/
+      - coverage/
+
diff --git a/CMakeLists.txt b/CMakeLists.txt
index f58a6609e5bab8fd8e3c7534a8c9768f3aaf25de..f8cbc3d9552312f143bc4bd1c9bff2e8901afca0 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -26,17 +26,31 @@ INCLUDE(cmake/eigen.cmake)
 include(cmake/ros.cmake)
 include(cmake/GNUInstallDirs.cmake)
 include(cmake/python.cmake)
+include(cmake/test.cmake)
 
 project(dynamic_graph_bridge)
 
-find_package(catkin REQUIRED COMPONENTS roscpp rospy std_msgs message_generation std_srvs geometry_msgs sensor_msgs tf)
-find_package(realtime_tools)
+SET(CATKIN_REQUIRED_COMPONENTS roscpp std_msgs message_generation std_srvs geometry_msgs sensor_msgs tf)
+SET(CATKIN_DEPENDS_LIBRARIES ros_bridge sot_loader)
 
 ## LAAS cmake submodule part
 set(PROJECT_DESCRIPTION "Dynamic graph bridge library")
 set(PROJECT_NAME dynamic_graph_bridge)
 set(PROJECT_URL "")
 
+OPTION (BUILD_PYTHON_INTERFACE "Build the python binding" ON)
+IF(BUILD_PYTHON_INTERFACE)
+  FINDPYTHON()
+  STRING(REGEX REPLACE "-" "_" PY_NAME ${PROJECT_NAME})
+  INCLUDE_DIRECTORIES(${PYTHON_INCLUDE_DIRS})
+  ADD_REQUIRED_DEPENDENCY("dynamic-graph-python >= 3.0.0")
+  SET(CATKIN_REQUIRED_COMPONENTS ${CATKIN_REQUIRED_COMPONENTS} rospy)
+  SET(CATKIN_DEPENDS_LIBRARIES ${CATKIN_DEPENDS_LIBRARIES} ros_interpreter)
+ENDIF(BUILD_PYTHON_INTERFACE)
+
+find_package(catkin REQUIRED COMPONENTS ${CATKIN_REQUIRED_COMPONENTS})
+find_package(realtime_tools)
+
 set(CXX_DISABLE_WERROR False)
 set(CUSTOM_HEADER_DIR dynamic_graph_bridge)
 set(${PROJECT_NAME}_HEADERS
@@ -70,7 +84,6 @@ add_required_dependency("realtime_tools >= 1.8")
 add_required_dependency(tf2_bullet)
 ADD_REQUIRED_DEPENDENCY("pinocchio")
 ADD_REQUIRED_DEPENDENCY("dynamic-graph >= 3.0.0")
-ADD_REQUIRED_DEPENDENCY("dynamic-graph-python >= 3.0.0")
 ADD_REQUIRED_DEPENDENCY("sot-dynamic-pinocchio >= 3.0.0")
 ADD_REQUIRED_DEPENDENCY("sot-core >= 3.0.0")
 ADD_REQUIRED_DEPENDENCY("sot-tools >= 2.0.0")
@@ -107,28 +120,26 @@ macro(compile_plugin NAME)
   add_library(${NAME} SHARED src/${NAME}.cpp src/${NAME}.hh)
   pkg_config_use_dependency(${NAME} dynamic-graph)
   pkg_config_use_dependency(${NAME} sot-core)
-  #pkg_config_use_dependency(${NAME} jrl-dynamics-urdf)
   pkg_config_use_dependency(${NAME} dynamic_graph_bridge_msgs)
   add_dependencies(${NAME} ros_bridge)
   target_link_libraries(${NAME} ros_bridge)
   set_target_properties(${NAME} PROPERTIES BUILD_WITH_INSTALL_RPATH True)
   set_target_properties(${NAME} PROPERTIES PREFIX "")
   install(TARGETS ${NAME} DESTINATION lib/plugin)
-  
-
-  dynamic_graph_python_module("ros/${NAME}"
-    ${NAME}
-    ros/${NAME}/wrap
-    )
 
-  PKG_CONFIG_USE_DEPENDENCY(ros/${NAME}/wrap realtime_tools)
-  PKG_CONFIG_USE_DEPENDENCY(ros/${NAME}/wrap dynamic_graph)
-  PKG_CONFIG_USE_DEPENDENCY(ros/${NAME}/wrap sot-core)
-  PKG_CONFIG_USE_DEPENDENCY(ros/${NAME}/wrap dynamic_graph_bridge_msgs)
+  IF(BUILD_PYTHON_INTERFACE)
+    dynamic_graph_python_module("ros/${NAME}"
+      ${NAME}
+      ros/${NAME}/wrap
+      )
+
+    PKG_CONFIG_USE_DEPENDENCY(ros/${NAME}/wrap realtime_tools)
+    PKG_CONFIG_USE_DEPENDENCY(ros/${NAME}/wrap dynamic_graph)
+    PKG_CONFIG_USE_DEPENDENCY(ros/${NAME}/wrap sot-core)
+    PKG_CONFIG_USE_DEPENDENCY(ros/${NAME}/wrap dynamic_graph_bridge_msgs)
+  ENDIF(BUILD_PYTHON_INTERFACE)
 endmacro()
 
-#include(cmake/python.cmake)
-
 # Build Sot Entities
 compile_plugin(ros_publish)
 compile_plugin(ros_subscribe)
@@ -144,29 +155,31 @@ target_link_libraries(ros_publish ros_bridge)
 #compile_plugin(robot_model)
 
 # ros_interperter library.
-add_library(ros_interpreter src/ros_interpreter.cpp)
-pkg_config_use_dependency(ros_interpreter dynamic-graph)
-pkg_config_use_dependency(ros_interpreter sot-core)
-pkg_config_use_dependency(ros_interpreter roscpp)
-pkg_config_use_dependency(ros_interpreter dynamic_graph_bridge_msgs)
-
-add_dependencies(ros_interpreter ros_bridge)
-target_link_libraries(ros_interpreter ros_bridge)
-set_target_properties(ros_interpreter PROPERTIES BUILD_WITH_INSTALL_RPATH True
-                      LIBRARY_OUTPUT_DIRECTORY ${PROJECT_BINARY_DIR}/lib)
-message(cmakeinstalllibdir " is ${CMAKE_INSTALL_LIBDIR} ")
-install(TARGETS ros_interpreter DESTINATION lib)
-
-# Stand alone remote dynamic-graph Python interpreter.
-add_executable(interpreter src/interpreter.cpp)
-add_dependencies(interpreter ros_interpreter)
-target_link_libraries(interpreter ros_interpreter)
-pkg_config_use_dependency(interpreter dynamic-graph)
-pkg_config_use_dependency(interpreter sot-core)
-pkg_config_use_dependency(interpreter sot-dynamic-pinocchio)
-pkg_config_use_dependency(interpreter dynamic_graph_bridge_msgs)
-# set_target_properties(interpreter PROPERTIES BUILD_WITH_INSTALL_RPATH True)
-#install(TARGETS interpreter DESTINATION bin)
+IF(BUILD_PYTHON_INTERFACE)
+  add_library(ros_interpreter src/ros_interpreter.cpp)
+  pkg_config_use_dependency(ros_interpreter dynamic-graph)
+  pkg_config_use_dependency(ros_interpreter sot-core)
+  pkg_config_use_dependency(ros_interpreter roscpp)
+  pkg_config_use_dependency(ros_interpreter dynamic_graph_bridge_msgs)
+
+  add_dependencies(ros_interpreter ros_bridge)
+  target_link_libraries(ros_interpreter ros_bridge)
+  set_target_properties(ros_interpreter PROPERTIES BUILD_WITH_INSTALL_RPATH True
+                        LIBRARY_OUTPUT_DIRECTORY ${PROJECT_BINARY_DIR}/lib)
+  message(cmakeinstalllibdir " is ${CMAKE_INSTALL_LIBDIR} ")
+  install(TARGETS ros_interpreter DESTINATION lib)
+
+  # Stand alone remote dynamic-graph Python interpreter.
+  add_executable(interpreter src/interpreter.cpp)
+  add_dependencies(interpreter ros_interpreter)
+  target_link_libraries(interpreter ros_interpreter)
+  pkg_config_use_dependency(interpreter dynamic-graph)
+  pkg_config_use_dependency(interpreter sot-core)
+  pkg_config_use_dependency(interpreter sot-dynamic-pinocchio)
+  pkg_config_use_dependency(interpreter dynamic_graph_bridge_msgs)
+  # set_target_properties(interpreter PROPERTIES BUILD_WITH_INSTALL_RPATH True)
+  #install(TARGETS interpreter DESTINATION bin)
+ENDIF(BUILD_PYTHON_INTERFACE)
 
 # Stand alone embedded intepreter with a robot controller.
 add_executable(geometric_simu src/geometric_simu.cpp src/sot_loader.cpp src/sot_loader_basic.cpp)
@@ -181,19 +194,24 @@ target_link_libraries(sot_loader ${Boost_LIBRARIES} roscpp ros_bridge tf)
 install(TARGETS sot_loader DESTINATION lib)
 
 add_subdirectory(src)
+add_subdirectory(tests)
 
 # Deal with the ROS part.
 add_service_files( FILES RunPythonFile.srv )
 generate_messages( DEPENDENCIES std_msgs )
 
+
 # This is necessary so that the pc file generated by catking is similar to the on
 # done directly by jrl-cmake-modules
 catkin_package(CATKIN_DEPENDS message_runtime roscpp realtime_tools tf2_bullet ${SOT_PKGNAMES} tf
-LIBRARIES ros_bridge ros_interpreter sot_loader
+  LIBRARIES ${CATKIN_DEPENDS_LIBRARIES}
 )
 
 # Add libraries in pc file generated by cmake submodule
-PKG_CONFIG_APPEND_LIBS(ros_bridge ros_interpreter sot_loader)
+PKG_CONFIG_APPEND_LIBS(ros_bridge sot_loader)
+IF(BUILD_PYTHON_INTERFACE)
+  PKG_CONFIG_APPEND_LIBS(ros_interpreter)
+ENDIF(BUILD_PYTHON_INTERFACE)
 
 #install ros executables
 install(PROGRAMS
diff --git a/README.md b/README.md
index c6648a75bfab056cb4e41104cf29cac5899b8053..d77c95d2ca6fc768d5a56b58bfc6613a279b288a 100644
--- a/README.md
+++ b/README.md
@@ -1,6 +1,9 @@
 dynamic-graph bindings
 ======================
-[![Build Status](https://travis-ci.org/stack-of-tasks/dynamic_graph_bridge.png?branch=master)](https://travis-ci.org/stack-of-tasks/dynamic_graph_bridge)
+
+[![Building Status](https://travis-ci.org/stack-of-tasks/dynamic_graph_bridge.svg?branch=master)](https://travis-ci.org/stack-of-tasks/dynamic_graph_bridge)
+[![Pipeline status](https://gepgitlab.laas.fr/stack-of-tasks/dynamic_graph_bridge/badges/master/pipeline.svg)](https://gepgitlab.laas.fr/stack-of-tasks/dynamic_graph_bridge/commits/master)
+[![Coverage report](https://gepgitlab.laas.fr/stack-of-tasks/dynamic_graph_bridge/badges/master/coverage.svg?job=doc-coverage)](http://projects.laas.fr/gepetto/doc/stack-of-tasks/dynamic_graph_bridge/master/coverage/)
 
 This ROS package binds together the ROS framework with the
 dynamic-graph real-time control architecture.
diff --git a/cmake b/cmake
index 54177e44a1440222184865f1449c40b708eeaaa4..8e7bedfcbd8524c0401a58fd74edc07c3d4308d0 160000
--- a/cmake
+++ b/cmake
@@ -1 +1 @@
-Subproject commit 54177e44a1440222184865f1449c40b708eeaaa4
+Subproject commit 8e7bedfcbd8524c0401a58fd74edc07c3d4308d0
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index f59f2399672d56c6a7c20cbcf4135a58eb0b4bee..85861d397e2fd9390d0b8b93a31257f7febed691 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -1,3 +1,8 @@
-PYTHON_INSTALL("dynamic_graph/ros" "__init__.py" "${PYTHON_SITELIB}")
-PYTHON_INSTALL("dynamic_graph/ros" "ros.py" "${PYTHON_SITELIB}")
-PYTHON_INSTALL("dynamic_graph/ros" "dgcompleter.py" "${PYTHON_SITELIB}")
+IF(BUILD_PYTHON_INTERFACE)
+  INSTALL(FILES
+    "dynamic_graph/ros/__init__.py"
+    "dynamic_graph/ros/ros.py"
+    "dynamic_graph/ros/dgcompleter.py"
+    DESTINATION "${PYTHON_SITELIB}/dynamic_graph/ros"
+    )
+ENDIF(BUILD_PYTHON_INTERFACE)
diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt
new file mode 100644
index 0000000000000000000000000000000000000000..92e10ebeee8bbdf9e86e85165efce935541b6c0d
--- /dev/null
+++ b/tests/CMakeLists.txt
@@ -0,0 +1,4 @@
+IF(BUILD_PYTHON_INTERFACE)
+  # TODO: this test requires a ros master
+  #ADD_PYTHON_UNIT_TEST("py-import" "tests/test_import.py")
+ENDIF(BUILD_PYTHON_INTERFACE)
diff --git a/tests/test_joint_state.py b/tests/test_joint_state.py
deleted file mode 100755
index 48196400937dc36048eb10d7e3d36694d38b4499..0000000000000000000000000000000000000000
--- a/tests/test_joint_state.py
+++ /dev/null
@@ -1,13 +0,0 @@
-#!/usr/bin/python
-
-try:
-    from dynamic_graph.sot.dynamics.tools import *
-except:
-    print("This test requires sot-dynamic.")
-    exit(42)
-
-from dynamic_graph.ros import RosJointState
-
-rjs = RosJointState('rosjointstate')
-plug(robot.device.state, rjs.state)
-rjs.trigger.recompute(rjs.trigger.time + 1)