From dd98d0712914a15bdd508177891ed66d5ab00c93 Mon Sep 17 00:00:00 2001
From: Sergi Hernandez Juan <shernand@iri.upc.edu>
Date: Tue, 4 Feb 2020 23:52:24 +0100
Subject: [PATCH] Separated the header and source file types. Added a new
 structure: Class hierarchy to handle each of the robots modules. Updated some
 examples.

---
 include/darwin_action.h                    |  20 ++
 {src => include}/darwin_arm_kinematics.h   |   0
 include/darwin_dyn_manager.h               |  28 ++
 include/darwin_imu.h                       |  26 ++
 {src => include}/darwin_leg_kinematics.h   |   0
 include/darwin_mmanager.h                  |  49 +++
 {src => include}/darwin_registers.h        |   0
 {src => include}/darwin_robot.h            |   0
 include/darwin_robot_base.h                |  22 ++
 {src => include}/darwin_robot_exceptions.h |   0
 src/CMakeLists.txt                         |  10 +-
 src/darwin_action.cpp                      |  62 ++++
 src/darwin_dyn_manager.cpp                 | 103 ++++++
 src/darwin_imu.cpp                         | 102 ++++++
 src/darwin_mmanager.cpp                    | 387 +++++++++++++++++++++
 src/darwin_robot_base.cpp                  |  63 ++++
 src/examples/CMakeLists.txt                |   4 +-
 src/examples/darwin_action_test.cpp        |  67 ++--
 src/examples/darwin_imu_test.cpp           |  24 +-
 src/examples/darwin_manager_test.cpp       |  63 ++--
 20 files changed, 946 insertions(+), 84 deletions(-)
 create mode 100644 include/darwin_action.h
 rename {src => include}/darwin_arm_kinematics.h (100%)
 create mode 100644 include/darwin_dyn_manager.h
 create mode 100644 include/darwin_imu.h
 rename {src => include}/darwin_leg_kinematics.h (100%)
 create mode 100644 include/darwin_mmanager.h
 rename {src => include}/darwin_registers.h (100%)
 rename {src => include}/darwin_robot.h (100%)
 create mode 100644 include/darwin_robot_base.h
 rename {src => include}/darwin_robot_exceptions.h (100%)
 create mode 100644 src/darwin_action.cpp
 create mode 100644 src/darwin_dyn_manager.cpp
 create mode 100644 src/darwin_imu.cpp
 create mode 100644 src/darwin_mmanager.cpp
 create mode 100644 src/darwin_robot_base.cpp

diff --git a/include/darwin_action.h b/include/darwin_action.h
new file mode 100644
index 0000000..cfd4793
--- /dev/null
+++ b/include/darwin_action.h
@@ -0,0 +1,20 @@
+#ifndef _DARWIN_ACTION_H
+#define _DARWIN_ACTION_H
+
+#include "darwin_robot_base.h"
+#include "darwin_registers.h"
+
+class CDarwinAction : public CDarwinRobotBase
+{
+  public:
+    CDarwinAction(const std::string &name,std::string &bus_id,int bus_speed, unsigned char id,bool sim=false);
+    void load_page(unsigned char page_id);
+    unsigned char get_current_page(void);
+    unsigned char get_current_step(void);
+    void start(void);
+    void stop(void);
+    bool is_page_running(void);
+    ~CDarwinAction();
+};
+
+#endif
diff --git a/src/darwin_arm_kinematics.h b/include/darwin_arm_kinematics.h
similarity index 100%
rename from src/darwin_arm_kinematics.h
rename to include/darwin_arm_kinematics.h
diff --git a/include/darwin_dyn_manager.h b/include/darwin_dyn_manager.h
new file mode 100644
index 0000000..d5804c6
--- /dev/null
+++ b/include/darwin_dyn_manager.h
@@ -0,0 +1,28 @@
+#ifndef _DARWIN_DYN_MANAGER_H
+#define _DARWIN_DYN_MANAGER_H
+
+#include "darwin_robot_base.h"
+#include "darwin_registers.h"
+
+class CDarwinDynManager : public CDarwinRobotBase
+{
+  protected:
+    double manager_period;
+    unsigned char num_devices;
+  public:
+    CDarwinDynManager(const std::string &name,std::string &bus_id,int bus_speed, unsigned char id,bool sim=false);
+    double get_base_period(void);
+    void set_base_period(double period_s);
+    unsigned int get_num_modules(void);
+    unsigned int get_num_masters(void);
+    void start(void);
+    void stop(void);
+    bool is_running(void);
+    void start_scan(void);
+    bool is_scanning(void);
+    unsigned char get_num_devices(void);
+    unsigned int get_present_devices(void);
+    ~CDarwinDynManager();
+};
+
+#endif
diff --git a/include/darwin_imu.h b/include/darwin_imu.h
new file mode 100644
index 0000000..925ce24
--- /dev/null
+++ b/include/darwin_imu.h
@@ -0,0 +1,26 @@
+#ifndef _DARWIN_IMU_H
+#define _DARWIN_IMU_H
+
+#include "darwin_robot_base.h"
+#include "darwin_registers.h"
+
+typedef enum {MM_FWD_FALL=0,MM_BWD_FALL=1,MM_STANDING=2} fall_t;
+
+class CDarwinIMU : public CDarwinRobotBase
+{
+  public:
+    CDarwinIMU(const std::string &name,std::string &bus_id,int bus_speed, unsigned char id,bool sim=false);
+    void start(void);
+    void stop(void);
+    void start_gyro_cal(void);
+    void set_cal_samples(unsigned short int num_samples);
+    unsigned short int get_cal_samples(void);
+    bool is_gyro_cal_done(void);
+    bool is_accel_detected(void);
+    bool is_gyro_detected(void);
+    void get_accel_data(double *x,double *y,double *z);
+    void get_gyro_data(double *x,double *y,double *z);
+    virtual ~CDarwinIMU();
+};
+
+#endif
diff --git a/src/darwin_leg_kinematics.h b/include/darwin_leg_kinematics.h
similarity index 100%
rename from src/darwin_leg_kinematics.h
rename to include/darwin_leg_kinematics.h
diff --git a/include/darwin_mmanager.h b/include/darwin_mmanager.h
new file mode 100644
index 0000000..30aee72
--- /dev/null
+++ b/include/darwin_mmanager.h
@@ -0,0 +1,49 @@
+#ifndef _DARWIN_MMANAGER_H
+#define _DARWIN_MMANAGER_H
+
+#include "darwin_dyn_manager.h"
+#include "darwin_registers.h"
+
+#define           MAX_NUM_SERVOS        32
+
+extern const std::string servo_names[MAX_NUM_SERVOS];
+/* available motion modules */
+typedef enum {DARWIN_MM_NONE=0x07,DARWIN_MM_ACTION=0x00,DARWIN_MM_WALKING=0x01,DARWIN_MM_JOINTS=0x02,DARWIN_MM_HEAD=0x03,DARWIN_MM_GRIPPER=0x04} mm_mode_t;
+
+typedef enum {MM_FWD_FALL=0,MM_BWD_FALL=1,MM_STANDING=2} fall_t;
+
+class CDarwinMManager : public CDarwinDynManager
+{
+  protected:
+    double mmanager_period;
+  public:
+    CDarwinMManager(const std::string &name,std::string &bus_id,int bus_speed, unsigned char id,bool sim=false);
+    unsigned int get_present_servos(void);
+    void set_period(double period_s);
+    double get_period(void);
+    void enable_servo(unsigned char servo_id);
+    void disable_servo(unsigned char servo_id);
+    bool is_servo_enabled(unsigned char servo_id);
+    void assign_module(unsigned char servo_id, mm_mode_t mode);
+    void assign_module(std::string &servo,std::string &module);
+    mm_mode_t get_module(unsigned char servo_id);
+//    void enable_balance(void);
+//    void disable_balance(void);
+//    bool is_balance_enabled(void);
+//    void enable_power(void);
+//    void disable_power(void);
+//    bool is_power_enabled(void);
+//    bool has_fallen(void);
+//    fall_t get_fallen_position(void);
+//    std::vector<double> get_servo_angles(void);
+//    double get_servo_angle(unsigned char servo_id);
+//    void set_servo_offset(unsigned char servo_id,double offset);
+//    double get_servo_offset(unsigned char servo_id);
+//    std::vector<double> get_servo_offsets(void);
+//    void load_config(std::string &filename);
+//    void set_balance_gains(double knee,double ankle_pitch,double hip_roll,double ankle_roll);
+//    void get_balance_gains(double *knee,double *ankle_pitch,double *hip_roll,double *ankle_roll);
+    virtual ~CDarwinMManager();
+};
+
+#endif
diff --git a/src/darwin_registers.h b/include/darwin_registers.h
similarity index 100%
rename from src/darwin_registers.h
rename to include/darwin_registers.h
diff --git a/src/darwin_robot.h b/include/darwin_robot.h
similarity index 100%
rename from src/darwin_robot.h
rename to include/darwin_robot.h
diff --git a/include/darwin_robot_base.h b/include/darwin_robot_base.h
new file mode 100644
index 0000000..a4c3610
--- /dev/null
+++ b/include/darwin_robot_base.h
@@ -0,0 +1,22 @@
+#ifndef _DARWIN_ROBOT_BASE_H
+#define _DARWIN_ROBOT_BASE_H
+
+#include "dynamixel.h"
+#include "dynamixelserver_ftdi.h"
+#include "dynamixelserver_serial.h"
+#include "darwin_registers.h"
+
+class CDarwinRobotBase
+{
+  protected:
+    CDynamixelServer *dyn_server;
+    CDynamixel *robot_device;
+    std::string robot_name;
+    unsigned char robot_id;
+  public:
+    CDarwinRobotBase(const std::string &name,std::string &bus_id,int bus_speed, unsigned char id,bool sim=false);
+    void is_valid(void);
+    virtual ~CDarwinRobotBase();
+};
+
+#endif
diff --git a/src/darwin_robot_exceptions.h b/include/darwin_robot_exceptions.h
similarity index 100%
rename from src/darwin_robot_exceptions.h
rename to include/darwin_robot_exceptions.h
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index dac5dab..40bfbb9 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -11,9 +11,9 @@ SET(KDL_INSTALL /opt/ros/indigo)
 INCLUDE (${PROJECT_SOURCE_DIR}/FindKDL.cmake)
 
 # driver source files
-SET(robot_sources darwin_robot.cpp darwin_robot_exceptions.cpp)
+SET(robot_sources darwin_robot_base.cpp darwin_robot_exceptions.cpp darwin_imu.cpp darwin_dyn_manager.cpp darwin_mmanager.cpp darwin_action.cpp)
 # application header files
-SET(robot_headers darwin_robot.h darwin_robot_exceptions.h)
+SET(robot_headers ../include/darwin_robot.h ../include/darwin_robot_exceptions.h ../include/darwin_imu.h ../include/darwin_dyn_manager.h ../include/darwin_mmanager.h ../include/darwin_action.h)
 
 # locate the necessary dependencies
 FIND_PACKAGE(iriutils REQUIRED)
@@ -24,18 +24,18 @@ IF(KDL_FOUND)
   # driver source files
   SET(kin_arm_sources darwin_arm_kinematics.cpp darwin_robot_exceptions.cpp)
   # application header files
-  SET(kin_arm_headers darwin_arm_kinematics.h darwin_robot_exceptions.h)
+  SET(kin_arm_headers ../include/darwin_arm_kinematics.h ../include/darwin_robot_exceptions.h)
 ENDIF(KDL_FOUND)
 
 IF(EIGEN3_FOUND)
   # driver source files
   SET(kin_leg_sources darwin_leg_kinematics.cpp darwin_robot_exceptions.cpp)
   # application header files
-  SET(kin_leg_headers darwin_leg_kinematics.h darwin_robot_exceptions.h)
+  SET(kin_leg_headers ../include/darwin_leg_kinematics.h ../include/darwin_robot_exceptions.h)
 ENDIF(EIGEN3_FOUND)
 
 # add the necessary include directories
-INCLUDE_DIRECTORIES(.)
+INCLUDE_DIRECTORIES(../include)
 INCLUDE_DIRECTORIES(${iriutils_INCLUDE_DIR})
 INCLUDE_DIRECTORIES(${dynamixel_INCLUDE_DIR})
 INCLUDE_DIRECTORIES(${EIGEN3_INCLUDE_DIR})
diff --git a/src/darwin_action.cpp b/src/darwin_action.cpp
new file mode 100644
index 0000000..4c16e46
--- /dev/null
+++ b/src/darwin_action.cpp
@@ -0,0 +1,62 @@
+#include "darwin_action.h"
+#include "darwin_robot_exceptions.h"
+
+CDarwinAction::CDarwinAction(const std::string &name,std::string &bus_id,int bus_speed, unsigned char id,bool sim) : CDarwinRobotBase(name,bus_id,bus_speed,id,sim)
+{
+}
+
+void CDarwinAction::load_page(unsigned char page_id)
+{
+  this->is_valid();
+  this->robot_device->write_byte_register(ACTION_PAGE_ID,page_id);
+}
+
+unsigned char CDarwinAction::get_current_page(void)
+{
+  unsigned char page_id;
+
+  this->is_valid();
+  this->robot_device->read_byte_register(ACTION_PAGE_ID,&page_id);
+  return page_id;
+}
+
+/*
+unsigned char CDarwinAction::get_current_step(void)
+{
+  unsigned char step_id;
+
+  this->is_valid();
+  this->robot_device->read_byte_register(DARWIN_ACTION_CNTRL,&step_id);
+
+  return (step_id>>5);
+}
+*/
+
+void CDarwinAction::start(void)
+{
+  this->is_valid();
+  this->robot_device->write_byte_register(ACTION_CONTROL,ACTION_START);
+}
+
+void CDarwinAction::stop(void)
+{
+  this->is_valid();
+  this->robot_device->write_byte_register(ACTION_CONTROL,ACTION_STOP);
+}
+
+bool CDarwinAction::is_page_running(void)
+{
+  unsigned char status;
+
+  this->is_valid();
+  this->robot_device->read_byte_register(ACTION_CONTROL,&status);
+  if(status&ACTION_STATUS)
+    return true;
+  else
+    return false;
+}
+
+CDarwinAction::~CDarwinAction()
+{
+}
+
diff --git a/src/darwin_dyn_manager.cpp b/src/darwin_dyn_manager.cpp
new file mode 100644
index 0000000..096ab43
--- /dev/null
+++ b/src/darwin_dyn_manager.cpp
@@ -0,0 +1,103 @@
+#include "darwin_dyn_manager.h"
+#include "darwin_robot_exceptions.h"
+
+CDarwinDynManager::CDarwinDynManager(const std::string &name,std::string &bus_id,int bus_speed, unsigned char id,bool sim) : CDarwinRobotBase(name,bus_id,bus_speed,id,sim)
+{
+  this->manager_period=this->get_base_period();
+}
+
+double CDarwinDynManager::get_base_period(void)
+{
+  unsigned char period;
+
+  this->is_valid();
+  this->robot_device->read_byte_register(MANAGER_PERIOD,&period);
+  return ((double)period/1000.0);
+}
+
+void CDarwinDynManager::set_base_period(double period_s)
+{
+  unsigned char period;
+
+  this->is_valid();
+  period=(period_s*1000.0);
+  this->robot_device->write_byte_register(MANAGER_PERIOD,period);
+  this->manager_period=period_s;
+}
+
+unsigned int CDarwinDynManager::get_num_modules(void)
+{
+  unsigned char num;
+
+  this->is_valid();
+  this->robot_device->read_byte_register(MANAGER_NUM_MODULES,&num);
+  return num;
+}
+
+unsigned int CDarwinDynManager::get_num_masters(void)
+{
+  unsigned char num;
+
+  this->is_valid();
+  this->robot_device->read_byte_register(MANAGER_NUM_MASTERS,&num);
+  return num;
+}
+
+void CDarwinDynManager::start(void)
+{
+  this->is_valid();
+  this->robot_device->write_byte_register(MANAGER_CONTROL,MANAGER_START);
+}
+
+void CDarwinDynManager::stop(void)
+{
+  this->is_valid();
+  this->robot_device->write_byte_register(MANAGER_CONTROL,MANAGER_STOP);
+}
+
+bool CDarwinDynManager::is_running(void)
+{
+  unsigned char running;
+  
+  this->is_valid();
+  this->robot_device->read_byte_register(MANAGER_CONTROL,&running);
+  return running&MANAGER_RUNNING;
+}
+
+void CDarwinDynManager::start_scan(void)
+{
+  this->is_valid();
+  this->robot_device->write_byte_register(MANAGER_CONTROL,MANAGER_START_SCAN);
+}
+
+bool CDarwinDynManager::is_scanning(void)
+{
+  unsigned char scanning;
+  
+  this->is_valid();
+  this->robot_device->read_byte_register(MANAGER_CONTROL,&scanning);
+  return scanning&MANAGER_SCANNING;
+}
+
+unsigned char CDarwinDynManager::get_num_devices(void)
+{
+  unsigned char num;
+
+  this->is_valid();
+  this->robot_device->read_byte_register(MANAGER_NUM_DEVICES,&num);
+  return num;
+}
+
+unsigned int CDarwinDynManager::get_present_devices(void)
+{
+  unsigned int present_devices;
+
+  this->is_valid();
+  this->robot_device->read_registers(MANAGER_PRESENT_DEVICES,(unsigned char *)&present_devices,4);
+  return present_devices;
+}
+
+CDarwinDynManager::~CDarwinDynManager()
+{
+}
+
diff --git a/src/darwin_imu.cpp b/src/darwin_imu.cpp
new file mode 100644
index 0000000..db357a8
--- /dev/null
+++ b/src/darwin_imu.cpp
@@ -0,0 +1,102 @@
+#include "darwin_imu.h"
+#include "darwin_robot_exceptions.h"
+
+CDarwinIMU::CDarwinIMU(const std::string &name,std::string &bus_id,int bus_speed, unsigned char id,bool sim) : CDarwinRobotBase(name,bus_id,bus_speed,id,sim)
+{
+}
+
+void CDarwinIMU::start(void)
+{
+  this->is_valid();
+  this->robot_device->write_byte_register(IMU_CONTROL_OFFSET,IMU_START);
+}
+
+void CDarwinIMU::set_cal_samples(unsigned short int num_samples)
+{
+  this->is_valid();
+  this->robot_device->write_word_register(IMU_CAL_SAMPLES_OFFSET,num_samples);
+}
+
+unsigned short int CDarwinIMU::get_cal_samples(void)
+{
+  unsigned short int samples;
+
+  this->is_valid();
+  this->robot_device->read_word_register(IMU_CAL_SAMPLES_OFFSET,&samples);
+  return samples;
+}
+
+void CDarwinIMU::stop(void)
+{
+  this->is_valid();
+  this->robot_device->write_byte_register(IMU_CONTROL_OFFSET,IMU_STOP);
+}
+
+void CDarwinIMU::start_gyro_cal(void)
+{
+  this->is_valid();
+  this->robot_device->write_byte_register(IMU_CONTROL_OFFSET,IMU_START_CAL);
+}
+
+bool CDarwinIMU::is_gyro_cal_done(void)
+{
+  unsigned char status;
+
+  this->is_valid();
+  this->robot_device->read_byte_register(IMU_CONTROL_OFFSET,&status);
+  if(status&IMU_CALIBRATING)
+    return false;
+  else
+    return true;
+}
+
+bool CDarwinIMU::is_accel_detected(void)
+{
+  unsigned char status;
+
+  this->is_valid();
+  this->robot_device->read_byte_register(IMU_CONTROL_OFFSET,&status);
+  if(status&IMU_ACCEL_DET)
+    return true;
+  else 
+    return false;
+}
+
+bool CDarwinIMU::is_gyro_detected(void)
+{
+  unsigned char status;
+
+  this->is_valid();
+  this->robot_device->read_byte_register(IMU_CONTROL_OFFSET,&status);
+  if(status&IMU_GYRO_DET)
+    return true;
+  else 
+    return false;
+}
+
+void CDarwinIMU::get_accel_data(double *x,double *y,double *z)
+{
+  unsigned char data[6];
+
+  this->is_valid();
+  this->robot_device->read_registers(IMU_ACCEL_X_OFFSET,data,6);
+  *x=((double)((signed short int)(data[0]+(data[1]<<8))))/1000.0;
+  *y=((double)((signed short int)(data[2]+(data[3]<<8))))/1000.0;
+  *z=((double)((signed short int)(data[4]+(data[5]<<8))))/1000.0;
+}
+
+void CDarwinIMU::get_gyro_data(double *x,double *y,double *z)
+{
+  unsigned char data[6];
+
+  this->is_valid();
+  this->robot_device->read_registers(IMU_GYRO_X_OFFSET,data,6);
+  *x=((double)((signed short int)(data[0]+(data[1]<<8))))/1000.0;
+  *y=((double)((signed short int)(data[2]+(data[3]<<8))))/1000.0;
+  *z=((double)((signed short int)(data[4]+(data[5]<<8))))/1000.0;
+}
+
+CDarwinIMU::~CDarwinIMU()
+{
+}
+
diff --git a/src/darwin_mmanager.cpp b/src/darwin_mmanager.cpp
new file mode 100644
index 0000000..51ea996
--- /dev/null
+++ b/src/darwin_mmanager.cpp
@@ -0,0 +1,387 @@
+#include "darwin_mmanager.h"
+#include "darwin_robot_exceptions.h"
+#ifdef _HAVE_XSD
+#include "xml/darwin_config.hxx"
+#endif
+
+const std::string servo_names[MAX_NUM_SERVOS]={std::string("Servo0"),
+                                               std::string("j_shoulder_pitch_r"),
+                                               std::string("j_shoulder_pitch_l"),
+                                               std::string("j_shoulder_roll_r"),
+                                               std::string("j_shoulder_roll_l"),
+                                               std::string("j_elbow_r"),
+                                               std::string("j_elbow_l"),
+                                               std::string("j_hip_yaw_r"),
+                                               std::string("j_hip_yaw_l"),
+                                               std::string("j_hip_roll_r"),
+                                               std::string("j_hip_roll_l"),
+                                               std::string("j_hip_pitch_r"),
+                                               std::string("j_hip_pitch_l"),
+                                               std::string("j_knee_r"),
+                                               std::string("j_knee_l"),
+                                               std::string("j_ankle_pitch_r"),
+                                               std::string("j_ankle_pitch_l"),
+                                               std::string("j_ankle_roll_r"),
+                                               std::string("j_ankle_roll_l"),
+                                               std::string("j_pan"),
+                                               std::string("j_tilt"),
+                                               std::string("j_gripper_top_l"),
+                                               std::string("j_gripper_bot_l"),
+                                               std::string("j_gripper_top_r"),
+                                               std::string("j_gripper_bot_r"),
+                                               std::string("Servo25"),
+                                               std::string("Servo26"),
+                                               std::string("Servo27"),
+                                               std::string("Servo28"),
+                                               std::string("Servo29"),
+                                               std::string("Servo30")};
+
+CDarwinMManager::CDarwinMManager(const std::string &name,std::string &bus_id,int bus_speed, unsigned char id,bool sim) : CDarwinDynManager(name,bus_id,bus_speed,id,sim)
+{
+  this->mmanager_period=this->get_period();
+}
+
+/* motion manager interface */
+unsigned int CDarwinMManager::get_present_servos(void)
+{
+  unsigned int present_servos;
+
+  this->is_valid();
+  this->robot_device->read_registers(MMANAGER_PRESENT_SERVOS,(unsigned char *)&present_servos,4);
+  return present_servos;
+}
+
+void CDarwinMManager::set_period(double period_s)
+{
+  unsigned char period;
+
+  this->is_valid();
+  period=(period_s/this->manager_period);
+  this->robot_device->write_word_register(MMANAGER_PERIOD,period);
+  usleep(1000);
+}
+
+double CDarwinMManager::get_period(void)
+{
+  unsigned short period;
+
+  this->is_valid();
+  this->robot_device->read_word_register(MMANAGER_PERIOD,&period);
+  return ((double)period*this->manager_period);
+}
+
+void CDarwinMManager::enable_servo(unsigned char servo_id)
+{
+  unsigned char value;
+
+  this->is_valid();
+  if(servo_id>MAX_NUM_SERVOS)
+    throw CDarwinRobotException(_HERE_,"Invalid servo identifier");
+  // get the current value
+  this->robot_device->read_byte_register(MMANAGER_ENABLE+servo_id/2,&value);
+  if(servo_id%2)// odd servo
+    value|=MMANAGER_ODD_SER_EN;
+  else// even servo
+    value|=MMANAGER_EVEN_SER_EN;
+  this->robot_device->write_byte_register(MMANAGER_ENABLE+servo_id/2,value);
+}
+
+void CDarwinMManager::disable_servo(unsigned char servo_id)
+{
+  unsigned char value;
+
+  this->is_valid();
+  if(servo_id>MAX_NUM_SERVOS)
+    throw CDarwinRobotException(_HERE_,"Invalid servo identifier");
+  // get the current value
+  this->robot_device->read_byte_register(MMANAGER_ENABLE+servo_id/2,&value);
+  if(servo_id%2)// odd servo
+    value&=(~MMANAGER_ODD_SER_EN);
+  else// even servo
+    value&=(~MMANAGER_EVEN_SER_EN);
+  this->robot_device->write_byte_register(MMANAGER_ENABLE+servo_id/2,value);
+}
+
+bool CDarwinMManager::is_servo_enabled(unsigned char servo_id)
+{
+  unsigned char value;
+
+  this->is_valid();
+  if(servo_id>MAX_NUM_SERVOS)
+    throw CDarwinRobotException(_HERE_,"Invalid servo identifier");
+  // get the current value
+  this->robot_device->read_byte_register(MMANAGER_ENABLE+servo_id/2,&value);
+  if(servo_id%2)// odd servo
+  {
+    if(value&MMANAGER_ODD_SER_EN)
+      return true;
+    else
+      return false;
+  }
+  else// even servo
+  {
+    if(value&MMANAGER_EVEN_SER_EN)
+      return true;
+    else
+      return false;
+  }
+}
+
+void CDarwinMManager::assign_module(unsigned char servo_id, mm_mode_t mode)
+{
+  unsigned char value;
+
+  this->is_valid();
+  if(servo_id>MAX_NUM_SERVOS)
+    throw CDarwinRobotException(_HERE_,"Invalid servo identifier");
+  // get the current value
+  this->robot_device->read_byte_register(MMANAGER_ENABLE+servo_id/2,&value);
+  if(servo_id%2)// odd servo
+  {
+    value&=(~MMANAGER_ODD_SER_MOD);
+    value|=(unsigned char)mode;
+  }
+  else// even servo
+  {
+    value&=(~MMANAGER_EVEN_SER_MOD);
+    value|=(((unsigned char)mode)<<4);
+  }
+  this->robot_device->write_byte_register(MMANAGER_ENABLE+servo_id/2,value);
+}
+
+void CDarwinMManager::assign_module(std::string &servo,std::string &module)
+{
+  unsigned int i=0;
+
+  for(i=0;i<MAX_NUM_SERVOS;i++)
+  {
+    if(servo==servo_names[i])
+    {
+      if(module=="action")
+        this->assign_module(i,DARWIN_MM_ACTION);
+      else if(module=="walking")
+        this->assign_module(i,DARWIN_MM_WALKING);
+      else if(module=="joints")
+        this->assign_module(i,DARWIN_MM_JOINTS);
+      else if(module=="head")
+        this->assign_module(i,DARWIN_MM_HEAD);
+      else if(module=="gripper")
+        this->assign_module(i,DARWIN_MM_GRIPPER);
+      else
+        this->assign_module(i,DARWIN_MM_NONE);
+      break;
+    }
+  }
+}
+
+mm_mode_t CDarwinMManager::get_module(unsigned char servo_id)
+{
+  unsigned char value;
+
+  this->is_valid();
+  if(servo_id>MAX_NUM_SERVOS)
+    throw CDarwinRobotException(_HERE_,"Invalid servo identifier");
+  // get the current value
+  this->robot_device->read_byte_register(MMANAGER_ENABLE+servo_id/2,&value);
+  if(servo_id%2)// odd servo
+    return (mm_mode_t)(value&MMANAGER_ODD_SER_MOD);
+  else
+    return (mm_mode_t)((value&MMANAGER_EVEN_SER_MOD)>>4);
+}
+
+/*
+void CDarwinMManager::enable_balance(void)
+{
+  this->is_valid();
+  this->manager_status|=MANAGER_EN_BAL;
+  this->robot_device->write_byte_register(DARWIN_MM_CNTRL,this->manager_status);
+}
+
+void CDarwinMManager::disable_balance(void)
+{
+  this->is_valid();
+  this->manager_status&=(~MANAGER_EN_BAL);
+  this->robot_device->write_byte_register(DARWIN_MM_CNTRL,this->manager_status);
+}
+
+bool CDarwinMManager::is_balance_enabled(void)
+{
+  unsigned char value;
+
+  this->is_valid();
+  this->robot_device->read_byte_register(DARWIN_MM_CNTRL,&value);
+  if(value&MANAGER_EN_BAL)
+    return true;
+  else
+    return false;
+}
+
+void CDarwinMManager::enable_power(void)
+{
+  this->is_valid();
+  this->manager_status|=MANAGER_EN_PWR;
+  this->robot_device->write_byte_register(DARWIN_MM_CNTRL,this->manager_status);
+}
+
+void CDarwinMManager::disable_power(void)
+{
+  this->is_valid();
+  this->manager_status&=(~MANAGER_EN_PWR);
+  this->robot_device->write_byte_register(DARWIN_MM_CNTRL,this->manager_status);
+}
+
+bool CDarwinMManager::is_power_enabled(void)
+{
+  unsigned char value;
+
+  this->is_valid();
+  this->robot_device->read_byte_register(DARWIN_MM_CNTRL,&value);
+  if(value&MANAGER_EN_PWR)
+    return true;
+  else
+    return false;
+}
+
+bool CDarwinMManager::has_fallen(void)
+{
+  unsigned char value;
+
+  this->is_valid();
+  this->robot_device->read_byte_register(DARWIN_MM_CNTRL,&value);
+  if(value&(MANAGER_FWD_FALL | MANAGER_BWD_FALL))
+    return true;
+  else
+    return false;
+}
+
+fall_t CDarwinMManager::get_fallen_position(void)
+{
+  unsigned char value;
+
+  this->is_valid();
+  this->robot_device->read_byte_register(DARWIN_MM_CNTRL,&value);
+  if(value&MANAGER_FWD_FALL) 
+    return MM_FWD_FALL;
+  else if(value&MANAGER_BWD_FALL)
+    return MM_BWD_FALL;
+  else
+    return MM_STANDING;
+}
+
+void CDarwinMManager::load_config(std::string &filename)
+{
+  darwin_config_t::servo_iterator iterator;
+  unsigned int i=0;
+  struct stat buffer;
+
+  if(stat(filename.c_str(),&buffer)==0)
+  {
+    try{
+      std::auto_ptr<darwin_config_t> cfg(darwin_config(filename.c_str(), xml_schema::flags::dont_validate));
+      for(iterator=cfg->servo().begin(),i=0;iterator!=cfg->servo().end();iterator++,i++)
+        this->mm_assign_module(iterator->name(),iterator->motion_module());
+    }catch(const xml_schema::exception& e){
+      std::ostringstream os;
+      os << e;
+      throw CDarwinRobotException(_HERE_,os.str());
+    }
+  }
+  else
+    throw CDarwinRobotException(_HERE_,"Configuration file does not exist");
+}
+
+std::vector<double> CDarwinMManager::get_servo_angles(void)
+{
+  int i=0;
+  short int values[MAX_NUM_SERVOS];
+  std::vector<double> angles(MAX_NUM_SERVOS);
+
+  this->is_valid();
+  this->robot_device->read_registers(DARWIN_MM_SERVO0_CUR_POS_L,(unsigned char *)values,MAX_NUM_SERVOS*2);
+  for(i=0;i<MAX_NUM_SERVOS;i++)
+    angles[i]=((double)(signed short int)values[i])/128.0;
+
+  return angles;
+}
+
+double CDarwinMManager::get_servo_angle(unsigned char servo_id)
+{
+  unsigned short int value;
+  double angle;
+
+  this->is_valid();
+  if(servo_id>MAX_NUM_SERVOS)
+    throw CDarwinRobotException(_HERE_,"Invalid servo identifier");
+  this->robot_device->read_word_register(DARWIN_MM_SERVO0_CUR_POS_L+servo_id*2,&value);
+  angle=((double)(signed short int)value)/128.0;
+
+  return angle;
+}
+
+void CDarwinMManager::set_servo_offset(unsigned char servo_id,double offset)
+{
+  if(offset<-9.0 || offset>9.0)
+    throw CDarwinMManagerException(_HERE_,"Desired offset out of range");
+  else
+  {
+    if(servo_id>MAX_NUM_SERVOS)
+      throw CDarwinMManagerException(_HERE_,"Invalid servo identifier");
+    else
+    {
+      this->is_valid();
+      this->robot_device->write_byte_register(DARWIN_MM_SERVO0_OFFSET+servo_id,(unsigned char)((int)(offset*16.0)));
+      usleep(1000);
+    }
+  }
+}
+
+double CDarwinMManager::get_servo_offset(unsigned char servo_id)
+{
+  unsigned char value;
+  double offset;
+
+  if(servo_id>MAX_NUM_SERVOS)
+    throw CDarwinMManagerException(_HERE_,"Invalid servo identifier");
+  else
+  {
+    this->is_valid();
+    this->robot_device->read_byte_register(DARWIN_MM_SERVO0_OFFSET+servo_id,&value);
+    offset=((double)((signed char)value))/16.0;
+
+    return offset;
+  }
+}
+
+std::vector<double> CDarwinMManager::get_servo_offsets(void)
+{
+  int i=0;
+  signed char values[MAX_NUM_SERVOS];
+  std::vector<double> offsets(MAX_NUM_SERVOS);
+
+  this->is_valid();
+  this->robot_device->read_registers(DARWIN_MM_SERVO0_OFFSET,(unsigned char *)values,MAX_NUM_SERVOS);
+  for(i=0;i<MAX_NUM_SERVOS;i++)
+    offsets[i]=((double)values[i])/16.0;
+
+  return offsets;
+}
+
+void CDarwinMManager::set_balance_gains(double knee,double ankle_pitch,double hip_roll,double ankle_roll)
+{
+
+}
+
+void CDarwinMManager::get_balance_gains(double *knee,double *ankle_pitch,double *hip_roll,double *ankle_roll)
+{
+
+}
+*/
+
+CDarwinMManager::~CDarwinMManager()
+{
+  if(this->robot_device!=NULL)
+  {
+    this->dyn_server->free_device(this->robot_id);
+  }
+}
+
diff --git a/src/darwin_robot_base.cpp b/src/darwin_robot_base.cpp
new file mode 100644
index 0000000..1f34197
--- /dev/null
+++ b/src/darwin_robot_base.cpp
@@ -0,0 +1,63 @@
+#include "darwin_robot_base.h"
+#include "darwin_robot_exceptions.h"
+#include "dynamixelexceptions.h"
+
+CDarwinRobotBase::CDarwinRobotBase(const std::string &name,std::string &bus_id,int bus_speed, unsigned char id,bool sim)
+{
+  int num_buses;
+
+  this->robot_device=NULL;
+  if(name!="")
+  {
+    this->robot_name=name;
+    if(sim)
+    {
+      this->dyn_server=CDynamixelServerSerial::instance();
+      ((CDynamixelServerSerial *)this->dyn_server)->config_bus(bus_id,bus_speed);
+      num_buses=1;
+    }
+    else
+    {
+      this->dyn_server=CDynamixelServerFTDI::instance();
+      num_buses=((CDynamixelServerFTDI *)this->dyn_server)->get_num_buses();
+      if(num_buses>0)
+        ((CDynamixelServerFTDI *)this->dyn_server)->config_bus(bus_id,bus_speed);
+    }
+    if(num_buses>0)
+    {
+      sleep(1);
+      try{
+        this->robot_device=dyn_server->get_device(id,dyn_version2);
+        this->robot_id=id;
+      }catch(CDynamixelServerException &e){
+        this->dyn_server->free_device(id);
+        throw e;
+      }
+    }
+    else
+    {
+      /* handle exceptions */
+      throw CDarwinRobotException(_HERE_,"No FTDI USB devices found");
+    }
+  }
+  else
+  {
+    /* handle exceptions */    
+    throw CDarwinRobotException(_HERE_,"Invalid robot name");
+  }
+}
+
+void CDarwinRobotBase::is_valid(void)
+{
+  if(this->robot_device==NULL)
+    throw CDarwinRobotException(_HERE_,"Invalid robot device");
+}
+
+CDarwinRobotBase::~CDarwinRobotBase()
+{
+  if(this->robot_device!=NULL)
+  {
+    this->dyn_server->free_device(this->robot_id);
+  }
+}
+
diff --git a/src/examples/CMakeLists.txt b/src/examples/CMakeLists.txt
index 63cdf24..a259c69 100644
--- a/src/examples/CMakeLists.txt
+++ b/src/examples/CMakeLists.txt
@@ -19,9 +19,9 @@ ADD_EXECUTABLE(darwin_imu_test darwin_imu_test.cpp)
 TARGET_LINK_LIBRARIES(darwin_imu_test darwin_robot)
 
 # create an example application
-#ADD_EXECUTABLE(darwin_action_test darwin_action_test.cpp)
+ADD_EXECUTABLE(darwin_action_test darwin_action_test.cpp)
 # link necessary libraries
-#TARGET_LINK_LIBRARIES(darwin_action_test darwin_robot)
+TARGET_LINK_LIBRARIES(darwin_action_test darwin_robot)
 
 # create an example application
 #ADD_EXECUTABLE(darwin_walking_test darwin_walking_test.cpp)
diff --git a/src/examples/darwin_action_test.cpp b/src/examples/darwin_action_test.cpp
index 5b11c43..016337f 100644
--- a/src/examples/darwin_action_test.cpp
+++ b/src/examples/darwin_action_test.cpp
@@ -1,11 +1,10 @@
-#include "darwin_robot.h"
+#include "darwin_mmanager.h"
+#include "darwin_action.h"
 #include "darwin_robot_exceptions.h"
-#include "action_id.h"
 
 #include <iostream>
 
-std::string robot_device="/dev/pts/20";
-//std::string robot_device="A603LOBS";
+std::string robot_device="/tmp/darwin_driver";
 
 int main(int argc, char *argv[])
 {
@@ -13,47 +12,51 @@ int main(int argc, char *argv[])
   unsigned int present_servos;
 
   try{
-    CDarwinRobot darwin("Darwin",robot_device,1000000,0x02,true);
-
-    num_servos=darwin.mm_get_num_servos();
-    present_servos=darwin.mm_get_present_servos();
-    std::cout << "Found " << num_servos << " servos " << std::endl;
-    std::cout << "Present servos: " << std::hex << "0x" << present_servos << std::dec << std::endl;
-    // enable all servos and assign them to the action module
-    darwin.mm_enable_power();
-    sleep(1);
-    for(i=0;i<MAX_NUM_SERVOS;i++)
+    CDarwinMManager darwin("Darwin",robot_device,1000000,0x01,true);
+    CDarwinAction action("Darwin",robot_device,1000000,0x01,true);
+    std::cout << "Manager period: " << darwin.get_base_period() << std::endl;
+    std::cout << "Number of modules: " << darwin.get_num_modules() << std::endl;
+    std::cout << "Number of masters: " << darwin.get_num_masters() << std::endl;
+    std::cout << "Motion manager period: " << darwin.get_period() << std::endl;
+    darwin.start_scan();
+    while(darwin.is_scanning())
     {
-      darwin.mm_enable_servo(i);
-      darwin.mm_assign_module(i,DARWIN_MM_ACTION);
+      std::cout << "scanning ..." << std::endl;
+      usleep(100000);
     }
-    darwin.mm_start();
-    // execute an action
-    darwin.action_load_page(WALK_READY);
-    darwin.action_start();
-    while(darwin.action_is_page_running())
+    num_servos=darwin.get_num_devices();
+    std::cout << "num. devices: " << num_servos << std::endl;
+    present_servos=darwin.get_present_devices();
+    std::cout << "present devices: " << std::hex << present_servos << std::endl;
+    present_servos=darwin.get_present_servos();
+    std::cout << "present servos: " << std::hex << present_servos << std::endl;
+    i=0;
+    while(i<num_servos)
     {
-      std::cout << "action running ... " << std::endl;
-      usleep(100000);
+      if(present_servos&(0x00000001<<i))
+      {
+        darwin.enable_servo(i);
+        darwin.assign_module(i,DARWIN_MM_ACTION);
+      }
+      i++;
     }
-    sleep(2);
-    darwin.action_load_page(SIT_DOWN);
-    darwin.action_start();
-    while(darwin.action_is_page_running())
+    darwin.start();
+    action.load_page(12);
+    action.start();
+    while(action.is_page_running())
     {
       std::cout << "action running ... " << std::endl;
       usleep(100000);
     }
     sleep(2);
-    darwin.action_load_page(STAND_UP);
-    darwin.action_start();
-    while(darwin.action_is_page_running())
+    action.load_page(13);
+    action.start();
+    while(action.is_page_running())
     {
       std::cout << "action running ... " << std::endl;
       usleep(100000);
     }
-    darwin.mm_stop();
-    darwin.mm_disable_power();
+    darwin.stop();
   }catch(CException &e){
     std::cout << e.what() << std::endl;
   }
diff --git a/src/examples/darwin_imu_test.cpp b/src/examples/darwin_imu_test.cpp
index ca5cc97..741bfaf 100644
--- a/src/examples/darwin_imu_test.cpp
+++ b/src/examples/darwin_imu_test.cpp
@@ -1,10 +1,8 @@
-#include "darwin_robot.h"
+#include "darwin_imu.h"
 #include "darwin_robot_exceptions.h"
 
 #include <iostream>
 
-//std::string robot_device="/dev/pts/20";
-//std::string robot_device="A4008atn";
 std::string robot_device="/tmp/darwin_driver";
 
 int main(int argc, char *argv[])
@@ -14,26 +12,26 @@ int main(int argc, char *argv[])
   double accel_x,accel_y,accel_z;
 
   try{
-    CDarwinRobot darwin("Darwin",robot_device,1000000,0x01,true);
+    CDarwinIMU darwin_imu("Darwin",robot_device,1000000,0x01,true);
     std::cout << "found darwin controller" << std::endl;
-    std::cout << "Number of calibration samples: " << darwin.imu_get_cal_samples() << std::endl;
-    darwin.imu_start();
-    std::cout << "Gyroscope detected: " << darwin.imu_is_gyro_detected() << std::endl;
-    std::cout << "Accelerometer detected: " << darwin.imu_is_accel_detected() << std::endl;
-    darwin.imu_start_gyro_cal();
-    while(!darwin.imu_is_gyro_cal_done())
+    std::cout << "Number of calibration samples: " << darwin_imu.get_cal_samples() << std::endl;
+    darwin_imu.start();
+    std::cout << "Gyroscope detected: " << darwin_imu.is_gyro_detected() << std::endl;
+    std::cout << "Accelerometer detected: " << darwin_imu.is_accel_detected() << std::endl;
+    darwin_imu.start_gyro_cal();
+    while(!darwin_imu.is_gyro_cal_done())
     {
       std::cout << "calibrating gyro ..." << std::endl;
       usleep(100000);
     }
     for(i=0;i<50;i++)
     {
-      darwin.imu_get_gyro_data(&gyro_x,&gyro_y,&gyro_z);
-      darwin.imu_get_accel_data(&accel_x,&accel_y,&accel_z);
+      darwin_imu.get_gyro_data(&gyro_x,&gyro_y,&gyro_z);
+      darwin_imu.get_accel_data(&accel_x,&accel_y,&accel_z);
       std::cout << "Gyro: x:" << gyro_x << ", y: " << gyro_y << ", z: " << gyro_z << " Accel: x: " << accel_x << ", y: " << accel_y << " , z: " << accel_z << std::endl;
       usleep(100000);
     }
-    darwin.imu_stop();
+    darwin_imu.stop();
   }catch(CException &e){
     std::cout << e.what() << std::endl;
   }
diff --git a/src/examples/darwin_manager_test.cpp b/src/examples/darwin_manager_test.cpp
index 5fbc977..2694b64 100644
--- a/src/examples/darwin_manager_test.cpp
+++ b/src/examples/darwin_manager_test.cpp
@@ -1,61 +1,60 @@
-#include "darwin_robot.h"
+#include "darwin_mmanager.h"
 #include "darwin_robot_exceptions.h"
 
 #include <iostream>
 
-//std::string robot_device="A603LOBS";
-//std::string robot_device="A4008atn";
 std::string robot_device="/tmp/darwin_driver";
 
 int main(int argc, char *argv[])
 {
   int i=0,num_servos;
   unsigned int present_servos;
-//  std::vector<int> servos;
-//  std::vector<double> angles,speeds,accels,offsets;
 
   try{
-    CDarwinRobot darwin("Darwin",robot_device,1000000,0x01,true);
-    std::cout << "Manager period: " << darwin.manager_get_period() << std::endl;
-    std::cout << "Number of modules: " << darwin.manager_get_num_modules() << std::endl;
-    std::cout << "Number of masters: " << darwin.managet_get_num_masters() << std::endl;
-    std::cout << "Motion manager period: " << darwin.mm_get_period() << std::endl;
-    darwin.manager_start_scan();
-    while(darwin.manager_is_scanning())
+    CDarwinMManager darwin("Darwin",robot_device,1000000,0x01,true);
+    std::cout << "Manager period: " << darwin.get_base_period() << std::endl;
+    std::cout << "Number of modules: " << darwin.get_num_modules() << std::endl;
+    std::cout << "Number of masters: " << darwin.get_num_masters() << std::endl;
+    std::cout << "Motion manager period: " << darwin.get_period() << std::endl;
+    darwin.stop();
+    darwin.start_scan();
+    while(darwin.is_scanning())
     {
       std::cout << "scanning ..." << std::endl;
       usleep(100000);
     }
-    num_servos=darwin.manager_get_num_devices();
+    num_servos=darwin.get_num_devices();
     std::cout << "num. devices: " << num_servos << std::endl;
-    present_servos=darwin.mm_get_present_servos();
+    present_servos=darwin.get_present_devices();
+    std::cout << "present devices: " << std::hex << present_servos << std::endl;
+    present_servos=darwin.get_present_servos();
     std::cout << "present servos: " << std::hex << present_servos << std::endl;
     i=0;
     while(i<num_servos)
     {
       if(present_servos&(0x00000001<<i))
       {
-        darwin.mm_enable_servo(i);
-        darwin.mm_assign_module(i,DARWIN_MM_ACTION);
+        darwin.enable_servo(i);
+        darwin.assign_module(i,DARWIN_MM_ACTION);
       }
       i++;
     }
-    darwin.manager_start();
-    darwin.action_load_page(12);
-    darwin.action_start();
-    while(darwin.action_is_page_running())
-    {
-      std::cout << "action running ... " << std::endl;
-      usleep(100000);
-    }
-    sleep(2);
-    darwin.action_load_page(13);
-    darwin.action_start();
-    while(darwin.action_is_page_running())
-    {
-      std::cout << "action running ... " << std::endl;
-      usleep(100000);
-    }
+    //darwin.start();
+//    darwin.action_load_page(12);
+//    darwin.action_start();
+//    while(darwin.action_is_page_running())
+//    {
+//      std::cout << "action running ... " << std::endl;
+//      usleep(100000);
+//    }
+//    sleep(2);
+//    darwin.action_load_page(13);
+//    darwin.action_start();
+//    while(darwin.action_is_page_running())
+//    {
+//      std::cout << "action running ... " << std::endl;
+//      usleep(100000);
+//    }
 
 //    std::cout << "Found " << num_servos << " servos " << std::endl;
 //    std::cout << "Present servos: " << present_servos << std::hex << "0x" << present_servos << std::dec << std::endl;
-- 
GitLab