commit 8c6c11632cbd6e46f9779ff88a25af1ffeeed088
Author: Simon Schulz <sschulz@cit-ec.uni-bielefeld.de>
Date:   Wed May 13 15:55:48 2015 +0200

    initial checkin

diff --git a/CMakeLists.txt b/CMakeLists.txt
new file mode 100644
index 0000000..3cd98ee
--- /dev/null
+++ b/CMakeLists.txt
@@ -0,0 +1,228 @@
+cmake_minimum_required(VERSION 2.8.3)
+project(humotion)
+
+set(ENV{ROS_LANG_DISABLE} "genjava")
+
+
+set(ROS_BUILD_TYPE Debug)
+
+
+#######################################
+# check if we have RSB support:
+FIND_PACKAGE(RSB 0.11)
+IF (RSB_FOUND)
+    #RSB
+    SET(CMAKE_INSTALL_RPATH "\$ORIGIN/../lib:\$ORIGIN/")
+    FIND_PACKAGE(RSC 0.11 REQUIRED)
+    FIND_PACKAGE(RSB 0.11 REQUIRED)
+    #RST
+    FIND_PACKAGE(RST REQUIRED COMPONENTS sandbox)
+    INCLUDE_DIRECTORIES(BEFORE SYSTEM ${RST_INCLUDE_DIRS})
+    ADD_DEFINITIONS(${RST_CFLAGS} ${RSTSANDBOX_CFLAGS})
+
+    INCLUDE_DIRECTORIES(BEFORE SYSTEM ${RSB_INCLUDE_DIRS})
+    LIST(INSERT CMAKE_MODULE_PATH 0 ${RSC_CMAKE_MODULE_PATH})
+    #RSB
+    SET(CMAKE_INSTALL_RPATH "\$ORIGIN/../lib:\$ORIGIN/")
+    FIND_PACKAGE(RSC 0.11 REQUIRED)
+    FIND_PACKAGE(RSB 0.11 REQUIRED)
+    #RST
+    FIND_PACKAGE(RST REQUIRED COMPONENTS sandbox)
+    INCLUDE_DIRECTORIES(BEFORE SYSTEM ${RST_INCLUDE_DIRS})
+    ADD_DEFINITIONS(${RST_CFLAGS} ${RSTSANDBOX_CFLAGS})
+
+    INCLUDE_DIRECTORIES(BEFORE SYSTEM ${RSB_INCLUDE_DIRS})
+    LIST(INSERT CMAKE_MODULE_PATH 0 ${RSC_CMAKE_MODULE_PATH})
+
+    message(STATUS "RSB Support is ON")
+    add_definitions(-DRSB_SUPPORT=1)
+ENDIF (RSB_FOUND)
+
+################################################################
+# check for ROS support:
+find_package(catkin)
+IF (catkin_FOUND)
+    SET(ROS_FOUND 1)
+
+    find_package(catkin REQUIRED COMPONENTS roscpp std_msgs sensor_msgs message_generation genmsg)
+
+    message(STATUS "ROS Support is ON")
+    add_definitions(-DROS_SUPPORT=1)
+ENDIF (catkin_FOUND)
+
+
+INCLUDE(FindPkgConfig)
+
+##libreflexxes
+IF (libreflexxes_DIR)
+  MESSAGE("using libreflexxes_DIR as override ('${libreflexxes_DIR}')")
+  SET(REFLEXXES_PREFIX ${libreflexxes_DIR})
+ELSE ()
+  PKG_CHECK_MODULES(REFLEXXES REQUIRED libReflexxesTypeII>=1.2.3)
+  IF (NOT REFLEXXES_FOUND)
+    message(FATAL_ERROR "Error: could not find lib libReflexxesTypeII")
+  ENDIF ()
+ENDIF()
+
+IF (NOT catkin_FOUND)
+    IF (NOT RSB_FOUND)
+        message(FATAL_ERROR "Error: could neither find RSB or ROS middleware!")
+    ENDIF (NOT RSB_FOUND)
+ENDIF (NOT catkin_FOUND)
+
+
+SET(REFLEXXES_LIBRARY_DIRS "${REFLEXXES_PREFIX}/lib")
+SET(REFLEXXES_INCLUDE_DIRS "${REFLEXXES_PREFIX}/include")
+MESSAGE("using libReflexxesTypeII version ${REFLEXXES_VERSION} from ${REFLEXXES_INCLUDE_DIRS} and ${REFLEXXES_LIBRARY_DIRS}")
+
+set(CMAKE_CXX_FLAGS "-g -Wall")
+add_definitions ("-Wall")
+
+
+IF (catkin_FOUND)
+    #######################################
+    ## Declare ROS messages and services ##
+    #######################################
+
+    add_message_files(
+            FILES
+            gaze.msg
+            position_lcr.msg
+            mouth.msg
+    )
+
+    ## Generate added messages and services with any dependencies listed here
+    generate_messages(
+            DEPENDENCIES
+            std_msgs
+            humotion
+    )
+
+
+    #
+    ###################################
+    ## catkin specific configuration ##
+    ###################################
+    ## The catkin_package macro generates cmake config files for your package
+    ## Declare things to be passed to dependent projects
+    ## INCLUDE_DIRS: uncomment this if you package contains header files
+    ## LIBRARIES: libraries you create in this project that dependent projects also need
+    ## CATKIN_DEPENDS: catkin_packages dependent projects also need
+    ## DEPENDS: system dependencies of this project that dependent projects also need
+    catkin_package(
+        INCLUDE_DIRS include
+        LIBRARIES humotion
+        #CATKIN_DEPENDS message_runtime
+        #DEPENDS system_lib
+    )
+ENDIF (catkin_FOUND)
+
+###########
+## Build ##
+###########
+
+## Specify additional locations of header files
+## Your package locations should be listed before other locations
+include_directories (BEFORE ${Boost_INCLUDE_DIRS} ${REFLEXXES_INCLUDE_DIRS})
+include_directories(include)
+include_directories( ${catkin_INCLUDE_DIRS})
+link_directories (${Boost_LIBRARY_DIRS} ${REFLEXXES_LIBRARY_DIRS} ${catkin_LIBRARY_DIRS})
+
+file(GLOB DUMMY_HEADER_LIST RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} include/*.h  include/client/*.h  include/server/*.h srv/*.srv msg/*.msg etc/*)
+
+## Declare a cpp library
+add_library(humotion
+    src/mouth_state.cpp
+    src/gaze_state.cpp
+
+    src/client/client.cpp
+    src/client/middleware.cpp
+    src/client/middleware_ros.cpp
+    src/client/middleware_rsb.cpp
+
+    src/server/server.cpp
+    src/server/middleware.cpp
+    src/server/middleware_ros.cpp
+    src/server/middleware_rsb.cpp
+
+    src/server/controller.cpp
+    src/server/joint_interface.cpp
+    src/server/motion_generator.cpp
+    src/server/gaze_motion_generator.cpp
+    src/server/reflexxes_motion_generator.cpp
+    src/server/mouth_motion_generator.cpp
+    src/server/eye_motion_generator.cpp
+    src/server/eyelid_motion_generator.cpp
+    src/server/eyebrow_motion_generator.cpp
+    src/server/neck_motion_generator.cpp
+
+    src/timestamped_list.cpp
+
+    ${DUMMY_HEADER_LIST}
+)
+
+set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++0x")
+
+
+## Add cmake target dependencies of the executable/library
+## as an example, message headers may need to be generated before nodes
+add_dependencies(humotion ${catkin_EXPORTED_TARGETS} humotion_gencpp)
+
+## Specify libraries to link a library or executable target against
+target_link_libraries(humotion
+			${Boost_LIBRARIES} 
+			${catkin_LIBRARIES}
+                        ${REFLEXXES_LIBRARIES}
+                        ${RST_LIBRARIES}
+                        ${RSB_LIBRARIES}
+)
+
+set_property(TARGET humotion PROPERTY INSTALL_RPATH_USE_LINK_PATH TRUE)
+
+#############
+## Install ##
+#############
+
+# all install targets should use catkin DESTINATION variables
+# See http://ros.org/doc/api/catkin/html/adv_user_guide/variables.html
+
+## Mark executable scripts (Python etc.) for installation
+## in contrast to setup.py, you can choose the destination
+# install(PROGRAMS
+#   scripts/my_python_script
+#   DESTINATION ${CATKIN_PACKAGE_BIN_DESTINATION}
+# )
+
+## Mark executables and/or libraries for installation
+IF (catkin_FOUND)
+    install(TARGETS humotion
+        ARCHIVE DESTINATION ${CATKIN_PACKAGE_LIB_DESTINATION}
+        LIBRARY DESTINATION ${CATKIN_PACKAGE_LIB_DESTINATION}
+        RUNTIME DESTINATION ${CATKIN_PACKAGE_BIN_DESTINATION}
+    )
+    ## Mark cpp header files for installation
+    install(DIRECTORY include/
+        DESTINATION ${CATKIN_PACKAGE_INCLUDE_DESTINATION}
+        PATTERN ".svn" EXCLUDE
+    )
+ENDIF (catkin_FOUND)
+
+
+#############
+## Testing ##
+#############
+IF (catkin_FOUND)
+    ## Add gtest based cpp test target and link libraries
+    catkin_add_gtest(${PROJECT_NAME}-test-server test/server.cpp)
+    if(TARGET ${PROJECT_NAME}-test-server)
+    target_link_libraries(${PROJECT_NAME}-test-server ${PROJECT_NAME})
+    endif()
+    catkin_add_gtest(${PROJECT_NAME}-test-client test/client.cpp)
+    if(TARGET ${PROJECT_NAME}-test-client)
+    target_link_libraries(${PROJECT_NAME}-test-client ${PROJECT_NAME})
+    endif()
+ENDIF (catkin_FOUND)
+
+
+### Add folders to be run by python nosetests
+# catkin_add_nosetests(test)
diff --git a/COPYING b/COPYING
new file mode 100644
index 0000000..65c5ca8
--- /dev/null
+++ b/COPYING
@@ -0,0 +1,165 @@
+                   GNU LESSER GENERAL PUBLIC LICENSE
+                       Version 3, 29 June 2007
+
+ Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+
+  This version of the GNU Lesser General Public License incorporates
+the terms and conditions of version 3 of the GNU General Public
+License, supplemented by the additional permissions listed below.
+
+  0. Additional Definitions.
+
+  As used herein, "this License" refers to version 3 of the GNU Lesser
+General Public License, and the "GNU GPL" refers to version 3 of the GNU
+General Public License.
+
+  "The Library" refers to a covered work governed by this License,
+other than an Application or a Combined Work as defined below.
+
+  An "Application" is any work that makes use of an interface provided
+by the Library, but which is not otherwise based on the Library.
+Defining a subclass of a class defined by the Library is deemed a mode
+of using an interface provided by the Library.
+
+  A "Combined Work" is a work produced by combining or linking an
+Application with the Library.  The particular version of the Library
+with which the Combined Work was made is also called the "Linked
+Version".
+
+  The "Minimal Corresponding Source" for a Combined Work means the
+Corresponding Source for the Combined Work, excluding any source code
+for portions of the Combined Work that, considered in isolation, are
+based on the Application, and not on the Linked Version.
+
+  The "Corresponding Application Code" for a Combined Work means the
+object code and/or source code for the Application, including any data
+and utility programs needed for reproducing the Combined Work from the
+Application, but excluding the System Libraries of the Combined Work.
+
+  1. Exception to Section 3 of the GNU GPL.
+
+  You may convey a covered work under sections 3 and 4 of this License
+without being bound by section 3 of the GNU GPL.
+
+  2. Conveying Modified Versions.
+
+  If you modify a copy of the Library, and, in your modifications, a
+facility refers to a function or data to be supplied by an Application
+that uses the facility (other than as an argument passed when the
+facility is invoked), then you may convey a copy of the modified
+version:
+
+   a) under this License, provided that you make a good faith effort to
+   ensure that, in the event an Application does not supply the
+   function or data, the facility still operates, and performs
+   whatever part of its purpose remains meaningful, or
+
+   b) under the GNU GPL, with none of the additional permissions of
+   this License applicable to that copy.
+
+  3. Object Code Incorporating Material from Library Header Files.
+
+  The object code form of an Application may incorporate material from
+a header file that is part of the Library.  You may convey such object
+code under terms of your choice, provided that, if the incorporated
+material is not limited to numerical parameters, data structure
+layouts and accessors, or small macros, inline functions and templates
+(ten or fewer lines in length), you do both of the following:
+
+   a) Give prominent notice with each copy of the object code that the
+   Library is used in it and that the Library and its use are
+   covered by this License.
+
+   b) Accompany the object code with a copy of the GNU GPL and this license
+   document.
+
+  4. Combined Works.
+
+  You may convey a Combined Work under terms of your choice that,
+taken together, effectively do not restrict modification of the
+portions of the Library contained in the Combined Work and reverse
+engineering for debugging such modifications, if you also do each of
+the following:
+
+   a) Give prominent notice with each copy of the Combined Work that
+   the Library is used in it and that the Library and its use are
+   covered by this License.
+
+   b) Accompany the Combined Work with a copy of the GNU GPL and this license
+   document.
+
+   c) For a Combined Work that displays copyright notices during
+   execution, include the copyright notice for the Library among
+   these notices, as well as a reference directing the user to the
+   copies of the GNU GPL and this license document.
+
+   d) Do one of the following:
+
+       0) Convey the Minimal Corresponding Source under the terms of this
+       License, and the Corresponding Application Code in a form
+       suitable for, and under terms that permit, the user to
+       recombine or relink the Application with a modified version of
+       the Linked Version to produce a modified Combined Work, in the
+       manner specified by section 6 of the GNU GPL for conveying
+       Corresponding Source.
+
+       1) Use a suitable shared library mechanism for linking with the
+       Library.  A suitable mechanism is one that (a) uses at run time
+       a copy of the Library already present on the user's computer
+       system, and (b) will operate properly with a modified version
+       of the Library that is interface-compatible with the Linked
+       Version.
+
+   e) Provide Installation Information, but only if you would otherwise
+   be required to provide such information under section 6 of the
+   GNU GPL, and only to the extent that such information is
+   necessary to install and execute a modified version of the
+   Combined Work produced by recombining or relinking the
+   Application with a modified version of the Linked Version. (If
+   you use option 4d0, the Installation Information must accompany
+   the Minimal Corresponding Source and Corresponding Application
+   Code. If you use option 4d1, you must provide the Installation
+   Information in the manner specified by section 6 of the GNU GPL
+   for conveying Corresponding Source.)
+
+  5. Combined Libraries.
+
+  You may place library facilities that are a work based on the
+Library side by side in a single library together with other library
+facilities that are not Applications and are not covered by this
+License, and convey such a combined library under terms of your
+choice, if you do both of the following:
+
+   a) Accompany the combined library with a copy of the same work based
+   on the Library, uncombined with any other library facilities,
+   conveyed under the terms of this License.
+
+   b) Give prominent notice with the combined library that part of it
+   is a work based on the Library, and explaining where to find the
+   accompanying uncombined form of the same work.
+
+  6. Revised Versions of the GNU Lesser General Public License.
+
+  The Free Software Foundation may publish revised and/or new versions
+of the GNU Lesser General Public License from time to time. Such new
+versions will be similar in spirit to the present version, but may
+differ in detail to address new problems or concerns.
+
+  Each version is given a distinguishing version number. If the
+Library as you received it specifies that a certain numbered version
+of the GNU Lesser General Public License "or any later version"
+applies to it, you have the option of following the terms and
+conditions either of that published version or of any later version
+published by the Free Software Foundation. If the Library as you
+received it does not specify a version number of the GNU Lesser
+General Public License, you may choose any version of the GNU Lesser
+General Public License ever published by the Free Software Foundation.
+
+  If the Library as you received it specifies that a proxy can decide
+whether future versions of the GNU Lesser General Public License shall
+apply, that proxy's public statement of acceptance of any version is
+permanent authorization for you to choose that version for the
+Library.
diff --git a/README.md b/README.md
new file mode 100644
index 0000000..1983f2f
--- /dev/null
+++ b/README.md
@@ -0,0 +1,5 @@
+# [hu]man [motion] low-level robot ontrol library
+
+this is the low level robot control software to allow
+human like motion generation on a humanoid robotic head
+
diff --git a/examples/yarp_icub/CMakeLists.txt b/examples/yarp_icub/CMakeLists.txt
new file mode 100644
index 0000000..bf9b861
--- /dev/null
+++ b/examples/yarp_icub/CMakeLists.txt
@@ -0,0 +1,29 @@
+PROJECT(icub_humotion)
+cmake_minimum_required(VERSION 2.8)
+
+FIND_PACKAGE(YARP)
+FIND_PACKAGE(ICUB)
+FIND_PACKAGE(Boost REQUIRED COMPONENTS system thread)
+FIND_PACKAGE(humotion)
+
+set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++0x")
+
+# add include directories
+INCLUDE_DIRECTORIES(${YARP_INCLUDE_DIRS} ${ICUB_INCLUDE_DIRS} ${humotion_INCLUDE_DIRS} ${Boost_INCLUDE_DIRS} include/)
+link_directories(${Boost_LIBRARY_DIRS} ${humotion_LIBRARY_DIRS})
+
+# add required linker flags
+SET(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} ${ICUB_LINK_FLAGS}")
+SET(MAIN icub_humotion_server)
+
+file(GLOB DUMMY_HEADER_LIST RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} include/*.h)
+
+ADD_EXECUTABLE(${MAIN} src/main.cpp src/icub_jointinterface.cpp src/icub_data_receiver.cpp ${DUMMY_HEADER_LIST})
+
+# we now add the YARP and iCub libraries to our project.
+TARGET_LINK_LIBRARIES(${MAIN} ${Boost_LIBRARIES} ${YARP_LIBRARIES} ${ICUB_LIBRARIES} ${humotion_LIBRARIES})
+set_property(TARGET ${MAIN} PROPERTY INSTALL_RPATH_USE_LINK_PATH TRUE)
+
+
+INSTALL(TARGETS ${MAIN} DESTINATION bin)
+
diff --git a/examples/yarp_icub/CMakeLists.txt.user b/examples/yarp_icub/CMakeLists.txt.user
new file mode 100644
index 0000000..4649f6e
--- /dev/null
+++ b/examples/yarp_icub/CMakeLists.txt.user
@@ -0,0 +1,183 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE QtCreatorProject>
+<!-- Written by QtCreator 3.0.1, 2015-03-12T13:07:35. -->
+<qtcreator>
+ <data>
+  <variable>ProjectExplorer.Project.ActiveTarget</variable>
+  <value type="int">0</value>
+ </data>
+ <data>
+  <variable>ProjectExplorer.Project.EditorSettings</variable>
+  <valuemap type="QVariantMap">
+   <value type="bool" key="EditorConfiguration.AutoIndent">true</value>
+   <value type="bool" key="EditorConfiguration.AutoSpacesForTabs">false</value>
+   <value type="bool" key="EditorConfiguration.CamelCaseNavigation">true</value>
+   <valuemap type="QVariantMap" key="EditorConfiguration.CodeStyle.0">
+    <value type="QString" key="language">Cpp</value>
+    <valuemap type="QVariantMap" key="value">
+     <value type="QByteArray" key="CurrentPreferences">CppGlobal</value>
+    </valuemap>
+   </valuemap>
+   <valuemap type="QVariantMap" key="EditorConfiguration.CodeStyle.1">
+    <value type="QString" key="language">QmlJS</value>
+    <valuemap type="QVariantMap" key="value">
+     <value type="QByteArray" key="CurrentPreferences">QmlJSGlobal</value>
+    </valuemap>
+   </valuemap>
+   <value type="int" key="EditorConfiguration.CodeStyle.Count">2</value>
+   <value type="QByteArray" key="EditorConfiguration.Codec">UTF-8</value>
+   <value type="bool" key="EditorConfiguration.ConstrainTooltips">false</value>
+   <value type="int" key="EditorConfiguration.IndentSize">4</value>
+   <value type="bool" key="EditorConfiguration.KeyboardTooltips">false</value>
+   <value type="bool" key="EditorConfiguration.MouseNavigation">true</value>
+   <value type="int" key="EditorConfiguration.PaddingMode">1</value>
+   <value type="bool" key="EditorConfiguration.ScrollWheelZooming">true</value>
+   <value type="int" key="EditorConfiguration.SmartBackspaceBehavior">0</value>
+   <value type="bool" key="EditorConfiguration.SpacesForTabs">true</value>
+   <value type="int" key="EditorConfiguration.TabKeyBehavior">0</value>
+   <value type="int" key="EditorConfiguration.TabSize">8</value>
+   <value type="bool" key="EditorConfiguration.UseGlobal">true</value>
+   <value type="int" key="EditorConfiguration.Utf8BomBehavior">1</value>
+   <value type="bool" key="EditorConfiguration.addFinalNewLine">true</value>
+   <value type="bool" key="EditorConfiguration.cleanIndentation">true</value>
+   <value type="bool" key="EditorConfiguration.cleanWhitespace">true</value>
+   <value type="bool" key="EditorConfiguration.inEntireDocument">false</value>
+  </valuemap>
+ </data>
+ <data>
+  <variable>ProjectExplorer.Project.PluginSettings</variable>
+  <valuemap type="QVariantMap"/>
+ </data>
+ <data>
+  <variable>ProjectExplorer.Project.Target.0</variable>
+  <valuemap type="QVariantMap">
+   <value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Desktop</value>
+   <value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName">Desktop</value>
+   <value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">{3152ed58-41d1-426c-b17f-dbe12171436a}</value>
+   <value type="int" key="ProjectExplorer.Target.ActiveBuildConfiguration">0</value>
+   <value type="int" key="ProjectExplorer.Target.ActiveDeployConfiguration">0</value>
+   <value type="int" key="ProjectExplorer.Target.ActiveRunConfiguration">0</value>
+   <valuemap type="QVariantMap" key="ProjectExplorer.Target.BuildConfiguration.0">
+    <value type="bool" key="CMakeProjectManager.CMakeBuildConfiguration.UseNinja">false</value>
+    <value type="QString" key="ProjectExplorer.BuildConfiguration.BuildDirectory">/homes/sschulz/src/flobidev.core/humotion/examples/yarp_icub/qbuild</value>
+    <valuemap type="QVariantMap" key="ProjectExplorer.BuildConfiguration.BuildStepList.0">
+     <valuemap type="QVariantMap" key="ProjectExplorer.BuildStepList.Step.0">
+      <value type="QString" key="CMakeProjectManager.MakeStep.AdditionalArguments"></value>
+      <valuelist type="QVariantList" key="CMakeProjectManager.MakeStep.BuildTargets"/>
+      <value type="bool" key="CMakeProjectManager.MakeStep.Clean">false</value>
+      <value type="bool" key="CMakeProjectManager.MakeStep.UseNinja">false</value>
+      <value type="bool" key="ProjectExplorer.BuildStep.Enabled">true</value>
+      <value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Make</value>
+      <value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
+      <value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">CMakeProjectManager.MakeStep</value>
+     </valuemap>
+     <value type="int" key="ProjectExplorer.BuildStepList.StepsCount">1</value>
+     <value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Build</value>
+     <value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
+     <value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">ProjectExplorer.BuildSteps.Build</value>
+    </valuemap>
+    <valuemap type="QVariantMap" key="ProjectExplorer.BuildConfiguration.BuildStepList.1">
+     <valuemap type="QVariantMap" key="ProjectExplorer.BuildStepList.Step.0">
+      <value type="QString" key="CMakeProjectManager.MakeStep.AdditionalArguments">clean</value>
+      <valuelist type="QVariantList" key="CMakeProjectManager.MakeStep.BuildTargets"/>
+      <value type="bool" key="CMakeProjectManager.MakeStep.Clean">true</value>
+      <value type="bool" key="CMakeProjectManager.MakeStep.UseNinja">false</value>
+      <value type="bool" key="ProjectExplorer.BuildStep.Enabled">true</value>
+      <value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Make</value>
+      <value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
+      <value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">CMakeProjectManager.MakeStep</value>
+     </valuemap>
+     <value type="int" key="ProjectExplorer.BuildStepList.StepsCount">1</value>
+     <value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Clean</value>
+     <value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
+     <value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">ProjectExplorer.BuildSteps.Clean</value>
+    </valuemap>
+    <value type="int" key="ProjectExplorer.BuildConfiguration.BuildStepListCount">2</value>
+    <value type="bool" key="ProjectExplorer.BuildConfiguration.ClearSystemEnvironment">false</value>
+    <valuelist type="QVariantList" key="ProjectExplorer.BuildConfiguration.UserEnvironmentChanges"/>
+    <value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Default</value>
+    <value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName">Default</value>
+    <value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">CMakeProjectManager.CMakeBuildConfiguration</value>
+   </valuemap>
+   <value type="int" key="ProjectExplorer.Target.BuildConfigurationCount">1</value>
+   <valuemap type="QVariantMap" key="ProjectExplorer.Target.DeployConfiguration.0">
+    <valuemap type="QVariantMap" key="ProjectExplorer.BuildConfiguration.BuildStepList.0">
+     <value type="int" key="ProjectExplorer.BuildStepList.StepsCount">0</value>
+     <value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Deploy</value>
+     <value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
+     <value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">ProjectExplorer.BuildSteps.Deploy</value>
+    </valuemap>
+    <value type="int" key="ProjectExplorer.BuildConfiguration.BuildStepListCount">1</value>
+    <value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Deploy locally</value>
+    <value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
+    <value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">ProjectExplorer.DefaultDeployConfiguration</value>
+   </valuemap>
+   <value type="int" key="ProjectExplorer.Target.DeployConfigurationCount">1</value>
+   <valuemap type="QVariantMap" key="ProjectExplorer.Target.PluginSettings"/>
+   <valuemap type="QVariantMap" key="ProjectExplorer.Target.RunConfiguration.0">
+    <valuelist type="QVariantList" key="Analyzer.Valgrind.AddedSuppressionFiles"/>
+    <value type="bool" key="Analyzer.Valgrind.Callgrind.CollectBusEvents">false</value>
+    <value type="bool" key="Analyzer.Valgrind.Callgrind.CollectSystime">false</value>
+    <value type="bool" key="Analyzer.Valgrind.Callgrind.EnableBranchSim">false</value>
+    <value type="bool" key="Analyzer.Valgrind.Callgrind.EnableCacheSim">false</value>
+    <value type="bool" key="Analyzer.Valgrind.Callgrind.EnableEventToolTips">true</value>
+    <value type="double" key="Analyzer.Valgrind.Callgrind.MinimumCostRatio">0.01</value>
+    <value type="double" key="Analyzer.Valgrind.Callgrind.VisualisationMinimumCostRatio">10</value>
+    <value type="bool" key="Analyzer.Valgrind.FilterExternalIssues">true</value>
+    <value type="int" key="Analyzer.Valgrind.LeakCheckOnFinish">1</value>
+    <value type="int" key="Analyzer.Valgrind.NumCallers">25</value>
+    <valuelist type="QVariantList" key="Analyzer.Valgrind.RemovedSuppressionFiles"/>
+    <value type="int" key="Analyzer.Valgrind.SelfModifyingCodeDetection">1</value>
+    <value type="bool" key="Analyzer.Valgrind.Settings.UseGlobalSettings">true</value>
+    <value type="bool" key="Analyzer.Valgrind.ShowReachable">false</value>
+    <value type="bool" key="Analyzer.Valgrind.TrackOrigins">true</value>
+    <value type="QString" key="Analyzer.Valgrind.ValgrindExecutable">valgrind</value>
+    <valuelist type="QVariantList" key="Analyzer.Valgrind.VisibleErrorKinds">
+     <value type="int">0</value>
+     <value type="int">1</value>
+     <value type="int">2</value>
+     <value type="int">3</value>
+     <value type="int">4</value>
+     <value type="int">5</value>
+     <value type="int">6</value>
+     <value type="int">7</value>
+     <value type="int">8</value>
+     <value type="int">9</value>
+     <value type="int">10</value>
+     <value type="int">11</value>
+     <value type="int">12</value>
+     <value type="int">13</value>
+     <value type="int">14</value>
+    </valuelist>
+    <value type="QString" key="CMakeProjectManager.CMakeRunConfiguation.Title">icub_humotion_server</value>
+    <value type="QString" key="CMakeProjectManager.CMakeRunConfiguration.Arguments"></value>
+    <value type="bool" key="CMakeProjectManager.CMakeRunConfiguration.UseTerminal">false</value>
+    <value type="QString" key="CMakeProjectManager.CMakeRunConfiguration.UserWorkingDirectory"></value>
+    <value type="int" key="PE.EnvironmentAspect.Base">-1</value>
+    <valuelist type="QVariantList" key="PE.EnvironmentAspect.Changes"/>
+    <value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">icub_humotion_server</value>
+    <value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
+    <value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">CMakeProjectManager.CMakeRunConfiguration.icub_humotion_server</value>
+    <value type="uint" key="RunConfiguration.QmlDebugServerPort">3768</value>
+    <value type="bool" key="RunConfiguration.UseCppDebugger">false</value>
+    <value type="bool" key="RunConfiguration.UseCppDebuggerAuto">true</value>
+    <value type="bool" key="RunConfiguration.UseMultiProcess">false</value>
+    <value type="bool" key="RunConfiguration.UseQmlDebugger">false</value>
+    <value type="bool" key="RunConfiguration.UseQmlDebuggerAuto">true</value>
+   </valuemap>
+   <value type="int" key="ProjectExplorer.Target.RunConfigurationCount">1</value>
+  </valuemap>
+ </data>
+ <data>
+  <variable>ProjectExplorer.Project.TargetCount</variable>
+  <value type="int">1</value>
+ </data>
+ <data>
+  <variable>ProjectExplorer.Project.Updater.EnvironmentId</variable>
+  <value type="QByteArray">{ccede451-c1b6-4b92-a13d-14bd6a65dd35}</value>
+ </data>
+ <data>
+  <variable>ProjectExplorer.Project.Updater.FileVersion</variable>
+  <value type="int">15</value>
+ </data>
+</qtcreator>
diff --git a/examples/yarp_icub/include/icub_data_receiver.h b/examples/yarp_icub/include/icub_data_receiver.h
new file mode 100644
index 0000000..13a5af4
--- /dev/null
+++ b/examples/yarp_icub/include/icub_data_receiver.h
@@ -0,0 +1,37 @@
+#pragma once
+#include <humotion/server/joint_interface.h>
+#include <boost/bimap.hpp>
+#include <yarp/dev/PolyDriver.h>
+#include <yarp/dev/IControlLimits2.h>
+#include <yarp/dev/ControlBoardInterfaces.h>
+#include <yarp/os/Time.h>
+#include <yarp/sig/Vector.h>
+#include "icub_jointinterface.h"
+#include <humotion/server/server.h>
+#include <yarp/os/Network.h>
+#include <yarp/os/RateThread.h>
+#include <yarp/os/Time.h>
+#include <yarp/os/Property.h>
+#include <yarp/dev/ControlBoardInterfaces.h>
+#include "icub_jointinterface.h"
+
+//forward declaration to solve loop
+class iCubJointInterface;
+
+class iCubDataReceiver : public yarp::os::RateThread{
+public:
+    iCubDataReceiver(int period, yarp::dev::IEncoders *_iencs, iCubJointInterface *_icub_jointinterface);
+    bool threadInit();
+    void threadRelease();
+    void run();
+private:
+    double get_timestamp_ms();
+
+    yarp::sig::Vector positions;
+    yarp::sig::Vector velocities;
+    yarp::sig::Vector commands;
+
+    yarp::dev::IEncoders *iencs;
+    iCubJointInterface *icub_jointinterface;
+};
+
diff --git a/examples/yarp_icub/include/icub_jointinterface.h b/examples/yarp_icub/include/icub_jointinterface.h
new file mode 100644
index 0000000..86dd237
--- /dev/null
+++ b/examples/yarp_icub/include/icub_jointinterface.h
@@ -0,0 +1,112 @@
+#pragma once
+#include <humotion/server/joint_interface.h>
+#include <boost/bimap.hpp>
+#include <yarp/dev/PolyDriver.h>
+#include <yarp/dev/IControlLimits2.h>
+#include <yarp/dev/ControlBoardInterfaces.h>
+#include <yarp/os/Time.h>
+#include <yarp/sig/Vector.h>
+#include "icub_jointinterface.h"
+#include <humotion/server/server.h>
+#include <yarp/os/Network.h>
+#include <yarp/os/RateThread.h>
+#include <yarp/os/Time.h>
+#include <yarp/os/Property.h>
+#include <yarp/os/Port.h>
+#include <yarp/dev/ControlBoardInterfaces.h>
+#include "icub_data_receiver.h"
+
+class iCubDataReceiver;
+
+class iCubJointInterface : public humotion::server::JointInterface{
+public:
+    iCubJointInterface(std::string scope);
+    ~iCubJointInterface();
+
+    //void fetch_position(Device *dev, double timestamp);
+    //void fetch_speed(Device *dev, double timestamp);
+    void fetch_position(int id, double value, double timestamp);
+    void fetch_speed(int id, double value, double timestamp);
+    void run();
+
+    enum JOINT_ID_ENUM{
+        ICUB_ID_NECK_TILT = 0,
+        ICUB_ID_NECK_ROLL = 1,
+        ICUB_ID_NECK_PAN  = 2,
+        ICUB_ID_EYES_BOTH_UD = 3,
+        ICUB_ID_EYES_PAN = 4,
+        ICUB_ID_EYES_VERGENCE = 5,
+        //the following ids are used for remapping:
+        ICUB_ID_EYES_LEFT_LR,
+        ICUB_ID_EYES_RIGHT_LR,
+        ICUB_ID_EYES_LEFT_LID_LOWER,
+        ICUB_ID_EYES_LEFT_LID_UPPER,
+        ICUB_ID_EYES_RIGHT_LID_LOWER,
+        ICUB_ID_EYES_RIGHT_LID_UPPER,
+        ICUB_ID_EYES_LEFT_BROW,
+        ICUB_ID_EYES_RIGHT_BROW,
+        ICUB_ID_LIP_LEFT_UPPER,
+        ICUB_ID_LIP_LEFT_LOWER,
+        ICUB_ID_LIP_CENTER_UPPER,
+        ICUB_ID_LIP_CENTER_LOWER,
+        ICUB_ID_LIP_RIGHT_UPPER,
+        ICUB_ID_LIP_RIGHT_LOWER,
+        ICUB_JOINT_ID_ENUM_SIZE
+    };
+
+    static const int MAIN_LOOP_FREQUENCY = 50;
+
+protected:
+    void disable_joint(int e);
+    void publish_target_position(int e);
+    void enable_joint(int e);
+    void execute_motion();
+
+private:
+    double get_timestamp_ms();
+    double target_angle[ICUB_JOINT_ID_ENUM_SIZE];
+    double target_angle_previous[ICUB_JOINT_ID_ENUM_SIZE];
+
+    void set_eyelid_angle(double angle);
+    void set_eyebrow_angle(int id);
+    void set_mouth();
+
+    iCubDataReceiver *icub_data_receiver;
+    void init_joints();
+    double lid_angle;
+    int lid_opening_previous;
+    int previous_mouth_state;
+
+    std::string scope;
+    yarp::dev::PolyDriver dd;
+    yarp::sig::Vector positions;
+    yarp::sig::Vector velocities;
+    yarp::sig::Vector commands;
+
+    yarp::os::BufferedPort<yarp::os::Bottle> emotion_port[4];
+
+    yarp::dev::IVelocityControl *ivel;
+    yarp::dev::IPositionControl *ipos;
+    yarp::dev::IEncoders *iencs;
+    yarp::dev::IControlLimits *ilimits;
+
+    void store_min_max(yarp::dev::IControlLimits *ilimits, int id, int e);
+
+    float last_pos_eye_vergence;
+    float last_pos_eye_pan;
+    float last_vel_eye_vergence;
+    float last_vel_eye_pan;
+
+    void store_joint(int id, float value);
+    void set_target_in_positionmode(int id, double value);
+    void set_target_in_velocitymode(int id, double value);
+
+
+    int convert_enum_to_motorid(int e);
+    int convert_motorid_to_enum(int id);
+
+
+    typedef boost::bimap<int, int > enum_id_bimap_t;
+    typedef enum_id_bimap_t::value_type enum_id_bimap_entry_t;
+    enum_id_bimap_t enum_id_bimap;
+};
diff --git a/examples/yarp_icub/src/icub_data_receiver.cpp b/examples/yarp_icub/src/icub_data_receiver.cpp
new file mode 100644
index 0000000..6efe5e1
--- /dev/null
+++ b/examples/yarp_icub/src/icub_data_receiver.cpp
@@ -0,0 +1,41 @@
+#include "icub_data_receiver.h"
+#include <yarp/os/Property.h>
+using namespace yarp::dev;
+using namespace yarp::sig;
+using namespace yarp::os;
+using namespace std;
+
+iCubDataReceiver::iCubDataReceiver(int period, IEncoders *_iencs, iCubJointInterface *_icub_jointinterface):RateThread(period){
+    iencs = _iencs;
+    icub_jointinterface = _icub_jointinterface;
+    int joints;
+    iencs->getAxes(&joints);
+    positions.resize(joints);
+    velocities.resize(joints);
+}
+
+bool iCubDataReceiver::threadInit(){ return true; }
+void iCubDataReceiver::threadRelease(){ }
+
+double iCubDataReceiver::get_timestamp_ms(){
+    struct timespec spec;
+    clock_gettime(CLOCK_REALTIME, &spec);
+    return spec.tv_sec+spec.tv_nsec/1000000000.0;
+}
+
+void iCubDataReceiver::run(){
+    //grab pos+vel data:
+    iencs->getEncoders(positions.data());
+    iencs->getEncoderSpeeds(velocities.data());
+    double timestamp = get_timestamp_ms();
+
+    //publish data to humotion
+    for(int i=0; i<positions.size(); i++){
+        icub_jointinterface->fetch_position(i, positions[i], timestamp);
+        icub_jointinterface->fetch_speed(i, velocities[i], timestamp);
+    }
+
+    //tell humotion to update lid angle (hack)
+    icub_jointinterface->fetch_position(100, 0.0, timestamp);
+    //fixme: use real id
+}
diff --git a/examples/yarp_icub/src/icub_jointinterface.cpp b/examples/yarp_icub/src/icub_jointinterface.cpp
new file mode 100644
index 0000000..105399f
--- /dev/null
+++ b/examples/yarp_icub/src/icub_jointinterface.cpp
@@ -0,0 +1,721 @@
+#include "icub_jointinterface.h"
+#include <yarp/os/Property.h>
+using namespace yarp::dev;
+using namespace yarp::sig;
+using namespace yarp::os;
+using namespace std;
+/*running:
+/media/local_data/sschulz/iros15/icub-nightly/share/iCub/contexts/simConfig:> iCub_SIM
+/media/local_data/sschulz/iros15/icub-nightly/share/iCub/contexts/simFaceExpressions:> ../../../../bin/simFaceExpressions
+yarp connect /face/eyelids /icubSim/face/eyelids
+yarp connect /face/image/out /icubSim/texture/face
+
+TEST: yarp write /writer /icubSim/face/raw/in
+
+http://wiki.icub.org/wiki/Motor_control
+*/
+
+//WARNING: DO NOT CHANGE THIS; VELOCITYMODE IS NOT YET IMPLEMENTED
+#define POSITION_CONTROL 1
+
+
+//! constructor
+iCubJointInterface::iCubJointInterface(string _scope) : humotion::server::JointInterface(){
+    scope = _scope;
+
+
+    //add mapping from ids to enums:
+    //this might look strange at the first sight but we need to have a generic
+    //way to acces joints from libhumotion. therefore the lib uses its enum with ID_* enum ids
+    //to access the joints. now we need to define a mapping to map those to our motor ids.
+    //this is what we use the enum bimap for (convertion fro/to motorid is handled
+    //by \sa convert_enum_to_motorid() and \sa convert_motorid_to_enum() lateron
+
+    //MOUTH
+    enum_id_bimap.insert(enum_id_bimap_entry_t(ICUB_ID_LIP_LEFT_UPPER,   ID_LIP_LEFT_UPPER));
+    enum_id_bimap.insert(enum_id_bimap_entry_t(ICUB_ID_LIP_LEFT_LOWER,   ID_LIP_LEFT_LOWER));
+    enum_id_bimap.insert(enum_id_bimap_entry_t(ICUB_ID_LIP_CENTER_UPPER, ID_LIP_CENTER_UPPER));
+    enum_id_bimap.insert(enum_id_bimap_entry_t(ICUB_ID_LIP_CENTER_LOWER, ID_LIP_CENTER_LOWER));
+    enum_id_bimap.insert(enum_id_bimap_entry_t(ICUB_ID_LIP_RIGHT_UPPER,  ID_LIP_RIGHT_UPPER));
+    enum_id_bimap.insert(enum_id_bimap_entry_t(ICUB_ID_LIP_RIGHT_LOWER,  ID_LIP_RIGHT_LOWER));
+
+    //NECK
+    enum_id_bimap.insert(enum_id_bimap_entry_t(ICUB_ID_NECK_PAN,    ID_NECK_PAN));
+    enum_id_bimap.insert(enum_id_bimap_entry_t(ICUB_ID_NECK_TILT,   ID_NECK_TILT));
+    enum_id_bimap.insert(enum_id_bimap_entry_t(ICUB_ID_NECK_ROLL,   ID_NECK_ROLL));
+
+    //EYES
+    enum_id_bimap.insert(enum_id_bimap_entry_t(ICUB_ID_EYES_LEFT_LR,   ID_EYES_LEFT_LR));
+    enum_id_bimap.insert(enum_id_bimap_entry_t(ICUB_ID_EYES_RIGHT_LR,   ID_EYES_RIGHT_LR));
+    enum_id_bimap.insert(enum_id_bimap_entry_t(ICUB_ID_EYES_BOTH_UD,   ID_EYES_BOTH_UD));
+
+    //EYELIDS
+    enum_id_bimap.insert(enum_id_bimap_entry_t(ICUB_ID_EYES_LEFT_LID_LOWER, ID_EYES_LEFT_LID_LOWER));
+    enum_id_bimap.insert(enum_id_bimap_entry_t(ICUB_ID_EYES_LEFT_LID_UPPER, ID_EYES_LEFT_LID_UPPER));
+    enum_id_bimap.insert(enum_id_bimap_entry_t(ICUB_ID_EYES_LEFT_BROW, ID_EYES_LEFT_BROW));
+
+    enum_id_bimap.insert(enum_id_bimap_entry_t(ICUB_ID_EYES_RIGHT_LID_LOWER, ID_EYES_RIGHT_LID_LOWER));
+    enum_id_bimap.insert(enum_id_bimap_entry_t(ICUB_ID_EYES_RIGHT_LID_UPPER,ID_EYES_RIGHT_LID_UPPER));
+    enum_id_bimap.insert(enum_id_bimap_entry_t(ICUB_ID_EYES_RIGHT_BROW, ID_EYES_RIGHT_BROW));
+
+    Property options;
+    options.put("device", "remote_controlboard");
+    options.put("local", "/local/head");
+    options.put("remote", scope+"/head");
+    dd.open(options);
+
+    //fetch views:
+    dd.view(iencs);
+    dd.view(ipos);
+    dd.view(ivel);
+    dd.view(ilimits);
+
+    if ( (!iencs) || (!ipos) || (!ilimits) || (!ivel)){
+        printf("> ERROR: failed to open icub views\n");
+        exit(EXIT_FAILURE);
+    }
+
+    int joints;
+
+    //tell humotion about min/max joint values:
+    init_joints();
+
+    iencs->getAxes(&joints);
+    positions.resize(joints);
+    velocities.resize(joints);
+    commands.resize(joints);
+
+    //set position mode:
+    if (POSITION_CONTROL){
+        commands=200000.0;
+        ipos->setRefAccelerations(commands.data());
+        ipos->setPositionMode();
+    }else{
+        ivel->setVelocityMode();
+        commands=1000000;
+        ivel->setRefAccelerations(commands.data());
+    }
+
+    //attach to facial expressions:
+    string emotion_scope = scope + "/face/raw/in";
+    printf("> opening connection to %s\n", emotion_scope.c_str());
+
+    for(int i=0; i<4; i++){
+        //strange, if we use one output port only the first command is executed?! flushing issues?
+        string emotion_port_out = "/emotionwriter" + to_string(i);
+        if (!emotion_port[i].open(emotion_port_out.c_str())){
+            printf("> ERROR: failed to open to %s\n",emotion_port_out.c_str());
+            exit(EXIT_FAILURE);
+        }
+        if (!Network::connect(emotion_port_out.c_str(), emotion_scope.c_str())){
+            printf("> ERROR: failed to connect emotion ports\n");
+            exit(EXIT_FAILURE);
+        }
+    }
+}
+
+//! destructor
+iCubJointInterface::~iCubJointInterface(){
+}
+
+
+
+//! conversion table for humotion motor ids to our ids:
+//! \param enum from JointInterface::JOINT_ID_ENUM
+//! \return int value of motor id
+int iCubJointInterface::convert_enum_to_motorid(int e){
+    enum_id_bimap_t::right_const_iterator it = enum_id_bimap.right.find(e);
+    if(it == enum_id_bimap.right.end()) {
+        //key does not exists, we are not interested in that dataset, return -1
+        return -1;
+    }
+    return it->second;
+}
+
+
+//! conversion table for our ids to humotion motor ids:
+//! \param  int value of motor id
+//! \return enum from JointInterface::JOINT_ID_ENUM
+int iCubJointInterface::convert_motorid_to_enum(int id){
+    enum_id_bimap_t::left_const_iterator it = enum_id_bimap.left.find(id);
+    if(it == enum_id_bimap.left.end()) {
+        //key does not exists, we are not interested in that dataset, return -1
+        return -1;
+    }
+    return it->second;
+}
+
+//! special command to set eyelid angle
+//! \param angle in degrees
+void iCubJointInterface::set_eyelid_angle(double angle){
+    if (emotion_port[0].getOutputCount()>0){
+        //try to set the value based on the upper one
+        //some guesses from the sim: S30 = 0° / S40 = 10°
+        int opening = (25.0 + 0.8*angle);
+        opening = min(48, max(24, opening));
+
+        if (opening == lid_opening_previous){
+            //no update necessary
+            return;
+        }
+
+        lid_angle = angle;
+        lid_opening_previous = opening;
+
+        char buf[20];
+        sprintf(buf, "S%2d", opening);
+
+        //printf("> SETTING EYELID '%s' (%f -> %d)\n",buf,angle,opening);
+        Bottle &cmd = emotion_port[0].prepare();
+        cmd.clear();
+        cmd.addString(buf);
+        emotion_port[0].write();
+    }else{
+        printf("> ERROR: no icub emotion output\n");
+        exit(EXIT_FAILURE);
+    }
+}
+
+//! special command to set the eyebrow angle
+//! \param id {0=left, 1=right)
+//! \param angle in degrees
+void iCubJointInterface::set_eyebrow_angle(int id){
+    int port_id;
+    if (id == ICUB_ID_EYES_LEFT_BROW){
+        port_id = 1;
+    }else{
+        port_id = 2;
+    }
+
+    if (emotion_port[port_id].getOutputCount()>0){
+        double angle = target_angle[id];
+        int icub_val = 0;
+
+        //swap rotation direction:
+        if (id==ICUB_ID_EYES_LEFT_BROW) angle = -angle;
+
+        //convert to icub representation
+        if (angle < -20){
+            icub_val = 1;
+        }else if (angle<10){
+            icub_val = 2;
+        }else if (angle<20){
+            icub_val = 4;
+        }else{
+            icub_val = 8;
+        }
+
+        //make sure to update only on new values:
+        if (icub_val == target_angle_previous[id]){
+                //no updata necessary
+                return;
+        }
+
+        //store actual value:
+        target_angle_previous[id] = icub_val;
+
+
+        string cmd_s;
+        if (id==ICUB_ID_EYES_LEFT_BROW){
+            cmd_s = "L0" + to_string(icub_val);
+        }else{
+            cmd_s = "R0" + to_string(icub_val);
+        }
+
+        printf("> SETTING EYEBROW %d (%f -> %s)\n",id,angle,cmd_s.c_str());
+
+        Bottle &cmd = emotion_port[port_id].prepare();
+        cmd.clear();
+        cmd.addString(cmd_s);
+        emotion_port[port_id].write();
+    }else{
+        printf("> ERROR: no icub emotion output\n");
+        exit(EXIT_FAILURE);
+    }
+}
+
+void iCubJointInterface::run(){
+    iCubDataReceiver *data_receiver = new iCubDataReceiver(10/*1000.0 / MAIN_LOOP_FREQUENCY*/, iencs, this);
+    data_receiver->start();
+}
+
+//! set the target position of a joint
+//! \param enum id of joint
+//! \param float value
+void iCubJointInterface::publish_target_position(int e){
+    //first: convert humotion enum to our enum:
+    int id = convert_enum_to_motorid(e);
+    if (id == -1){
+        return; //we are not interested in that data, so we just return here
+    }
+
+    if (id == ICUB_ID_NECK_PAN){
+        //PAN seems to be swapped
+        store_joint(ICUB_ID_NECK_PAN, -joint_target[e]);
+    }else if ((id == ICUB_ID_EYES_LEFT_LR) || ( id == ICUB_ID_EYES_RIGHT_LR)){
+        //icub handles eyes differently, we have to set pan angle + vergence
+        float pan      = (joint_target[ID_EYES_LEFT_LR] + joint_target[ID_EYES_RIGHT_LR]) / 2;
+        float vergence = (joint_target[ID_EYES_LEFT_LR]  - joint_target[ID_EYES_RIGHT_LR]);
+        //printf("EYEDBG %3.2f %3.2f --_> pan %3.2f verg=%3.2f\n",joint_target[ID_EYES_LEFT_LR], joint_target[ID_EYES_RIGHT_LR],pan,vergence);
+
+        store_joint(ICUB_ID_EYES_PAN, pan);
+        store_joint(ICUB_ID_EYES_VERGENCE, vergence);
+    }else{
+        store_joint(id, joint_target[e]);
+    }
+}
+
+
+//! set the target position of a joint
+//! \param id of joint
+//! \param float value of position
+void iCubJointInterface::store_joint(int id, float value){
+    //printf("> set joint %d = %f\n",id,value);
+    target_angle[id] = value;
+    //ipos->positionMove(id, value);
+}
+
+//! execute a move in position mode
+//! \param id of joint
+//! \param angle
+void iCubJointInterface::set_target_in_positionmode(int id, double value){
+    if (id>ICUB_ID_EYES_VERGENCE){
+        printf("> ERROR: set_target_positionmode(id=%d, %3.2f) not supported for this id\n",id,value);
+        return;
+    }
+#if 0
+    //set speed cacluated as in velocity + set position -> replicates smoothmotion from flobi?!
+
+    //first: calculate necessary speed to reach the given target within the next clock tick:
+    double distance = value - target_angle_previous[id];
+    //make the motion smooth: we want to reach 85% of the target in the next iteration:
+    //calculate speed for that:
+    double speed = 0.85 * distance * ((double)MAIN_LOOP_FREQUENCY);
+
+    //set up speed for controller:
+    ipos->setRefSpeed(id, speed);
+#endif
+    //execute motion
+    ipos->positionMove(id, value);
+}
+
+//! execute a move in velocity mode
+//! \param id of joint
+//! \param angle
+void iCubJointInterface::set_target_in_velocitymode(int id, double value){
+    //first: calculate necessary speed to reach the given target within the next clock tick:
+    double distance = value - target_angle_previous[id];
+    //make the motion smooth: we want to reach 85% of the target in the next iteration:
+    distance = 0.85 * distance;
+    //calculate speed
+    double speed = distance * ((double)MAIN_LOOP_FREQUENCY);
+    //execute:
+    ivel->velocityMove(id, speed);
+    //if (id == ICUB_ID_NECK_PAN) printf("> VEL now=%3.2f target=%3.2f --> dist=%3.2f speed=%3.2f\n",target_angle_previous[id],value,distance,speed);
+
+    target_angle_previous[id] = get_ts_position(convert_motorid_to_enum(id)).get_newest_value();
+}
+
+//! actually execute the scheduled motion commands
+void iCubJointInterface::execute_motion(){
+
+    // set up neck and eye motion commands:
+    if (POSITION_CONTROL){
+        //position control
+        for(int i=ICUB_ID_NECK_TILT; i<=ICUB_ID_EYES_VERGENCE; i++){
+            set_target_in_positionmode(i, target_angle[i]);
+        }
+    }else{
+        //velocity control
+        for(int i=ICUB_ID_NECK_TILT; i<=ICUB_ID_EYES_VERGENCE; i++){
+            set_target_in_velocitymode(i, target_angle[i]);
+        }
+    }
+    //printf("> TARGET PAN = %3.2f\n",target_angle[ICUB_ID_NECK_PAN]);
+
+
+    //eyelids: unfortuantely the icub has only 1dof for eyelids, so we use only one dof here:
+    set_eyelid_angle(target_angle[ICUB_ID_EYES_RIGHT_LID_UPPER]);
+
+    //eyebrows are set using a special command as well:
+    set_eyebrow_angle(ICUB_ID_EYES_LEFT_BROW);
+    set_eyebrow_angle(ICUB_ID_EYES_RIGHT_BROW);
+
+    //mouth
+    set_mouth();
+
+
+}
+
+void iCubJointInterface::set_mouth(){
+    //convert from 6DOF mouth displacement to icub leds:
+    int led_value = 0;
+
+    //fetch center opening:
+    double center_opening = target_angle[ICUB_ID_LIP_CENTER_LOWER] - target_angle[ICUB_ID_LIP_CENTER_UPPER];
+    bool mouth_open = (center_opening>15.0)?true:false;
+
+    //side of mouth high or low?
+    double center_avg = (target_angle[ICUB_ID_LIP_CENTER_LOWER] + target_angle[ICUB_ID_LIP_CENTER_UPPER])/2.0;
+    double left_avg   = (target_angle[ICUB_ID_LIP_LEFT_LOWER] + target_angle[ICUB_ID_LIP_LEFT_UPPER])/2.0;
+    double right_avg  = (target_angle[ICUB_ID_LIP_RIGHT_LOWER] + target_angle[ICUB_ID_LIP_RIGHT_UPPER])/2.0;
+
+    //happy, neutral or sad?
+    double diff_l = center_avg - left_avg;
+    double diff_r = center_avg - right_avg;
+    double diff   = (diff_l+diff_r)/2.0;
+
+    if (diff > 2.0){
+        if (mouth_open){
+            led_value = 0x14;
+        }else{
+            if (diff > 2.6){
+                led_value = 0x0A;
+            }else{
+                led_value = 0x0B;
+            }
+        }
+    }else if (diff < -3.0){
+        if (mouth_open){
+            led_value = 0x06;
+        }else{
+            led_value = 0x18;
+        }
+    }else if (diff < -2.0){
+        if (mouth_open){
+            led_value = 0x04; //0x25;
+        }else{
+            led_value = 0x08;
+        }
+    }else{
+        if (mouth_open){
+            led_value = 0x16;
+        }else{
+            led_value = 0x08;
+        }
+    }
+
+
+    if (led_value == previous_mouth_state){
+        //no update necessary
+        return;
+    }
+
+    previous_mouth_state = led_value;
+
+    //convert to string:
+    char buf[10];
+    sprintf(buf, "M%02X",led_value);
+
+    /*printf("> sending mouth '%s'\n",buf);
+    printf("> mouth angles: %3.2f %3.2f %3.2f\n",target_angle[ICUB_ID_LIP_LEFT_UPPER],target_angle[ICUB_ID_LIP_CENTER_UPPER],target_angle[ICUB_ID_LIP_RIGHT_UPPER]);
+    printf("  mouth         %3.2f %3.2f %3.2f\n",target_angle[ICUB_ID_LIP_LEFT_LOWER],target_angle[ICUB_ID_LIP_CENTER_LOWER],target_angle[ICUB_ID_LIP_RIGHT_LOWER]);
+    printf("  mouth  open=%3.2f diff=%3.2f\n", center_opening, diff);*/
+
+    //add mouth:
+    Bottle &cmd = emotion_port[3].prepare();
+    cmd.clear();
+    cmd.addString(buf);
+    emotion_port[3].write();
+
+
+    //store joint values which we do not handle on icub here:
+    double timestamp = get_timestamp_ms();
+    JointInterface::store_incoming_position(ID_LIP_LEFT_UPPER,   target_angle[ICUB_ID_LIP_LEFT_UPPER], timestamp);
+    JointInterface::store_incoming_position(ID_LIP_LEFT_LOWER,   target_angle[ICUB_ID_LIP_LEFT_LOWER], timestamp);
+    JointInterface::store_incoming_position(ID_LIP_CENTER_UPPER, target_angle[ICUB_ID_LIP_CENTER_UPPER], timestamp);
+    JointInterface::store_incoming_position(ID_LIP_CENTER_LOWER, target_angle[ICUB_ID_LIP_CENTER_LOWER], timestamp);
+    JointInterface::store_incoming_position(ID_LIP_RIGHT_UPPER,  target_angle[ICUB_ID_LIP_RIGHT_UPPER], timestamp);
+    JointInterface::store_incoming_position(ID_LIP_RIGHT_LOWER,  target_angle[ICUB_ID_LIP_RIGHT_LOWER], timestamp);
+
+}
+
+double iCubJointInterface::get_timestamp_ms(){
+    struct timespec spec;
+    clock_gettime(CLOCK_REALTIME, &spec);
+    return spec.tv_sec*1000 + spec.tv_nsec / 1.0e6;
+}
+
+//! set the current position of a joint
+//! \param id of joint
+//! \param float value of position
+//! \param double timestamp
+void iCubJointInterface::fetch_position(int id, double value, double timestamp){
+    //store joint based on id:
+    switch(id){
+        default:
+            printf("> ERROR: unhandled joint id %d\n",id);
+            return;
+
+        case(100):
+            JointInterface::store_incoming_position(ID_EYES_RIGHT_LID_UPPER, lid_angle, timestamp);
+            break;
+
+        case(2):
+            //PAN is inverted!
+            JointInterface::store_incoming_position(ID_NECK_PAN, -value, timestamp);
+            break;
+
+        case(0):
+            JointInterface::store_incoming_position(ID_NECK_TILT, value, timestamp);
+            break;
+
+        case(1):
+            JointInterface::store_incoming_position(ID_NECK_ROLL, value, timestamp);
+            break;
+
+        case(3):
+            JointInterface::store_incoming_position(ID_EYES_BOTH_UD, value, timestamp);
+            break;
+
+        //icub handles eyes differently, we have to set pan angle + vergence
+        case(4): {//pan
+            last_pos_eye_pan = value;
+            float left  = last_pos_eye_pan + last_pos_eye_vergence/2.0;
+            float right = last_pos_eye_pan - last_pos_eye_vergence/2.0;
+
+            //printf("> eye: pan=%3.2f vergence=%3.2f --> L=%3.2f R=%3.2f\n", last_pos_eye_pan, last_pos_eye_vergence, left, right);
+            JointInterface::store_incoming_position(ID_EYES_LEFT_LR, left, timestamp);
+            JointInterface::store_incoming_position(ID_EYES_RIGHT_LR, right, timestamp);
+            break;
+        }
+
+        case(5): { //vergence
+            last_pos_eye_vergence = value;
+            float left  = last_pos_eye_pan + last_pos_eye_vergence/2.0;
+            float right = last_pos_eye_pan - last_pos_eye_vergence/2.0;
+
+            //printf("> eye: pan=%3.2f vergence=%3.2f --> L=%3.2f R=%3.2f\n", last_pos_eye_pan, last_pos_eye_vergence, left, right);
+            JointInterface::store_incoming_position(ID_EYES_LEFT_LR, left, timestamp);
+            JointInterface::store_incoming_position(ID_EYES_RIGHT_LR, right, timestamp);
+            break;
+        }
+    }
+
+
+}
+
+//! set the current speed of a joint
+//! \param enum id of joint
+//! \param float value of speed
+//! \param double timestamp
+void iCubJointInterface::fetch_speed(int id, double value, double timestamp){
+
+    switch(id){
+        default:
+            printf("> ERROR: unhandled joint id %d\n",id);
+            return;
+
+        case(2):
+            JointInterface::store_incoming_speed(ID_NECK_PAN, value, timestamp);
+            break;
+
+        case(0):
+            JointInterface::store_incoming_speed(ID_NECK_TILT, value, timestamp);
+            break;
+
+        case(1):
+            JointInterface::store_incoming_speed(ID_NECK_ROLL, value, timestamp);
+            break;
+
+        case(3):
+            JointInterface::store_incoming_speed(ID_EYES_BOTH_UD, value, timestamp);
+            break;
+
+        //icub handles eyes differently, we have to set pan angle + vergence
+        case(4): {//pan
+            last_vel_eye_pan = value;
+            float left  = last_vel_eye_pan + last_vel_eye_vergence/2.0;
+            float right = last_vel_eye_pan - last_vel_eye_vergence/2.0;
+
+            //printf("> eye: velocity pan=%3.2f vergence=%3.2f --> L=%3.2f R=%3.2f\n", last_vel_eye_pan, last_vel_eye_vergence, left, right);
+            JointInterface::store_incoming_speed(ID_EYES_LEFT_LR, left, timestamp);
+            JointInterface::store_incoming_speed(ID_EYES_RIGHT_LR, right, timestamp);
+            break;
+        }
+
+        case(5): { //vergence
+            last_vel_eye_pan = value;
+            float left  = last_vel_eye_pan + last_vel_eye_vergence/2.0;
+            float right = last_vel_eye_pan - last_vel_eye_vergence/2.0;
+
+            //printf("> eye: velocity pan=%3.2f vergence=%3.2f --> L=%3.2f R=%3.2f\n", last_vel_eye_pan, last_vel_eye_vergence, left, right);
+            JointInterface::store_incoming_speed(ID_EYES_LEFT_LR, left, timestamp);
+            JointInterface::store_incoming_speed(ID_EYES_RIGHT_LR, right, timestamp);
+            break;
+        }
+    }
+/*
+    JointInterface::store_incoming_speed(ID_LIP_LEFT_UPPER, 0.0, timestamp);
+    JointInterface::store_incoming_speed(ID_LIP_LEFT_LOWER, 0.0, timestamp);
+    JointInterface::store_incoming_speed(ID_LIP_CENTER_UPPER, 0.0, timestamp);
+    JointInterface::store_incoming_speed(ID_LIP_CENTER_LOWER, 0.0, timestamp);
+    JointInterface::store_incoming_speed(ID_LIP_RIGHT_UPPER, 0.0, timestamp);
+    JointInterface::store_incoming_speed(ID_LIP_RIGHT_LOWER, 0.0, timestamp);
+
+    JointInterface::store_incoming_speed(ID_EYES_LEFT_LID_LOWER, 0.0, timestamp);
+    JointInterface::store_incoming_speed(ID_EYES_LEFT_LID_UPPER, 0.0, timestamp);
+    JointInterface::store_incoming_speed(ID_EYES_LEFT_BROW, 0.0, timestamp);
+
+    JointInterface::store_incoming_speed(ID_EYES_RIGHT_LID_LOWER, 0.0, timestamp);
+    JointInterface::store_incoming_speed(ID_EYES_RIGHT_LID_UPPER,0.0, timestamp);
+    JointInterface::store_incoming_speed(ID_EYES_RIGHT_BROW, 0.0, timestamp);*/
+    /*
+    //fetch enum id:
+    int e = convert_motorid_to_enum(device->get_device_id());
+    if (e == -1){
+        return; //we are not interested in that data, so we just return here
+    }
+
+    JointInterface::store_incoming_speed(e, device->get_register(XSC3_REGISTER_MOTORSPEED), timestamp);*/
+
+}
+/*
+//! conversion table for humotion motor ids to our ids:
+//! \param enum from JointInterface::JOINT_ID_ENUM
+//! \return int value of motor id
+int HumotionJointInterface::convert_enum_to_motorid(int e){
+    enum_id_bimap_t::right_const_iterator it = enum_id_bimap.right.find(e);
+    if(it == enum_id_bimap.right.end()) {
+        //key does not exists, we are not interested in that dataset, return -1
+        return -1;
+    }
+
+    return it->second;
+}
+
+
+//! conversion table for our ids to humotion motor ids:
+//! \param  int value of motor id
+//! \return enum from JointInterface::JOINT_ID_ENUM
+int HumotionJointInterface::convert_motorid_to_enum(int id){
+    enum_id_bimap_t::left_const_iterator it = enum_id_bimap.left.find(id);
+    if(it == enum_id_bimap.left.end()) {
+        //key does not exists, we are not interested in that dataset, return -1
+        return -1;
+    }
+
+    return it->second;
+}
+*/
+
+//! prepare and enable a joint
+//! NOTE: this should also prefill the min/max positions for this joint
+//! \param the enum id of a joint
+void iCubJointInterface::enable_joint(int e){
+    //FIXME ADD THIS:
+    // enable the amplifier and the pid controller on each joint
+    /*for (i = 0; i < nj; i++) {
+       amp->enableAmp(i);
+       pid->enablePid(i);
+    }*/
+
+
+    //set up smooth motion controller
+    //step1: set up framerate
+    //dev->set_register_blocking(XSC3_REGISTER_PID_RAMP, framerate, true);
+
+    //step2: set controllertype:
+    //printf("> activating smooth motion control for joint id 0x%02X (%s)\n", motor_id, joint_name.c_str());
+    //dev->set_register_blocking(XSC3_REGISTER_PID_CONTROLLER, XSC3_PROTOCOL_PID_CONTROLLERTYPE_SMOOTH_PLAYBACK, true);
+
+    //step3: set pid controller:
+    /*if ((e == ID_LIP_LEFT_UPPER) || (e == ID_LIP_LEFT_LOWER) || (e == ID_LIP_CENTER_UPPER) || (e == ID_LIP_CENTER_LOWER) || (e == ID_LIP_RIGHT_UPPER) || (e == ID_LIP_RIGHT_LOWER)){
+        printf("> fixing PID i controller value for smooth motion (FIXME: restore old value!!)\n");
+        dev->set_register_blocking(XSC3_REGISTER_CONST_I, 10, true);
+    }*/
+
+    //uint16_t result = dev->get_register_blocking_raw(XSC3_REGISTER_PID_CONTROLLER);
+
+    //check if setting pid controllertype was successfull:
+    /*if (result != XSC3_PROTOCOL_PID_CONTROLLERTYPE_SMOOTH_PLAYBACK){
+        printf("> failed to set smooth motion controller for joint %s (res=0x%04X)\n",joint_name.c_str(),result);
+        exit(1);
+    }*/
+
+    //fetch min/max:
+   // init_joint(e);
+
+    //ok fine, now enable motor:
+    //printf("> enabling motor %s\n", joint_name.c_str());
+    //dev->set_register_blocking(XSC3_REGISTER_STATUS, XSC3_PROTOCOL_STATUS_BITMASK_MOTOR_ENABLE, true);
+
+}
+
+void iCubJointInterface::store_min_max(IControlLimits *ilimits, int id, int e){
+    double min, max;
+    ilimits->getLimits(id, &min, &max);
+    joint_min[e] = min;
+    joint_max[e] = max;
+}
+
+//! initialise a joint (set up controller mode etc)
+//! \param joint enum
+void iCubJointInterface::init_joints(){
+    store_min_max(ilimits, 0, ID_NECK_TILT);
+    store_min_max(ilimits, 1, ID_NECK_ROLL);
+    store_min_max(ilimits, 2, ID_NECK_PAN);
+    store_min_max(ilimits, 3, ID_EYES_BOTH_UD);
+
+    //icub handles eyes differently, we have to set pan angle + vergence
+    double pan_min, pan_max, vergence_min, vergence_max;
+    ilimits->getLimits(4, &pan_min, &pan_max);
+    ilimits->getLimits(5, &vergence_min, &vergence_max);
+
+    //this is not 100% correct, should be fixed:
+    joint_min[ID_EYES_LEFT_LR] = pan_min; // - vergence_max/2;
+    joint_max[ID_EYES_LEFT_LR] = pan_max; // - vergence_max/2;
+    joint_min[ID_EYES_RIGHT_LR] = joint_min[ID_EYES_LEFT_LR];
+    joint_max[ID_EYES_RIGHT_LR] = joint_max[ID_EYES_LEFT_LR];
+
+    //eyelids:
+    joint_min[ID_EYES_RIGHT_LID_UPPER] = -50; //24-30;
+    joint_max[ID_EYES_RIGHT_LID_UPPER] = 50; //48-30;
+    lid_angle = joint_max[ID_EYES_RIGHT_LID_UPPER];
+
+    //eyebrows:
+    joint_min[ID_EYES_LEFT_BROW] = -50;
+    joint_max[ID_EYES_LEFT_BROW] = 50;
+    joint_min[ID_EYES_RIGHT_BROW] = joint_min[ID_EYES_LEFT_BROW];
+    joint_max[ID_EYES_RIGHT_BROW] = joint_max[ID_EYES_LEFT_BROW];
+
+    //mouth:
+    joint_min[ID_LIP_CENTER_UPPER] = 5;
+    joint_max[ID_LIP_CENTER_UPPER] = 50;
+    joint_min[ID_LIP_CENTER_LOWER] = 5;
+    joint_max[ID_LIP_CENTER_LOWER] = 50;
+    joint_min[ID_LIP_LEFT_UPPER] = 5;
+    joint_max[ID_LIP_LEFT_UPPER] = 50;
+    joint_min[ID_LIP_LEFT_LOWER] = 5;
+    joint_max[ID_LIP_LEFT_LOWER] = 50;
+    joint_min[ID_LIP_RIGHT_UPPER] = 5;
+    joint_max[ID_LIP_RIGHT_UPPER] = 50;
+    joint_min[ID_LIP_RIGHT_LOWER] = 5;
+    joint_max[ID_LIP_RIGHT_LOWER] = 50;
+
+
+}
+
+//! shutdown and disable a joint
+//! \param the enum id of a joint
+void iCubJointInterface::disable_joint(int e){
+    /*
+        //first: convert humotion enum to our enum:
+        int motor_id = convert_enum_to_motorid(e);
+        if (motor_id == -1){
+            return; //we are not interested in that data, so we just return here
+        }
+
+        //fetch device:
+        Device *dev = get_device(motor_id);
+        printf("> FIXME: ADD DISABLE CODE\n");
+        printf("> FIXME: ADD DISABLE CODE\n");
+        printf("> FIXME: ADD DISABLE CODE\n");
+        printf("> FIXME: ADD DISABLE CODE\n");
+        printf("> FIXME: ADD DISABLE CODE\n");
+        printf("> FIXME: ADD DISABLE CODE\n");
+        printf("> FIXME: ADD DISABLE CODE\n");
+        printf("> FIXME: ADD DISABLE CODE\n");
+        printf("> FIXME: ADD DISABLE CODE\n");
+        */
+}
diff --git a/examples/yarp_icub/src/main.cpp b/examples/yarp_icub/src/main.cpp
new file mode 100644
index 0000000..f2d373f
--- /dev/null
+++ b/examples/yarp_icub/src/main.cpp
@@ -0,0 +1,55 @@
+#include <stdio.h>
+#include <yarp/os/Network.h>
+#include <yarp/dev/ControlBoardInterfaces.h>
+#include <yarp/dev/PolyDriver.h>
+#include <yarp/os/Time.h>
+#include <yarp/sig/Vector.h>
+#include "icub_jointinterface.h"
+#include <humotion/server/server.h>
+#include <yarp/os/Network.h>
+#include <yarp/os/RateThread.h>
+#include <yarp/os/Time.h>
+#include <yarp/os/Property.h>
+#include <yarp/dev/ControlBoardInterfaces.h>
+#include <string>
+#include <iostream>
+#include <icub_data_receiver.h>
+
+
+using namespace yarp::dev;
+using namespace yarp::sig;
+using namespace yarp::os;
+using namespace std;
+
+
+int main(int argc, char *argv[]){
+    Network yarp;
+
+    if (!yarp.checkNetwork()){
+        printf("No yarp network, quitting\n");
+        return false;
+    }
+
+    Property params;
+    params.fromCommand(argc, argv);
+
+    if (!params.check("robot")){
+        fprintf(stderr, "Please specify the name of the robot\n");
+        fprintf(stderr, "--robot name (e.g. icub or icubSim)\n");
+        return -1;
+    }
+
+    string robotName=params.find("robot").asString().c_str();
+    string scope="/"+robotName;
+
+
+    //create humotion interface
+    iCubJointInterface *icub_jointinterface = new iCubJointInterface(scope);
+    humotion::server::Server *humotion_server = new humotion::server::Server("/icub", "RSB", icub_jointinterface);
+    icub_jointinterface->run();
+
+    while(humotion_server->ok()){
+        usleep(100000);
+    }
+    return 0;
+}
diff --git a/include/client/client.h b/include/client/client.h
new file mode 100644
index 0000000..70febc4
--- /dev/null
+++ b/include/client/client.h
@@ -0,0 +1,56 @@
+/*
+* This file is part of humotion
+*
+* Copyright(c) sschulz <AT> techfak.uni-bielefeld.de
+* http://opensource.cit-ec.de/projects/humotion
+*
+* This file may be licensed under the terms of the
+* GNU Lesser General Public License Version 3 (the ``LGPL''),
+* or (at your option) any later version.
+*
+* Software distributed under the License is distributed
+* on an ``AS IS'' basis, WITHOUT WARRANTY OF ANY KIND, either
+* express or implied. See the LGPL for the specific language
+* governing rights and limitations.
+*
+* You should have received a copy of the LGPL along with this
+* program. If not, go to http://www.gnu.org/licenses/lgpl.html
+* or write to the Free Software Foundation, Inc.,
+* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+*
+* The development of this software was supported by the
+* Excellence Cluster EXC 277 Cognitive Interaction Technology.
+* The Excellence Cluster EXC 277 is a grant of the Deutsche
+* Forschungsgemeinschaft (DFG) in the context of the German
+* Excellence Initiative.
+*/
+
+#pragma once
+#include "middleware.h"
+#include <cstdio>
+#include <cstdint>
+#include <string>
+
+namespace humotion{
+namespace client{
+
+class Client{
+public:
+    Client(std::string name, std::string mw);
+	~Client();
+
+    bool ok();
+    void tick();
+
+    void update_mouth_target(MouthState s, bool send=false);
+    void update_gaze_target(GazeState s, bool send=false);
+
+    void send_all();
+
+
+private:
+    Middleware *middleware;
+};
+
+}
+}
diff --git a/include/client/middleware.h b/include/client/middleware.h
new file mode 100644
index 0000000..33b7167
--- /dev/null
+++ b/include/client/middleware.h
@@ -0,0 +1,60 @@
+/*
+* This file is part of humotion
+*
+* Copyright(c) sschulz <AT> techfak.uni-bielefeld.de
+* http://opensource.cit-ec.de/projects/humotion
+*
+* This file may be licensed under the terms of the
+* GNU Lesser General Public License Version 3 (the ``LGPL''),
+* or (at your option) any later version.
+*
+* Software distributed under the License is distributed
+* on an ``AS IS'' basis, WITHOUT WARRANTY OF ANY KIND, either
+* express or implied. See the LGPL for the specific language
+* governing rights and limitations.
+*
+* You should have received a copy of the LGPL along with this
+* program. If not, go to http://www.gnu.org/licenses/lgpl.html
+* or write to the Free Software Foundation, Inc.,
+* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+*
+* The development of this software was supported by the
+* Excellence Cluster EXC 277 Cognitive Interaction Technology.
+* The Excellence Cluster EXC 277 is a grant of the Deutsche
+* Forschungsgemeinschaft (DFG) in the context of the German
+* Excellence Initiative.
+*/
+
+#pragma once
+#include <cstdio>
+#include <cstdint>
+#include <string>
+#include "../mouth_state.h"
+#include "../gaze_state.h"
+
+namespace humotion{
+namespace client{
+
+
+class Middleware{
+public:
+    Middleware(std::string name);
+    ~Middleware();
+
+    void update_mouth_target(MouthState s, bool send);
+    void update_gaze_target(GazeState s, bool send);
+    void send_all();
+
+    virtual void send_mouth_target() = 0;
+    virtual void send_gaze_target() = 0;
+    virtual bool ok() = 0;
+    virtual void tick() = 0;
+
+protected:
+	MouthState mouth_state;
+    GazeState gaze_state;
+    std::string base_scope;
+};
+
+}
+}
diff --git a/include/client/middleware_ros.h b/include/client/middleware_ros.h
new file mode 100644
index 0000000..f294226
--- /dev/null
+++ b/include/client/middleware_ros.h
@@ -0,0 +1,71 @@
+#pragma once
+#include "middleware.h"
+#ifdef ROS_SUPPORT
+    #include "ros/ros.h"
+#endif
+#include <boost/shared_ptr.hpp>
+/*
+* This file is part of humotion
+*
+* Copyright(c) sschulz <AT> techfak.uni-bielefeld.de
+* http://opensource.cit-ec.de/projects/humotion
+*
+* This file may be licensed under the terms of the
+* GNU Lesser General Public License Version 3 (the ``LGPL''),
+* or (at your option) any later version.
+*
+* Software distributed under the License is distributed
+* on an ``AS IS'' basis, WITHOUT WARRANTY OF ANY KIND, either
+* express or implied. See the LGPL for the specific language
+* governing rights and limitations.
+*
+* You should have received a copy of the LGPL along with this
+* program. If not, go to http://www.gnu.org/licenses/lgpl.html
+* or write to the Free Software Foundation, Inc.,
+* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+*
+* The development of this software was supported by the
+* Excellence Cluster EXC 277 Cognitive Interaction Technology.
+* The Excellence Cluster EXC 277 is a grant of the Deutsche
+* Forschungsgemeinschaft (DFG) in the context of the German
+* Excellence Initiative.
+*/
+
+namespace humotion{
+namespace client{
+
+class MiddlewareROS : public Middleware{
+#ifndef ROS_SUPPORT
+public:
+    MiddlewareROS(std::string name) : Middleware(name){
+        printf("> ERROR: humotion was compiled without ROS middleware support. Please use MiddlewareRSB() instead!\n\n");
+        exit(EXIT_FAILURE);
+    }
+
+    ~MiddlewareROS(){}
+    void send_mouth_target(){};
+    void send_gaze_target(){};
+    bool ok(){ return false; }
+    void tick(){}
+
+#else
+public:
+    MiddlewareROS(std::string name);
+    ~MiddlewareROS();
+
+    void send_mouth_target();
+    void send_gaze_target();
+    bool ok();
+    void tick();
+
+
+private:
+    bool tick_necessary;
+    //boost::shared_ptr<ros::NodeHandle> node_handle;
+    ros::Publisher mouth_target_publisher;
+    ros::Publisher gaze_target_publisher;
+#endif
+};
+
+}
+}
diff --git a/include/client/middleware_rsb.h b/include/client/middleware_rsb.h
new file mode 100644
index 0000000..ecba9c4
--- /dev/null
+++ b/include/client/middleware_rsb.h
@@ -0,0 +1,75 @@
+/*
+* This file is part of humotion
+*
+* Copyright(c) sschulz <AT> techfak.uni-bielefeld.de
+* http://opensource.cit-ec.de/projects/humotion
+*
+* This file may be licensed under the terms of the
+* GNU Lesser General Public License Version 3 (the ``LGPL''),
+* or (at your option) any later version.
+*
+* Software distributed under the License is distributed
+* on an ``AS IS'' basis, WITHOUT WARRANTY OF ANY KIND, either
+* express or implied. See the LGPL for the specific language
+* governing rights and limitations.
+*
+* You should have received a copy of the LGPL along with this
+* program. If not, go to http://www.gnu.org/licenses/lgpl.html
+* or write to the Free Software Foundation, Inc.,
+* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+*
+* The development of this software was supported by the
+* Excellence Cluster EXC 277 Cognitive Interaction Technology.
+* The Excellence Cluster EXC 277 is a grant of the Deutsche
+* Forschungsgemeinschaft (DFG) in the context of the German
+* Excellence Initiative.
+*/
+
+#pragma once
+#include "middleware.h"
+
+#ifdef RSB_SUPPORT
+    #define BOOST_SIGNALS_NO_DEPRECATION_WARNING 1
+    #include <rsb/Informer.h>
+    #include <rst/robot/HumotionGazeTarget.pb.h>
+    #include <rst/robot/MouthTarget.pb.h>
+#endif
+
+
+namespace humotion{
+namespace client{
+
+class MiddlewareRSB : public Middleware{
+
+#ifndef RSB_SUPPORT
+public:
+    MiddlewareRSB(std::string name){
+        printf("> ERROR: humotion was compiled without RSB middleware support. Please use MiddlewareROS() instead!\n\n");
+        exit(EXIT_FAILURE);
+    }
+
+    ~MiddlewareRSB(){}
+    bool ok(){ return false; }
+    void tick(){}
+    void send_mouth_target(){};
+    void send_gaze_target(){};
+
+#else
+public:
+    MiddlewareRSB(std::string name);
+    ~MiddlewareRSB();
+
+    void send_mouth_target();
+    void send_gaze_target();
+    bool ok();
+    void tick();
+
+
+private:
+    rsb::Informer<rst::robot::MouthTarget>::Ptr mouth_target_informer;
+    rsb::Informer<rst::robot::HumotionGazeTarget>::Ptr gaze_target_informer;
+#endif
+};
+
+}
+}
diff --git a/include/gaze_state.h b/include/gaze_state.h
new file mode 100644
index 0000000..0458ba1
--- /dev/null
+++ b/include/gaze_state.h
@@ -0,0 +1,94 @@
+/*
+* This file is part of humotion
+*
+* Copyright(c) sschulz <AT> techfak.uni-bielefeld.de
+* http://opensource.cit-ec.de/projects/humotion
+*
+* This file may be licensed under the terms of the
+* GNU Lesser General Public License Version 3 (the ``LGPL''),
+* or (at your option) any later version.
+*
+* Software distributed under the License is distributed
+* on an ``AS IS'' basis, WITHOUT WARRANTY OF ANY KIND, either
+* express or implied. See the LGPL for the specific language
+* governing rights and limitations.
+*
+* You should have received a copy of the LGPL along with this
+* program. If not, go to http://www.gnu.org/licenses/lgpl.html
+* or write to the Free Software Foundation, Inc.,
+* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+*
+* The development of this software was supported by the
+* Excellence Cluster EXC 277 Cognitive Interaction Technology.
+* The Excellence Cluster EXC 277 is a grant of the Deutsche
+* Forschungsgemeinschaft (DFG) in the context of the German
+* Excellence Initiative.
+*/
+
+#pragma once
+#include <math.h>
+
+namespace humotion{
+class GazeState{
+public:
+        GazeState();
+        ~GazeState();
+
+        void dump();
+
+        //pan tilt roll
+        float pan;
+        float tilt;
+        float roll;
+
+        float pan_offset;
+        float tilt_offset;
+        float roll_offset;
+
+        //pan,tilt,roll can be relative or absolute
+        int type;
+
+        //when was this target requested?
+        double timestamp;
+
+        //is this relative or
+        enum GAZE_STATE_TYPE{
+            ABSOLUTE=0,
+            RELATIVE=1,
+            OVERRIDE=2
+        };
+
+        //
+        float vergence;
+
+        //eyelid opening angle
+        float eyelid_opening_upper;
+        float eyelid_opening_lower;
+
+        //eyebrow angles
+        float eyebrow_left;
+        float eyebrow_right;
+
+        //eyeblink request
+        int eyeblink_request_left;
+        int eyeblink_request_right;
+        static const int EYEBLINK_TIME_DEFAULT = 150; //ms
+
+        float distance_pt_abs(GazeState b){
+            float dist_pan = (b.pan + b.pan_offset) - (pan + pan_offset);
+            float dist_tilt = (b.tilt + b.tilt_offset) - (tilt + tilt_offset);
+            return sqrt(pow(dist_pan, 2.0) + pow(dist_tilt, 2.0));
+        }
+
+        float distance_tilt_abs(GazeState b){
+            float dist_tilt = (b.tilt + b.tilt_offset) - (tilt + tilt_offset);
+            return fabs(dist_tilt);
+        }
+
+        float distance_pan_abs(GazeState b){
+            float dist_pan = (b.pan + b.pan_offset) - (pan + pan_offset);
+            return fabs(dist_pan);
+        }
+};
+
+}
diff --git a/include/mouth_state.h b/include/mouth_state.h
new file mode 100644
index 0000000..8c8d501
--- /dev/null
+++ b/include/mouth_state.h
@@ -0,0 +1,49 @@
+/*
+* This file is part of humotion
+*
+* Copyright(c) sschulz <AT> techfak.uni-bielefeld.de
+* http://opensource.cit-ec.de/projects/humotion
+*
+* This file may be licensed under the terms of the
+* GNU Lesser General Public License Version 3 (the ``LGPL''),
+* or (at your option) any later version.
+*
+* Software distributed under the License is distributed
+* on an ``AS IS'' basis, WITHOUT WARRANTY OF ANY KIND, either
+* express or implied. See the LGPL for the specific language
+* governing rights and limitations.
+*
+* You should have received a copy of the LGPL along with this
+* program. If not, go to http://www.gnu.org/licenses/lgpl.html
+* or write to the Free Software Foundation, Inc.,
+* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+*
+* The development of this software was supported by the
+* Excellence Cluster EXC 277 Cognitive Interaction Technology.
+* The Excellence Cluster EXC 277 is a grant of the Deutsche
+* Forschungsgemeinschaft (DFG) in the context of the German
+* Excellence Initiative.
+*/
+
+#pragma once
+#include <string>
+
+namespace humotion{
+class MouthState{
+public:
+        MouthState();
+        ~MouthState();
+
+        void dump();
+
+        float opening_left;
+        float opening_center;
+        float opening_right;
+
+        float position_left;
+        float position_center;
+        float position_right;
+
+};
+
+}
diff --git a/include/server/controller.h b/include/server/controller.h
new file mode 100644
index 0000000..3846098
--- /dev/null
+++ b/include/server/controller.h
@@ -0,0 +1,61 @@
+/*
+* This file is part of humotion
+*
+* Copyright(c) sschulz <AT> techfak.uni-bielefeld.de
+* http://opensource.cit-ec.de/projects/humotion
+*
+* This file may be licensed under the terms of the
+* GNU Lesser General Public License Version 3 (the ``LGPL''),
+* or (at your option) any later version.
+*
+* Software distributed under the License is distributed
+* on an ``AS IS'' basis, WITHOUT WARRANTY OF ANY KIND, either
+* express or implied. See the LGPL for the specific language
+* governing rights and limitations.
+*
+* You should have received a copy of the LGPL along with this
+* program. If not, go to http://www.gnu.org/licenses/lgpl.html
+* or write to the Free Software Foundation, Inc.,
+* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+*
+* The development of this software was supported by the
+* Excellence Cluster EXC 277 Cognitive Interaction Technology.
+* The Excellence Cluster EXC 277 is a grant of the Deutsche
+* Forschungsgemeinschaft (DFG) in the context of the German
+* Excellence Initiative.
+*/
+
+#pragma once
+#include "../gaze_state.h"
+#include "../mouth_state.h"
+#include "motion_generator.h"
+#include "joint_interface.h"
+
+namespace humotion{
+namespace server{
+
+class Controller{
+public:
+    Controller(JointInterface *j);
+    ~Controller();
+
+    void init_motion_generators();
+    void calculate_targets();
+    void publish_targets();
+
+
+    void set_gaze_target(GazeState s);
+    void set_mouth_target(MouthState s);
+
+private:
+    void add_motion_generator(MotionGenerator *m);
+
+    typedef std::vector<MotionGenerator *> motion_generator_vector_t;
+    motion_generator_vector_t motion_generator_vector;
+    JointInterface *joint_interface;
+
+
+};
+
+}
+}
diff --git a/include/server/eye_motion_generator.h b/include/server/eye_motion_generator.h
new file mode 100644
index 0000000..7b38638
--- /dev/null
+++ b/include/server/eye_motion_generator.h
@@ -0,0 +1,55 @@
+/*
+* This file is part of humotion
+*
+* Copyright(c) sschulz <AT> techfak.uni-bielefeld.de
+* http://opensource.cit-ec.de/projects/humotion
+*
+* This file may be licensed under the terms of the
+* GNU Lesser General Public License Version 3 (the ``LGPL''),
+* or (at your option) any later version.
+*
+* Software distributed under the License is distributed
+* on an ``AS IS'' basis, WITHOUT WARRANTY OF ANY KIND, either
+* express or implied. See the LGPL for the specific language
+* governing rights and limitations.
+*
+* You should have received a copy of the LGPL along with this
+* program. If not, go to http://www.gnu.org/licenses/lgpl.html
+* or write to the Free Software Foundation, Inc.,
+* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+*
+* The development of this software was supported by the
+* Excellence Cluster EXC 277 Cognitive Interaction Technology.
+* The Excellence Cluster EXC 277 is a grant of the Deutsche
+* Forschungsgemeinschaft (DFG) in the context of the German
+* Excellence Initiative.
+*/
+
+#pragma once
+#include "gaze_motion_generator.h"
+#include "timestamped_list.h"
+
+namespace humotion{
+namespace server{
+
+class EyeMotionGenerator : public GazeMotionGenerator{
+public:
+    EyeMotionGenerator(JointInterface *j);
+    ~EyeMotionGenerator();
+
+    void calculate_targets();
+    void publish_targets();
+
+
+    static const float SACCADE_SPEED_THRESHOLD;
+private:
+    void setup_eyemotion(int dof, float target, float now);
+
+    TimestampedList tsl_gaze_target_pan;
+    TimestampedList tsl_gaze_target_tilt;
+    TimestampedList tsl_gaze_target_vergence;
+
+};
+
+}
+}
diff --git a/include/server/eyebrow_motion_generator.h b/include/server/eyebrow_motion_generator.h
new file mode 100644
index 0000000..5fff08c
--- /dev/null
+++ b/include/server/eyebrow_motion_generator.h
@@ -0,0 +1,45 @@
+/*
+* This file is part of humotion
+*
+* Copyright(c) sschulz <AT> techfak.uni-bielefeld.de
+* http://opensource.cit-ec.de/projects/humotion
+*
+* This file may be licensed under the terms of the
+* GNU Lesser General Public License Version 3 (the ``LGPL''),
+* or (at your option) any later version.
+*
+* Software distributed under the License is distributed
+* on an ``AS IS'' basis, WITHOUT WARRANTY OF ANY KIND, either
+* express or implied. See the LGPL for the specific language
+* governing rights and limitations.
+*
+* You should have received a copy of the LGPL along with this
+* program. If not, go to http://www.gnu.org/licenses/lgpl.html
+* or write to the Free Software Foundation, Inc.,
+* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+*
+* The development of this software was supported by the
+* Excellence Cluster EXC 277 Cognitive Interaction Technology.
+* The Excellence Cluster EXC 277 is a grant of the Deutsche
+* Forschungsgemeinschaft (DFG) in the context of the German
+* Excellence Initiative.
+*/
+
+#pragma once
+#include "motion_generator.h"
+
+namespace humotion{
+namespace server{
+
+class EyebrowMotionGenerator : public MotionGenerator{
+public:
+    EyebrowMotionGenerator(JointInterface *j);
+    ~EyebrowMotionGenerator();
+    void calculate_targets();
+    void publish_targets();
+private:
+
+};
+
+}
+}
diff --git a/include/server/eyelid_motion_generator.h b/include/server/eyelid_motion_generator.h
new file mode 100644
index 0000000..e3db8fa
--- /dev/null
+++ b/include/server/eyelid_motion_generator.h
@@ -0,0 +1,82 @@
+/*
+* This file is part of humotion
+*
+* Copyright(c) sschulz <AT> techfak.uni-bielefeld.de
+* http://opensource.cit-ec.de/projects/humotion
+*
+* This file may be licensed under the terms of the
+* GNU Lesser General Public License Version 3 (the ``LGPL''),
+* or (at your option) any later version.
+*
+* Software distributed under the License is distributed
+* on an ``AS IS'' basis, WITHOUT WARRANTY OF ANY KIND, either
+* express or implied. See the LGPL for the specific language
+* governing rights and limitations.
+*
+* You should have received a copy of the LGPL along with this
+* program. If not, go to http://www.gnu.org/licenses/lgpl.html
+* or write to the Free Software Foundation, Inc.,
+* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+*
+* The development of this software was supported by the
+* Excellence Cluster EXC 277 Cognitive Interaction Technology.
+* The Excellence Cluster EXC 277 is a grant of the Deutsche
+* Forschungsgemeinschaft (DFG) in the context of the German
+* Excellence Initiative.
+*/
+
+#pragma once
+#include "eye_motion_generator.h"
+#include "boost/date_time/posix_time/posix_time.hpp"
+#include <boost/thread/thread_time.hpp>
+
+namespace humotion{
+namespace server{
+
+class EyelidMotionGenerator : public EyeMotionGenerator{
+public:
+    EyelidMotionGenerator(JointInterface *j);
+    ~EyelidMotionGenerator();
+
+    void calculate_targets();
+    void publish_targets();
+
+
+
+private:
+    bool saccade_blink_active;
+    bool saccade_blink_requested;
+
+    enum SIDE_ID{
+        LEFT = 0,
+        RIGHT,
+        SIDE_ID_SIZE
+    };
+
+    bool eyeblink_active[SIDE_ID_SIZE];
+    bool eyelid_closed[SIDE_ID_SIZE];
+
+    void start_external_eyeblinks(int duration_left, int duration_right);
+    void process_saccadic_eyeblinks();
+    void process_periodic_eyeblinks();
+    void handle_eyeblink_timeout();
+    void override_lids_for_eyeblink();
+    void check_for_saccade();
+    void start_eyeblink(int side, int duration=EYEBLINK_DURATION_MS);
+
+    void close_eyelid(int joint_id);
+
+    static const float SACCADE_SPEED_THRESHOLD;
+    static const float EYEBLINK_DURATION_MS;
+    static const float EYEBLINK_EYERY_MS_MIN;
+    static const float EYEBLINK_EYERY_MS_MAX;
+    static const float EYEBLINK_BLOCKING_TIME;
+
+    boost::system_time periodic_blink_start_time;
+    boost::system_time eyeblink_timeout[SIDE_ID_SIZE];
+    boost::system_time eyeblink_blocked_timeout;
+
+};
+
+}
+}
diff --git a/include/server/gaze_motion_generator.h b/include/server/gaze_motion_generator.h
new file mode 100644
index 0000000..a2bf907
--- /dev/null
+++ b/include/server/gaze_motion_generator.h
@@ -0,0 +1,63 @@
+/*
+* This file is part of humotion
+*
+* Copyright(c) sschulz <AT> techfak.uni-bielefeld.de
+* http://opensource.cit-ec.de/projects/humotion
+*
+* This file may be licensed under the terms of the
+* GNU Lesser General Public License Version 3 (the ``LGPL''),
+* or (at your option) any later version.
+*
+* Software distributed under the License is distributed
+* on an ``AS IS'' basis, WITHOUT WARRANTY OF ANY KIND, either
+* express or implied. See the LGPL for the specific language
+* governing rights and limitations.
+*
+* You should have received a copy of the LGPL along with this
+* program. If not, go to http://www.gnu.org/licenses/lgpl.html
+* or write to the Free Software Foundation, Inc.,
+* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+*
+* The development of this software was supported by the
+* Excellence Cluster EXC 277 Cognitive Interaction Technology.
+* The Excellence Cluster EXC 277 is a grant of the Deutsche
+* Forschungsgemeinschaft (DFG) in the context of the German
+* Excellence Initiative.
+*/
+
+#pragma once
+#include "reflexxes_motion_generator.h"
+#include "timestamped_list.h"
+
+namespace humotion{
+namespace server{
+
+class GazeMotionGenerator : public ReflexxesMotionGenerator{
+public:
+    GazeMotionGenerator(JointInterface *j, int dof, float t);
+    ~GazeMotionGenerator();
+
+    void set_gaze_target(GazeState s);
+
+    static const float SACCADE_SPEED_THRESHOLD;
+    static const float SACCADE_LATENCY;
+
+protected:
+    GazeState get_current_gaze();
+
+    bool get_eye_saccade_active();
+    bool neck_saccade_requested;
+    bool neck_saccade_omr;
+
+private:
+
+    //constants
+    static const float NECK_SACCADE_THRESHOLD;
+    static const float EYE_SACCADE_SPEED_THRESHOLD;
+    static const float OMR_LIMIT_TRIGGERS_NECK_SACCADE;
+
+};
+
+}
+}
+
diff --git a/include/server/joint_interface.h b/include/server/joint_interface.h
new file mode 100644
index 0000000..b97ddcb
--- /dev/null
+++ b/include/server/joint_interface.h
@@ -0,0 +1,133 @@
+/*
+* This file is part of humotion
+*
+* Copyright(c) sschulz <AT> techfak.uni-bielefeld.de
+* http://opensource.cit-ec.de/projects/humotion
+*
+* This file may be licensed under the terms of the
+* GNU Lesser General Public License Version 3 (the ``LGPL''),
+* or (at your option) any later version.
+*
+* Software distributed under the License is distributed
+* on an ``AS IS'' basis, WITHOUT WARRANTY OF ANY KIND, either
+* express or implied. See the LGPL for the specific language
+* governing rights and limitations.
+*
+* You should have received a copy of the LGPL along with this
+* program. If not, go to http://www.gnu.org/licenses/lgpl.html
+* or write to the Free Software Foundation, Inc.,
+* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+*
+* The development of this software was supported by the
+* Excellence Cluster EXC 277 Cognitive Interaction Technology.
+* The Excellence Cluster EXC 277 is a grant of the Deutsche
+* Forschungsgemeinschaft (DFG) in the context of the German
+* Excellence Initiative.
+*/
+
+#pragma once
+#include <cstdio>
+#include <cstdint>
+#include <string>
+#include <map>
+#include "../timestamped_list.h"
+#include "../mouth_state.h"
+#include "../gaze_state.h"
+#include "boost/date_time/posix_time/posix_time.hpp"
+#include <boost/thread/thread_time.hpp>
+#include <boost/thread/thread.hpp>
+#include <boost/thread/mutex.hpp>
+
+namespace humotion{
+namespace server{
+
+//forward declaration to solve include loop
+class Controller;
+
+
+class JointInterface{
+public:
+    JointInterface();
+    ~JointInterface();
+
+    void set_target_position(int joint_id, float position);
+    float get_target_position(int joint_id);
+    virtual void publish_target_position(int joint_id) = 0;
+    virtual void execute_motion() = 0;
+
+    typedef std::map<int, TimestampedList> joint_tsl_map_t;
+
+    TimestampedList get_ts_position(int joint_id);
+    TimestampedList get_ts_speed(int joint_id);
+
+    void set_framerate(float f);
+
+    void enable_mouth_joints();
+    void disable_mouth_joints();
+    bool mouth_target_input_active();
+
+    void enable_gaze_joints();
+    void disable_gaze_joints();
+    bool gaze_target_input_active();
+
+    float get_joint_min(int joint_id);
+    float get_joint_max(int joint_id);
+
+    void dump_angles();
+
+    unsigned int get_and_clear_incoming_position_count();
+
+    enum JOINT_ID_ENUM{
+        ZERO = 0,
+        ID_LIP_LEFT_UPPER,
+        ID_LIP_LEFT_LOWER,
+        ID_LIP_CENTER_UPPER,
+        ID_LIP_CENTER_LOWER,
+        ID_LIP_RIGHT_UPPER,
+        ID_LIP_RIGHT_LOWER,
+        ID_NECK_PAN,
+        ID_NECK_TILT,
+        ID_NECK_ROLL,
+        ID_EYES_LEFT_LR,
+        ID_EYES_RIGHT_LR,
+        ID_EYES_BOTH_UD,
+        ID_EYES_LEFT_LID_LOWER,
+        ID_EYES_LEFT_LID_UPPER,
+        ID_EYES_RIGHT_LID_LOWER,
+        ID_EYES_RIGHT_LID_UPPER,
+        ID_EYES_LEFT_BROW,
+        ID_EYES_RIGHT_BROW,
+        JOINT_ID_ENUM_SIZE
+    };
+
+    bool get_joint_position_map_empty();
+
+protected:
+
+    void store_incoming_position(int joint_id, float position, double timestamp);
+    void store_incoming_speed(int joint_id, float speed, double timestamp);
+
+    virtual void enable_joint(int id) = 0;
+    virtual void disable_joint(int id) = 0;
+    float framerate;
+
+    float joint_min[JOINT_ID_ENUM_SIZE];
+    float joint_max[JOINT_ID_ENUM_SIZE];
+    float joint_target[JOINT_ID_ENUM_SIZE];
+
+
+
+private:
+    boost::mutex joint_ts_position_map_access_mutex;
+    boost::mutex joint_ts_speed_map_access_mutex;
+    joint_tsl_map_t joint_ts_position_map;
+    joint_tsl_map_t joint_ts_speed_map;
+
+    bool mouth_enabled;
+    bool gaze_enabled;
+    unsigned int incoming_position_count;
+
+};
+
+}
+}
diff --git a/include/server/middleware.h b/include/server/middleware.h
new file mode 100644
index 0000000..bfc05f9
--- /dev/null
+++ b/include/server/middleware.h
@@ -0,0 +1,55 @@
+/*
+* This file is part of humotion
+*
+* Copyright(c) sschulz <AT> techfak.uni-bielefeld.de
+* http://opensource.cit-ec.de/projects/humotion
+*
+* This file may be licensed under the terms of the
+* GNU Lesser General Public License Version 3 (the ``LGPL''),
+* or (at your option) any later version.
+*
+* Software distributed under the License is distributed
+* on an ``AS IS'' basis, WITHOUT WARRANTY OF ANY KIND, either
+* express or implied. See the LGPL for the specific language
+* governing rights and limitations.
+*
+* You should have received a copy of the LGPL along with this
+* program. If not, go to http://www.gnu.org/licenses/lgpl.html
+* or write to the Free Software Foundation, Inc.,
+* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+*
+* The development of this software was supported by the
+* Excellence Cluster EXC 277 Cognitive Interaction Technology.
+* The Excellence Cluster EXC 277 is a grant of the Deutsche
+* Forschungsgemeinschaft (DFG) in the context of the German
+* Excellence Initiative.
+*/
+
+#pragma once
+#include <cstdio>
+#include <cstdint>
+#include <string>
+#include "../mouth_state.h"
+#include "../gaze_state.h"
+#include "controller.h"
+
+namespace humotion{
+namespace server{
+
+class Middleware{
+public:
+    Middleware(std::string name, Controller *c);
+    ~Middleware();
+
+    virtual bool ok() = 0;
+    virtual void tick() = 0;
+
+protected:
+    Controller *controller;
+    std::string base_scope;
+
+
+};
+
+}
+}
diff --git a/include/server/middleware_ros.h b/include/server/middleware_ros.h
new file mode 100644
index 0000000..fed80c8
--- /dev/null
+++ b/include/server/middleware_ros.h
@@ -0,0 +1,74 @@
+/*
+* This file is part of humotion
+*
+* Copyright(c) sschulz <AT> techfak.uni-bielefeld.de
+* http://opensource.cit-ec.de/projects/humotion
+*
+* This file may be licensed under the terms of the
+* GNU Lesser General Public License Version 3 (the ``LGPL''),
+* or (at your option) any later version.
+*
+* Software distributed under the License is distributed
+* on an ``AS IS'' basis, WITHOUT WARRANTY OF ANY KIND, either
+* express or implied. See the LGPL for the specific language
+* governing rights and limitations.
+*
+* You should have received a copy of the LGPL along with this
+* program. If not, go to http://www.gnu.org/licenses/lgpl.html
+* or write to the Free Software Foundation, Inc.,
+* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+*
+* The development of this software was supported by the
+* Excellence Cluster EXC 277 Cognitive Interaction Technology.
+* The Excellence Cluster EXC 277 is a grant of the Deutsche
+* Forschungsgemeinschaft (DFG) in the context of the German
+* Excellence Initiative.
+*/
+
+#pragma once
+#include "middleware.h"
+#include "humotion/mouth.h"
+#include "humotion/gaze.h"
+
+#ifdef ROS_SUPPORT
+#include "ros/ros.h"
+#endif
+
+#include <boost/shared_ptr.hpp>
+
+namespace humotion{
+namespace server{
+
+class MiddlewareROS : public Middleware{
+#ifndef ROS_SUPPORT
+public:
+    MiddlewareROS(std::string name, Controller *c) : Middleware(name, c){
+        printf("> ERROR: humotion was compiled without ROS middleware support. Please use MiddlewareRSB() instead!\n\n");
+        exit(EXIT_FAILURE);
+    }
+
+    ~MiddlewareROS(){}
+    bool ok(){ return false; }
+    void tick(){}
+
+#else
+public:
+    MiddlewareROS(std::string name, Controller *c);
+    ~MiddlewareROS();
+    bool ok();
+    void tick();
+
+private:
+    double convert_ros_to_timestamp_ms(ros::Time t);
+    bool tick_necessary;
+    void incoming_mouth_target(const humotion::mouth::ConstPtr& msg);
+    void incoming_gaze_target(const humotion::gaze::ConstPtr& msg);
+
+    ros::Subscriber mouth_target_subscriber;
+    ros::Subscriber gaze_target_subscriber;
+#endif
+};
+
+}
+}
+
diff --git a/include/server/middleware_rsb.h b/include/server/middleware_rsb.h
new file mode 100644
index 0000000..9be0567
--- /dev/null
+++ b/include/server/middleware_rsb.h
@@ -0,0 +1,77 @@
+/*
+* This file is part of humotion
+*
+* Copyright(c) sschulz <AT> techfak.uni-bielefeld.de
+* http://opensource.cit-ec.de/projects/humotion
+*
+* This file may be licensed under the terms of the
+* GNU Lesser General Public License Version 3 (the ``LGPL''),
+* or (at your option) any later version.
+*
+* Software distributed under the License is distributed
+* on an ``AS IS'' basis, WITHOUT WARRANTY OF ANY KIND, either
+* express or implied. See the LGPL for the specific language
+* governing rights and limitations.
+*
+* You should have received a copy of the LGPL along with this
+* program. If not, go to http://www.gnu.org/licenses/lgpl.html
+* or write to the Free Software Foundation, Inc.,
+* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+*
+* The development of this software was supported by the
+* Excellence Cluster EXC 277 Cognitive Interaction Technology.
+* The Excellence Cluster EXC 277 is a grant of the Deutsche
+* Forschungsgemeinschaft (DFG) in the context of the German
+* Excellence Initiative.
+*/
+
+#pragma once
+#include "middleware.h"
+#include "humotion/mouth.h"
+#include "humotion/gaze.h"
+
+#ifdef RSB_SUPPORT
+    #define BOOST_SIGNALS_NO_DEPRECATION_WARNING 1
+    #include <rsb/Listener.h>
+    #include <rst/robot/HumotionGazeTarget.pb.h>
+    #include <rst/robot/MouthTarget.pb.h>
+#endif
+
+namespace humotion{
+namespace server{
+
+class MiddlewareRSB : public Middleware{
+
+#ifndef RSB_SUPPORT
+public:
+    MiddlewareRSB(std::string name, Controller *c) : Middleware(name, c){
+        printf("> ERROR: humotion was compiled without RSB middleware support. Please use MiddlewareROS() instead!\n\n");
+        exit(EXIT_FAILURE);
+    }
+
+    ~MiddlewareRSB(){}
+    bool ok(){ return false; }
+    void tick(){}
+
+#else
+public:
+    MiddlewareRSB(std::string name, Controller *c);
+    ~MiddlewareRSB();
+
+    bool ok();
+    void tick();
+
+
+private:
+
+    void incoming_mouth_target(boost::shared_ptr<rst::robot::MouthTarget> event);
+    void incoming_gaze_target(rsb::EventPtr e);
+
+    rsb::ListenerPtr mouth_target_listener;
+    rsb::ListenerPtr gaze_target_listener;
+
+#endif
+};
+
+}
+}
diff --git a/include/server/motion_generator.h b/include/server/motion_generator.h
new file mode 100644
index 0000000..7c4f75a
--- /dev/null
+++ b/include/server/motion_generator.h
@@ -0,0 +1,66 @@
+/*
+* This file is part of humotion
+*
+* Copyright(c) sschulz <AT> techfak.uni-bielefeld.de
+* http://opensource.cit-ec.de/projects/humotion
+*
+* This file may be licensed under the terms of the
+* GNU Lesser General Public License Version 3 (the ``LGPL''),
+* or (at your option) any later version.
+*
+* Software distributed under the License is distributed
+* on an ``AS IS'' basis, WITHOUT WARRANTY OF ANY KIND, either
+* express or implied. See the LGPL for the specific language
+* governing rights and limitations.
+*
+* You should have received a copy of the LGPL along with this
+* program. If not, go to http://www.gnu.org/licenses/lgpl.html
+* or write to the Free Software Foundation, Inc.,
+* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+*
+* The development of this software was supported by the
+* Excellence Cluster EXC 277 Cognitive Interaction Technology.
+* The Excellence Cluster EXC 277 is a grant of the Deutsche
+* Forschungsgemeinschaft (DFG) in the context of the German
+* Excellence Initiative.
+*/
+
+#pragma once
+#include "joint_interface.h"
+#include "boost/date_time/posix_time/posix_time.hpp"
+#include <string>
+
+namespace humotion{
+namespace server{
+
+class MotionGenerator{
+public:
+    MotionGenerator(JointInterface *j);
+    ~MotionGenerator();
+
+    virtual void calculate_targets()=0;
+    virtual void publish_targets()=0;
+
+    virtual void set_gaze_target(GazeState s);
+    virtual void set_mouth_target(MouthState s);
+
+protected:
+    float get_current_position(int joint_id);
+    float limit_target(int joint_id, float val);
+
+    JointInterface *joint_interface;
+
+    //GAZE:
+    GazeState  requested_gaze_state;
+    boost::system_time last_gaze_target_update;
+    bool gaze_target_input_active();
+
+    //MOUTH
+    MouthState requested_mouth_target;
+    boost::system_time last_mouth_target_update;
+    bool mouth_target_input_active();
+
+};
+
+}
+}
diff --git a/include/server/mouth_motion_generator.h b/include/server/mouth_motion_generator.h
new file mode 100644
index 0000000..6461e02
--- /dev/null
+++ b/include/server/mouth_motion_generator.h
@@ -0,0 +1,52 @@
+/*
+* This file is part of humotion
+*
+* Copyright(c) sschulz <AT> techfak.uni-bielefeld.de
+* http://opensource.cit-ec.de/projects/humotion
+*
+* This file may be licensed under the terms of the
+* GNU Lesser General Public License Version 3 (the ``LGPL''),
+* or (at your option) any later version.
+*
+* Software distributed under the License is distributed
+* on an ``AS IS'' basis, WITHOUT WARRANTY OF ANY KIND, either
+* express or implied. See the LGPL for the specific language
+* governing rights and limitations.
+*
+* You should have received a copy of the LGPL along with this
+* program. If not, go to http://www.gnu.org/licenses/lgpl.html
+* or write to the Free Software Foundation, Inc.,
+* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+*
+* The development of this software was supported by the
+* Excellence Cluster EXC 277 Cognitive Interaction Technology.
+* The Excellence Cluster EXC 277 is a grant of the Deutsche
+* Forschungsgemeinschaft (DFG) in the context of the German
+* Excellence Initiative.
+*/
+
+#pragma once
+#include "motion_generator.h"
+
+namespace humotion{
+namespace server{
+
+class MouthMotionGenerator : public MotionGenerator{
+public:
+    MouthMotionGenerator(JointInterface *j);
+    ~MouthMotionGenerator();
+    void calculate_targets();
+    void publish_targets();
+
+private:
+    void calculate_mouth_target(int upper, int lower);
+    float mouthstate_to_opening(MouthState m, int e);
+    float mouthstate_to_position(MouthState m, int e);
+    void update_mouth_target(int upper_id, int lower_id);
+
+    //minimum mouth opening:
+    static const float MOUTH_MIN_OPENING;
+};
+
+}
+}
diff --git a/include/server/neck_motion_generator.h b/include/server/neck_motion_generator.h
new file mode 100644
index 0000000..c8078a2
--- /dev/null
+++ b/include/server/neck_motion_generator.h
@@ -0,0 +1,61 @@
+/*
+* This file is part of humotion
+*
+* Copyright(c) sschulz <AT> techfak.uni-bielefeld.de
+* http://opensource.cit-ec.de/projects/humotion
+*
+* This file may be licensed under the terms of the
+* GNU Lesser General Public License Version 3 (the ``LGPL''),
+* or (at your option) any later version.
+*
+* Software distributed under the License is distributed
+* on an ``AS IS'' basis, WITHOUT WARRANTY OF ANY KIND, either
+* express or implied. See the LGPL for the specific language
+* governing rights and limitations.
+*
+* You should have received a copy of the LGPL along with this
+* program. If not, go to http://www.gnu.org/licenses/lgpl.html
+* or write to the Free Software Foundation, Inc.,
+* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+*
+* The development of this software was supported by the
+* Excellence Cluster EXC 277 Cognitive Interaction Technology.
+* The Excellence Cluster EXC 277 is a grant of the Deutsche
+* Forschungsgemeinschaft (DFG) in the context of the German
+* Excellence Initiative.
+*/
+
+#pragma once
+#include "gaze_motion_generator.h"
+
+namespace humotion{
+namespace server{
+
+class NeckMotionGenerator : public GazeMotionGenerator {
+public:
+    NeckMotionGenerator(JointInterface *j);
+    ~NeckMotionGenerator();
+    void calculate_targets();
+    void publish_targets();
+    void setup_neckmotion(int dof, float target, float now);
+
+private:
+    float get_breath_offset();
+
+    GazeState previous_neck_target;
+    GazeState  requested_neck_state;
+    bool neck_saccade_reached_goal;
+    bool neck_saccade_active;
+
+    static const float CONST_GUITTON87_A;
+    static const float CONST_GUITTON87_B;
+
+    float breath_time;
+    static const float CONST_BREATH_PERIOD;
+    static const float CONST_BREATH_AMPLITUDE;
+
+
+};
+
+}
+}
diff --git a/include/server/reflexxes_motion_generator.h b/include/server/reflexxes_motion_generator.h
new file mode 100644
index 0000000..aa9883e
--- /dev/null
+++ b/include/server/reflexxes_motion_generator.h
@@ -0,0 +1,60 @@
+/*
+* This file is part of humotion
+*
+* Copyright(c) sschulz <AT> techfak.uni-bielefeld.de
+* http://opensource.cit-ec.de/projects/humotion
+*
+* This file may be licensed under the terms of the
+* GNU Lesser General Public License Version 3 (the ``LGPL''),
+* or (at your option) any later version.
+*
+* Software distributed under the License is distributed
+* on an ``AS IS'' basis, WITHOUT WARRANTY OF ANY KIND, either
+* express or implied. See the LGPL for the specific language
+* governing rights and limitations.
+*
+* You should have received a copy of the LGPL along with this
+* program. If not, go to http://www.gnu.org/licenses/lgpl.html
+* or write to the Free Software Foundation, Inc.,
+* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+*
+* The development of this software was supported by the
+* Excellence Cluster EXC 277 Cognitive Interaction Technology.
+* The Excellence Cluster EXC 277 is a grant of the Deutsche
+* Forschungsgemeinschaft (DFG) in the context of the German
+* Excellence Initiative.
+*/
+
+#pragma once
+#include "motion_generator.h"
+#include <ReflexxesAPI.h>
+#include <RMLPositionFlags.h>
+#include <RMLPositionInputParameters.h>
+#include <RMLPositionOutputParameters.h>
+
+namespace humotion{
+namespace server{
+
+class ReflexxesMotionGenerator : public MotionGenerator{
+public:
+    ReflexxesMotionGenerator(JointInterface *j, int dof, float t);
+    ~ReflexxesMotionGenerator();
+
+protected:
+    void reflexxes_set_input(int dof, float target, float max_speed, float max_accel);
+    void reflexxes_calculate_profile();
+
+    //*****************************************
+    ReflexxesAPI *reflexxes_api;
+    RMLPositionInputParameters *reflexxes_position_input;
+    RMLPositionOutputParameters *reflexxes_position_output;
+    RMLPositionFlags reflexxes_motion_flags;
+    //*****************************************
+    int dof_count;
+
+private:
+
+};
+
+}
+}
diff --git a/include/server/server.h b/include/server/server.h
new file mode 100644
index 0000000..07e92fd
--- /dev/null
+++ b/include/server/server.h
@@ -0,0 +1,59 @@
+/*
+* This file is part of humotion
+*
+* Copyright(c) sschulz <AT> techfak.uni-bielefeld.de
+* http://opensource.cit-ec.de/projects/humotion
+*
+* This file may be licensed under the terms of the
+* GNU Lesser General Public License Version 3 (the ``LGPL''),
+* or (at your option) any later version.
+*
+* Software distributed under the License is distributed
+* on an ``AS IS'' basis, WITHOUT WARRANTY OF ANY KIND, either
+* express or implied. See the LGPL for the specific language
+* governing rights and limitations.
+*
+* You should have received a copy of the LGPL along with this
+* program. If not, go to http://www.gnu.org/licenses/lgpl.html
+* or write to the Free Software Foundation, Inc.,
+* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+*
+* The development of this software was supported by the
+* Excellence Cluster EXC 277 Cognitive Interaction Technology.
+* The Excellence Cluster EXC 277 is a grant of the Deutsche
+* Forschungsgemeinschaft (DFG) in the context of the German
+* Excellence Initiative.
+*/
+
+#pragma once
+
+#include "ros/ros.h"
+#include "middleware.h"
+#include "controller.h"
+#include <cstdio>
+#include <cstdint>
+#include <string>
+#include <boost/thread/thread.hpp>
+
+namespace humotion{
+namespace server{
+
+class Server{
+public:
+    Server(std::string name, std::string mw, JointInterface *_joint_interface);
+	~Server();
+    bool ok();
+    static const float MOTION_UPDATERATE;
+
+private:
+    void start_motion_generation_thread();
+    void motion_generation_thread();
+    boost::thread *motion_generation_thread_ptr;
+
+    Middleware *middleware;
+    Controller *controller;
+    JointInterface *joint_interface;
+};
+
+}
+}
diff --git a/include/timestamped_float.h b/include/timestamped_float.h
new file mode 100644
index 0000000..8016d81
--- /dev/null
+++ b/include/timestamped_float.h
@@ -0,0 +1,61 @@
+/*
+* This file is part of humotion
+*
+* Copyright(c) sschulz <AT> techfak.uni-bielefeld.de
+* http://opensource.cit-ec.de/projects/humotion
+*
+* This file may be licensed under the terms of the
+* GNU Lesser General Public License Version 3 (the ``LGPL''),
+* or (at your option) any later version.
+*
+* Software distributed under the License is distributed
+* on an ``AS IS'' basis, WITHOUT WARRANTY OF ANY KIND, either
+* express or implied. See the LGPL for the specific language
+* governing rights and limitations.
+*
+* You should have received a copy of the LGPL along with this
+* program. If not, go to http://www.gnu.org/licenses/lgpl.html
+* or write to the Free Software Foundation, Inc.,
+* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+*
+* The development of this software was supported by the
+* Excellence Cluster EXC 277 Cognitive Interaction Technology.
+* The Excellence Cluster EXC 277 is a grant of the Deutsche
+* Forschungsgemeinschaft (DFG) in the context of the German
+* Excellence Initiative.
+*/
+
+#pragma once
+#include <stdlib.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <string>
+
+namespace humotion{
+
+class TimestampedFloat{
+public:
+    TimestampedFloat(){
+		timestamp = 0.0;
+		value = 0.0;
+	}
+	
+    TimestampedFloat(double ts, float val){
+		timestamp = ts;
+		value = val;
+	}
+	
+	static double get_timestamp(){
+		//fetch time
+		struct timespec tp;
+		clock_gettime(CLOCK_REALTIME, &tp);
+		return tp.tv_sec+tp.tv_nsec/1000000000.0;
+	};
+	
+	double timestamp;
+    float value;
+	
+};
+
+
+}
diff --git a/include/timestamped_list.h b/include/timestamped_list.h
new file mode 100644
index 0000000..c67dbd5
--- /dev/null
+++ b/include/timestamped_list.h
@@ -0,0 +1,53 @@
+/*
+* This file is part of humotion
+*
+* Copyright(c) sschulz <AT> techfak.uni-bielefeld.de
+* http://opensource.cit-ec.de/projects/humotion
+*
+* This file may be licensed under the terms of the
+* GNU Lesser General Public License Version 3 (the ``LGPL''),
+* or (at your option) any later version.
+*
+* Software distributed under the License is distributed
+* on an ``AS IS'' basis, WITHOUT WARRANTY OF ANY KIND, either
+* express or implied. See the LGPL for the specific language
+* governing rights and limitations.
+*
+* You should have received a copy of the LGPL along with this
+* program. If not, go to http://www.gnu.org/licenses/lgpl.html
+* or write to the Free Software Foundation, Inc.,
+* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+*
+* The development of this software was supported by the
+* Excellence Cluster EXC 277 Cognitive Interaction Technology.
+* The Excellence Cluster EXC 277 is a grant of the Deutsche
+* Forschungsgemeinschaft (DFG) in the context of the German
+* Excellence Initiative.
+*/
+
+#pragma once
+#include "timestamped_float.h"
+#include <boost/thread/mutex.hpp>
+#include <list>
+
+namespace humotion{
+class TimestampedList{
+public:
+    typedef std::list<TimestampedFloat> timestamped_float_list_t;
+
+    TimestampedList( TimestampedList const &l);
+	TimestampedList(unsigned int size=10);
+    void insert(double ts, float val);
+    float get_interpolated_value(double target_ts);
+    float get_newest_value();
+	static void run_tests();
+    void copy_tsf_list_to(timestamped_float_list_t *target);
+    double get_last_timestamp();
+
+private:
+    mutable boost::mutex access_mutex;
+    float interpolate(TimestampedFloat a, TimestampedFloat b, double timestamp);
+    timestamped_float_list_t tsf_list;
+};
+
+}
diff --git a/msg/gaze.msg b/msg/gaze.msg
new file mode 100644
index 0000000..f56bbf4
--- /dev/null
+++ b/msg/gaze.msg
@@ -0,0 +1,25 @@
+Header header
+
+#type of pan/tilt/roll targets
+int32 type
+int32 ABSOLUTE=0
+int32 RELATIVE=1
+
+float32 pan
+float32 tilt
+float32 roll
+float32 vergence
+
+
+float32 pan_offset
+float32 tilt_offset
+float32 roll_offset
+
+float32 eyelid_opening_upper
+float32 eyelid_opening_lower
+
+float32 eyebrow_left
+float32 eyebrow_right
+
+int32 eyeblink_request_left
+int32 eyeblink_request_right
diff --git a/msg/mouth.msg b/msg/mouth.msg
new file mode 100644
index 0000000..a0c80c6
--- /dev/null
+++ b/msg/mouth.msg
@@ -0,0 +1,4 @@
+Header header
+
+position_lcr position
+position_lcr opening
diff --git a/msg/position_lcr.msg b/msg/position_lcr.msg
new file mode 100644
index 0000000..4f1a746
--- /dev/null
+++ b/msg/position_lcr.msg
@@ -0,0 +1,3 @@
+float32 left
+float32 center
+float32 right
diff --git a/msg/state.msg b/msg/state.msg
new file mode 100644
index 0000000..b8588d7
--- /dev/null
+++ b/msg/state.msg
@@ -0,0 +1,13 @@
+Header header
+
+float32 gaze_pan_l
+float32 gaze_pan_r
+float32 gaze_tilt
+
+float32 mouth_opening_left
+float32 mouth_opening_center
+float32 mouth_opening_right
+
+float32 mouth_position_left
+float32 mouth_position_center
+float32 mouth_position_right
diff --git a/package.xml b/package.xml
new file mode 100644
index 0000000..111e0e5
--- /dev/null
+++ b/package.xml
@@ -0,0 +1,61 @@
+<?xml version="1.0"?>
+<package>
+  <name>humotion</name>
+  <version>0.0.1</version>
+  <description>the human motion library</description>
+
+  <!-- One maintainer tag required, multiple allowed, one person per tag --> 
+  <maintainer email="sschulz@todo.todo">Simon Schulz</maintainer>
+
+
+  <!-- One license tag required, multiple allowed, one license per tag -->
+  <!-- Commonly used license strings: -->
+  <!--   BSD, MIT, Boost Software License, GPLv2, GPLv3, LGPLv2.1, LGPLv3 -->
+  <license>TODO</license>
+
+
+  <!-- Url tags are optional, but mutiple are allowed, one per tag -->
+  <!-- Optional attribute type can be: website, bugtracker, or repository -->
+  <!-- Example: -->
+  <url type="website">https://projects.cit-ec.uni-bielefeld.de/git/flobidev.core.git</url> -->
+
+
+  <!-- Author tags are optional, mutiple are allowed, one per tag -->
+  <!-- Authors do not have to be maintianers, but could be -->
+  <!-- Example: -->
+  <!-- <author email="jane.doe@example.com">Jane Doe</author> -->
+
+
+  <!-- The *_depend tags are used to specify dependencies -->
+  <!-- Dependencies can be catkin packages or system dependencies -->
+  <!-- Examples: -->
+  <!-- Use build_depend for packages you need at compile time: -->
+  <!-- <build_depend>message_generation</build_depend> -->
+  <build_depend></build_depend>
+  <run_depend></run_depend>
+  <!-- Use buildtool_depend for build tool packages: -->
+  <!--   <buildtool_depend>catkin</buildtool_depend> -->
+  <!-- Use run_depend for packages you need at runtime: -->
+  <!-- <run_depend>message_runtime</run_depend> -->
+  <!-- Use test_depend for packages you need only for testing: -->
+  <!--   <test_depend>gtest</test_depend> -->
+  <buildtool_depend>catkin</buildtool_depend>
+  <build_depend>roscpp</build_depend>
+  <build_depend>std_msgs</build_depend>
+  <!-- <run_depend>roscpp</run_depend> -->
+  <!-- <run_depend>std_msgs</run_depend> -->
+
+  <!--<build_depend>actionlib</build_depend>
+  <build_depend>actionlib_msgs</build_depend>
+  <run_depend>actionlib</run_depend> -->
+  <!-- <run_depend>actionlib_msgs</run_depend> -->
+
+  <!-- The export tag contains other, unspecified, tags -->
+  <export>
+    <!-- You can specify that this package is a metapackage here: -->
+    <!-- <metapackage/> -->
+
+    <!-- Other tools can request additional information be placed here -->
+
+  </export>
+</package>
diff --git a/src/client/client.cpp b/src/client/client.cpp
new file mode 100644
index 0000000..0af09bc
--- /dev/null
+++ b/src/client/client.cpp
@@ -0,0 +1,91 @@
+/*
+* This file is part of humotion
+*
+* Copyright(c) sschulz <AT> techfak.uni-bielefeld.de
+* http://opensource.cit-ec.de/projects/humotion
+*
+* This file may be licensed under the terms of the
+* GNU Lesser General Public License Version 3 (the ``LGPL''),
+* or (at your option) any later version.
+*
+* Software distributed under the License is distributed
+* on an ``AS IS'' basis, WITHOUT WARRANTY OF ANY KIND, either
+* express or implied. See the LGPL for the specific language
+* governing rights and limitations.
+*
+* You should have received a copy of the LGPL along with this
+* program. If not, go to http://www.gnu.org/licenses/lgpl.html
+* or write to the Free Software Foundation, Inc.,
+* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+*
+* The development of this software was supported by the
+* Excellence Cluster EXC 277 Cognitive Interaction Technology.
+* The Excellence Cluster EXC 277 is a grant of the Deutsche
+* Forschungsgemeinschaft (DFG) in the context of the German
+* Excellence Initiative.
+*/
+
+#include "client/client.h"
+#include "client/middleware_ros.h"
+#include "client/middleware_rsb.h"
+#include <boost/algorithm/string.hpp>
+
+using namespace std;
+using namespace boost;
+using namespace humotion;
+using namespace humotion::client;
+
+//! constructor
+//! open a new client instance.
+Client::Client(string scope, string mw){
+    //convert mw to uppercase:
+    to_upper(mw);
+
+    printf("> initializing humotion client (on %s, middleware=%s)\n",scope.c_str(),mw.c_str());
+
+    //start middleware:
+    if (mw == "ROS"){
+        middleware = new MiddlewareROS(scope);
+    }else if (mw == "RSB"){
+        middleware = new MiddlewareRSB(scope);
+    }else{
+        printf("> ERROR: invalid mw '%s' given. Please use ROS or RSB\n\n",mw.c_str());
+        exit(EXIT_FAILURE);
+    }
+}
+
+//! destructor
+Client::~Client(){
+}
+
+//! check if connection is ok
+//! \return true if conn is alive
+bool Client::ok(){
+    return middleware->ok();
+}
+
+//! do a single middleware tick:
+void Client::tick(){
+    middleware->tick();
+}
+
+//! set mouth position
+//! \param MouthState m to set
+//! \param send data to server (optional, use manual call to send_*() to trigger update on server)
+void Client::update_mouth_target(MouthState m, bool send){
+    middleware->update_mouth_target(m, send);
+}
+
+//! set gaze direction
+//! \param GazeState m to set
+//! \param send data to server (optional, use manual call to send_*() to trigger update on server)
+void Client::update_gaze_target(GazeState s, bool send){
+    middleware->update_gaze_target(s, send);
+}
+
+
+//! send all targets to server
+void Client::send_all(){
+    middleware->send_all();
+}
+
diff --git a/src/client/middleware.cpp b/src/client/middleware.cpp
new file mode 100644
index 0000000..24b5f1d
--- /dev/null
+++ b/src/client/middleware.cpp
@@ -0,0 +1,71 @@
+/*
+* This file is part of humotion
+*
+* Copyright(c) sschulz <AT> techfak.uni-bielefeld.de
+* http://opensource.cit-ec.de/projects/humotion
+*
+* This file may be licensed under the terms of the
+* GNU Lesser General Public License Version 3 (the ``LGPL''),
+* or (at your option) any later version.
+*
+* Software distributed under the License is distributed
+* on an ``AS IS'' basis, WITHOUT WARRANTY OF ANY KIND, either
+* express or implied. See the LGPL for the specific language
+* governing rights and limitations.
+*
+* You should have received a copy of the LGPL along with this
+* program. If not, go to http://www.gnu.org/licenses/lgpl.html
+* or write to the Free Software Foundation, Inc.,
+* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+*
+* The development of this software was supported by the
+* Excellence Cluster EXC 277 Cognitive Interaction Technology.
+* The Excellence Cluster EXC 277 is a grant of the Deutsche
+* Forschungsgemeinschaft (DFG) in the context of the German
+* Excellence Initiative.
+*/
+
+#include "client/middleware.h"
+
+using namespace std;
+using namespace humotion;
+using namespace humotion::client;
+
+//! constructor
+//! open a new Middleware instance.
+Middleware::Middleware(string scope){
+    base_scope = scope;
+}
+
+//! destructor
+Middleware::~Middleware(){
+}
+
+
+//! set mouth position
+//! \param MouthState m to set
+//! \param send data to server (optional, use manual call to send_*() to trigger update on server)
+void Middleware::update_mouth_target(MouthState m, bool send){
+	mouth_state = m;
+	if (send){
+		send_mouth_target();
+	}
+}
+
+//! set gaze target
+//! \param GazeState m to set
+//! \param send data to server (optional, use manual call to send_*() to trigger update on server)
+void Middleware::update_gaze_target(GazeState s, bool send){
+    gaze_state = s;
+    if (send){
+        send_gaze_target();
+    }
+}
+
+
+//! send all targets to server
+void Middleware::send_all(){
+	send_mouth_target();
+    send_gaze_target();
+}
+
diff --git a/src/client/middleware_ros.cpp b/src/client/middleware_ros.cpp
new file mode 100644
index 0000000..336069e
--- /dev/null
+++ b/src/client/middleware_ros.cpp
@@ -0,0 +1,143 @@
+/*
+* This file is part of humotion
+*
+* Copyright(c) sschulz <AT> techfak.uni-bielefeld.de
+* http://opensource.cit-ec.de/projects/humotion
+*
+* This file may be licensed under the terms of the
+* GNU Lesser General Public License Version 3 (the ``LGPL''),
+* or (at your option) any later version.
+*
+* Software distributed under the License is distributed
+* on an ``AS IS'' basis, WITHOUT WARRANTY OF ANY KIND, either
+* express or implied. See the LGPL for the specific language
+* governing rights and limitations.
+*
+* You should have received a copy of the LGPL along with this
+* program. If not, go to http://www.gnu.org/licenses/lgpl.html
+* or write to the Free Software Foundation, Inc.,
+* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+*
+* The development of this software was supported by the
+* Excellence Cluster EXC 277 Cognitive Interaction Technology.
+* The Excellence Cluster EXC 277 is a grant of the Deutsche
+* Forschungsgemeinschaft (DFG) in the context of the German
+* Excellence Initiative.
+*/
+
+#include "client/middleware_ros.h"
+
+#ifdef ROS_SUPPORT
+
+#include <humotion/mouth.h>
+#include <humotion/gaze.h>
+#include <boost/range/algorithm/remove_if.hpp>
+#include <boost/algorithm/string/classification.hpp>
+
+using namespace std;
+using namespace boost;
+using namespace humotion;
+using namespace humotion::client;
+
+//! constructor
+MiddlewareROS::MiddlewareROS(string scope) : Middleware(scope){
+    //start ros core
+    if (!ros::isInitialized()){
+        tick_necessary = true;
+        string node_name = "humotion_client__"+ base_scope;
+        node_name.erase(boost::remove_if(node_name, boost::is_any_of("/")), node_name.end());
+
+        ros::M_string no_remapping;
+        ros::init(no_remapping, node_name);
+    }else{
+        //another ros thread takes care of spinning
+        tick_necessary = false;
+    }
+
+	//create node handle	
+    ros::NodeHandle n;
+
+	//set up publishers:
+    mouth_target_publisher = n.advertise<humotion::mouth>(base_scope + "/humotion/mouth/target", 100);
+    gaze_target_publisher  = n.advertise<humotion::gaze>(base_scope + "/humotion/gaze/target", 100);
+
+}
+
+//! destructor
+MiddlewareROS::~MiddlewareROS(){
+}
+
+//! connection ok?
+//! \return true if conn is alive
+bool MiddlewareROS::ok(){
+    return ros::ok();
+}
+
+//! do a single tick
+void MiddlewareROS::tick(){
+    if (tick_necessary){
+        ros::spinOnce();
+    }
+}
+
+
+//! send mouth target to server
+void MiddlewareROS::send_mouth_target(){
+    //build target packet:
+    humotion::mouth msg;
+
+    //set timestamp
+    msg.header.stamp = ros::Time::now();
+
+    msg.position.left   = mouth_state.position_left;
+    msg.position.center = mouth_state.position_center;
+    msg.position.right  = mouth_state.position_right;
+
+    msg.opening.left   = mouth_state.opening_left;
+    msg.opening.center = mouth_state.opening_center;
+    msg.opening.right  = mouth_state.opening_right;
+
+
+    //add position to send queue
+    mouth_target_publisher.publish(msg);
+
+    //allow ros to handle data
+    tick();
+}
+
+//! send mouth target to server
+void MiddlewareROS::send_gaze_target(){
+    //build target packet:
+    humotion::gaze msg;
+
+    //set timestamp
+    msg.header.stamp = ros::Time::now();
+
+    msg.pan   = gaze_state.pan;
+    msg.tilt  = gaze_state.tilt;
+    msg.roll  = gaze_state.roll;
+    msg.vergence = gaze_state.vergence;
+
+    msg.pan_offset = gaze_state.pan_offset;
+    msg.tilt_offset = gaze_state.tilt_offset;
+    msg.roll_offset = gaze_state.roll_offset;
+
+    msg.eyelid_opening_upper = gaze_state.eyelid_opening_upper;
+    msg.eyelid_opening_lower = gaze_state.eyelid_opening_lower;
+
+    msg.eyebrow_left = gaze_state.eyebrow_left;
+    msg.eyebrow_right = gaze_state.eyebrow_right;
+
+    msg.eyeblink_request_left = gaze_state.eyeblink_request_left;
+    msg.eyeblink_request_right = gaze_state.eyeblink_request_right;
+
+    msg.type = humotion::gaze::ABSOLUTE;
+
+    //add position to send queue
+    gaze_target_publisher.publish(msg);
+
+    //allow ros to handle data
+    tick();
+}
+
+#endif
diff --git a/src/client/middleware_rsb.cpp b/src/client/middleware_rsb.cpp
new file mode 100644
index 0000000..ed747bb
--- /dev/null
+++ b/src/client/middleware_rsb.cpp
@@ -0,0 +1,141 @@
+/*
+* This file is part of humotion
+*
+* Copyright(c) sschulz <AT> techfak.uni-bielefeld.de
+* http://opensource.cit-ec.de/projects/humotion
+*
+* This file may be licensed under the terms of the
+* GNU Lesser General Public License Version 3 (the ``LGPL''),
+* or (at your option) any later version.
+*
+* Software distributed under the License is distributed
+* on an ``AS IS'' basis, WITHOUT WARRANTY OF ANY KIND, either
+* express or implied. See the LGPL for the specific language
+* governing rights and limitations.
+*
+* You should have received a copy of the LGPL along with this
+* program. If not, go to http://www.gnu.org/licenses/lgpl.html
+* or write to the Free Software Foundation, Inc.,
+* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+*
+* The development of this software was supported by the
+* Excellence Cluster EXC 277 Cognitive Interaction Technology.
+* The Excellence Cluster EXC 277 is a grant of the Deutsche
+* Forschungsgemeinschaft (DFG) in the context of the German
+* Excellence Initiative.
+*/
+
+#include "client/middleware_rsb.h"
+
+#ifdef RSB_SUPPORT
+#define BOOST_SIGNALS_NO_DEPRECATION_WARNING 1
+#include <rsb/Listener.h>
+#include <rsb/patterns/RemoteServer.h>
+#include <rsb/MetaData.h>
+#include <rsb/converter/Repository.h>
+#include <rsb/converter/ProtocolBufferConverter.h>
+#include <rsb/Factory.h>
+
+#include <humotion/mouth.h>
+#include <humotion/gaze.h>
+
+using namespace std;
+using namespace rsb;
+using namespace boost;
+using namespace humotion;
+using namespace humotion::client;
+
+//! constructor
+MiddlewareRSB::MiddlewareRSB(string scope) : Middleware(scope){
+    printf("> registering converters\n");
+
+    try{
+        //converter for GazeTarget
+        rsb::converter::Converter<string>::Ptr gazeTargetConverter(new rsb::converter::ProtocolBufferConverter<rst::robot::HumotionGazeTarget>());
+        rsb::converter::converterRepository<string>()->registerConverter(gazeTargetConverter);
+    }catch (std::invalid_argument e){
+        printf("> it seems like a converter for rst::robot::HumotionGazeTarget is already registered. fine, will not add another converter\n");
+    }
+
+    try{
+        //converter for MouthTarget
+        rsb::converter::Converter<string>::Ptr mouthTargetConverter(new rsb::converter::ProtocolBufferConverter<rst::robot::MouthTarget>());
+        rsb::converter::converterRepository<string>()->registerConverter(mouthTargetConverter);
+    }catch (std::invalid_argument e){
+        printf("> it seems like a converter for rst::robot::MouthTarget is already registered. fine, will not add another converter\n");
+    }
+
+
+    //first get a factory instance that is used to create RSB domain objects
+    Factory &factory = getFactory();
+
+    //create informer
+    mouth_target_informer = factory.createInformer<rst::robot::MouthTarget> (base_scope + "/humotion/mouth/target");
+    gaze_target_informer  = factory.createInformer<rst::robot::HumotionGazeTarget> (base_scope + "/humotion/gaze/target");
+
+    printf("> MiddlewareRSB initialised\n");
+}
+
+//! destructor
+MiddlewareRSB::~MiddlewareRSB(){
+}
+
+//! connection ok?
+//! \return true if conn is alive
+bool MiddlewareRSB::ok(){
+    return true;
+}
+
+//! do a single tick
+void MiddlewareRSB::tick(){
+    //nothing to do
+}
+
+
+//! send mouth target to server
+void MiddlewareRSB::send_mouth_target(){
+    //build target packet:
+    boost::shared_ptr<rst::robot::MouthTarget> request(new rst::robot::MouthTarget());
+
+    request->set_position_left(mouth_state.position_left);
+    request->set_position_center(mouth_state.position_center);
+    request->set_position_right(mouth_state.position_right);
+
+    request->set_opening_left(mouth_state.opening_left);
+    request->set_opening_center(mouth_state.opening_center);
+    request->set_opening_right(mouth_state.opening_right);
+
+
+    mouth_target_informer->publish(request);
+}
+
+//! send mouth target to server
+void MiddlewareRSB::send_gaze_target(){
+    //build target packet:
+    boost::shared_ptr<rst::robot::HumotionGazeTarget> request(new rst::robot::HumotionGazeTarget());
+
+    request->set_pan(gaze_state.pan);
+    request->set_tilt(gaze_state.tilt);
+    request->set_roll (gaze_state.roll);
+    request->set_vergence(gaze_state.vergence);
+
+    request->set_pan_offset(gaze_state.pan_offset);
+    request->set_tilt_offset(gaze_state.tilt_offset);
+    request->set_roll_offset(gaze_state.roll_offset);
+
+    request->set_eyelid_opening_upper(gaze_state.eyelid_opening_upper);
+    request->set_eyelid_opening_lower(gaze_state.eyelid_opening_lower);
+
+    request->set_eyebrow_left(gaze_state.eyebrow_left);
+    request->set_eyebrow_right(gaze_state.eyebrow_right);
+
+    request->set_eyeblink_request_left(gaze_state.eyeblink_request_left);
+    request->set_eyeblink_request_right(gaze_state.eyeblink_request_right);
+
+    request->set_type(rst::robot::HumotionGazeTarget::ABSOLUTE);
+
+    //add position to send queue
+    gaze_target_informer->publish(request);
+}
+
+#endif
diff --git a/src/gaze_state.cpp b/src/gaze_state.cpp
new file mode 100644
index 0000000..34347b0
--- /dev/null
+++ b/src/gaze_state.cpp
@@ -0,0 +1,66 @@
+/*
+* This file is part of humotion
+*
+* Copyright(c) sschulz <AT> techfak.uni-bielefeld.de
+* http://opensource.cit-ec.de/projects/humotion
+*
+* This file may be licensed under the terms of the
+* GNU Lesser General Public License Version 3 (the ``LGPL''),
+* or (at your option) any later version.
+*
+* Software distributed under the License is distributed
+* on an ``AS IS'' basis, WITHOUT WARRANTY OF ANY KIND, either
+* express or implied. See the LGPL for the specific language
+* governing rights and limitations.
+*
+* You should have received a copy of the LGPL along with this
+* program. If not, go to http://www.gnu.org/licenses/lgpl.html
+* or write to the Free Software Foundation, Inc.,
+* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+*
+* The development of this software was supported by the
+* Excellence Cluster EXC 277 Cognitive Interaction Technology.
+* The Excellence Cluster EXC 277 is a grant of the Deutsche
+* Forschungsgemeinschaft (DFG) in the context of the German
+* Excellence Initiative.
+*/
+
+#include "gaze_state.h"
+#include <stdio.h>
+
+using namespace humotion;
+GazeState::GazeState(){
+    pan=0.0;
+    tilt=0.0;
+    roll=0.0;
+    vergence=0.0;
+
+    pan_offset = 0.0;
+    tilt_offset = 0.0;
+    roll_offset = 0.0;
+
+    eyelid_opening_upper = 35.0;
+    eyelid_opening_lower = 35.0;
+
+    eyebrow_left   = -3.0;
+    eyebrow_right  = 3.0;
+
+    type = ABSOLUTE;
+
+    eyeblink_request_right = 0;
+    eyeblink_request_left  = 0;
+}
+
+GazeState::~GazeState(){
+}
+
+void GazeState::dump(){
+    //dump values to stdout:
+    printf("> GAZE STATE: %4.2f [%2.1f] %4.2f [%2.1f] %4.2f [%2.1f] (PTR) vergence=%4.2f eyelid_opening=%4.2f/%4.2f eyebrows = %4.2f %4.2f type=%s eyeblink_requests=%d %d\n",
+           pan, pan_offset, tilt, tilt_offset, roll, roll_offset, vergence,
+           eyelid_opening_upper,eyelid_opening_lower,
+           eyebrow_left, eyebrow_right,
+           (type==ABSOLUTE?"absolute":(type==RELATIVE?"relative":(type==OVERRIDE?"override":"!INVALID!"))),
+           eyeblink_request_left, eyeblink_request_right
+           );
+}
diff --git a/src/mouth_state.cpp b/src/mouth_state.cpp
new file mode 100644
index 0000000..a9012e9
--- /dev/null
+++ b/src/mouth_state.cpp
@@ -0,0 +1,52 @@
+/*
+* This file is part of humotion
+*
+* Copyright(c) sschulz <AT> techfak.uni-bielefeld.de
+* http://opensource.cit-ec.de/projects/humotion
+*
+* This file may be licensed under the terms of the
+* GNU Lesser General Public License Version 3 (the ``LGPL''),
+* or (at your option) any later version.
+*
+* Software distributed under the License is distributed
+* on an ``AS IS'' basis, WITHOUT WARRANTY OF ANY KIND, either
+* express or implied. See the LGPL for the specific language
+* governing rights and limitations.
+*
+* You should have received a copy of the LGPL along with this
+* program. If not, go to http://www.gnu.org/licenses/lgpl.html
+* or write to the Free Software Foundation, Inc.,
+* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+*
+* The development of this software was supported by the
+* Excellence Cluster EXC 277 Cognitive Interaction Technology.
+* The Excellence Cluster EXC 277 is a grant of the Deutsche
+* Forschungsgemeinschaft (DFG) in the context of the German
+* Excellence Initiative.
+*/
+
+#include "mouth_state.h"
+#include <stdio.h>
+
+using namespace humotion;
+using namespace std;
+
+MouthState::MouthState(){
+    opening_left=0.0;
+    opening_center=0.0;
+    opening_right=0.0;
+
+    position_left=0.0;
+    position_center=0.0;
+    position_right=0.0;
+}
+
+MouthState::~MouthState(){
+}
+
+
+
+void MouthState::dump(){
+    //dump values to stdout:
+    printf("> MOUTH STATE: %4.2f (%4.2f) %4.2f (%4.2f) %4.2f (%4.2f)  [= pos (opening)]\n", position_left,opening_left,position_center,opening_center,position_right,opening_right);
+}
diff --git a/src/server/controller.cpp b/src/server/controller.cpp
new file mode 100644
index 0000000..14e0efd
--- /dev/null
+++ b/src/server/controller.cpp
@@ -0,0 +1,104 @@
+/*
+* This file is part of humotion
+*
+* Copyright(c) sschulz <AT> techfak.uni-bielefeld.de
+* http://opensource.cit-ec.de/projects/humotion
+*
+* This file may be licensed under the terms of the
+* GNU Lesser General Public License Version 3 (the ``LGPL''),
+* or (at your option) any later version.
+*
+* Software distributed under the License is distributed
+* on an ``AS IS'' basis, WITHOUT WARRANTY OF ANY KIND, either
+* express or implied. See the LGPL for the specific language
+* governing rights and limitations.
+*
+* You should have received a copy of the LGPL along with this
+* program. If not, go to http://www.gnu.org/licenses/lgpl.html
+* or write to the Free Software Foundation, Inc.,
+* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+*
+* The development of this software was supported by the
+* Excellence Cluster EXC 277 Cognitive Interaction Technology.
+* The Excellence Cluster EXC 277 is a grant of the Deutsche
+* Forschungsgemeinschaft (DFG) in the context of the German
+* Excellence Initiative.
+*/
+
+#include "server/controller.h"
+#include "server/eye_motion_generator.h"
+#include "server/eyelid_motion_generator.h"
+#include "server/eyebrow_motion_generator.h"
+#include "server/neck_motion_generator.h"
+#include "server/mouth_motion_generator.h"
+
+using namespace std;
+using namespace humotion;
+using namespace humotion::server;
+
+//! constructor
+Controller::Controller(JointInterface *j){
+    joint_interface = j;
+}
+
+//! destructor
+Controller::~Controller(){
+}
+
+//! initialise motion generators
+void Controller::init_motion_generators(){
+    //NOTE: the order of these generators is important!
+    //       (i.e. the neck generator must be added after the eye generator!)
+
+    //1) eye motion generation:
+    add_motion_generator(new EyeMotionGenerator(joint_interface));
+
+    //2) eyelid motion generator
+    add_motion_generator(new EyelidMotionGenerator(joint_interface));
+
+    //3) neck motion generator
+    add_motion_generator(new NeckMotionGenerator(joint_interface));
+
+    //4) mouth motion generator
+    add_motion_generator(new MouthMotionGenerator(joint_interface));
+
+    //5) eyebrow motion generator
+    add_motion_generator(new EyebrowMotionGenerator(joint_interface));
+}
+
+//! add a single motion genrator
+void Controller::add_motion_generator(MotionGenerator *m){
+    motion_generator_vector.push_back(m);
+}
+
+//! calculate target angles for all motion generators:
+void Controller::calculate_targets(){
+    for(motion_generator_vector_t::iterator it = motion_generator_vector.begin(); it<motion_generator_vector.end(); it++){
+        (*it)->calculate_targets();
+    }
+}
+
+//! publish all target angles to the devices:
+//! NOTE: this is done in an extra loop to have a low delay between consequent sets:
+void Controller::publish_targets(){
+    for(motion_generator_vector_t::iterator it = motion_generator_vector.begin(); it<motion_generator_vector.end(); it++){
+        (*it)->publish_targets();
+    }
+}
+
+
+//! update gaze target:
+//! \param GazeState with target values for the overall gaze
+void Controller::set_gaze_target(GazeState new_gaze_target){
+    for(motion_generator_vector_t::iterator it = motion_generator_vector.begin(); it<motion_generator_vector.end(); it++){
+        (*it)->set_gaze_target(new_gaze_target);
+    }
+}
+
+//! update mouth state:
+//! \param MouthState with target values for the mouth joints
+void Controller::set_mouth_target(MouthState s){
+    for(motion_generator_vector_t::iterator it = motion_generator_vector.begin(); it<motion_generator_vector.end(); it++){
+        (*it)->set_mouth_target(s);
+    }
+}
diff --git a/src/server/eye_motion_generator.cpp b/src/server/eye_motion_generator.cpp
new file mode 100644
index 0000000..b720955
--- /dev/null
+++ b/src/server/eye_motion_generator.cpp
@@ -0,0 +1,111 @@
+/*
+* This file is part of humotion
+*
+* Copyright(c) sschulz <AT> techfak.uni-bielefeld.de
+* http://opensource.cit-ec.de/projects/humotion
+*
+* This file may be licensed under the terms of the
+* GNU Lesser General Public License Version 3 (the ``LGPL''),
+* or (at your option) any later version.
+*
+* Software distributed under the License is distributed
+* on an ``AS IS'' basis, WITHOUT WARRANTY OF ANY KIND, either
+* express or implied. See the LGPL for the specific language
+* governing rights and limitations.
+*
+* You should have received a copy of the LGPL along with this
+* program. If not, go to http://www.gnu.org/licenses/lgpl.html
+* or write to the Free Software Foundation, Inc.,
+* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+*
+* The development of this software was supported by the
+* Excellence Cluster EXC 277 Cognitive Interaction Technology.
+* The Excellence Cluster EXC 277 is a grant of the Deutsche
+* Forschungsgemeinschaft (DFG) in the context of the German
+* Excellence Initiative.
+*/
+
+#include "server/eye_motion_generator.h"
+#include "server/server.h"
+
+using namespace std;
+using namespace humotion;
+using namespace humotion::server;
+
+//saccade detection threshold in deg/s
+const float EyeMotionGenerator::SACCADE_SPEED_THRESHOLD = 15.0;
+
+//! constructor
+EyeMotionGenerator::EyeMotionGenerator(JointInterface *j) : GazeMotionGenerator(j, 3, 1.0/Server::MOTION_UPDATERATE){
+}
+
+
+//! destructor
+EyeMotionGenerator::~EyeMotionGenerator(){
+}
+
+//! set up an eyemotion profile
+//! this will use speed and acceleration calc formulas from literature:
+//! \param dof id of joint
+//! \param target angle
+//! \param current angle
+void EyeMotionGenerator::setup_eyemotion(int dof, float target, float now){
+    //get distance to target:
+    float distance_abs = fabs(target - now);
+    //get max speed: factor can be found in encyc britannica: "linear.... being 300° per second for 10° and 500° per second for 30°" (max=700)
+    float max_speed = fmin(700.0, 10.0*distance_abs + 200.0);
+    //max accel: use data from ""Speed and Accuracy of Saccadic Eye Movements: Characteristics of Impulse Variability in the Oculomotor System"
+    //                 http://www-personal.umich.edu/~kornblum/files/journal_exp_psych_HPP_15-3.pdf
+    //           gathered from table2
+    float max_accel = fmin(80000.0, 1526.53*distance_abs + 10245.4);
+
+    //feed reflexxes api with data
+    reflexxes_set_input(dof, target, max_speed, max_accel);
+}
+
+//! calculate joint targets
+void EyeMotionGenerator::calculate_targets(){
+    //use the target values for a faster response
+    float neck_pan_now  = joint_interface->get_target_position(JointInterface::ID_NECK_PAN);
+    float neck_tilt_now = joint_interface->get_target_position(JointInterface::ID_NECK_TILT);
+
+    //calculate target angles for the eyes:
+    //right eye is dominant -> direct output
+    float eye_pan_r_target = (requested_gaze_state.pan + requested_gaze_state.vergence/2.0) - (neck_pan_now);
+
+    //left eye is non dominant -> filtered output: TODO: activate low pass filtered output
+    //FIXME: USE LOWPASS FILTER HERE --> output_angle[angle_names::EYE_PAN_L] + 0.1 * (eye_pan_l_target - output_angle[angle_names::EYE_PAN_L]) etc;
+    float eye_pan_l_target = (requested_gaze_state.pan - requested_gaze_state.vergence/2.0) - (neck_pan_now);
+
+    //tilt:
+    float eye_tilt_target = requested_gaze_state.tilt - (neck_tilt_now);
+
+    //fetch current angles:
+    float eye_pan_l_now = get_current_position(JointInterface::ID_EYES_LEFT_LR);
+    float eye_pan_r_now = get_current_position(JointInterface::ID_EYES_RIGHT_LR);
+    float eye_tilt_now  = get_current_position(JointInterface::ID_EYES_BOTH_UD);
+
+    //pass paramaters to reflexxes api:
+    setup_eyemotion(0, eye_pan_l_target, eye_pan_l_now);
+    setup_eyemotion(1, eye_pan_r_target, eye_pan_r_now);
+    setup_eyemotion(2, eye_tilt_target, eye_tilt_now);
+
+    //call reflexxes to handle profile calculation:
+    reflexxes_calculate_profile();
+
+    //tell the joint about the new values:
+    joint_interface->set_target_position(JointInterface::ID_EYES_LEFT_LR, reflexxes_position_output->NewPositionVector->VecData[0]);
+    joint_interface->set_target_position(JointInterface::ID_EYES_RIGHT_LR, reflexxes_position_output->NewPositionVector->VecData[1]);
+    joint_interface->set_target_position(JointInterface::ID_EYES_BOTH_UD,  reflexxes_position_output->NewPositionVector->VecData[2]);
+}
+
+
+//! pubish the calculated targets to the joint subsystem
+void EyeMotionGenerator::publish_targets(){
+    //publish values if there is an active gaze input within the last timerange
+    if (gaze_target_input_active()){
+        joint_interface->publish_target_position(JointInterface::ID_EYES_LEFT_LR);
+        joint_interface->publish_target_position(JointInterface::ID_EYES_RIGHT_LR);
+        joint_interface->publish_target_position(JointInterface::ID_EYES_BOTH_UD);
+    }
+}
diff --git a/src/server/eyebrow_motion_generator.cpp b/src/server/eyebrow_motion_generator.cpp
new file mode 100644
index 0000000..9dadf37
--- /dev/null
+++ b/src/server/eyebrow_motion_generator.cpp
@@ -0,0 +1,36 @@
+#include "server/eyebrow_motion_generator.h"
+#include "server/server.h"
+
+using namespace std;
+using namespace humotion;
+using namespace humotion::server;
+
+//! constructor
+EyebrowMotionGenerator::EyebrowMotionGenerator(JointInterface *j) : MotionGenerator(j){
+}
+
+
+//! destructor
+EyebrowMotionGenerator::~EyebrowMotionGenerator(){
+
+}
+
+//! calculate joint targets
+void EyebrowMotionGenerator::calculate_targets(){
+    //printf("> humotion: calculating eyebrow targets\n");
+    float eyebrow_left_target = requested_gaze_state.eyebrow_left;
+    float eyebrow_right_target = requested_gaze_state.eyebrow_right;
+
+    //store targets:
+    joint_interface->set_target_position(JointInterface::ID_EYES_LEFT_BROW, eyebrow_left_target);
+    joint_interface->set_target_position(JointInterface::ID_EYES_RIGHT_BROW, eyebrow_right_target);
+}
+
+//! publish targets to motor boards:
+void EyebrowMotionGenerator::publish_targets(){
+   //publish values if there is an active gaze input within the last timerange
+   if (gaze_target_input_active()){
+    joint_interface->publish_target_position(JointInterface::ID_EYES_LEFT_BROW);
+    joint_interface->publish_target_position(JointInterface::ID_EYES_RIGHT_BROW);
+   }
+}
diff --git a/src/server/eyelid_motion_generator.cpp b/src/server/eyelid_motion_generator.cpp
new file mode 100644
index 0000000..0b8afa9
--- /dev/null
+++ b/src/server/eyelid_motion_generator.cpp
@@ -0,0 +1,270 @@
+/*
+* This file is part of humotion
+*
+* Copyright(c) sschulz <AT> techfak.uni-bielefeld.de
+* http://opensource.cit-ec.de/projects/humotion
+*
+* This file may be licensed under the terms of the
+* GNU Lesser General Public License Version 3 (the ``LGPL''),
+* or (at your option) any later version.
+*
+* Software distributed under the License is distributed
+* on an ``AS IS'' basis, WITHOUT WARRANTY OF ANY KIND, either
+* express or implied. See the LGPL for the specific language
+* governing rights and limitations.
+*
+* You should have received a copy of the LGPL along with this
+* program. If not, go to http://www.gnu.org/licenses/lgpl.html
+* or write to the Free Software Foundation, Inc.,
+* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+*
+* The development of this software was supported by the
+* Excellence Cluster EXC 277 Cognitive Interaction Technology.
+* The Excellence Cluster EXC 277 is a grant of the Deutsche
+* Forschungsgemeinschaft (DFG) in the context of the German
+* Excellence Initiative.
+*/
+
+#include "server/eyelid_motion_generator.h"
+#include "server/server.h"
+
+using namespace boost;
+using namespace std;
+using namespace humotion;
+using namespace humotion::server;
+
+//saccade detection threshold in deg/s
+const float EyelidMotionGenerator::SACCADE_SPEED_THRESHOLD = 15.0; //deg/s
+//eyeblink duration:
+const float EyelidMotionGenerator::EYEBLINK_DURATION_MS    = 150.0;//ms
+//periodic eyeblinks: every 2..10s:
+const float EyelidMotionGenerator::EYEBLINK_EYERY_MS_MIN =  2000.0; //ms
+const float EyelidMotionGenerator::EYEBLINK_EYERY_MS_MAX = 10000.0; //ms
+//how many seconds do we block further blinks after each eyeblink?
+const float EyelidMotionGenerator::EYEBLINK_BLOCKING_TIME = 1000.0; //ms
+
+//! constructor
+EyelidMotionGenerator::EyelidMotionGenerator(JointInterface *j) : EyeMotionGenerator(j){
+    saccade_blink_active = false;
+    saccade_blink_requested = false;
+    eyelid_closed[LEFT] = false;
+    eyelid_closed[RIGHT] = false;
+}
+
+//! destructor
+EyelidMotionGenerator::~EyelidMotionGenerator(){
+}
+
+
+//! calculate joint targets
+//! \TODO: make up motion twice as slow as down motion
+void EyelidMotionGenerator::calculate_targets(){
+    //printf("> humotion: calculating eyelid targets\n");
+
+    //fetch current angles:
+    float eye_tilt_now  = get_current_position(JointInterface::ID_EYES_BOTH_UD);
+
+    //calculate left eyelid targets:
+    float eyelid_upper_left_target = eye_tilt_now + requested_gaze_state.eyelid_opening_upper;
+    float eyelid_lower_left_target = eye_tilt_now - requested_gaze_state.eyelid_opening_lower;
+
+    //calculate right eyelid targets:
+    float eyelid_upper_right_target = eye_tilt_now + requested_gaze_state.eyelid_opening_upper;
+    float eyelid_lower_right_target = eye_tilt_now - requested_gaze_state.eyelid_opening_lower;
+
+    //limit target angles:
+    eyelid_upper_left_target  = limit_target(JointInterface::ID_EYES_LEFT_LID_UPPER,  eyelid_upper_left_target);
+    eyelid_lower_left_target  = limit_target(JointInterface::ID_EYES_LEFT_LID_LOWER,  eyelid_lower_left_target);
+    eyelid_upper_right_target = limit_target(JointInterface::ID_EYES_RIGHT_LID_UPPER,  eyelid_upper_right_target);
+    eyelid_lower_right_target = limit_target(JointInterface::ID_EYES_RIGHT_LID_LOWER,  eyelid_lower_right_target);
+
+    //(temporarily) store the target
+    joint_interface->set_target_position(JointInterface::ID_EYES_LEFT_LID_UPPER,  eyelid_upper_left_target);
+    joint_interface->set_target_position(JointInterface::ID_EYES_LEFT_LID_LOWER,  eyelid_lower_left_target);
+    joint_interface->set_target_position(JointInterface::ID_EYES_RIGHT_LID_UPPER,  eyelid_upper_right_target);
+    joint_interface->set_target_position(JointInterface::ID_EYES_RIGHT_LID_LOWER,  eyelid_lower_right_target);
+
+    //check for saccade
+    check_for_saccade();
+
+    //is there a blink request?
+    start_external_eyeblinks(requested_gaze_state.eyeblink_request_left, requested_gaze_state.eyeblink_request_right);
+
+    //do we have a saccade & do we want to exec an eyeblink?
+    process_saccadic_eyeblinks();
+
+    //execute for periodic eyeblinks every ? ms
+    process_periodic_eyeblinks();
+
+    //close eyes again after a given timeout
+    handle_eyeblink_timeout();
+
+    //eyeblinks override position target (if necessary)
+    override_lids_for_eyeblink();    
+}
+
+//! process any external blink requests
+void EyelidMotionGenerator::start_external_eyeblinks(int duration_left, int duration_right){
+    //manual eyeblinks will ALWAYs get executed as we use a negative block timeout (=timout has already passed)
+    eyeblink_blocked_timeout = get_system_time() - posix_time::seconds(100);
+
+    if (duration_left == 0){
+        //nothing to do
+    }else if (duration_left < 0){
+        //infinite sleep -> close
+        eyelid_closed[LEFT] = true;
+    }else{
+        //timeout sleep
+        start_eyeblink(LEFT, duration_left);
+        eyelid_closed[LEFT] = false;
+    }
+
+    if (duration_right == 0){
+        //nothing to do
+    }else if (duration_right < 0){
+        //infinite sleep -> close
+        eyelid_closed[RIGHT] = true;
+    }else{
+        //timeout sleep
+        start_eyeblink(RIGHT, duration_right);
+        eyelid_closed[RIGHT] = false;
+    }
+}
+
+//! process saccadic blink requests
+//! -> when we do a saccade, the chances to blink are much higher
+void EyelidMotionGenerator::process_saccadic_eyeblinks(){
+    if (saccade_blink_requested){
+        //every n-th's saccade requests an eyeblink
+        //here: use 0.3 even though humans use bigger prob value (but that looks stupid on robot)
+        if ((rand()%3) == 0){
+            ///printf("> saccadic eyeblink:\n");
+            start_eyeblink(LEFT);
+            start_eyeblink(RIGHT);
+        }
+        saccade_blink_requested = false;
+    }
+}
+
+//! process periodic blink requests
+//! -> we want to have an eyeblink every n...m seconds
+void EyelidMotionGenerator::process_periodic_eyeblinks(){
+    if((eyeblink_active[LEFT]) || eyeblink_active[RIGHT]){
+        //calculate next timeout for a new periodic eyeblink
+        int milliseconds_to_next_blink = EYEBLINK_EYERY_MS_MIN + (rand()%(int)(EYEBLINK_EYERY_MS_MAX-EYEBLINK_EYERY_MS_MIN));
+        periodic_blink_start_time = get_system_time() +   posix_time::milliseconds(milliseconds_to_next_blink);
+    }
+
+    if (get_system_time() > periodic_blink_start_time){
+        ///printf("> periodic eyeblink:\n");
+        start_eyeblink(LEFT);
+        start_eyeblink(RIGHT);
+    }
+}
+
+//! handle eyeblink timeouts.
+//! this function will actually re-open the eyes after a predefined time
+void EyelidMotionGenerator::handle_eyeblink_timeout(){
+    boost::system_time now = get_system_time();
+
+    //take care of re-opening eye timeout:
+    for(int i=LEFT; i<=RIGHT; i++){
+        if (eyeblink_active[i]){
+            if (now >= eyeblink_timeout[i]){
+                eyeblink_active[i] = false;
+            }
+        }
+    }
+
+    //take care of blocking time
+    if (eyeblink_active[LEFT] || eyeblink_active[RIGHT]){
+        eyeblink_blocked_timeout = get_system_time() + posix_time::milliseconds(EYEBLINK_BLOCKING_TIME);
+    }
+
+
+}
+
+//! override eyelid positions
+//! this will override (=close) the eyelids for all possible eyeblink requests
+void EyelidMotionGenerator::override_lids_for_eyeblink(){
+    //close the requested eyelids
+    if (eyeblink_active[LEFT] || eyelid_closed[LEFT]){
+        close_eyelid(JointInterface::ID_EYES_LEFT_LID_UPPER);
+        close_eyelid(JointInterface::ID_EYES_LEFT_LID_LOWER);
+    }
+    if(eyeblink_active[RIGHT] || eyelid_closed[RIGHT]){
+        close_eyelid(JointInterface::ID_EYES_RIGHT_LID_UPPER);
+        close_eyelid(JointInterface::ID_EYES_RIGHT_LID_LOWER);
+    }
+}
+
+
+
+//! overwrite the intermediate target to close the given eyelid:
+void EyelidMotionGenerator::close_eyelid(int joint_id){
+    float value = 0.0;
+
+    //set upper to minimal allowed value (=as closed as possible) + a small offset
+    //set lower to the same value (instead of max) in order to avoid collisions
+    switch(joint_id){
+        default:
+            //no eyelid -> return
+            return;
+
+        case(JointInterface::ID_EYES_LEFT_LID_UPPER):
+        case(JointInterface::ID_EYES_LEFT_LID_LOWER):
+            //use the upper value + 10 deg as close state:
+            value = joint_interface->get_joint_min(JointInterface::ID_EYES_LEFT_LID_UPPER) + 10.0;
+            //overwrite last target_
+            joint_interface->set_target_position(joint_id, value);
+            break;
+
+        case(JointInterface::ID_EYES_RIGHT_LID_UPPER):
+        case(JointInterface::ID_EYES_RIGHT_LID_LOWER):
+            //use the upper value + 10 deg as close state:
+            value = joint_interface->get_joint_min(JointInterface::ID_EYES_RIGHT_LID_UPPER) + 10.0;
+            //overwrite last target_
+            joint_interface->set_target_position(joint_id, value);
+            break;
+    }
+}
+
+//! start an eyeblink request
+//! this will actually set a flag and a timeout for reopening the given eyelid pair again
+//! \param int id of side (LEFT or RIGHT)
+void EyelidMotionGenerator::start_eyeblink(int side, int duration){
+    if (get_system_time() < eyeblink_blocked_timeout){
+        //return if we are still in the block time
+        return;
+    }
+    //request for n ms eyeblink:
+    eyeblink_timeout[side] = get_system_time() + posix_time::milliseconds(duration);
+
+    eyeblink_active[side] = true;
+}
+
+//! check if there is an ongoing saccade:
+void EyelidMotionGenerator::check_for_saccade(){
+    if (get_eye_saccade_active()){
+        //this is a saccade, check if not already in saccade:
+        if (!saccade_blink_active){
+            //this is a new saccade! restart blink timer
+            saccade_blink_requested = true;
+            saccade_blink_active = true;
+        }
+    }else{
+        saccade_blink_active = false;
+    }
+}
+
+
+//! publish targets to motor boards:
+void EyelidMotionGenerator::publish_targets(){
+    //publish values if there is an active gaze input within the last timerange
+    if (gaze_target_input_active()){
+        joint_interface->publish_target_position(JointInterface::ID_EYES_LEFT_LID_UPPER);
+        joint_interface->publish_target_position(JointInterface::ID_EYES_LEFT_LID_LOWER);
+        joint_interface->publish_target_position(JointInterface::ID_EYES_RIGHT_LID_UPPER);
+        joint_interface->publish_target_position(JointInterface::ID_EYES_RIGHT_LID_LOWER);
+    }
+}
diff --git a/src/server/gaze_motion_generator.cpp b/src/server/gaze_motion_generator.cpp
new file mode 100644
index 0000000..9f34879
--- /dev/null
+++ b/src/server/gaze_motion_generator.cpp
@@ -0,0 +1,141 @@
+/*
+* This file is part of humotion
+*
+* Copyright(c) sschulz <AT> techfak.uni-bielefeld.de
+* http://opensource.cit-ec.de/projects/humotion
+*
+* This file may be licensed under the terms of the
+* GNU Lesser General Public License Version 3 (the ``LGPL''),
+* or (at your option) any later version.
+*
+* Software distributed under the License is distributed
+* on an ``AS IS'' basis, WITHOUT WARRANTY OF ANY KIND, either
+* express or implied. See the LGPL for the specific language
+* governing rights and limitations.
+*
+* You should have received a copy of the LGPL along with this
+* program. If not, go to http://www.gnu.org/licenses/lgpl.html
+* or write to the Free Software Foundation, Inc.,
+* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+*
+* The development of this software was supported by the
+* Excellence Cluster EXC 277 Cognitive Interaction Technology.
+* The Excellence Cluster EXC 277 is a grant of the Deutsche
+* Forschungsgemeinschaft (DFG) in the context of the German
+* Excellence Initiative.
+*/
+
+#include "server/gaze_motion_generator.h"
+#include "server/server.h"
+
+using namespace std;
+using namespace humotion;
+using namespace humotion::server;
+
+//saccade detection threshold in deg/s
+///const float GazeMotionGenerator::SACCADE_SPEED_THRESHOLD = 15.0;
+//some constants to decide if the requested move will trigger a neck or eye saccade
+const float GazeMotionGenerator::NECK_SACCADE_THRESHOLD      = 15.0; //deg
+const float GazeMotionGenerator::EYE_SACCADE_SPEED_THRESHOLD = 15.0; //deg/s
+//close to ocolumotor-range?
+const float GazeMotionGenerator::OMR_LIMIT_TRIGGERS_NECK_SACCADE = 0.95; //0.95 = reaching 95% of OMR will trigger a correction
+
+
+//! constructor
+GazeMotionGenerator::GazeMotionGenerator(JointInterface *j, int dof, float t) : ReflexxesMotionGenerator(j, dof, t){
+}
+
+//! destructor
+GazeMotionGenerator::~GazeMotionGenerator(){
+}
+
+//! update gaze target:
+//! \param GazeState with target values for the overall gaze
+void GazeMotionGenerator::set_gaze_target(GazeState new_gaze_target){
+    if (requested_gaze_state.type == GazeState::RELATIVE){
+        //relative gaze target -> calculate target angle:
+        printf("> FIXME: add code to interpolate the current position based on timestamp of gaze correction\n");
+        exit(0);
+    }
+
+    //check magnitude of gaze change to detect eye-neck saccades:
+    float dist = fabs(requested_gaze_state.distance_pt_abs(new_gaze_target));
+
+    //check requested speed
+    float speed = fabs(requested_gaze_state.distance_pt_abs(new_gaze_target)) / (new_gaze_target.timestamp-requested_gaze_state.timestamp);
+
+    //check magnitude and speed of gaze change to detect eye-neck saccades:
+    if (dist > NECK_SACCADE_THRESHOLD){
+        //the next saccade has to use neck motion as well
+        if (speed > EYE_SACCADE_SPEED_THRESHOLD){
+            neck_saccade_requested = true;
+        }
+    }else{
+        neck_saccade_requested = false;
+    }
+
+    //check for eye getting close to ocolomotor range
+    float eye_pos_l = joint_interface->get_ts_position(JointInterface::ID_EYES_LEFT_LR).get_newest_value();
+    float eye_pos_r = joint_interface->get_ts_position(JointInterface::ID_EYES_RIGHT_LR).get_newest_value();
+    float eye_pos_ud = joint_interface->get_ts_position(JointInterface::ID_EYES_BOTH_UD).get_newest_value();
+
+    //min/max bounds:
+    float left_min  = OMR_LIMIT_TRIGGERS_NECK_SACCADE * joint_interface->get_joint_min(JointInterface::ID_EYES_LEFT_LR);
+    float left_max  = OMR_LIMIT_TRIGGERS_NECK_SACCADE * joint_interface->get_joint_max(JointInterface::ID_EYES_LEFT_LR);
+    float right_min = OMR_LIMIT_TRIGGERS_NECK_SACCADE * joint_interface->get_joint_min(JointInterface::ID_EYES_RIGHT_LR);
+    float right_max = OMR_LIMIT_TRIGGERS_NECK_SACCADE * joint_interface->get_joint_max(JointInterface::ID_EYES_RIGHT_LR);
+    float ud_min    = OMR_LIMIT_TRIGGERS_NECK_SACCADE * joint_interface->get_joint_min(JointInterface::ID_EYES_BOTH_UD);
+    float ud_max    = OMR_LIMIT_TRIGGERS_NECK_SACCADE * joint_interface->get_joint_max(JointInterface::ID_EYES_BOTH_UD);
+
+    if (
+        (eye_pos_l < left_min) || (eye_pos_l > left_max) ||
+        (eye_pos_r < right_min) || (eye_pos_r > right_max) ||
+        (eye_pos_ud < ud_min) || (eye_pos_ud > ud_max)){
+        //the eyeball gets close to OMR, activate a neck compensation motion:
+        neck_saccade_omr = true;
+    }else{
+        neck_saccade_omr = false;
+    }
+
+    //use base class set method:
+    MotionGenerator::set_gaze_target(new_gaze_target);
+}
+
+//! check if an eye saccade is active:
+bool GazeMotionGenerator::get_eye_saccade_active(){
+    bool saccade_active;
+
+    float speed_left  = joint_interface->get_ts_speed(JointInterface::ID_EYES_LEFT_LR).get_newest_value();
+    float speed_right = joint_interface->get_ts_speed(JointInterface::ID_EYES_RIGHT_LR).get_newest_value();
+    float speed_tilt  = joint_interface->get_ts_speed(JointInterface::ID_EYES_BOTH_UD).get_newest_value();
+
+    float speed_total_l = sqrt(speed_left*speed_left + speed_tilt*speed_tilt);
+    float speed_total_r = sqrt(speed_right*speed_right + speed_tilt*speed_tilt);
+
+    //thresholding
+    if ((speed_total_l > EYE_SACCADE_SPEED_THRESHOLD) || (speed_total_r > EYE_SACCADE_SPEED_THRESHOLD)){
+        //this is a saccade
+        saccade_active = true;
+    }else{
+        saccade_active = false;
+    }
+
+    return saccade_active;
+}
+
+//! get overall gaze
+GazeState GazeMotionGenerator::get_current_gaze(){
+    //shortcut, makes the following easier to read
+    JointInterface *j = joint_interface;
+
+    GazeState gaze = requested_gaze_state;
+
+    gaze.pan = j->get_ts_position(JointInterface::ID_NECK_PAN).get_newest_value() +
+            (j->get_ts_position(JointInterface::ID_EYES_LEFT_LR).get_newest_value() + j->get_ts_position(JointInterface::ID_EYES_RIGHT_LR).get_newest_value())/2.0;
+    gaze.tilt = j->get_ts_position(JointInterface::ID_NECK_TILT).get_newest_value() + j->get_ts_position(JointInterface::ID_EYES_BOTH_UD).get_newest_value();
+    gaze.roll = j->get_ts_position(JointInterface::ID_NECK_ROLL).get_newest_value();
+
+    gaze.vergence = j->get_ts_position(JointInterface::ID_EYES_LEFT_LR).get_newest_value() - j->get_ts_position(JointInterface::ID_EYES_RIGHT_LR).get_newest_value();
+
+    return gaze;
+}
diff --git a/src/server/joint_interface.cpp b/src/server/joint_interface.cpp
new file mode 100644
index 0000000..d8292a1
--- /dev/null
+++ b/src/server/joint_interface.cpp
@@ -0,0 +1,254 @@
+/*
+* This file is part of humotion
+*
+* Copyright(c) sschulz <AT> techfak.uni-bielefeld.de
+* http://opensource.cit-ec.de/projects/humotion
+*
+* This file may be licensed under the terms of the
+* GNU Lesser General Public License Version 3 (the ``LGPL''),
+* or (at your option) any later version.
+*
+* Software distributed under the License is distributed
+* on an ``AS IS'' basis, WITHOUT WARRANTY OF ANY KIND, either
+* express or implied. See the LGPL for the specific language
+* governing rights and limitations.
+*
+* You should have received a copy of the LGPL along with this
+* program. If not, go to http://www.gnu.org/licenses/lgpl.html
+* or write to the Free Software Foundation, Inc.,
+* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+*
+* The development of this software was supported by the
+* Excellence Cluster EXC 277 Cognitive Interaction Technology.
+* The Excellence Cluster EXC 277 is a grant of the Deutsche
+* Forschungsgemeinschaft (DFG) in the context of the German
+* Excellence Initiative.
+*/
+
+#include "server/joint_interface.h"
+#include "server/controller.h"
+
+using namespace std;
+using namespace humotion;
+using namespace humotion::server;
+using namespace boost;
+
+
+//! constructor
+JointInterface::JointInterface(){
+    framerate = 50.0;
+    mouth_enabled = false;
+    gaze_enabled  = false;
+}
+
+//! destructor
+JointInterface::~JointInterface(){
+}
+
+//! set joint target position
+//! \param joint_id of joint
+//! \param float position
+void JointInterface::set_target_position(int joint_id, float position){
+    assert(joint_id < JOINT_ID_ENUM_SIZE);
+
+    //update current value
+    joint_target[joint_id] = position;
+}
+
+//! fetch target position
+//! \param joint_id of joint
+float JointInterface::get_target_position(int joint_id){
+    assert(joint_id < JOINT_ID_ENUM_SIZE);
+    return joint_target[joint_id];
+}
+
+//! incoming position data
+//! \param joint name
+//! \param position
+//! \param timestamp when the position was measured
+void JointInterface::store_incoming_position(int joint_id, float position, double timestamp){
+    //lock the tsd_list for this access. by doing this we assure
+    //that no other thread accessing this element can diturb the
+    //following atomic instructions:
+    mutex::scoped_lock scoped_lock(joint_ts_position_map_access_mutex);
+
+    //printf("> humotion: incoming joint position for joint id 0x%02X = %4.2f (ts=%.2f)\n",joint_id,position,timestamp);
+    joint_ts_position_map[joint_id].insert(timestamp, position);
+
+    incoming_position_count++;
+}
+
+//! return incoming position data count & clear this counter
+//! this can be used as a keep alive status check
+//! \return number of incoming joint positions since the last call
+unsigned int JointInterface::get_and_clear_incoming_position_count(){
+    unsigned int i = incoming_position_count;
+    incoming_position_count = 0;
+    return i;
+}
+
+//! incoming speed data
+//! \param joint name
+//! \param speed
+//! \param timestamp when the position was measured
+void JointInterface::store_incoming_speed(int joint_id, float speed, double timestamp){
+    //lock the tsd_list for this access. by doing this we assure
+    //that no other thread accessing this element can diturb the
+    //following atomic instructions:
+    mutex::scoped_lock scoped_lock(joint_ts_speed_map_access_mutex);
+
+    //printf("> humotion: incoming joint speed for joint id 0x%02X = %4.2f (ts=%.2f)\n",joint_id,speed,timestamp);
+    joint_ts_speed_map[joint_id].insert(timestamp, speed);
+}
+
+//! return the timestamped float for the given joints position
+TimestampedList JointInterface::get_ts_position(int joint_id){
+    //lock the tsd_list for this access. by doing this we assure
+    //that no other thread accessing this element can diturb the
+    //following atomic instructions:
+    mutex::scoped_lock scoped_lock(joint_ts_position_map_access_mutex);
+
+    //search map:
+    joint_tsl_map_t::iterator it = joint_ts_position_map.find(joint_id);
+
+    if (it == joint_ts_position_map.end()){
+        printf("> humotion: no ts_position for joint id 0x%02X found\n", joint_id);
+        return TimestampedList();
+    }
+
+    //ok fine, we found our value:
+    return it->second;
+}
+
+//! return the timestamped float for the given joints speed
+TimestampedList JointInterface::get_ts_speed(int joint_id){
+    //lock the tsd_list for this access. by doing this we assure
+    //that no other thread accessing this element can diturb the
+    //following atomic instructions:
+    mutex::scoped_lock scoped_lock(joint_ts_speed_map_access_mutex);
+
+    //search map:
+    joint_tsl_map_t::iterator it = joint_ts_speed_map.find(joint_id);
+
+    if (it == joint_ts_speed_map.end()){
+        printf("> humotion: no ts_speed for joint id 0x%02X found\n", joint_id);
+        return TimestampedList();
+    }
+
+    //ok fine, we found our value:
+    return it->second;
+}
+
+//! set framerate
+void JointInterface::set_framerate(float f){
+    framerate = f;
+}
+
+//! enable all mouth joints
+void JointInterface::enable_mouth_joints(){
+    //already enabled? skip this
+    if (mouth_enabled){
+        return;
+    }
+
+    printf("> humotion: ENABLING MOUTH JOINTS\n");
+    enable_joint(ID_LIP_LEFT_UPPER);
+    enable_joint(ID_LIP_LEFT_LOWER);
+    enable_joint(ID_LIP_CENTER_UPPER);
+    enable_joint(ID_LIP_CENTER_LOWER);
+    enable_joint(ID_LIP_RIGHT_UPPER);
+    enable_joint(ID_LIP_RIGHT_LOWER);
+    mouth_enabled = true;
+}
+
+
+//! disable all mouth joints
+void JointInterface::disable_mouth_joints(){
+    //already disabled? skip this
+    if (!mouth_enabled){
+        return;
+    }
+
+    printf("> humotion: DISABLING MOUTH JOINTS\n");
+    disable_joint(ID_LIP_LEFT_UPPER);
+    disable_joint(ID_LIP_LEFT_LOWER);
+    disable_joint(ID_LIP_CENTER_UPPER);
+    disable_joint(ID_LIP_CENTER_LOWER);
+    disable_joint(ID_LIP_RIGHT_UPPER);
+    disable_joint(ID_LIP_RIGHT_LOWER);
+    mouth_enabled = false;
+}
+
+//! enable all gaze joints
+void JointInterface::enable_gaze_joints(){
+    //already enabled? skip this
+    if (gaze_enabled){
+        return;
+    }
+
+    printf("> humotion: ENABLING GAZE JOINTS\n");
+    enable_joint(ID_EYES_LEFT_LR);
+    enable_joint(ID_EYES_RIGHT_LR);
+    enable_joint(ID_EYES_BOTH_UD);
+
+    enable_joint(ID_EYES_LEFT_LID_UPPER);
+    enable_joint(ID_EYES_LEFT_LID_LOWER);
+    enable_joint(ID_EYES_RIGHT_LID_UPPER);
+    enable_joint(ID_EYES_RIGHT_LID_LOWER);
+
+    enable_joint(ID_EYES_LEFT_BROW);
+    enable_joint(ID_EYES_RIGHT_BROW);
+
+    enable_joint(ID_NECK_PAN);
+    enable_joint(ID_NECK_TILT);
+    enable_joint(ID_NECK_ROLL);
+
+    gaze_enabled = true;
+}
+
+//! disable all gaze joints
+void JointInterface::disable_gaze_joints(){
+    //already disabled? skip this
+    if (!gaze_enabled){
+        return;
+    }
+
+    printf("> humotion: DISABLING GAZE JOINTS\n");
+    disable_joint(ID_EYES_LEFT_LR);
+    disable_joint(ID_EYES_RIGHT_LR);
+    disable_joint(ID_EYES_BOTH_UD);
+
+    disable_joint(ID_EYES_LEFT_LID_UPPER);
+    disable_joint(ID_EYES_LEFT_LID_LOWER);
+    disable_joint(ID_EYES_RIGHT_LID_UPPER);
+    disable_joint(ID_EYES_RIGHT_LID_LOWER);
+
+    disable_joint(ID_EYES_LEFT_BROW);
+    disable_joint(ID_EYES_RIGHT_BROW);
+
+    disable_joint(ID_NECK_PAN);
+    disable_joint(ID_NECK_TILT);
+    disable_joint(ID_NECK_ROLL);
+
+    gaze_enabled = false;
+}
+
+//! fetch maximum allowable joint position
+//! \return max position
+float JointInterface::get_joint_max(int joint_id){
+    assert((joint_id > 0) && (joint_id < JOINT_ID_ENUM_SIZE));
+    return joint_max[joint_id];
+}
+
+//! fetch minimum allowable joint position
+//! \return min position
+float JointInterface::get_joint_min(int joint_id){
+    assert((joint_id > 0) && (joint_id < JOINT_ID_ENUM_SIZE));
+    return joint_min[joint_id];
+}
+
+//! check if joint position map is empty
+//! \return true if empty
+bool JointInterface::get_joint_position_map_empty(){
+    return (joint_ts_position_map.empty());
+}
diff --git a/src/server/middleware.cpp b/src/server/middleware.cpp
new file mode 100644
index 0000000..4fd34c0
--- /dev/null
+++ b/src/server/middleware.cpp
@@ -0,0 +1,44 @@
+/*
+* This file is part of humotion
+*
+* Copyright(c) sschulz <AT> techfak.uni-bielefeld.de
+* http://opensource.cit-ec.de/projects/humotion
+*
+* This file may be licensed under the terms of the
+* GNU Lesser General Public License Version 3 (the ``LGPL''),
+* or (at your option) any later version.
+*
+* Software distributed under the License is distributed
+* on an ``AS IS'' basis, WITHOUT WARRANTY OF ANY KIND, either
+* express or implied. See the LGPL for the specific language
+* governing rights and limitations.
+*
+* You should have received a copy of the LGPL along with this
+* program. If not, go to http://www.gnu.org/licenses/lgpl.html
+* or write to the Free Software Foundation, Inc.,
+* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+*
+* The development of this software was supported by the
+* Excellence Cluster EXC 277 Cognitive Interaction Technology.
+* The Excellence Cluster EXC 277 is a grant of the Deutsche
+* Forschungsgemeinschaft (DFG) in the context of the German
+* Excellence Initiative.
+*/
+
+#include "server/middleware.h"
+
+using namespace std;
+using namespace humotion;
+using namespace humotion::server;
+
+//! constructor
+//! open a new Middleware instance.
+Middleware::Middleware(string scope, Controller *c){
+    controller = c;
+    base_scope = scope;
+}
+
+//! destructor
+Middleware::~Middleware(){
+}
+
diff --git a/src/server/middleware_ros.cpp b/src/server/middleware_ros.cpp
new file mode 100644
index 0000000..96fcb41
--- /dev/null
+++ b/src/server/middleware_ros.cpp
@@ -0,0 +1,135 @@
+/*
+* This file is part of humotion
+*
+* Copyright(c) sschulz <AT> techfak.uni-bielefeld.de
+* http://opensource.cit-ec.de/projects/humotion
+*
+* This file may be licensed under the terms of the
+* GNU Lesser General Public License Version 3 (the ``LGPL''),
+* or (at your option) any later version.
+*
+* Software distributed under the License is distributed
+* on an ``AS IS'' basis, WITHOUT WARRANTY OF ANY KIND, either
+* express or implied. See the LGPL for the specific language
+* governing rights and limitations.
+*
+* You should have received a copy of the LGPL along with this
+* program. If not, go to http://www.gnu.org/licenses/lgpl.html
+* or write to the Free Software Foundation, Inc.,
+* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+*
+* The development of this software was supported by the
+* Excellence Cluster EXC 277 Cognitive Interaction Technology.
+* The Excellence Cluster EXC 277 is a grant of the Deutsche
+* Forschungsgemeinschaft (DFG) in the context of the German
+* Excellence Initiative.
+*/
+
+#include "server/middleware_ros.h"
+
+#ifdef ROS_SUPPORT
+
+#include <boost/range/algorithm/remove_if.hpp>
+#include <boost/algorithm/string/classification.hpp>
+using namespace std;
+using namespace boost;
+using namespace humotion;
+using namespace humotion::server;
+
+//! constructor
+MiddlewareROS::MiddlewareROS(string scope, Controller *c) : Middleware(scope, c){
+
+
+    //start ros core?
+    if (ros::isInitialized()){
+       //oh another process is doing ros comm, fine, we do not need to call it
+        tick_necessary = false;
+    }else{
+        //we have to take care of ros
+        printf("> no active ros middleware, calling ros::init() and we will call tick() periodically!");
+        string node_name = "humotion_server__"+ scope;
+        node_name.erase(boost::remove_if(node_name, boost::is_any_of("/")), node_name.end());
+        printf("> registering on ROS as node %s\n",node_name.c_str());
+        ros::M_string no_remapping;
+        ros::init(no_remapping, node_name);
+        tick_necessary = true;
+    }
+
+    //create node handle
+    ros::NodeHandle n;
+
+    //set up subscribers:
+    mouth_target_subscriber = n.subscribe(scope + "/humotion/mouth/target", 150, &MiddlewareROS::incoming_mouth_target , this, ros::TransportHints().unreliable());
+    gaze_target_subscriber  = n.subscribe(scope + "/humotion/gaze/target",  150, &MiddlewareROS::incoming_gaze_target, this, ros::TransportHints().unreliable());
+
+}
+
+//! destructor
+MiddlewareROS::~MiddlewareROS(){
+}
+
+//! connection ok?
+//! \return true if conn is alive
+bool MiddlewareROS::ok(){
+    return ros::ok();
+}
+
+//! do a single tick
+void MiddlewareROS::tick(){
+    if (tick_necessary){
+        ros::spinOnce();
+    }
+}
+
+//! callback to handle incoming mouth  target
+void MiddlewareROS::incoming_mouth_target(const humotion::mouth::ConstPtr& msg){
+    //printf("> incoming mouth_target\n");
+    MouthState mouth_state;
+
+    mouth_state.position_left   = msg->position.left;
+    mouth_state.position_center = msg->position.center;
+    mouth_state.position_right  = msg->position.right;
+
+    mouth_state.opening_left   = msg->opening.left;
+    mouth_state.opening_center = msg->opening.center;
+    mouth_state.opening_right  = msg->opening.right;
+
+    controller->set_mouth_target(mouth_state);
+}
+
+//! this provides a consistent transformation of ros ts to double
+double MiddlewareROS::convert_ros_to_timestamp_ms(ros::Time t){
+        return t.sec + t.nsec/1000000000.0;
+}
+
+//! callback to handle incoming gaze  target
+void MiddlewareROS::incoming_gaze_target(const humotion::gaze::ConstPtr& msg){
+    ///printf("> incoming gaze_target [P:%3.1f, T:%3.1f, R:%3.1f] %s\n", msg->pan, msg->tilt, msg->roll, msg->type==humotion::gaze::ABSOLUTE?"ABSOLUTE":"RELATIVE");
+    GazeState gaze_state;
+
+    gaze_state.type = msg->type;
+    gaze_state.pan  = msg->pan;
+    gaze_state.tilt = msg->tilt;
+    gaze_state.roll = msg->roll;
+    gaze_state.vergence = msg->vergence;
+
+    gaze_state.pan_offset  = msg->pan_offset;
+    gaze_state.tilt_offset = msg->tilt_offset;
+    gaze_state.roll_offset = msg->roll_offset;
+
+    gaze_state.eyelid_opening_upper = msg->eyelid_opening_upper;
+    gaze_state.eyelid_opening_lower = msg->eyelid_opening_lower;
+
+    gaze_state.eyebrow_left = msg->eyebrow_left;
+    gaze_state.eyebrow_right = msg->eyebrow_right;
+
+    gaze_state.eyeblink_request_left = msg->eyeblink_request_left;
+    gaze_state.eyeblink_request_right = msg->eyeblink_request_right;
+
+    gaze_state.timestamp = convert_ros_to_timestamp_ms(msg->header.stamp);
+
+    controller->set_gaze_target(gaze_state);
+
+}
+
+#endif
diff --git a/src/server/middleware_rsb.cpp b/src/server/middleware_rsb.cpp
new file mode 100644
index 0000000..d6b2e3f
--- /dev/null
+++ b/src/server/middleware_rsb.cpp
@@ -0,0 +1,145 @@
+/*
+* This file is part of humotion
+*
+* Copyright(c) sschulz <AT> techfak.uni-bielefeld.de
+* http://opensource.cit-ec.de/projects/humotion
+*
+* This file may be licensed under the terms of the
+* GNU Lesser General Public License Version 3 (the ``LGPL''),
+* or (at your option) any later version.
+*
+* Software distributed under the License is distributed
+* on an ``AS IS'' basis, WITHOUT WARRANTY OF ANY KIND, either
+* express or implied. See the LGPL for the specific language
+* governing rights and limitations.
+*
+* You should have received a copy of the LGPL along with this
+* program. If not, go to http://www.gnu.org/licenses/lgpl.html
+* or write to the Free Software Foundation, Inc.,
+* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+*
+* The development of this software was supported by the
+* Excellence Cluster EXC 277 Cognitive Interaction Technology.
+* The Excellence Cluster EXC 277 is a grant of the Deutsche
+* Forschungsgemeinschaft (DFG) in the context of the German
+* Excellence Initiative.
+*/
+
+#include "server/middleware_rsb.h"
+
+#ifdef RSB_SUPPORT
+
+#define BOOST_SIGNALS_NO_DEPRECATION_WARNING 1
+#include <rsb/Listener.h>
+#include <rsb/patterns/RemoteServer.h>
+#include <rsb/MetaData.h>
+#include <rsb/converter/Repository.h>
+#include <rsb/converter/ProtocolBufferConverter.h>
+#include <rsb/Factory.h>
+
+
+
+using namespace std;
+using namespace boost;
+using namespace humotion;
+using namespace humotion::server;
+using namespace rsb;
+using namespace rsb::patterns;
+
+//! constructor
+MiddlewareRSB::MiddlewareRSB(string scope, Controller *c) : Middleware(scope, c){
+    printf("> registering converters\n");
+
+    //converter for GazeTarget
+    rsb::converter::Converter<string>::Ptr gazeTargetConverter(new rsb::converter::ProtocolBufferConverter<rst::robot::HumotionGazeTarget>());
+    rsb::converter::converterRepository<string>()->registerConverter(gazeTargetConverter);
+
+    //converter for MouthTarget
+    rsb::converter::Converter<string>::Ptr mouthTargetConverter(new rsb::converter::ProtocolBufferConverter<rst::robot::MouthTarget>());
+    rsb::converter::converterRepository<string>()->registerConverter(mouthTargetConverter);
+
+    //first get a factory instance that is used to create RSB domain objects
+    Factory &factory = getFactory();
+
+    //create listeners
+    mouth_target_listener = factory.createListener(base_scope + "/humotion/mouth/target");
+    mouth_target_listener->addHandler(HandlerPtr(new DataFunctionHandler<rst::robot::MouthTarget> (boost::bind(&MiddlewareRSB::incoming_mouth_target, this, _1))));
+
+    gaze_target_listener  = factory.createListener(base_scope + "/humotion/gaze/target");
+    gaze_target_listener->addHandler(HandlerPtr(new EventFunctionHandler(boost::bind(&MiddlewareRSB::incoming_gaze_target, this, _1))));
+
+    //informer->publish(gaze_target);
+    printf("> MiddlewareRSB initialised\n");
+}
+
+
+//! destructor
+MiddlewareRSB::~MiddlewareRSB(){
+}
+
+//! connection ok?
+//! \return true if conn is alive
+bool MiddlewareRSB::ok(){
+    return true;
+}
+
+//! do a single tick
+void MiddlewareRSB::tick(){
+    //nothing to do
+}
+
+//! callback to handle incoming mouth  target
+void MiddlewareRSB::incoming_mouth_target(boost::shared_ptr<rst::robot::MouthTarget> msg){
+    //printf("> incoming mouth_target\n");
+    MouthState mouth_state;
+
+    mouth_state.position_left   = msg->position_left();
+    mouth_state.position_center = msg->position_center();
+    mouth_state.position_right  = msg->position_right();
+
+    mouth_state.opening_left   = msg->opening_left();
+    mouth_state.opening_center = msg->opening_center();
+    mouth_state.opening_right  = msg->opening_right();
+
+    controller->set_mouth_target(mouth_state);
+}
+
+//! callback to handle incoming gaze  target
+void MiddlewareRSB::incoming_gaze_target(rsb::EventPtr event){
+    //printf("> incoming gaze_target [P:%3.1f, T:%3.1f, R:%3.1f]\n", msg->pan(), msg->tilt(), msg->roll());
+
+    boost::shared_ptr<void> ev_data = event->getData();
+    rst::robot::HumotionGazeTarget *msg = (rst::robot::HumotionGazeTarget*) ev_data.get();
+
+    GazeState gaze_state;
+
+    if (msg->type() == rst::robot::HumotionGazeTarget::ABSOLUTE){
+        gaze_state.type = GazeState::ABSOLUTE;
+    }else{
+        gaze_state.type = GazeState::RELATIVE;
+    }
+
+    gaze_state.pan  = msg->pan();
+    gaze_state.tilt = msg->tilt();
+    gaze_state.roll = msg->roll();
+    gaze_state.vergence = msg->vergence();
+
+    gaze_state.pan_offset  = msg->pan_offset();
+    gaze_state.tilt_offset = msg->tilt_offset();
+    gaze_state.roll_offset = msg->roll_offset();
+
+    gaze_state.eyelid_opening_upper = msg->eyelid_opening_upper();
+    gaze_state.eyelid_opening_lower = msg->eyelid_opening_lower();
+
+    gaze_state.eyebrow_left = msg->eyebrow_left();
+    gaze_state.eyebrow_right = msg->eyebrow_right();
+
+    gaze_state.eyeblink_request_left = msg->eyeblink_request_left();
+    gaze_state.eyeblink_request_right = msg->eyeblink_request_right();
+
+    gaze_state.timestamp = event->getMetaData().getCreateTime() / 1000.0; //createTime() returns milliseconds -> convert to seconds
+
+    controller->set_gaze_target(gaze_state);
+}
+
+#endif
diff --git a/src/server/motion_generator.cpp b/src/server/motion_generator.cpp
new file mode 100644
index 0000000..8d11d2f
--- /dev/null
+++ b/src/server/motion_generator.cpp
@@ -0,0 +1,119 @@
+/*
+* This file is part of humotion
+*
+* Copyright(c) sschulz <AT> techfak.uni-bielefeld.de
+* http://opensource.cit-ec.de/projects/humotion
+*
+* This file may be licensed under the terms of the
+* GNU Lesser General Public License Version 3 (the ``LGPL''),
+* or (at your option) any later version.
+*
+* Software distributed under the License is distributed
+* on an ``AS IS'' basis, WITHOUT WARRANTY OF ANY KIND, either
+* express or implied. See the LGPL for the specific language
+* governing rights and limitations.
+*
+* You should have received a copy of the LGPL along with this
+* program. If not, go to http://www.gnu.org/licenses/lgpl.html
+* or write to the Free Software Foundation, Inc.,
+* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+*
+* The development of this software was supported by the
+* Excellence Cluster EXC 277 Cognitive Interaction Technology.
+* The Excellence Cluster EXC 277 is a grant of the Deutsche
+* Forschungsgemeinschaft (DFG) in the context of the German
+* Excellence Initiative.
+*/
+
+#include "server/motion_generator.h"
+
+using namespace std;
+using namespace humotion;
+using namespace humotion::server;
+using namespace boost;
+
+//! constructor
+MotionGenerator::MotionGenerator(JointInterface *j){
+    joint_interface = j;
+}
+
+
+//! destructor
+MotionGenerator::~MotionGenerator(){
+}
+
+//! fetch thr latest (=current) position of a joint
+//! \param joint_id
+//! \return float value of joint position
+float MotionGenerator::get_current_position(int joint_id){
+    return joint_interface->get_ts_position(joint_id).get_newest_value();
+}
+
+//! update gaze target:
+//! \param GazeState with target values for the overall gaze
+void MotionGenerator::set_gaze_target(GazeState new_gaze_target){
+    //store value for next iteration
+    requested_gaze_state        = new_gaze_target;
+
+    //keep track if the gaze targets are comming in regulary
+    last_gaze_target_update = get_system_time();
+}
+
+//! update mouth state:
+//! \param MouthState with target values for the mouth joints
+void MotionGenerator::set_mouth_target(MouthState s){
+    //store value
+    requested_mouth_target = s;
+
+    //keep track if the mouth targets are comming in regulary
+    last_mouth_target_update = get_system_time();
+}
+
+
+//! was there incoming gaze data the last second?
+//! \return true if there was data incoming in the last second, false otherwise
+bool MotionGenerator::gaze_target_input_active(){
+    if (last_gaze_target_update + posix_time::milliseconds(1000) > get_system_time() ){
+        //incoming data -> if gaze is disabled, enable it!
+        joint_interface->enable_gaze_joints();
+        return true;
+    }else{
+        //no incoming data, disable!
+        joint_interface->disable_gaze_joints();
+        return false;
+    }
+}
+
+//! was there incoming mouth data the last second?
+//! \return true if there was data incoming in the last second, false otherwise
+bool MotionGenerator::mouth_target_input_active(){
+    if (last_mouth_target_update + posix_time::milliseconds(1000) > get_system_time() ){
+        //incoming data -> if mouth is disabled, enable it!
+        joint_interface->enable_mouth_joints();
+        return true;
+    }else{
+        //no incoming data, disable!
+        joint_interface->disable_mouth_joints();
+        return false;
+    }
+}
+
+//! limit target to min/max bounds:
+float MotionGenerator::limit_target(int joint_id, float val){
+    assert(joint_id < JointInterface::JOINT_ID_ENUM_SIZE);
+
+    //fetch min/max for joint:
+    float min = joint_interface->get_joint_min(joint_id);
+    float max = joint_interface->get_joint_max(joint_id);
+
+    if (max < min){
+        printf("> ERROR: how can min (%4.2f) be bigger than max (%4.2f)?? FIX THIS! EXITING NOW\n",min,max);
+        exit(0);
+    }
+
+    val = fmin(val, max);
+    val = fmax(val, min);
+
+    return val;
+}
+
diff --git a/src/server/mouth_motion_generator.cpp b/src/server/mouth_motion_generator.cpp
new file mode 100644
index 0000000..a95b5b8
--- /dev/null
+++ b/src/server/mouth_motion_generator.cpp
@@ -0,0 +1,150 @@
+/*
+* This file is part of humotion
+*
+* Copyright(c) sschulz <AT> techfak.uni-bielefeld.de
+* http://opensource.cit-ec.de/projects/humotion
+*
+* This file may be licensed under the terms of the
+* GNU Lesser General Public License Version 3 (the ``LGPL''),
+* or (at your option) any later version.
+*
+* Software distributed under the License is distributed
+* on an ``AS IS'' basis, WITHOUT WARRANTY OF ANY KIND, either
+* express or implied. See the LGPL for the specific language
+* governing rights and limitations.
+*
+* You should have received a copy of the LGPL along with this
+* program. If not, go to http://www.gnu.org/licenses/lgpl.html
+* or write to the Free Software Foundation, Inc.,
+* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+*
+* The development of this software was supported by the
+* Excellence Cluster EXC 277 Cognitive Interaction Technology.
+* The Excellence Cluster EXC 277 is a grant of the Deutsche
+* Forschungsgemeinschaft (DFG) in the context of the German
+* Excellence Initiative.
+*/
+
+#include "server/mouth_motion_generator.h"
+
+using namespace std;
+using namespace humotion;
+using namespace humotion::server;
+
+//minimum mouth opening:
+const float MouthMotionGenerator::MOUTH_MIN_OPENING = 9.0; //mm
+
+//! constructor
+MouthMotionGenerator::MouthMotionGenerator(JointInterface *j) : MotionGenerator(j){
+}
+
+//! destructor
+MouthMotionGenerator::~MouthMotionGenerator(){
+
+}
+
+//! calculate joint targets
+void MouthMotionGenerator::calculate_targets(){
+    ///printf("> humotion: calculating mouth targets\n");
+    update_mouth_target(JointInterface::ID_LIP_LEFT_UPPER,   JointInterface::ID_LIP_LEFT_LOWER);
+    update_mouth_target(JointInterface::ID_LIP_CENTER_UPPER, JointInterface::ID_LIP_CENTER_LOWER);
+    update_mouth_target(JointInterface::ID_LIP_RIGHT_UPPER,  JointInterface::ID_LIP_RIGHT_LOWER);
+}
+
+//! calculate mouth target angles for a given combination of upper/lower joints
+//! \param int upper joint id
+//! \param int lower joint id
+void MouthMotionGenerator::update_mouth_target(int upper_id, int lower_id){
+    //fetch min/max for joints:
+    float min_upper = joint_interface->get_joint_min(upper_id);
+    float max_lower = joint_interface->get_joint_max(lower_id);
+    float min_opening = MOUTH_MIN_OPENING;
+
+    //fetch position & opening for joint, parameter is only used to determine LEFT/CENTER/RIGHT. upper/lower plays no role here:
+    float position = mouthstate_to_position(requested_mouth_target, upper_id);
+    float opening  = min_opening + mouthstate_to_opening(requested_mouth_target, upper_id);
+
+    //check opening larger than minimum:
+    if (opening < min_opening){
+        //oops, not safe to move to this opening, abort move!
+        printf("> invalid opening (%f)\n", opening);
+        opening = min_opening;
+    }
+
+    float unsafe_target_upper = position - opening/2.0;
+    float unsafe_target_lower = position + opening/2.0;
+
+    //now check if this would exceed the allowed limits for that joint:
+    float distance_min_upper = unsafe_target_upper - min_upper;
+    if (distance_min_upper < 0){
+        //oops, we will get to close to the safe border, abort move!
+        printf("> collision on TOP [u=%4.2f l=%4.2f]\n",unsafe_target_upper, unsafe_target_lower);
+        unsafe_target_upper = min_upper;
+        unsafe_target_lower = unsafe_target_upper + opening;
+    }
+
+    float distance_max_lower = max_lower - unsafe_target_lower;
+    if (distance_max_lower < 0){
+        //oops, we will get to close to the safe border, abort move!
+        printf("> collision on BOT[u=%4.2f l=%4.2f]\n",unsafe_target_upper, unsafe_target_lower);
+        unsafe_target_lower = max_lower;
+        unsafe_target_upper = unsafe_target_lower - opening;
+    }
+
+    //tell the joint about the new values:
+    joint_interface->set_target_position(upper_id, unsafe_target_upper);
+    joint_interface->set_target_position(lower_id, unsafe_target_lower);
+
+    //printf("> update_mouth_target(u=%d, l=%d) -> upper = %4.2f, lower = %4.2f\n",upper_id, lower_id,unsafe_target_upper,unsafe_target_lower);
+}
+
+
+//! extract opening from mouth state for given joint enum id
+//! \param MouthState m
+//! \param int enum with joint id
+float MouthMotionGenerator::mouthstate_to_opening(MouthState m, int e){
+    switch (e){
+        default: printf("> get_opening(0x%02X): invalid joint enum!\n",e); exit(0);
+        case(JointInterface::ID_LIP_LEFT_UPPER):
+        case(JointInterface::ID_LIP_LEFT_LOWER):
+            return m.opening_left;
+        case(JointInterface::ID_LIP_CENTER_UPPER):
+        case(JointInterface::ID_LIP_CENTER_LOWER):
+            return m.opening_center;
+        case(JointInterface::ID_LIP_RIGHT_UPPER):
+        case(JointInterface::ID_LIP_RIGHT_LOWER):
+            return m.opening_right;
+    }
+}
+
+//! extract position from mouth state for given joint enum id
+//! \param MouthState m
+//! \param int enum with joint id
+float MouthMotionGenerator::mouthstate_to_position(MouthState m, int e){
+    switch (e){
+        default: printf("> get_position(0x%02X): invalid joint enum!\n",e); exit(0);
+        case(JointInterface::ID_LIP_LEFT_UPPER):
+        case(JointInterface::ID_LIP_LEFT_LOWER):
+            return m.position_left;
+        case(JointInterface::ID_LIP_CENTER_UPPER):
+        case(JointInterface::ID_LIP_CENTER_LOWER):
+            return m.position_center;
+        case(JointInterface::ID_LIP_RIGHT_UPPER):
+        case(JointInterface::ID_LIP_RIGHT_LOWER):
+            return m.position_right;
+    }
+}
+
+//! publish targets to motor boards:
+void MouthMotionGenerator::publish_targets(){
+    //publish values if there is an active gaze input within the last timerange
+    if (mouth_target_input_active()){
+        joint_interface->publish_target_position(JointInterface::ID_LIP_LEFT_UPPER);
+        joint_interface->publish_target_position(JointInterface::ID_LIP_LEFT_LOWER);
+        joint_interface->publish_target_position(JointInterface::ID_LIP_CENTER_UPPER);
+        joint_interface->publish_target_position(JointInterface::ID_LIP_CENTER_LOWER);
+        joint_interface->publish_target_position(JointInterface::ID_LIP_RIGHT_UPPER);
+        joint_interface->publish_target_position(JointInterface::ID_LIP_RIGHT_LOWER);
+    }
+}
+
diff --git a/src/server/neck_motion_generator.cpp b/src/server/neck_motion_generator.cpp
new file mode 100644
index 0000000..e2c2706
--- /dev/null
+++ b/src/server/neck_motion_generator.cpp
@@ -0,0 +1,211 @@
+/*
+* This file is part of humotion
+*
+* Copyright(c) sschulz <AT> techfak.uni-bielefeld.de
+* http://opensource.cit-ec.de/projects/humotion
+*
+* This file may be licensed under the terms of the
+* GNU Lesser General Public License Version 3 (the ``LGPL''),
+* or (at your option) any later version.
+*
+* Software distributed under the License is distributed
+* on an ``AS IS'' basis, WITHOUT WARRANTY OF ANY KIND, either
+* express or implied. See the LGPL for the specific language
+* governing rights and limitations.
+*
+* You should have received a copy of the LGPL along with this
+* program. If not, go to http://www.gnu.org/licenses/lgpl.html
+* or write to the Free Software Foundation, Inc.,
+* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+*
+* The development of this software was supported by the
+* Excellence Cluster EXC 277 Cognitive Interaction Technology.
+* The Excellence Cluster EXC 277 is a grant of the Deutsche
+* Forschungsgemeinschaft (DFG) in the context of the German
+* Excellence Initiative.
+*/
+
+#include "server/neck_motion_generator.h"
+#include "server/gaze_motion_generator.h"
+#include "server/server.h"
+#include <cmath>
+
+using namespace std;
+using namespace humotion;
+using namespace humotion::server;
+
+const float NeckMotionGenerator::CONST_GUITTON87_A = 4.39; // / 2.0;
+const float NeckMotionGenerator::CONST_GUITTON87_B = 160.0; // /2.0;
+
+//healthy adult human: 12-15 breaths/min (see "Ganong's review of medical physiology")
+//total: 60/12-15 = 3-5s
+//inhale 1.5-2s
+//exhale 1.5-2s
+//pause      2s
+const float NeckMotionGenerator::CONST_BREATH_PERIOD = 1500.0+1500.0+1500.0; //given in ms
+const float NeckMotionGenerator::CONST_BREATH_AMPLITUDE = 1.0; //degrees
+
+
+//! constructor
+NeckMotionGenerator::NeckMotionGenerator(JointInterface *j) : GazeMotionGenerator(j, 3, 1.0/Server::MOTION_UPDATERATE){
+    breath_time = 0.0;
+}
+
+
+//! destructor
+NeckMotionGenerator::~NeckMotionGenerator(){
+}
+
+//! get a breath offset angle
+//! @return float of breath offset value
+float NeckMotionGenerator::get_breath_offset(){
+    //we want to have a constant acceleration -> triangular wave as speeds -> (x<0.5)? 2*x*x:  1- 2*(1-x)**2 = 4x - 2x**2 - 1
+    float breath_offset = 0.0;
+    float breath_time_normalized = (breath_time * 3)/CONST_BREATH_PERIOD; //0...1 -> move up, 1..2 -> return, 2..3 -> still
+
+    if (breath_time_normalized <= 0.5){
+        //accelerated motion:
+        breath_offset = CONST_BREATH_AMPLITUDE * (2.0 * pow(breath_time_normalized, 2));
+    }else if (breath_time_normalized <= 1.0){
+        //deaccelerate:
+        breath_offset = CONST_BREATH_AMPLITUDE * (1.0 - 2.0 * pow(1.0 - breath_time_normalized, 2));
+    }else if (breath_time_normalized <= 1.5){
+        //accelerate again:
+        breath_offset = CONST_BREATH_AMPLITUDE * (1.0 - (2.0 * pow(breath_time_normalized-1, 2)));
+    }else if (breath_time_normalized <= 2.0){
+        breath_offset = CONST_BREATH_AMPLITUDE * (2.0 * pow(2.0 - breath_time_normalized, 2));
+    }else if (breath_time_normalized <= 3.0){
+        //pause for some time
+        breath_offset = 0;
+    }
+
+    //fetch next time
+    breath_time += 1000.0/Server::MOTION_UPDATERATE;
+    if (breath_time >= CONST_BREATH_PERIOD){
+        breath_time -= CONST_BREATH_PERIOD;
+    }
+
+    return breath_offset;
+}
+
+
+//! calculate joint targets
+void NeckMotionGenerator::calculate_targets(){
+    //fetch current angles:
+    float neck_pan_now  = get_current_position(JointInterface::ID_NECK_PAN);
+    float neck_tilt_now = get_current_position(JointInterface::ID_NECK_TILT);
+    float neck_roll_now = get_current_position(JointInterface::ID_NECK_ROLL);
+
+    //reached target?
+    float goal_diff   = fabs(get_current_gaze().distance_pt_abs(requested_gaze_state));
+    float target_diff = fabs(requested_gaze_state.distance_pt_abs(previous_neck_target));
+
+    //printf("GOAL DIFF = %f TARGET DIFF = %f\n",goal_diff,target_diff);
+    //get_current_gaze().dump();
+    //requested_gaze_state.dump();
+
+    //check if new target
+    //close to goal?
+    if ( (neck_saccade_active) && (goal_diff < 1.0)){
+        neck_saccade_reached_goal = true;
+    }
+
+    if (neck_saccade_active){
+        previous_neck_target = requested_gaze_state;
+    }
+
+    //if we get a new target now, we can stop the neck saccade
+    if (target_diff > .1){
+        if (neck_saccade_reached_goal){
+            // joint_interface->neck_saccade_done();
+            neck_saccade_active = false;
+            neck_saccade_reached_goal = false;
+        }
+    }
+
+    if (neck_saccade_requested){
+        neck_saccade_active = true;
+    }
+
+    //check if this is a small or big saccade:
+    if (neck_saccade_active || neck_saccade_omr){
+        //full saccade with neck motion -> update neck target
+        requested_neck_state = requested_gaze_state;
+    }
+
+    //get targets: this is the sum of stored neck target and up-to-date offset:
+    float neck_pan_target  = requested_neck_state.pan  + requested_gaze_state.pan_offset;
+    float neck_tilt_target = requested_neck_state.tilt + requested_gaze_state.tilt_offset;
+    //roll is always equal to requested gaze (not neck) state
+    float neck_roll_target = requested_gaze_state.roll + requested_gaze_state.roll_offset;
+
+    //add breath wave to tilt:
+    neck_tilt_target += get_breath_offset();
+
+    //pass parameters to reflexxes api:
+    setup_neckmotion(0, neck_pan_target,  neck_pan_now);
+    setup_neckmotion(1, neck_tilt_target, neck_tilt_now);
+    setup_neckmotion(2, neck_roll_target, neck_roll_now);
+
+    //call reflexxes to handle profile calculation:
+    reflexxes_calculate_profile();
+
+    //tell the joint if about the new values:
+    joint_interface->set_target_position(JointInterface::ID_NECK_PAN,  reflexxes_position_output->NewPositionVector->VecData[0]);
+    joint_interface->set_target_position(JointInterface::ID_NECK_TILT, reflexxes_position_output->NewPositionVector->VecData[1]);
+    joint_interface->set_target_position(JointInterface::ID_NECK_ROLL, reflexxes_position_output->NewPositionVector->VecData[2]);
+}
+
+//! publish targets to motor boards:
+void NeckMotionGenerator::publish_targets(){
+    //publish values if there is an active gaze input within the last timerange
+    if (gaze_target_input_active()){
+        joint_interface->publish_target_position(JointInterface::ID_NECK_PAN);
+        joint_interface->publish_target_position(JointInterface::ID_NECK_TILT);
+        joint_interface->publish_target_position(JointInterface::ID_NECK_ROLL);
+    }
+}
+
+
+//! set up neck motion profile
+//! this will use speed and acceleration calc formulas from literature:
+//! \param dof id of joint
+//! \param target angle
+//! \param current angle
+void NeckMotionGenerator::setup_neckmotion(int dof, float target, float now){
+    //get distance to target:
+    float distance_abs = fabs(target - now);
+
+    //get max speed: according to [guitton87] there is a relation between distance_abs and v_max_head:
+    //v_max = 4.39 * d_total + 106.0 (in degrees)
+    float max_speed = (CONST_GUITTON87_A * distance_abs + CONST_GUITTON87_B);
+
+    //max accel: 	assuming linear acceleration we have
+    // v ^
+    //   |  / \
+    //   | /   \
+    //   |/_____\___> t
+    //
+    // d_total = 2 * 1/2 * a * (t_total/2)^2 = 1/4 * a * t_total^2
+    // as we use linear accel we have
+    // v_max = a * t_total/2  --> t_total = 2*v_max / a
+    // combine both
+    // d_total = 1/4 * a * 4 * vmax^2 / a^2 = v_max^2 / a
+    // d_total = a * 2 * d_total / (v_max^2)
+    // and therefore
+    //  a = v_max^2 / d_total
+    float max_accel = 0.0;
+    if (distance_abs > 0.0){
+        max_accel = pow(max_speed, 2) / distance_abs;
+    }
+
+    //limit maximum acceleration to reduce noise FIXME!
+    if (max_accel>1000){
+        max_accel = 1000;
+    }
+
+    ///printf("MAX SPEED %4.2f / max accel %4.2f\n",max_speed, max_accel);
+
+    //feed reflexxes api with data
+    reflexxes_set_input(dof, target, max_speed, max_accel);
+}
diff --git a/src/server/reflexxes_motion_generator.cpp b/src/server/reflexxes_motion_generator.cpp
new file mode 100644
index 0000000..c16bd77
--- /dev/null
+++ b/src/server/reflexxes_motion_generator.cpp
@@ -0,0 +1,85 @@
+/*
+* This file is part of humotion
+*
+* Copyright(c) sschulz <AT> techfak.uni-bielefeld.de
+* http://opensource.cit-ec.de/projects/humotion
+*
+* This file may be licensed under the terms of the
+* GNU Lesser General Public License Version 3 (the ``LGPL''),
+* or (at your option) any later version.
+*
+* Software distributed under the License is distributed
+* on an ``AS IS'' basis, WITHOUT WARRANTY OF ANY KIND, either
+* express or implied. See the LGPL for the specific language
+* governing rights and limitations.
+*
+* You should have received a copy of the LGPL along with this
+* program. If not, go to http://www.gnu.org/licenses/lgpl.html
+* or write to the Free Software Foundation, Inc.,
+* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+*
+* The development of this software was supported by the
+* Excellence Cluster EXC 277 Cognitive Interaction Technology.
+* The Excellence Cluster EXC 277 is a grant of the Deutsche
+* Forschungsgemeinschaft (DFG) in the context of the German
+* Excellence Initiative.
+*/
+
+#include "server/eye_motion_generator.h"
+
+using namespace std;
+using namespace humotion;
+using namespace humotion::server;
+
+//! constructor
+ReflexxesMotionGenerator::ReflexxesMotionGenerator(JointInterface *j, int dof, float t) : MotionGenerator(j){
+    dof_count = dof;
+
+    //create Reflexxes API for 3 DOF
+    reflexxes_api = new ReflexxesAPI(dof, t);
+    reflexxes_position_input  = new RMLPositionInputParameters(dof);
+    reflexxes_position_output = new RMLPositionOutputParameters(dof);
+
+    //synchronize phase
+    reflexxes_motion_flags.SynchronizationBehavior = RMLPositionFlags::PHASE_SYNCHRONIZATION_IF_POSSIBLE;
+}
+
+//! destructor
+ReflexxesMotionGenerator::~ReflexxesMotionGenerator(){
+
+}
+
+//! feed motion generator with target data:
+//! \param dof id
+//! \param target angle
+//! \param max_speed max reachable speed during accel
+//! \param max_accel max allowable acceleration
+void ReflexxesMotionGenerator::reflexxes_set_input(int dof, float target, float max_speed, float max_accel){
+    //set up reflexxes:
+    reflexxes_position_input->TargetPositionVector->VecData[dof]  = target;
+    reflexxes_position_input->SelectionVector->VecData[dof]       = true;
+    reflexxes_position_input->MaxVelocityVector->VecData[dof]     = max_speed;
+    reflexxes_position_input->MaxAccelerationVector->VecData[dof] = 0.0001 + max_accel;
+    reflexxes_position_input->TargetVelocityVector->VecData[dof]  = 0.0; //target speed is zero (really?)
+}
+
+//! calculate motion profile
+
+void ReflexxesMotionGenerator::reflexxes_calculate_profile(){
+    int res = reflexxes_api->RMLPosition(*reflexxes_position_input, reflexxes_position_output, reflexxes_motion_flags);
+
+    if (res < 0){
+        if (res == ReflexxesAPI::RML_ERROR_INVALID_INPUT_VALUES){
+            printf("> ReflexxesMotionGenerator --> ReflexxesAPI::RML_ERROR_INVALID_INPUT_VALUES error\n");
+        }else{
+            printf("> ReflexxesMotionGenerator --> ReflexxesAPI::UNKNOWN_ERROR: reflexxes error %d\n",res);
+        }
+    }
+
+    //feed back values:
+    for(int i=0; i<dof_count; i++){
+        reflexxes_position_input->CurrentPositionVector->VecData[i]     = reflexxes_position_output->NewPositionVector->VecData[i];
+        reflexxes_position_input->CurrentVelocityVector->VecData[i]     = reflexxes_position_output->NewVelocityVector->VecData[i];
+        reflexxes_position_input->CurrentAccelerationVector->VecData[i] = reflexxes_position_output->NewAccelerationVector->VecData[i];
+    }
+}
diff --git a/src/server/server.cpp b/src/server/server.cpp
new file mode 100644
index 0000000..37b5e35
--- /dev/null
+++ b/src/server/server.cpp
@@ -0,0 +1,135 @@
+/*
+* This file is part of humotion
+*
+* Copyright(c) sschulz <AT> techfak.uni-bielefeld.de
+* http://opensource.cit-ec.de/projects/humotion
+*
+* This file may be licensed under the terms of the
+* GNU Lesser General Public License Version 3 (the ``LGPL''),
+* or (at your option) any later version.
+*
+* Software distributed under the License is distributed
+* on an ``AS IS'' basis, WITHOUT WARRANTY OF ANY KIND, either
+* express or implied. See the LGPL for the specific language
+* governing rights and limitations.
+*
+* You should have received a copy of the LGPL along with this
+* program. If not, go to http://www.gnu.org/licenses/lgpl.html
+* or write to the Free Software Foundation, Inc.,
+* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+*
+* The development of this software was supported by the
+* Excellence Cluster EXC 277 Cognitive Interaction Technology.
+* The Excellence Cluster EXC 277 is a grant of the Deutsche
+* Forschungsgemeinschaft (DFG) in the context of the German
+* Excellence Initiative.
+*/
+
+#include "server/server.h"
+#include "server/middleware_ros.h"
+#include "server/middleware_rsb.h"
+#include <boost/algorithm/string.hpp>
+#include <string>
+
+using namespace std;
+using namespace boost;
+using namespace humotion;
+using namespace humotion::server;
+
+//! set up constant for updaterate (50Hz)
+const float Server::MOTION_UPDATERATE = 50.0;
+
+//! constructor
+//! open a new server instance.
+Server::Server(string scope, string mw, JointInterface *_joint_interface){
+    //convert mw to uppercase:
+    to_upper(mw);
+
+    printf("> initializing humotion server (on %s, middleware=%s)\n",scope.c_str(),mw.c_str());
+
+    //store pointer to joint interface
+    joint_interface = _joint_interface;
+
+    //tell joint interface our framerate:
+    joint_interface->set_framerate(MOTION_UPDATERATE);
+
+    //create controller
+    controller = new Controller(joint_interface);
+    controller->init_motion_generators();
+
+    //start middleware:
+    if (mw == "ROS"){
+        middleware = new MiddlewareROS(scope, controller);
+    }else if (mw == "RSB"){
+        middleware = new MiddlewareRSB(scope, controller);
+    }else{
+        printf("> ERROR: invalid mw '%s' given. Please use ROS or RSB\n\n",mw.c_str());
+        exit(EXIT_FAILURE);
+    }
+
+    //start motion generation thread:
+    start_motion_generation_thread();
+
+}
+
+//! destructor
+Server::~Server(){
+}
+
+//! middleware still running?
+bool Server::ok(){
+    return middleware->ok();
+}
+
+//! start main thread
+void Server::start_motion_generation_thread(){
+    motion_generation_thread_ptr = new boost::thread(boost::bind( &Server::motion_generation_thread, this));
+}
+
+//! main thread that handles all data in/out
+//! this thread will take care of gathering all input data and
+//! then generate the output targets at a fixed rate of \sa MOTION_UPDATERATE
+void Server::motion_generation_thread(){
+    unsigned int incoming_data_count_invalid = 0;
+
+    printf("> started motion generation thread\n");
+
+    //calculate loop delay:
+    float loop_delay = 1000.0 / MOTION_UPDATERATE;
+    boost::system_time timeout = get_system_time() + posix_time::milliseconds(loop_delay);
+
+    while (middleware->ok()){
+        //mw tick
+        middleware->tick();
+
+        //do some logging:
+        //controller->dump_angles();
+
+        //calculate all targets
+        controller->calculate_targets();
+
+        //publish data to joints
+        controller->publish_targets();
+
+        //finally execute the movement:
+        joint_interface->execute_motion();
+
+        //check if we received joint information in the last step:
+        unsigned int incoming_data_count = joint_interface->get_and_clear_incoming_position_count();
+        if (incoming_data_count == 0){
+                printf("> WARNING: no incoming joint data during the last iteration...\n");
+                incoming_data_count_invalid++;
+                if (incoming_data_count_invalid >= MOTION_UPDATERATE){
+                    printf("> ERROR: no incoming joint data for 1s -> will exit now\n");
+                    exit(EXIT_FAILURE);
+                }
+        }else{
+                incoming_data_count_invalid = 0;
+        }
+
+        thread::sleep(timeout);
+        timeout = get_system_time() + posix_time::milliseconds(loop_delay);
+    }
+
+    printf("> motion generation thread exited.\n");
+}
diff --git a/src/timestamped_list.cpp b/src/timestamped_list.cpp
new file mode 100644
index 0000000..3172b64
--- /dev/null
+++ b/src/timestamped_list.cpp
@@ -0,0 +1,175 @@
+/*
+* This file is part of humotion
+*
+* Copyright(c) sschulz <AT> techfak.uni-bielefeld.de
+* http://opensource.cit-ec.de/projects/humotion
+*
+* This file may be licensed under the terms of the
+* GNU Lesser General Public License Version 3 (the ``LGPL''),
+* or (at your option) any later version.
+*
+* Software distributed under the License is distributed
+* on an ``AS IS'' basis, WITHOUT WARRANTY OF ANY KIND, either
+* express or implied. See the LGPL for the specific language
+* governing rights and limitations.
+*
+* You should have received a copy of the LGPL along with this
+* program. If not, go to http://www.gnu.org/licenses/lgpl.html
+* or write to the Free Software Foundation, Inc.,
+* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+*
+* The development of this software was supported by the
+* Excellence Cluster EXC 277 Cognitive Interaction Technology.
+* The Excellence Cluster EXC 277 is a grant of the Deutsche
+* Forschungsgemeinschaft (DFG) in the context of the German
+* Excellence Initiative.
+*/
+
+#include "timestamped_list.h"
+#include "assert.h"
+
+using namespace std;
+using namespace boost;
+using namespace humotion;
+
+TimestampedList::TimestampedList(unsigned int s){
+	//initialize the list to its desired size:
+    TimestampedFloat now;
+    tsf_list.resize(s, now);
+}
+
+TimestampedList::TimestampedList(TimestampedList const &l){
+    //lock the tsf_list for this access. by doing this we assure
+    //that no other thread accessing this element can diturb the
+    //following atomic instructions:
+    mutex::scoped_lock scoped_lock(l.access_mutex);
+
+    //now do a deep copy with locking!
+    tsf_list = l.tsf_list;
+}
+
+void TimestampedList::copy_tsf_list_to(timestamped_float_list_t *target){
+    //lock the tsf_list for this access. by doing this we assure
+    //that no other thread accessing this element can diturb the
+    //following atomic instructions:
+    mutex::scoped_lock scoped_lock(access_mutex);
+
+    *target = tsf_list;
+}
+
+double TimestampedList::get_last_timestamp(){
+    //lock the tsf_list for this access. by doing this we assure
+    //that no other thread accessing this element can diturb the
+    //following atomic instructions:
+    mutex::scoped_lock scoped_lock(access_mutex);
+
+    if (tsf_list.empty()){
+        return 0.0;
+    }
+
+    timestamped_float_list_t::iterator it = tsf_list.end();
+    it--;
+    return it->timestamp;
+}
+
+void TimestampedList::insert(double timestamp, float val){
+	//erase first element:
+    tsf_list.pop_front();
+    tsf_list.push_back(TimestampedFloat(timestamp, val));
+    //printf("insert [%5.3f] = %5.1f\n",timestamp,val);
+}
+
+float TimestampedList::get_newest_value(){
+    //lock the tsf_list for this access. by doing this we assure
+    //that no other thread accessing this element can diturb the
+    //following atomic instructions:
+    mutex::scoped_lock scoped_lock(access_mutex);
+
+    if (tsf_list.empty()){
+        return 0.0;
+    }
+
+    timestamped_float_list_t::iterator it = tsf_list.end();
+	it--;
+	return it->value;
+}
+
+float TimestampedList::get_interpolated_value(double target_ts){
+    //lock the tsf_list for this access. by doing this we assure
+    //that no other thread accessing this element can diturb the
+    //following atomic instructions:
+    mutex::scoped_lock scoped_lock(access_mutex);
+
+    ///target_ts -= 0.001 * 4;
+	
+    TimestampedFloat previous;
+    //printf("> latency %3.2fms\n", (TimestampedFloat::get_timestamp() - target_ts)*1000.0);
+
+    for ( timestamped_float_list_t::iterator it = tsf_list.begin(); it != tsf_list.end(); ++it ){
+		if (it->timestamp >= target_ts){
+			//ok found close target
+            if (it == tsf_list.begin()){
+				//no preceding element
+                printf("> warning, timestamp %6.3f smaller than first element %6.3f in timestamped list. this should not happen (increase ts buffer?)\n",target_ts,tsf_list.begin()->timestamp);
+				return it->value;
+			}else{
+				//do interpolation
+				return interpolate(*it, previous, target_ts);
+			}
+		}
+		previous = *it;
+	}
+	//we reached the end, return the last value
+	printf("> warning: found no timestamp bigger than %f in timestamped list...\n", target_ts);
+	printf("           this should not happen as images will always be behind\n");
+	printf("           the motor data. returning most recent value (ts=%f)\n", previous.timestamp);
+	
+	return previous.value;
+}
+
+float TimestampedList::interpolate(TimestampedFloat a, TimestampedFloat b, double timestamp){
+	//a->timestamp < timestamp <= b->timestamp
+    double dist_a = timestamp - a.timestamp;
+	double dist_b = b.timestamp - timestamp;
+	double dist   = dist_a + dist_b;
+	
+    float interpolation = a.value + (dist_a / dist) * (b.value - a.value);
+	return interpolation;
+}
+
+
+///tests
+void TimestampedList::run_tests(){
+	int size = 10;
+	TimestampedList list(size);
+	
+	for(int i=0; i<size; i++){
+		list.insert(i * 100.0, i*10.0);
+	}
+	
+	//test algorithm:
+	
+	//test exact match:
+	for(int i=0; i<size; i++){
+		printf("> testing get_interpolated_value(%f) == %f (value read back = %f)\n",i*100.0, i*10.0, list.get_interpolated_value(i*100.0));
+		assert( list.get_interpolated_value(i*100.0) == i*10.0);
+	}
+	printf("passed test 1\n");
+	
+	assert(list.get_interpolated_value(0.0) == 0.0);
+	assert(list.get_interpolated_value(110.0) == 11.0);
+	assert(list.get_interpolated_value(150.0) == 15.0);
+	assert(list.get_interpolated_value(999990.0) == 90.0);
+	
+	printf("passed test 2\n");
+	
+	list.insert(1000.0, 200.0);
+	list.insert(1300.0, -100.0);
+	assert(list.get_interpolated_value(1100) == 100.0);
+	assert(list.get_interpolated_value(1200) == 0.0);
+	assert(list.get_interpolated_value(1300) == -100.0);
+	assert(list.get_interpolated_value(1250) == -50.0);
+	
+	printf("passed test 3\n");
+	exit(0);
+}
diff --git a/test/client.cpp b/test/client.cpp
new file mode 100644
index 0000000..3c1b6da
--- /dev/null
+++ b/test/client.cpp
@@ -0,0 +1,69 @@
+// Bring in my package's API, which is what I'm testing
+#include "client.h"
+#include <gtest/gtest.h>
+#include <string>
+#include <cstdio>
+using namespace std;
+
+namespace {
+
+//the fixture for testing class Foo.
+class client_Test : public ::testing::Test {
+protected:
+    client_Test() {
+		//set-up work for EACH test here
+        s = new client();
+
+	}
+	
+    virtual ~client_Test() {
+		//clean-up work that doesn't throw exceptions here
+		delete(s);
+		s = NULL;
+	}
+	
+	//if the constructor and destructor are not enough for setting up
+	//and cleaning up each test, you can define the following methods:
+	virtual void SetUp() {
+		//code here will be called immediately after the constructor (right before each test).
+	}
+
+	virtual void TearDown() {
+		//code here will be called immediately after each test (right
+		//before the destructor).
+	}
+
+	//ojects declared here can be used by all tests in the test case for Foo
+    client *s;
+};
+
+// Tests that the Foo::Bar() method does Abc.
+TEST_F(client_Test, send_mouth_data) {
+
+    MouthState m;
+    for(int i=0; i<100; i++){
+        m.opening_left   = 12.0;
+        m.opening_center = 12.0;
+        m.opening_right  = 12.0;
+        m.position_left   = 10+(20.0*i)/100.0;
+        m.position_center = 10+(20.0*i)/100.0;
+        m.position_right  = 10+(20.0*i)/100.0;
+
+        s->update_mouth_target(m, true);
+    }
+
+    SUCCEED();
+}
+
+// Tests that Foo does Xyz.
+// TEST_F(xsc3_client_cpp_Test, DoesXyz) {
+// 	CheckConnection(xsc3_client);
+// }
+
+}  // namespace
+
+// Run all the tests that were declared with TEST()
+int main(int argc, char **argv){
+	testing::InitGoogleTest(&argc, argv);
+	return RUN_ALL_TESTS();
+}
diff --git a/test/server.cpp b/test/server.cpp
new file mode 100644
index 0000000..24fe677
--- /dev/null
+++ b/test/server.cpp
@@ -0,0 +1,79 @@
+// Bring in my package's API, which is what I'm testing
+#include "server.h"
+#include <gtest/gtest.h>
+#include <string>
+#include <cstdio>
+using namespace std;
+
+namespace {
+
+//the fixture for testing class Foo.
+class server_Test : public ::testing::Test {
+protected:
+	server_Test() {
+		//set-up work for EACH test here
+		s = new Server();
+
+	}
+	
+	virtual ~server_Test() {
+		//clean-up work that doesn't throw exceptions here
+		delete(s);
+		s = NULL;
+	}
+	
+	//if the constructor and destructor are not enough for setting up
+	//and cleaning up each test, you can define the following methods:
+	virtual void SetUp() {
+		//code here will be called immediately after the constructor (right before each test).
+	}
+
+	virtual void TearDown() {
+		//code here will be called immediately after each test (right
+		//before the destructor).
+	}
+
+	//ojects declared here can be used by all tests in the test case for Foo
+	Server *s;
+};
+
+void dump_incoming_data(Server *s){
+	SCOPED_TRACE("dump incoming data");
+	
+	//make sure it is not null
+	if (s == NULL){
+		SCOPED_TRACE("server ptr NULL?");
+		FAIL();
+	}
+	
+	//make sure we are connected
+	EXPECT_EQ(s->ok(), true);
+	
+	for(int i=0; i<100000; i++){
+		s->tick();
+	}
+}
+
+
+// Tests that the Foo::Bar() method does Abc.
+TEST_F(server_Test, dump_incoming_data) {
+	//connected?
+	dump_incoming_data(s);
+//   const string input_filepath = "this/package/testdata/myinputfile.dat";
+//   const string output_filepath = "this/package/testdata/myoutputfile.dat";
+//   Foo f;
+//   EXPECT_EQ(0, f.Bar(input_filepath, output_filepath));
+}
+
+// Tests that Foo does Xyz.
+// TEST_F(xsc3_client_cpp_Test, DoesXyz) {
+// 	CheckConnection(xsc3_client);
+// }
+
+}  // namespace
+
+// Run all the tests that were declared with TEST()
+int main(int argc, char **argv){
+	testing::InitGoogleTest(&argc, argv);
+	return RUN_ALL_TESTS();
+}
