diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index 26b899230de257e66801bf79636009ce407de148..c626213960026842e233717dde865f1d5ce084ad 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -11,17 +11,15 @@ FIND_PACKAGE(comm REQUIRED)
 
 FIND_PACKAGE(dynamixel REQUIRED)
 
-FIND_PACKAGE(motor_control REQUIRED)
-
 # edit the following line to add the necessary include directories
-INCLUDE_DIRECTORIES(${iriutils_INCLUDE_DIR} ${comm_INCLUDE_DIR} ${dynamixel_INCLUDE_DIR} ${motor_control_INCLUDE_DIR} .)
+INCLUDE_DIRECTORIES(. ${iriutils_INCLUDE_DIR} ${comm_INCLUDE_DIR} ${dynamixel_INCLUDE_DIR})
 
 SET_SOURCE_FILES_PROPERTIES(${XSD_SOURCES} PROPERTIES GENERATED 1)
 
 ADD_LIBRARY(dynamixel_motor_cont SHARED ${sources} ${XSD_SOURCES})
 
 #edit the following line to add the necessary system libraries (if any)
-TARGET_LINK_LIBRARIES(dynamixel_motor_cont ${iriutils_LIBRARY} ${comm_LIBRARY} ${dynamixel_LIBRARY} ${motor_control_LIBRARY} ${XSD_LIBRARY})
+TARGET_LINK_LIBRARIES(dynamixel_motor_cont ${iriutils_LIBRARY} ${comm_LIBRARY} ${dynamixel_LIBRARY} ${XSD_LIBRARY})
 
 ADD_DEPENDENCIES(dynamixel_motor_cont xsd_files_gen)
 
diff --git a/src/dynamixel_motor.cpp b/src/dynamixel_motor.cpp
index 4a0966780f68a8cccfd81bd72589fa47c3c1e086..3648b1d35f56624bda3711511d69579707574b62 100644
--- a/src/dynamixel_motor.cpp
+++ b/src/dynamixel_motor.cpp
@@ -12,60 +12,52 @@
 #include "xml/dynamixel_motor_cfg_file.hxx"
 #endif
 
-CDynamixelMotor::CDynamixelMotor(std::string& cont_id,unsigned char bus_id,int baudrate,unsigned char dev_id):CMotorControl(cont_id,1)
+CDynamixelMotor::CDynamixelMotor(std::string& cont_id,unsigned char bus_id,int baudrate,unsigned char dev_id)
 {
-  std::vector<float> max,min,gear;
-  std::vector<int> enc_res;
-  TMotorConfig config;
-
   this->info.model="";
-  this->info.firmware_ver=0x00;
-  this->control.cw_compliance_margin=0x00;
-  this->control.ccw_compliance_margin=0x00;
-  this->control.cw_compliance_slope=0x20;
-  this->control.ccw_compliance_slope=0x20;
+  this->info.firmware_ver=(unsigned char)-1;
+  this->info.gear_ratio=(unsigned int)-1;
+  this->info.encoder_resolution=(unsigned int)-1;
+  this->info.pid_control=false;
+  this->info.max_angle=-1;
+  this->info.center_angle=-1;
+  this->info.max_speed=-1;
+  this->info.bus_id="";
+  this->info.baudrate=(unsigned int)-1;
+  this->info.id=(unsigned char)-1;
+  this->compliance.cw_compliance_margin=0x00;
+  this->compliance.ccw_compliance_margin=0x00;
+  this->compliance.cw_compliance_slope=0x20;
+  this->compliance.ccw_compliance_slope=0x20;
+  this->pid.p=0x00;
+  this->pid.i=0x00;
+  this->pid.d=0x00;
+  this->config.max_angle=0.0;
+  this->config.min_angle=0.0;
+  this->config.max_temperature=0.0;
+  this->config.max_voltage=0.0;
+  this->config.min_voltage=0.0;
+  this->config.max_torque=0.0;
   this->dyn_server=CDynamixelServer::instance();
   this->dynamixel_dev=NULL;
-  this->alarms=0x24;
-  this->dyn_enc_res=-1;
-  this->dyn_max_angle=-1;
-  this->dyn_max_speed=-1;
-  this->dyn_max_torque=-1;
-  this->torque_control=false;
   try{
     this->dyn_server->config_bus(bus_id,baudrate);
+    this->info.baudrate=baudrate;
+    this->info.bus_id=this->dyn_server->get_bus_serial();
     this->dynamixel_dev=this->dyn_server->get_device(dev_id);
-    this->info.model=this->get_model();
-    enc_res.push_back(this->dyn_enc_res);
-    config.encoder_resolution=enc_res;
-    this->set_encoder_resolution(enc_res);
-    gear.push_back(1);
-    config.gear_factor=gear;
-    this->set_gear_factor(gear);
-    this->alarms=this->get_turn_off_alarms();
-    this->info.firmware_ver=this->get_firmware_version();
-    this->get_position_range(min,max);
-    this->dyn_max_torque=this->get_max_torque();
-    config.acceleration.resize(1);
-    config.acceleration[0].min=0.0;
-    config.acceleration[0].max=0.0;
-    config.velocity.resize(1);
-    config.velocity[0].min=0.0;
-    config.velocity[0].max=0.0;
-    config.position.resize(1);
-    config.position[0].min=min[0];
-    config.position[0].max=max[0];
-    config.open_loop=false;
-    this->config(&config);
-    if(min[0]==0.0 && max[0]==0.0)
-      this->enable_torque_control();
+    this->info.id=dev_id;
+    this->get_model();
+    this->get_position_range(&this->config.min_angle,&this->config.max_angle);
+    if(this->config.min_angle==-this->info.center_angle && this->config.max_angle==-this->info.center_angle)
+      this->mode=torque_ctrl;
     else
-    {
-      this->config_position_feedback(fb_polling,100.0);
-      this->enable_position_feedback();
-      this->torque_control=false;
-    }
-    this->current_position=this->cont_get_position()[0];
+      this->mode=angle_ctrl;
+    this->config.max_temperature=this->get_temperature_limit();
+    this->get_voltage_limits(&this->config.min_voltage,&this->config.max_voltage);
+    this->config.max_torque=this->get_max_torque();
+    this->get_compliance_control(this->compliance);
+    this->get_pid_control(this->pid);
+    this->alarms=this->get_turn_off_alarms();
   }catch(CException &e){
     /* handle exceptions */
     if(this->dynamixel_dev!=NULL)
@@ -75,60 +67,52 @@ CDynamixelMotor::CDynamixelMotor(std::string& cont_id,unsigned char bus_id,int b
   }
 }
 
-CDynamixelMotor::CDynamixelMotor(std::string& cont_id,std::string &bus_id,int baudrate,unsigned char dev_id):CMotorControl(cont_id,1)
+CDynamixelMotor::CDynamixelMotor(std::string& cont_id,std::string &bus_id,int baudrate,unsigned char dev_id)
 {
-  std::vector<float> max,min,gear;
-  std::vector<int> enc_res;
-  TMotorConfig config;
-
   this->info.model="";
-  this->info.firmware_ver=0x00;
-  this->control.cw_compliance_margin=0x00;
-  this->control.ccw_compliance_margin=0x00;
-  this->control.cw_compliance_slope=0x20;
-  this->control.ccw_compliance_slope=0x20;
+  this->info.firmware_ver=(unsigned char)-1;
+  this->info.gear_ratio=(unsigned int)-1;
+  this->info.encoder_resolution=(unsigned int)-1;
+  this->info.pid_control=false;
+  this->info.max_angle=-1;
+  this->info.center_angle=-1;
+  this->info.max_speed=-1;
+  this->info.bus_id="";
+  this->info.baudrate=(unsigned int)-1;
+  this->info.id=(unsigned char)-1;
+  this->compliance.cw_compliance_margin=0x00;
+  this->compliance.ccw_compliance_margin=0x00;
+  this->compliance.cw_compliance_slope=0x00;
+  this->compliance.ccw_compliance_slope=0x00;
+  this->pid.p=0x00;
+  this->pid.i=0x00;
+  this->pid.d=0x00;
+  this->config.max_angle=0.0;
+  this->config.min_angle=0.0;
+  this->config.max_temperature=0.0;
+  this->config.max_voltage=0.0;
+  this->config.min_voltage=0.0;
+  this->config.max_torque=0.0;
   this->dyn_server=CDynamixelServer::instance();
   this->dynamixel_dev=NULL;
-  this->alarms=0x24;
-  this->dyn_enc_res=-1;
-  this->dyn_max_angle=-1;
-  this->dyn_max_speed=-1;
-  this->dyn_max_torque=-1;
-  this->torque_control=false;
   try{
     this->dyn_server->config_bus(bus_id,baudrate);
+    this->info.baudrate=baudrate;
+    this->info.bus_id=bus_id;
     this->dynamixel_dev=this->dyn_server->get_device(dev_id);
-    this->info.model=this->get_model();
-    enc_res.push_back(this->dyn_enc_res);
-    config.encoder_resolution=enc_res;
-    this->set_encoder_resolution(enc_res);
-    gear.push_back(1);
-    config.gear_factor=gear;
-    this->set_gear_factor(gear);
-    this->alarms=this->get_turn_off_alarms();
-    this->info.firmware_ver=this->get_firmware_version();
-    this->get_position_range(min,max);
-    this->dyn_max_torque=this->get_max_torque();
-    config.acceleration.resize(1);
-    config.acceleration[0].min=0.0;
-    config.acceleration[0].max=0.0;
-    config.velocity.resize(1);
-    config.velocity[0].min=0.0;
-    config.velocity[0].max=0.0;
-    config.position.resize(1);
-    config.position[0].min=min[0];
-    config.position[0].max=max[0];
-    config.open_loop=false;
-    this->config(&config);
-    if(min[0]==0.0 && max[0]==0.0)
-      this->enable_torque_control();
+    this->info.id=dev_id;
+    this->get_model();
+    this->get_position_range(&this->config.min_angle,&this->config.max_angle);
+    if(this->config.min_angle==-this->info.center_angle && this->config.max_angle==-this->info.center_angle)
+      this->mode=torque_ctrl;
     else
-    {
-      this->config_position_feedback(fb_polling,100.0);
-      this->enable_position_feedback();
-      this->torque_control=false;
-    }
-    this->current_position=this->cont_get_position()[0];
+      this->mode=angle_ctrl;
+    this->config.max_temperature=this->get_temperature_limit();
+    this->get_voltage_limits(&this->config.min_voltage,&this->config.max_voltage);
+    this->config.max_torque=this->get_max_torque();
+    this->get_compliance_control(this->compliance);
+    this->get_pid_control(this->pid);
+    this->alarms=this->get_turn_off_alarms();
   }catch(CException &e){
     /* handle exceptions */
     if(this->dynamixel_dev!=NULL)
@@ -138,328 +122,79 @@ CDynamixelMotor::CDynamixelMotor(std::string& cont_id,std::string &bus_id,int ba
   }
 }
 
-void CDynamixelMotor::angles_to_controller(std::vector<float>& angles,std::vector<float>& counts)
+unsigned int CDynamixelMotor::from_angles(double angle)
 {
-  if(angles.size()!=1)
-  {
-    /* handle exceptions */
-    throw CDynamixelMotorException(_HERE_,"Invalid input vector size (it must have only one element).");
-  }
-  else
-  {
-    counts.clear();
-    counts.push_back(angles[0]*this->dyn_enc_res/this->dyn_max_angle);
-  }
-}
+  unsigned int counts;
 
-void CDynamixelMotor::speeds_to_controller(std::vector<float>& speeds,std::vector<float>& counts)
-{
-  if(speeds.size()!=1)
-  {
-    /* handle exceptions */
-    throw CDynamixelMotorException(_HERE_,"Invalid input vector size (it must have only one element).");
-  }
-  else
-  {
-    counts.clear();
-    if(speeds[0]>0.0)
-      counts.push_back(fabs(speeds[0])*1024/(this->dyn_max_speed*6.0));
-    else 
-      counts.push_back(fabs(speeds[0])*1024/(this->dyn_max_speed*6.0));
-  }
-}
+  counts=(angle+this->info.center_angle)*this->info.encoder_resolution/this->info.max_angle;
 
-void CDynamixelMotor::accels_to_controller(std::vector<float>& accels,std::vector<float>& counts)
-{
-  if(accels.size()!=1)
-  {
-    /* handle exceptions */
-    throw CDynamixelMotorException(_HERE_,"Invalid input vector size (it must have only one element).");
-  }
-  else
-  {
-    counts.clear();
-    counts.push_back((long int)accels[0]);
-  }
+  return counts;
 }
 
-void CDynamixelMotor::controller_to_angles(std::vector<float>& counts,std::vector<float>& angles)
+unsigned int CDynamixelMotor::from_speeds(double speed)
 {
-  if(counts.size()!=1)
-  {
-    /* handle exceptions */
-    throw CDynamixelMotorException(_HERE_,"Invalid input vector size (it must have only one element).");
-  }
-  else
-  {
-    angles.clear();
-    angles.push_back(counts[0]*this->dyn_max_angle/this->dyn_enc_res);
-  }
-}
+  unsigned int counts;
 
-void CDynamixelMotor::controller_to_speeds(std::vector<float>& counts,std::vector<float>& speeds)
-{
-  if(counts.size()!=1)
-  {
-    /* handle exceptions */
-    throw CDynamixelMotorException(_HERE_,"Invalid input vector size (it must have only one element).");
-  }
-  else
-  {
-    speeds.clear();
-    speeds.push_back(counts[0]*this->dyn_max_speed*6.0/1024);
-  }
-}
+  if(speed>this->info.max_speed)
+    speed=this->info.max_speed;
+  counts=fabs(speed)/0.666;
 
-void CDynamixelMotor::controller_to_accels(std::vector<float>& counts,std::vector<float>& accels)
-{
-  if(counts.size()!=1)
-  {
-    /* handle exceptions */
-    throw CDynamixelMotorException(_HERE_,"Invalid input vector size (it must have only one element).");
-  }
-  else
-  {
-    accels.clear();
-    accels.push_back((float)counts[0]);
-  }
+  return counts;
 }
 
-void CDynamixelMotor::cont_set_position_range(std::vector<float>& min, std::vector<float>& max)
+double CDynamixelMotor::to_angles(unsigned short int counts)
 {
-  if(this->dynamixel_dev==NULL)
-  {
-    /* handle exceptions */
-    throw CDynamixelMotorException(_HERE_,"The dynamixel device is not properly configured.");
-  }
-  else
-  {
-    if(min[0]<0 || max[0]>(this->dyn_enc_res))
-    {
-      /* handle exceptions */
-      throw CDynamixelMotorException(_HERE_,"The desired range is outside the valid range of the servo.");
-    }
-    else
-    {
-      try{
-        this->dynamixel_dev->write_word_register(ccw_angle_limit,(unsigned short int)max[0]);
-        this->dynamixel_dev->write_word_register(cw_angle_limit,(unsigned short int)min[0]);
-      }catch(CDynamixelAlarmException &e){
-        /* handle dynamixel exception */
-        if(e.get_alarm()&this->alarms)
-          this->reset_motor();
-        throw;
-      }
-    }
-  }
-}
+  double angle;
 
-void CDynamixelMotor::cont_get_position_range(std::vector<float>& min, std::vector<float>& max)
-{
-  unsigned short int angle_limit;
+  angle=counts*this->info.max_angle/this->info.encoder_resolution-this->info.center_angle;
 
-  min.clear();
-  max.clear();
-  if(this->dynamixel_dev==NULL)
-  {
-    /* handle exceptions */
-    throw CDynamixelMotorException(_HERE_,"The dynamixel device is not properly configured.");
-  }
-  else
-  {
-    try{
-      this->dynamixel_dev->read_word_register(ccw_angle_limit,&angle_limit);
-      max.push_back(angle_limit);
-      this->dynamixel_dev->read_word_register(cw_angle_limit,&angle_limit);
-      min.push_back(angle_limit);
-    }catch(CDynamixelAlarmException &e){
-      /* handle dynamixel exception */
-      if(e.get_alarm()&this->alarms)
-        this->reset_motor();
-      throw;
-    }
-  }
+  return angle;
 }
 
-void CDynamixelMotor::cont_get_gear_factor(std::vector<float>& gear)
+double CDynamixelMotor::to_speeds(unsigned short int counts)
 {
-  gear.clear();
-  gear.push_back(1);
-}
-
-std::vector<float> CDynamixelMotor::cont_get_position(void)
-{
-  unsigned short int current_position;
-  std::vector<float> position;
-
-  position.clear();
-  if(this->dynamixel_dev==NULL)
-  { 
-    /* handle exceptions */
-    throw CDynamixelMotorException(_HERE_,"The dynamixel device is not properly configured.");
-  }
-  else
-  {
-    try{
-      this->dynamixel_dev->read_word_register(current_pos,&current_position);
-      position.push_back(current_position&(this->dyn_enc_res));
-    }catch(CDynamixelAlarmException &e){
-      /* handle dynamixel exception */
-      if(e.get_alarm()&this->alarms)
-        this->reset_motor();
-      throw;
-    }
-  }
-
-  return position;
-}
-
-std::vector<float> CDynamixelMotor::cont_get_velocity(void)
-{
-  unsigned short int current_velocity;
-  std::vector<float> velocity;
-
-  velocity.clear();
-  if(this->dynamixel_dev==NULL)
-  {
-    /* handle exceptions */
-    throw CDynamixelMotorException(_HERE_,"The dynamixel device is not properly configured.");
-  }
-  else
-  {
-    try{
-      this->dynamixel_dev->read_word_register(current_speed,&current_velocity);
-      velocity.push_back(current_velocity&1023);
-    }catch(CDynamixelAlarmException &e){
-      /* handle dynamixel exception */
-      if(e.get_alarm()&this->alarms)
-        this->reset_motor();
-      throw;
-    }
-  }
-
-  return velocity;
-}
+  double speed;
 
-void CDynamixelMotor::cont_enable(std::vector<bool> &enable)
-{
-  unsigned char value;
+  speed = counts*0.666; // Taken from the datasheets (sfoix)
 
-  if(this->dynamixel_dev==NULL)
-  {
-    /* handle exceptions */
-    throw CDynamixelMotorException(_HERE_,"The dynamixel device is not properly configured.");
-  }
-  else
-  {
-    try{
-      if(enable[0]==true)
-        value=0x01;
-      else 
-        value=0x00;
-      this->dynamixel_dev->write_byte_register(torque_en,value);
-    }catch(CDynamixelAlarmException &e){
-      /* handle dynamixel exception */
-      if(e.get_alarm()&this->alarms)
-        this->reset_motor();
-      throw;
-    }
-  }
+  return speed;
 }
 
-void CDynamixelMotor::cont_disable(std::vector<bool> &disable)
+void CDynamixelMotor::reset_motor(void)
 {
-  unsigned char value;
+  unsigned short int current_position;
+  unsigned short int maximum_torque;
 
-  if(this->dynamixel_dev==NULL)
-  {
-    /* handle exceptions */
-    throw CDynamixelMotorException(_HERE_,"The dynamixel device is not properly configured.");
-  }
-  else
-  {
-    try{
-      if(disable[0]==true)
-        value=0x00;
-      else
-        value=0x01;
-      this->dynamixel_dev->write_byte_register(torque_en,value);
-    }catch(CDynamixelAlarmException &e){
-      /* handle dynamixel exception */
-      if(e.get_alarm()&this->alarms)
-        this->reset_motor();
-      throw;
-    }
+  try{
+    this->dynamixel_dev->read_word_register(current_pos,&current_position);
+  }catch(CDynamixelAlarmException &e){
+    /* do nothing - expected exception */
   }
-}
-
-void CDynamixelMotor::cont_load(std::vector<float>& position, std::vector<float>& velocity, std::vector<float>& accel)
-{
-  std::vector<bool> relative;
-
-  if(this->dynamixel_dev==NULL)
-  {
-    /* handle exceptions */
-    throw CDynamixelMotorException(_HERE_,"The dynamixel device is not properly configured.");
+  try{
+    this->dynamixel_dev->write_word_register(goal_pos,current_position);
+  }catch(CDynamixelAlarmException &e){
+    /* do nothing - expected exception */
   }
-  else
-  {
-    if(this->get_motor_group_id()=="")
-    {
-      try{
-        if(!this->torque_control)
-        {
-          this->dynamixel_dev->write_word_register(goal_speed,(unsigned short int)velocity[0]);
-          this->is_motion_relative(relative);
-          if(relative[0])
-          {
-            this->dynamixel_dev->registered_word_write(goal_pos,(unsigned short int)(this->current_position+position[0]));
-            this->current_position+=position[0];
-          }
-          else
-          {
-            this->dynamixel_dev->registered_word_write(goal_pos,(unsigned short int)position[0]);
-            this->current_position=position[0];
-          }
-        }
-        else
-        {
-          /* handle exceptions */
-        }
-      }catch(CDynamixelAlarmException &e){
-        /* handle dynamixel exception */
-        if(e.get_alarm()&this->alarms)
-          this->reset_motor();
-        throw;
-      }
-    }
+  try{
+    this->dynamixel_dev->read_word_register(max_torque,&maximum_torque);
+  }catch(CDynamixelAlarmException &e){
+    /* do nothing - expected exception */
   }
-}
-
-void CDynamixelMotor::cont_load(std::vector<float>& velocity, std::vector<float>& accel)
-{
-  if(this->dynamixel_dev==NULL)
-  {
-    /* handle exceptions */
-    throw CDynamixelMotorException(_HERE_,"The dynamixel device is not properly configured.");
+  try{
+    this->dynamixel_dev->write_word_register(torque_limit,maximum_torque);
+  }catch(CDynamixelAlarmException &e){
+    /* do nothing - expected exception */
   }
-  else
-  {
-    /* handle exceptions */
-    throw CDynamixelMotorException(_HERE_,"Velocity control is not supported. Use torque control instead.");
-    // velocity control is not supported
+  try{
+    this->dynamixel_dev->write_byte_register(led,0x00);
+  }catch(CDynamixelAlarmException &e){
+    /* do nothing - expected exception */
   }
 }
 
-void CDynamixelMotor::cont_move(void)
+void CDynamixelMotor::get_model(void)
 {
-  if(this->get_motor_group_id()=="")
-    this->dyn_server->action();
-}
-
-void CDynamixelMotor::cont_stop(void)
-{ 
-  unsigned short int current_position;
+  unsigned short int model;
 
   if(this->dynamixel_dev==NULL)
   {
@@ -469,75 +204,181 @@ void CDynamixelMotor::cont_stop(void)
   else
   {
     try{
-      this->dynamixel_dev->read_word_register(current_pos,&current_position);
-    this->dynamixel_dev->write_word_register(goal_pos,current_position);
-	
+      this->dynamixel_dev->read_byte_register(firmware_version,&this->info.firmware_ver);
+      this->dynamixel_dev->read_word_register(model_number,&model);
+      switch(model)
+      {
+	case 0x000C: this->info.model="AX-12A";
+		     this->info.max_angle=300.0;
+		     this->info.center_angle=150.0;
+		     this->info.max_speed=354;
+		     this->info.encoder_resolution=1023;
+		     this->info.gear_ratio=254;
+		     this->info.pid_control=false;
+		     break;
+	case 0x012C: this->info.model="AX-12W";
+		     this->info.max_angle=300.0;
+		     this->info.center_angle=150.0;
+		     this->info.max_speed=2830;
+		     this->info.encoder_resolution=1023;
+		     this->info.gear_ratio=32;
+		     this->info.pid_control=false;
+		     break;
+	case 0x0012: this->info.model="AX-18A";
+		     this->info.max_angle=300.0;
+		     this->info.center_angle=150.0;
+		     this->info.max_speed=582;
+		     this->info.encoder_resolution=1023;
+		     this->info.gear_ratio=254;
+		     this->info.pid_control=false;
+		     break;
+	case 0x001D: this->info.model="MX-28";
+		     this->info.max_angle=360.0;
+		     this->info.center_angle=180.0;
+		     this->info.max_speed=330;
+		     this->info.encoder_resolution=4095;
+		     this->info.gear_ratio=193;
+		     this->info.pid_control=true;
+		     break;
+	case 0x0018: this->info.model="RX-24F";
+		     this->info.max_angle=300.0;
+		     this->info.center_angle=150.0;
+		     this->info.max_speed=756;
+		     this->info.encoder_resolution=1023;
+		     this->info.gear_ratio=193;
+		     this->info.pid_control=false;
+		     break;
+	case 0x001C: this->info.model="RX-28";
+		     this->info.max_angle=300.0;
+		     this->info.center_angle=150.0;
+		     this->info.max_speed=402;
+		     this->info.encoder_resolution=1023;
+		     this->info.gear_ratio=193;
+		     this->info.pid_control=false;
+		     break;
+	case 0x0136: this->info.model="MX-64";
+		     this->info.max_angle=360.0;
+		     this->info.center_angle=180.0;
+		     this->info.max_speed=378;
+		     this->info.encoder_resolution=4095;
+		     this->info.gear_ratio=200;
+		     this->info.pid_control=true;
+		     break;
+	case 0x0040: this->info.model="Rx-64";
+		     this->info.max_angle=300.0;
+		     this->info.center_angle=150.0;
+		     this->info.max_speed=294;
+		     this->info.encoder_resolution=1023;
+		     this->info.gear_ratio=200;
+		     this->info.pid_control=false;
+		     break;
+	case 0x0140: this->info.model="MX-106";
+		     this->info.max_angle=360.0;
+		     this->info.center_angle=180.0;
+		     this->info.max_speed=270;
+		     this->info.encoder_resolution=4095;
+		     this->info.gear_ratio=225;
+		     this->info.pid_control=true;
+		     break;
+	case 0x006B: this->info.model="Ex-106+";
+		     this->info.max_angle=250.0;
+		     this->info.center_angle=125;
+		     this->info.max_speed=414;
+		     this->info.encoder_resolution=4095;
+		     this->info.gear_ratio=184;
+		     this->info.pid_control=false;
+		     break;
+	default: this->info.model="unknown";
+		 break;
+      }
     }catch(CDynamixelAlarmException &e){
       /* handle dynamixel exception */
       if(e.get_alarm()&this->alarms)
-        this->reset_motor();
+	this->reset_motor();
       throw;
     }
   }
 }
 
-void CDynamixelMotor::cont_close(void)
+void CDynamixelMotor::load_config(TDynamixel_config &config)
 {
-  if(this->dynamixel_dev!=NULL)
-  {
-    this->dyn_server->free_device(this->dynamixel_dev->get_id());
-    delete this->dynamixel_dev;
-    this->dynamixel_dev=NULL;
-  }
+  this->set_position_range(config.min_angle,config.max_angle);
+  this->set_temperature_limit(config.max_temperature);
+  this->set_voltage_limits(config.min_voltage,config.max_voltage);
+  this->set_max_torque(config.max_torque);
+  this->set_limit_torque(config.max_torque);
 }
 
 #ifdef _HAVE_XSD
-void CDynamixelMotor::cont_load_config(std::string &filename)
+void CDynamixelMotor::load_config(std::string &filename)
 {
+  TDynamixel_compliance compliance;
+  TDynamixel_pid pid;
+
   // try to open the specified file
   try{
-    std::auto_ptr<dynamixel_motor_config_t> cfg(dynamixel_motor_config(filename.c_str(),xml_schema::flags::dont_validate));
+    std::auto_ptr<dynamixel_motor_config_t> cfg(dynamixel_motor_config(filename.c_str(), xml_schema::flags::dont_validate));
     // configure the parameters of the controller
+    this->set_turn_off_alarms(cfg->alarm_shtdwn());
+    this->set_position_range(cfg->min_angle(), cfg->max_angle());
     this->set_temperature_limit(cfg->temp_limit());
     this->set_voltage_limits(cfg->min_voltage(),cfg->max_voltage());
-    if(this->info.model=="EX-106" || this->info.model=="MX-28")
-      this->set_pid(cfg->cw_comp_margin(),cfg->ccw_comp_margin(),cfg->cw_comp_slope());
+    if(this->info.pid_control)
+    {
+      pid.p=cfg->kp();
+      pid.i=cfg->ki();
+      pid.d=cfg->kd();
+      this->set_pid_control(pid);
+    }
     else
     {
-      this->set_compliance_margin(cfg->cw_comp_margin(),cfg->ccw_comp_margin());
-      this->set_compliance_slope(cfg->cw_comp_slope(),cfg->ccw_comp_slope());
+      compliance.cw_compliance_margin=cfg->cw_comp_margin();
+      compliance.ccw_compliance_margin=cfg->ccw_comp_margin();
+      compliance.cw_compliance_slope=cfg->cw_comp_slope();
+      compliance.ccw_compliance_slope=cfg->ccw_comp_slope();
+      compliance.punch=cfg->punch();
+      this->set_compliance_control(compliance);
     }
-    this->set_punch(cfg->punch());
+    this->set_max_torque(cfg->max_torque());
+    this->set_limit_torque(cfg->max_torque());
   }catch (const xml_schema::exception& e){
     std::ostringstream os;
     os << e;
     /* handle exceptions */
-    throw CMotorConfigException(_HERE_,os.str());
+    throw CDynamixelMotorException(_HERE_,os.str());
   }
 }
 
-void CDynamixelMotor::cont_save_config(std::string &filename)
+void CDynamixelMotor::save_config(std::string &filename)
 {
   xml_schema::namespace_infomap map;
-  float max_voltage, min_voltage;
-  unsigned char cw_margin=0x00, ccw_margin=0x00;
-  unsigned char cw_slope=0x00, ccw_slope=0x00;
+  double max_voltage,min_voltage,max_angle,min_angle;
+  TDynamixel_compliance compliance;
+  TDynamixel_pid pid;
 
   try{
     std::ofstream output_file(filename.c_str(),std::ios_base::out);
+    this->get_position_range(&min_angle,&max_angle);
     this->get_voltage_limits(&min_voltage,&max_voltage);
-    if(this->info.model=="EX-106" || this->info.model=="MX-28")
-      this->get_pid(&cw_margin,&ccw_margin,&cw_slope);
+    if(this->info.pid_control)
+      this->get_pid_control(pid);
     else
-    {
-      this->get_compliance_margin(&cw_margin,&ccw_margin);
-      this->get_compliance_slope(&cw_slope,&ccw_slope);
-    }
-    dynamixel_motor_config_t dyn_cfg(this->get_temperature_limit(),
-                                     max_voltage,min_voltage,
-                                     cw_margin,ccw_margin,
-                                     cw_slope,ccw_slope,
-                                     this->get_punch());
+      this->get_compliance_control(compliance);
+    dynamixel_motor_config_t dyn_cfg((int)this->get_turn_off_alarms(),
+	max_angle,
+	min_angle,
+	this->get_temperature_limit(),
+	max_voltage,
+	min_voltage,
+	this->get_max_torque(),
+	compliance.cw_compliance_margin,
+	compliance.ccw_compliance_margin,
+	compliance.cw_compliance_slope,
+	compliance.ccw_compliance_slope,
+	compliance.punch,
+	pid.p,
+	pid.i,
+	pid.d);
     map[""].name="";
     map[""].schema="dynamixel_motor_config.xsd";
     dynamixel_motor_config(output_file,dyn_cfg,map);
@@ -545,41 +386,29 @@ void CDynamixelMotor::cont_save_config(std::string &filename)
     std::ostringstream os;
     os << e;
     /* handle exceptions */
-    CMotorConfigException(_HERE_,os.str());
+    throw CDynamixelMotorException(_HERE_,os.str());
   }
 }
 #endif
 
-void CDynamixelMotor::reset_motor(void)
+void CDynamixelMotor::get_servo_info(TDynamixel_info &info)
 {
-  unsigned short int current_position;
-
-  try{
-    this->dynamixel_dev->read_word_register(current_pos,&current_position);
-  }catch(CDynamixelAlarmException &e){
-    /* do nothing - expected exception */
-  }
-  try{
-    this->dynamixel_dev->write_word_register(goal_pos,current_position);
-  }catch(CDynamixelAlarmException &e){
-    /* do nothing - expected exception */
-  }
-  try{
-    this->dynamixel_dev->write_word_register(torque_limit,((unsigned short int)(fabs(this->dyn_max_torque)*1023.0/100.0))&0x03FF);
-  }catch(CDynamixelAlarmException &e){
-    /* do nothing - expected exception */
-  }
-  try{
-    this->dynamixel_dev->write_byte_register(led,0x00);
-  }catch(CDynamixelAlarmException &e){
-    /* do nothing - expected exception */
-  }
+  info.model=this->info.model;
+  info.firmware_ver=this->info.firmware_ver;
+  info.gear_ratio=this->info.gear_ratio;
+  info.encoder_resolution=this->info.encoder_resolution;
+  info.pid_control=this->info.pid_control;
+  info.max_angle=this->info.max_angle;
+  info.center_angle=this->info.center_angle;
+  info.max_speed=this->info.max_speed;
+  info.bus_id=this->info.bus_id;
+  info.baudrate=this->info.baudrate;
+  info.id=this->info.id;
 }
 
-int CDynamixelMotor::get_baudrate(void)
+void CDynamixelMotor::set_position_range(double min, double max)
 {
-  unsigned char value=0;
-  int baud_rate=0;
+  unsigned short int max_pos,min_pos;
 
   if(this->dynamixel_dev==NULL)
   {
@@ -588,148 +417,33 @@ int CDynamixelMotor::get_baudrate(void)
   }
   else
   {
-    try{
-      this->dynamixel_dev->read_byte_register(baudrate,&value);
-      baud_rate=(2000000/value)+1;
-    }catch(CDynamixelAlarmException &e){
-      /* handle dynamixel exception */
-      if(e.get_alarm()&this->alarms)
-        this->reset_motor();
-      throw;
-    }
-  }
-
-  return baud_rate;
-}
-
-unsigned char CDynamixelMotor::get_node_address(void)
-{
-  unsigned char address=0x00;
-
-  if(this->dynamixel_dev==NULL)
-  {
-    /* handle exceptions */
-    throw CDynamixelMotorException(_HERE_,"The dynamixel device is not properly configured.");
-  }
-  else
-  {
-    try{
-      this->dynamixel_dev->read_byte_register(id,&address);
-    }catch(CDynamixelAlarmException &e){
-      /* handle dynamixel exception */
-      if(e.get_alarm()&this->alarms)
-        this->reset_motor();
-      throw;
-    }
-  }
-
-  return (unsigned char)address;
-}
-
-void CDynamixelMotor::set_node_address(unsigned char dev_id)
-{
-  if(this->dynamixel_dev==NULL)
-  {
-    /* handle exceptions */
-    throw CDynamixelMotorException(_HERE_,"The dynamixel device is not properly configured.");
-  }
-  else
-  {
-    try{
-      this->dynamixel_dev->set_id(dev_id);
-    }catch(CDynamixelAlarmException &e){
-      /* handle dynamixel exception */
-      if(e.get_alarm()&this->alarms)
-        this->reset_motor();
-      throw;
+    max_pos=this->from_angles(max);
+    min_pos=this->from_angles(min);
+    if(min_pos<0.0 || max_pos>(this->info.encoder_resolution))
+    {
+      /* handle exceptions */
+      throw CDynamixelMotorException(_HERE_,"The desired range is outside the valid range of the servo.");
     }
-  }
-}
-
-std::string CDynamixelMotor::get_model(void)
-{
-  unsigned short int model;
-
-  if(this->dynamixel_dev==NULL)
-  {
-    /* handle exceptions */
-    throw CDynamixelMotorException(_HERE_,"The dynamixel device is not properly configured.");
-  }
-  else
-  {
-    try{
-      this->dynamixel_dev->read_word_register(model_number,&model);
-      switch(model)
-      {
-        case 0x000C: this->info.model="AX-12";
-                     // set maximum angle
-                     this->dyn_max_angle=300;
-                     // set maximum speed
-                     this->dyn_max_speed=114;
-                     // set resolution
-                     this->dyn_enc_res=1023;
-                     break;
-        case 0x000A: this->info.model="RX-10";
-                     // set maximum angle
-                     this->dyn_max_angle=300;
-                     // set maximum speed
-                     this->dyn_max_speed=114;
-                     // set resolution
-                     this->dyn_enc_res=1023;
-                     break;
-        case 0x001C: this->info.model="RX-28";
-                     // set maximum angle
-                     this->dyn_max_angle=300;
-                     // set maximum speed
-                     this->dyn_max_speed=114;
-                     // set resolution
-                     this->dyn_enc_res=1023;
-                     break;
-        case 0x0040: this->info.model="RX-64";
-                     // set maximum angle
-                     this->dyn_max_angle=300;
-                     // set maximum speed
-                     this->dyn_max_speed=114;
-                     // set resolution
-                     this->dyn_enc_res=1023;
-                     break;
-        case 0x006B: this->info.model="EX-106";
-                     // set maximum angle
-                     this->dyn_max_angle=251;
-                     // set maximum speed
-                     this->dyn_max_speed=114;
-                     // set resolution
-                     this->dyn_enc_res=4095;
-                     break;
-        case 0x001D: this->info.model="MX-28";
-                     // set maximum angle
-                     this->dyn_max_angle=360;
-                     // set maximum speed
-                     this->dyn_max_speed=54;
-                     // set resolution
-                     this->dyn_enc_res=4095;
-                     break;
-        default: this->info.model="unknown";
-                 break;
+    else
+    {
+      try{
+	this->config.max_angle=max;
+	this->config.min_angle=min;
+	this->dynamixel_dev->write_word_register(ccw_angle_limit,max_pos);
+	this->dynamixel_dev->write_word_register(cw_angle_limit,min_pos);
+      }catch(CDynamixelAlarmException &e){
+	/* handle dynamixel exception */
+	if(e.get_alarm()&this->alarms)
+	  this->reset_motor();
+	throw;
       }
-    }catch(CDynamixelAlarmException &e){
-      /* handle dynamixel exception */
-      if(e.get_alarm()&this->alarms)
-        this->reset_motor();
-      throw;
     }
   }
-
-  return this->info.model;
 }
 
-int CDynamixelMotor::get_id(void)
-{
-  return this->dynamixel_dev->get_id();
-}
-
-unsigned char CDynamixelMotor::get_firmware_version(void)
+void CDynamixelMotor::get_position_range(double *min, double *max)
 {
+  unsigned short int angle_limit;
 
   if(this->dynamixel_dev==NULL)
   {
@@ -739,16 +453,17 @@ unsigned char CDynamixelMotor::get_firmware_version(void)
   else
   {
     try{
-      this->dynamixel_dev->read_byte_register(firmware_version,&this->info.firmware_ver);
+      this->dynamixel_dev->read_word_register(ccw_angle_limit,&angle_limit);
+      (*max)=this->to_angles(angle_limit);
+      this->dynamixel_dev->read_word_register(cw_angle_limit,&angle_limit);
+      (*min)=this->to_angles(angle_limit);
     }catch(CDynamixelAlarmException &e){
       /* handle dynamixel exception */
-      if(e.get_alarm()&this->alarms) 
-        this->reset_motor();
+      if(e.get_alarm()&this->alarms)
+	this->reset_motor();
       throw;
     }
   }
-
-  return this->info.firmware_ver;
 }
 
 int CDynamixelMotor::get_temperature_limit(void)
@@ -767,7 +482,7 @@ int CDynamixelMotor::get_temperature_limit(void)
     }catch(CDynamixelAlarmException &e){
       /* handle dynamixel exception */
       if(e.get_alarm()&this->alarms)
-        this->reset_motor();
+	this->reset_motor();
       throw;
     }
   }
@@ -777,7 +492,6 @@ int CDynamixelMotor::get_temperature_limit(void)
 
 void CDynamixelMotor::set_temperature_limit(int limit)
 {
-
   if(limit<0 && limit>255)
   {
     /* handle exceptions */
@@ -793,42 +507,19 @@ void CDynamixelMotor::set_temperature_limit(int limit)
     else
     {
       try{
-        this->dynamixel_dev->write_byte_register(temp_limit,(unsigned char)limit);
+	this->config.max_temperature=limit;
+	this->dynamixel_dev->write_byte_register(temp_limit,(unsigned char)limit);
       }catch(CDynamixelAlarmException &e){
-        /* handle dynamixel exception */
-        if(e.get_alarm()&this->alarms)
-          this->reset_motor();
-        throw;
+	/* handle dynamixel exception */
+	if(e.get_alarm()&this->alarms)
+	  this->reset_motor();
+	throw;
       }
     }
   }
 }
 
-int CDynamixelMotor::get_current_temperature(void)
-{
-  unsigned char current;
-
-  if(this->dynamixel_dev==NULL)
-  {
-    /* handle exceptions */
-    throw CDynamixelMotorException(_HERE_,"The dynamixel device is not properly configured.");
-  }
-  else
-  {
-    try{
-      this->dynamixel_dev->read_byte_register(current_temp,&current);
-    }catch(CDynamixelAlarmException &e){
-      /* handle dynamixel exception */
-      if(e.get_alarm()&this->alarms)
-        this->reset_motor();
-      throw;
-    }
-  }
-
-  return current;
-}
-
-void CDynamixelMotor::get_voltage_limits(float *min, float *max)
+void CDynamixelMotor::get_voltage_limits(double *min, double *max)
 {
   unsigned char min_voltage,max_voltage;
 
@@ -842,18 +533,18 @@ void CDynamixelMotor::get_voltage_limits(float *min, float *max)
     try{
       this->dynamixel_dev->read_byte_register(low_voltage_limit,&min_voltage);
       this->dynamixel_dev->read_byte_register(high_voltage_limit,&max_voltage);
-      *min=((float)min_voltage/10.0);
-      *max=((float)max_voltage/10.0);
+      *min=((double)min_voltage/10.0);
+      *max=((double)max_voltage/10.0);
     }catch(CDynamixelAlarmException &e){
       /* handle dynamixel exception */
       if(e.get_alarm()&this->alarms)
-        this->reset_motor();
+	this->reset_motor();
       throw;
     }
   }
 }
 
-void CDynamixelMotor::set_voltage_limits(float min, float max)
+void CDynamixelMotor::set_voltage_limits(double min, double max)
 {
   unsigned char min_voltage,max_voltage;
 
@@ -873,51 +564,29 @@ void CDynamixelMotor::set_voltage_limits(float min, float max)
     {
       if(min<5.0 || min>25.0 || max<5.0 || max>25.0)
       {
-        /* handle exceptions */
-        throw CDynamixelMotorException(_HERE_,"The desired voltage range is outside the valid range.");
+	/* handle exceptions */
+	throw CDynamixelMotorException(_HERE_,"The desired voltage range is outside the valid range.");
       }
       else
       {
-        try{
-          min_voltage=min*10;
-          max_voltage=max*10;
-          this->dynamixel_dev->write_byte_register(low_voltage_limit,min_voltage);
-          this->dynamixel_dev->write_byte_register(high_voltage_limit,max_voltage);
-        }catch(CDynamixelAlarmException &e){
-          /* handle dynamixel exception */
-          if(e.get_alarm()&this->alarms)
-            this->reset_motor();
-          throw;
-        }
+	try{
+	  this->config.min_voltage=min;
+	  this->config.max_voltage=max;
+	  min_voltage=min*10;
+	  max_voltage=max*10;
+	  this->dynamixel_dev->write_byte_register(low_voltage_limit,min_voltage);
+	  this->dynamixel_dev->write_byte_register(high_voltage_limit,max_voltage);
+	}catch(CDynamixelAlarmException &e){
+	  /* handle dynamixel exception */
+	  if(e.get_alarm()&this->alarms)
+	    this->reset_motor();
+	  throw;
+	}
       }
     }
   }
 }
 
-float CDynamixelMotor::get_current_voltage(void)
-{
-  unsigned char voltage;
-
-  if(this->dynamixel_dev==NULL)
-  {
-    /* handle exceptions */
-    throw CDynamixelMotorException(_HERE_,"The dynamixel device is not properly configured.");
-  }
-  else
-  {
-    try{
-      this->dynamixel_dev->read_byte_register(current_voltage,&voltage);
-    }catch(CDynamixelAlarmException &e){
-      /* handle dynamixel exception */
-      if(e.get_alarm()&this->alarms)
-        this->reset_motor();
-      throw;
-    }
-  }
-
-  return ((float)voltage/10.0);
-}
-
 unsigned char CDynamixelMotor::get_led_alarms(void)
 {
   unsigned char led_alarms=0x00;
@@ -934,7 +603,7 @@ unsigned char CDynamixelMotor::get_led_alarms(void)
     }catch(CDynamixelAlarmException &e){
       /* handle dynamixel exception */
       if(e.get_alarm()&this->alarms)
-        this->reset_motor();
+	this->reset_motor();
       throw;
     }
   }
@@ -944,7 +613,6 @@ unsigned char CDynamixelMotor::get_led_alarms(void)
 
 void CDynamixelMotor::set_led_alarms(unsigned char alarms)
 {
-
   if(alarms&0x80)
   {
     /* handle exceptions */
@@ -960,12 +628,12 @@ void CDynamixelMotor::set_led_alarms(unsigned char alarms)
     else
     {
       try{
-        this->dynamixel_dev->write_byte_register(alarm_led,(unsigned char)alarms);
+	this->dynamixel_dev->write_byte_register(alarm_led,(unsigned char)alarms);
       }catch(CDynamixelAlarmException &e){
-        /* handle dynamixel exception */
-        if(e.get_alarm()&this->alarms)
-          this->reset_motor();
-        throw;
+	/* handle dynamixel exception */
+	if(e.get_alarm()&this->alarms)
+	  this->reset_motor();
+	throw;
       }
     }
   }
@@ -983,11 +651,11 @@ unsigned char CDynamixelMotor::get_turn_off_alarms(void)
   else
   {
     try{
-      this->dynamixel_dev->read_byte_register(alarm_shtdwn,&shutdown_alarms);
+      this->dynamixel_dev->read_byte_register(alarm_shtdwn, &shutdown_alarms);
     }catch(CDynamixelAlarmException &e){
       /* handle dynamixel exception */
       if(e.get_alarm()&this->alarms)
-        this->reset_motor();
+	this->reset_motor();
       throw;
     }
   }  
@@ -997,7 +665,6 @@ unsigned char CDynamixelMotor::get_turn_off_alarms(void)
 
 void CDynamixelMotor::set_turn_off_alarms(unsigned char alarms)
 {
-
   if(alarms&0x80)
   {
     /* handle exceptions */
@@ -1013,19 +680,22 @@ void CDynamixelMotor::set_turn_off_alarms(unsigned char alarms)
     else
     {
       try{
-        this->dynamixel_dev->write_byte_register(alarm_shtdwn,(unsigned char)alarms);
+	this->alarms=alarms;
+	this->dynamixel_dev->write_byte_register(alarm_shtdwn,(unsigned char)alarms);
       }catch(CDynamixelAlarmException &e){
-        /* handle dynamixel exception */
-        if(e.get_alarm()&this->alarms)
-          this->reset_motor();
-        throw;
+	/* handle dynamixel exception */
+	if(e.get_alarm()&this->alarms)
+	  this->reset_motor();
+	throw;
       }
     }
   }
 }
 
-void CDynamixelMotor::turn_led_on(void)
+double CDynamixelMotor::get_max_torque(void)
 {
+  unsigned short int load;
+  double torque;
 
   if(this->dynamixel_dev==NULL)
   {
@@ -1035,18 +705,25 @@ void CDynamixelMotor::turn_led_on(void)
   else
   {
     try{
-      this->dynamixel_dev->write_byte_register(led,1);
+      this->dynamixel_dev->read_word_register(max_torque,&load);
+      torque=(load&0x3FF)*100.0/1023;
+      if(load>0x3FF)
+	torque=-1*torque;
     }catch(CDynamixelAlarmException &e){
       /* handle dynamixel exception */
       if(e.get_alarm()&this->alarms)
-        this->reset_motor();
+	this->reset_motor();
       throw;
     }
   }
+
+  return torque;
 }
 
-void CDynamixelMotor::turn_led_off(void)
+double CDynamixelMotor::get_limit_torque(void)
 {
+  unsigned short int load;
+  double torque;
 
   if(this->dynamixel_dev==NULL)
   {
@@ -1056,18 +733,25 @@ void CDynamixelMotor::turn_led_off(void)
   else
   {
     try{
-      this->dynamixel_dev->write_byte_register(led,0);
+      this->dynamixel_dev->read_word_register(torque_limit,&load);
+      torque=(load&0x3FF)*100.0/1023;
+      if(load>0x3FF)
+	torque=-1*torque;
     }catch(CDynamixelAlarmException &e){
       /* handle dynamixel exception */
       if(e.get_alarm()&this->alarms)
-        this->reset_motor();
+	this->reset_motor();
       throw;
     }
   }
+
+  return torque;
 }
 
-void CDynamixelMotor::get_compliance_margin(unsigned char *cw_margin, unsigned char *ccw_margin)
+void CDynamixelMotor::set_max_torque(double torque_ratio)
 {
+  unsigned short int load;
+
   if(this->dynamixel_dev==NULL)
   {
     /* handle exceptions */
@@ -1075,36 +759,30 @@ void CDynamixelMotor::get_compliance_margin(unsigned char *cw_margin, unsigned c
   }
   else
   {
-    if(this->info.model=="MX-28" || this->info.model=="EX-106")
+    if(torque_ratio<0.0 || torque_ratio>100.0)
     {
-      /* handle exceptions */
-      throw CDynamixelMotorException(_HERE_,"This servo model does not support compliance margin.");
+      throw CDynamixelMotorException(_HERE_,"The desired torque ratio is outside the valid range.");
     }
     else
     {
-      if(cw_margin==NULL || ccw_margin==NULL)
-      {
-        /* handle exceptions */
-        throw CDynamixelMotorException(_HERE_,"Invalid complinace margin.");
-      }
-      else
-      {
-        try{
-          this->dynamixel_dev->read_byte_register(cw_comp_margin,cw_margin);
-          this->dynamixel_dev->read_byte_register(ccw_comp_margin,ccw_margin);
-        }catch(CDynamixelAlarmException &e){
-          /* handle dynamixel exception */
-          if(e.get_alarm()&this->alarms)
-            this->reset_motor();
-          throw;
-        }
+      load=torque_ratio*1023/100.0;
+      try{
+	this->config.max_torque=torque_ratio;
+	this->dynamixel_dev->write_word_register(max_torque,load);
+      }catch(CDynamixelAlarmException &e){
+	/* handle dynamixel exception */
+	if(e.get_alarm()&this->alarms)
+	  this->reset_motor();
+	throw;
       }
     }
   }
 }
 
-void CDynamixelMotor::set_compliance_margin(unsigned char cw_margin, unsigned char ccw_margin)
+void CDynamixelMotor::set_limit_torque(double torque_ratio)
 {
+  unsigned short int load;
+
   if(this->dynamixel_dev==NULL)
   {
     /* handle exceptions */
@@ -1112,37 +790,26 @@ void CDynamixelMotor::set_compliance_margin(unsigned char cw_margin, unsigned ch
   }
   else
   {
-    if(this->info.model=="MX-28" || this->info.model=="EX-106")
+    if(torque_ratio<0.0 || torque_ratio>100.0)
     {
-      /* handle exceptions */
-      throw CDynamixelMotorException(_HERE_,"This servo model does not support compliance margin.");
+      throw CDynamixelMotorException(_HERE_,"The desired torque ratio is outside the valid range.");
     }
     else
     {
-      if(cw_margin>254)
-      {
-        /* handle exceptions */
-        throw CDynamixelMotorException(_HERE_,"Invalid clockwise compliance margin.");
-      }
-      if(ccw_margin>254)
-      {
-        /*  handle exceptions */
-        throw CDynamixelMotorException(_HERE_,"Invalid counterclockwise compliance margin.");
-      }
+      load=torque_ratio*1023/100.0;
       try{
-        this->dynamixel_dev->write_byte_register(cw_comp_margin,cw_margin);
-        this->dynamixel_dev->write_byte_register(ccw_comp_margin,ccw_margin);
+	this->dynamixel_dev->write_word_register(torque_limit,load);
       }catch(CDynamixelAlarmException &e){
-        /* handle dynamixel exception */
-        if(e.get_alarm()&this->alarms)
-          this->reset_motor();
-        throw;
+	/* handle dynamixel exception */
+	if(e.get_alarm()&this->alarms)
+	  this->reset_motor();
+	throw;
       }
     }
   }
 }
 
-void CDynamixelMotor::get_compliance_slope(unsigned char *cw_slope, unsigned char *ccw_slope)
+void CDynamixelMotor::get_compliance_control(TDynamixel_compliance &config)
 {
   if(this->dynamixel_dev==NULL)
   {
@@ -1151,35 +818,25 @@ void CDynamixelMotor::get_compliance_slope(unsigned char *cw_slope, unsigned cha
   }
   else
   {
-    if(this->info.model=="MX-28" || this->info.model=="EX-106")
+    if(!this->info.pid_control)
     {
-      /* handle exceptions */
-      throw CDynamixelMotorException(_HERE_,"This servo model does not support compliance slope.");
-    }
-    else
-    {
-      if(cw_slope==NULL || ccw_slope==NULL)
-      {
-        /* handle exceptions */
-        throw CDynamixelMotorException(_HERE_,"Invalid compliance slope.");
-      }
-      else
-      {
-        try{
-          this->dynamixel_dev->read_byte_register(cw_comp_slope,cw_slope);
-          this->dynamixel_dev->read_byte_register(ccw_comp_slope,ccw_slope);
-        }catch(CDynamixelAlarmException &e){
-          /* handle dynamixel exception */
-          if(e.get_alarm()&this->alarms)
-            this->reset_motor();
-          throw;
-        }
+      try{
+	this->dynamixel_dev->read_byte_register(cw_comp_margin,&config.cw_compliance_margin);
+	this->dynamixel_dev->read_byte_register(ccw_comp_margin,&config.ccw_compliance_margin);
+	this->dynamixel_dev->read_byte_register(cw_comp_slope,&config.cw_compliance_slope);
+	this->dynamixel_dev->read_byte_register(ccw_comp_slope,&config.ccw_compliance_slope);
+	this->dynamixel_dev->read_byte_register(punch,&config.punch);
+      }catch(CDynamixelAlarmException &e){
+	/* handle dynamixel exception */
+	if(e.get_alarm()&this->alarms)
+	  this->reset_motor();
+	throw;
       }
     }
   }
 }
 
-void CDynamixelMotor::set_compliance_slope(unsigned char cw_slope, unsigned char ccw_slope)
+void CDynamixelMotor::set_compliance_control(TDynamixel_compliance &config)
 {
   if(this->dynamixel_dev==NULL)
   {
@@ -1187,55 +844,116 @@ void CDynamixelMotor::set_compliance_slope(unsigned char cw_slope, unsigned char
     throw CDynamixelMotorException(_HERE_,"The dynamixel device is not properly configured.");
   }
   else
-  { 
-    if(this->info.model=="MX-28" || this->info.model=="EX-106")
-    {
-      /* handle exceptions */
-      throw CDynamixelMotorException(_HERE_,"This servo model does not support compliance slope.");
-    }
-    else
+  {
+    if(!this->info.pid_control)
     {
-      if(cw_slope>=1 && cw_slope<=5) cw_slope=4;
-      else if(cw_slope>=6 && cw_slope<=11) cw_slope=8;
-      else if(cw_slope>=12 && cw_slope<=23) cw_slope=16;
-      else if(cw_slope>=24 && cw_slope<=47) cw_slope=32;
-      else if(cw_slope>=48 && cw_slope<=95) cw_slope=64;
-      else if(cw_slope>=96 && cw_slope<=191) cw_slope=128;
-      else if(cw_slope>=192 && cw_slope<=254) cw_slope=254;
+      if(config.cw_compliance_margin>254)
+      {
+	/* handle exceptions */
+	throw CDynamixelMotorException(_HERE_,"Invalid clockwise compliance margin.");
+      }
+      if(config.ccw_compliance_margin>254)
+      {
+	/*  handle exceptions */
+	throw CDynamixelMotorException(_HERE_,"Invalid counterclockwise compliance margin.");
+      }
+      if(config.cw_compliance_slope>=1 && config.cw_compliance_slope<=5) config.cw_compliance_slope=4;
+      else if(config.cw_compliance_slope>=6 && config.cw_compliance_slope<=11) config.cw_compliance_slope=8;
+      else if(config.cw_compliance_slope>=12 && config.cw_compliance_slope<=23) config.cw_compliance_slope=16;
+      else if(config.cw_compliance_slope>=24 && config.cw_compliance_slope<=47) config.cw_compliance_slope=32;
+      else if(config.cw_compliance_slope>=48 && config.cw_compliance_slope<=95) config.cw_compliance_slope=64;
+      else if(config.cw_compliance_slope>=96 && config.cw_compliance_slope<=191) config.cw_compliance_slope=128;
+      else if(config.cw_compliance_slope>=192 && config.cw_compliance_slope<=254) config.cw_compliance_slope=254;
       else
       {
-        /* handle exceptions */
-        throw CDynamixelMotorException(_HERE_,"Invalid clockwise compliance slope.");
+	/* handle exceptions */
+	throw CDynamixelMotorException(_HERE_,"Invalid clockwise compliance slope.");
       }
-      if(ccw_slope>=1 && ccw_slope<=5) ccw_slope=4;
-      else if(ccw_slope>=6 && ccw_slope<=11) ccw_slope=8;
-      else if(ccw_slope>=12 && ccw_slope<=23) ccw_slope=16;
-      else if(ccw_slope>=24 && ccw_slope<=47) ccw_slope=32;
-      else if(ccw_slope>=48 && ccw_slope<=95) ccw_slope=64;
-      else if(ccw_slope>=96 && ccw_slope<=191) ccw_slope=128;
-      else if(ccw_slope>=192 && ccw_slope<=254) ccw_slope=254;
+      if(config.ccw_compliance_slope>=1 && config.ccw_compliance_slope<=5) config.ccw_compliance_slope=4;
+      else if(config.ccw_compliance_slope>=6 && config.ccw_compliance_slope<=11) config.ccw_compliance_slope=8;
+      else if(config.ccw_compliance_slope>=12 && config.ccw_compliance_slope<=23) config.ccw_compliance_slope=16;
+      else if(config.ccw_compliance_slope>=24 && config.ccw_compliance_slope<=47) config.ccw_compliance_slope=32;
+      else if(config.ccw_compliance_slope>=48 && config.ccw_compliance_slope<=95) config.ccw_compliance_slope=64;
+      else if(config.ccw_compliance_slope>=96 && config.ccw_compliance_slope<=191) config.ccw_compliance_slope=128;
+      else if(config.ccw_compliance_slope>=192 && config.ccw_compliance_slope<=254) config.ccw_compliance_slope=254;
       else
       {
-        /* handle exceptions */
-        throw CDynamixelMotorException(_HERE_,"Invalid counterclockwise compliance slope.");
+	/* handle exceptions */
+	throw CDynamixelMotorException(_HERE_,"Invalid counterclockwise compliance slope.");
+      }
+      if(config.punch<0 || config.punch>1023)
+      {
+	/* handle exceptions */
+	throw CDynamixelMotorException(_HERE_,"Invalid punch value.");
+      }
+      try{
+	this->compliance.cw_compliance_margin=config.cw_compliance_margin;
+	this->compliance.ccw_compliance_margin=config.ccw_compliance_margin;
+	this->compliance.cw_compliance_slope=config.cw_compliance_slope;
+	this->compliance.ccw_compliance_slope=config.ccw_compliance_slope;
+	this->dynamixel_dev->write_byte_register(cw_comp_margin,config.cw_compliance_margin);
+	this->dynamixel_dev->write_byte_register(ccw_comp_margin,config.ccw_compliance_margin);
+	this->dynamixel_dev->write_byte_register(cw_comp_slope,config.cw_compliance_slope);
+	this->dynamixel_dev->write_byte_register(ccw_comp_slope,config.ccw_compliance_slope);
+	this->dynamixel_dev->write_word_register(punch,config.punch);
+      }catch(CDynamixelAlarmException &e){
+	/* handle dynamixel exception */
+	if(e.get_alarm()&this->alarms)
+	  this->reset_motor();
+	throw;
       }
+    }
+  }
+}
+
+void CDynamixelMotor::get_pid_control(TDynamixel_pid &config)
+{
+  if(this->dynamixel_dev==NULL)
+  {
+    /* handle exceptions */
+    throw CDynamixelMotorException(_HERE_,"The dynamixel device is not properly configured.");
+  }
+  else
+  {
+    if(this->info.pid_control)
+    {
       try{
-        this->dynamixel_dev->write_byte_register(cw_comp_slope,cw_slope);
-        this->dynamixel_dev->write_byte_register(ccw_comp_slope,ccw_slope);
+	this->dynamixel_dev->read_byte_register(pid_p,&config.p);
+	this->dynamixel_dev->read_byte_register(pid_i,&config.i);
+	this->dynamixel_dev->read_byte_register(pid_d,&config.d);
       }catch(CDynamixelAlarmException &e){
-        /* handle dynamixel exception */
-        if(e.get_alarm()&this->alarms)
-          this->reset_motor();
-        throw;
+	/* handle dynamixel exception */
+	if(e.get_alarm()&this->alarms)
+	  this->reset_motor();
+	throw;
       }
     }
-  } 
+  }
 }
 
-short int CDynamixelMotor::get_punch(void)
+void CDynamixelMotor::set_pid_control(TDynamixel_pid &config)
 {
-  unsigned short int punch_value;
+  if(this->dynamixel_dev==NULL)
+  {
+    /* handle exceptions */
+    throw CDynamixelMotorException(_HERE_,"The dynamixel device is not properly configured.");
+  }
+  else
+  {
+    if(this->info.pid_control)
+    {
+      this->pid.p=config.p;
+      this->pid.i=config.i;
+      this->pid.d=config.d;
+      this->dynamixel_dev->write_byte_register(pid_p,config.p);
+      this->dynamixel_dev->write_byte_register(pid_i,config.i);
+      this->dynamixel_dev->write_byte_register(pid_d,config.d);
+    }
+  }
+}
 
+void CDynamixelMotor::turn_led_on(void)
+{
   if(this->dynamixel_dev==NULL)
   {
     /* handle exceptions */
@@ -1244,19 +962,17 @@ short int CDynamixelMotor::get_punch(void)
   else
   {
     try{
-      this->dynamixel_dev->read_word_register(punch,&punch_value);
+      this->dynamixel_dev->write_byte_register(led,1);
     }catch(CDynamixelAlarmException &e){
       /* handle dynamixel exception */
       if(e.get_alarm()&this->alarms)
-        this->reset_motor();
+	this->reset_motor();
       throw;
     }
   }
-
-  return (short int)punch_value;
 }
 
-void CDynamixelMotor::set_punch(short int punch_value)
+void CDynamixelMotor::turn_led_off(void)
 {
   if(this->dynamixel_dev==NULL)
   {
@@ -1265,23 +981,28 @@ void CDynamixelMotor::set_punch(short int punch_value)
   }
   else
   {
-    if(punch<0 || punch>1023)
-    {
-      /* handle exceptions */
-      throw CDynamixelMotorException(_HERE_,"Invalid punch value.");
-    }
     try{
-      this->dynamixel_dev->write_word_register(punch,punch_value);
+      this->dynamixel_dev->write_byte_register(led,0);
     }catch(CDynamixelAlarmException &e){
       /* handle dynamixel exception */
       if(e.get_alarm()&this->alarms)
-        this->reset_motor();
+	this->reset_motor();
       throw;
     }
   }
 }
 
-void CDynamixelMotor::get_pid(unsigned char *p,unsigned char *i,unsigned char *d)
+bool CDynamixelMotor::is_locked(void)
+{
+  return false;
+}
+
+void CDynamixelMotor::lock(void)
+{
+
+}
+
+void CDynamixelMotor::enable(void)
 {
   if(this->dynamixel_dev==NULL)
   {
@@ -1290,21 +1011,18 @@ void CDynamixelMotor::get_pid(unsigned char *p,unsigned char *i,unsigned char *d
   }
   else
   {
-    if(this->info.model=="MX-28" || this->info.model=="EX-106")
-    {
-      this->dynamixel_dev->read_byte_register(pid_p,p);
-      this->dynamixel_dev->read_byte_register(pid_i,i);
-      this->dynamixel_dev->read_byte_register(pid_d,d);
-    }
-    else
-    {
-      /* handle exceptions */
-      throw CDynamixelMotorException(_HERE_,"This servo model does not support PID.");
+    try{
+      this->dynamixel_dev->write_byte_register(torque_en,1);
+    }catch(CDynamixelAlarmException &e){
+      /* handle dynamixel exception */
+      if(e.get_alarm()&this->alarms)
+	this->reset_motor();
+      throw;
     }
   }
 }
 
-void CDynamixelMotor::set_pid(unsigned char p,unsigned char i,unsigned char d)
+void CDynamixelMotor::disable(void)
 {
   if(this->dynamixel_dev==NULL)
   {
@@ -1313,33 +1031,79 @@ void CDynamixelMotor::set_pid(unsigned char p,unsigned char i,unsigned char d)
   }
   else
   {
-    if(this->info.model=="MX-28" || this->info.model=="EX-106")
-    {
-      this->dynamixel_dev->write_byte_register(pid_p,p);
-      this->dynamixel_dev->write_byte_register(pid_i,i);
-      this->dynamixel_dev->write_byte_register(pid_d,d);
-    }
-    else
-    {
-      /* handle exceptions */
-      throw CDynamixelMotorException(_HERE_,"This servo model does not support PID.");
+    try{
+      this->dynamixel_dev->write_byte_register(torque_en,0);
+    }catch(CDynamixelAlarmException &e){
+      /* handle dynamixel exception */
+      if(e.get_alarm()&this->alarms)
+	this->reset_motor();
+      throw;
     }
   }
 }
 
-bool CDynamixelMotor::is_locked(void)
+void CDynamixelMotor::move_absolute_angle(double angle,double speed)
 {
-  return false;
+  unsigned short int cmd[2];
+
+  if(this->dynamixel_dev==NULL)
+  {
+    /* handle exceptions */
+    throw CDynamixelMotorException(_HERE_,"The dynamixel device is not properly configured.");
+  }
+  else
+  {
+    try{
+      if(this->mode==torque_ctrl)
+      {
+	this->set_position_range(-this->info.center_angle, this->info.max_angle - this->info.center_angle);
+	this->mode=angle_ctrl;
+      }
+      cmd[0]=this->from_angles(angle);
+      cmd[1]=this->from_speeds(speed);
+      this->dynamixel_dev->write_registers(goal_pos,(unsigned char *)cmd,4);
+    }catch(CDynamixelAlarmException &e){
+      /* handle dynamixel exception */
+      if(e.get_alarm()&this->alarms)
+	this->reset_motor();
+      throw;
+    }
+  }
 }
 
-void CDynamixelMotor::lock(void)
+void CDynamixelMotor::move_relative_angle(double angle,double speed)
 {
+  unsigned short int cmd[2],pos;
 
+  if(this->dynamixel_dev==NULL)
+  {
+    /* handle exceptions */
+    throw CDynamixelMotorException(_HERE_,"The dynamixel device is not properly configured.");
+  }
+  else
+  {
+    try{
+      if(this->mode==torque_ctrl)
+      {
+	this->set_position_range(-this->info.center_angle,this->info.max_angle-this->info.center_angle);
+	this->mode=angle_ctrl;
+      }
+      this->dynamixel_dev->read_word_register(current_pos,&pos);
+      cmd[0]=this->from_angles(angle+this->to_angles(pos));
+      cmd[1]=this->from_speeds(speed);
+      this->dynamixel_dev->write_registers(goal_pos,(unsigned char *)cmd,4);
+    }catch(CDynamixelAlarmException &e){
+      /* handle dynamixel exception */
+      if(e.get_alarm()&this->alarms)
+	this->reset_motor();
+      throw;
+    }
+  }
 }
 
-void CDynamixelMotor::enable_torque_control(void)
+void CDynamixelMotor::move_torque(double torque_ratio)
 {
-  std::vector<float> min,max;
+  unsigned short int torque=0;
 
   if(this->dynamixel_dev==NULL)
   {
@@ -1348,17 +1112,28 @@ void CDynamixelMotor::enable_torque_control(void)
   }
   else
   {
-    min.push_back(0.0);
-    max.push_back(0.0);
-    this->set_position_range(min,max);
-    this->disable_position_feedback();
-    this->torque_control=true;
+    try{
+      if(this->mode==angle_ctrl)
+      {
+	this->set_position_range(-this->info.center_angle,-this->info.center_angle);
+	this->mode=torque_ctrl;
+      }
+      if(torque_ratio<0.0)
+	torque+=0x0400;
+      torque+=((unsigned short int)(fabs(torque_ratio)*1023.0/100.0))&0x03FF;
+      this->dynamixel_dev->write_word_register(goal_speed,torque);
+    }catch(CDynamixelAlarmException &e){
+      /* handle dynamixel exception */
+      if(e.get_alarm()&this->alarms)
+	this->reset_motor();
+      throw;
+    }
   }
 }
-    
-void CDynamixelMotor::disable_torque_control(void)
+
+void CDynamixelMotor::stop(void)
 {
-  std::vector<float> min,max;
+  unsigned short int current_position;
 
   if(this->dynamixel_dev==NULL)
   {
@@ -1367,23 +1142,53 @@ void CDynamixelMotor::disable_torque_control(void)
   }
   else
   {
-    min.push_back(0.0);
-    max.push_back(this->dyn_max_angle);
-    this->set_position_range(min,max);
-    this->config_position_feedback(fb_polling,100.0);
-    this->enable_position_feedback();
-    this->torque_control=false;
+    try{
+      if(this->mode==angle_ctrl)
+      {
+	this->dynamixel_dev->read_word_register(current_pos,&current_position);
+	this->dynamixel_dev->write_word_register(goal_pos,current_position);
+      }
+      else
+	this->dynamixel_dev->write_word_register(goal_speed,0);
+    }catch(CDynamixelAlarmException &e){
+      /* handle dynamixel exception */
+      if(e.get_alarm()&this->alarms)
+	this->reset_motor();
+      throw;
+    }
   }
 }
-    
-bool CDynamixelMotor::is_torque_control_enabled(void)
+
+double CDynamixelMotor::get_current_angle(void)
 {
-  return this->torque_control;
+  unsigned short int data;
+  double current_position;
+
+  if(this->dynamixel_dev==NULL)
+  {
+    /* handle exceptions */
+    throw CDynamixelMotorException(_HERE_,"The dynamixel device is not properly configured.");
+  }
+  else
+  {
+    try{
+      this->dynamixel_dev->read_word_register(current_pos,&data);
+      current_position = this->to_angles(data);
+    }catch(CDynamixelAlarmException &e){
+      /* handle dynamixel exception */
+      if(e.get_alarm()&this->alarms)
+	this->reset_motor();
+      throw;
+    }
+  }
+
+  return current_position;
 }
 
-void CDynamixelMotor::set_torque(float torque_ratio)
+double CDynamixelMotor::get_current_speed(void)
 {
-  unsigned short int torque=0x0000;
+  unsigned short int data;
+  double c_speed;
 
   if(this->dynamixel_dev==NULL)
   {
@@ -1392,45 +1197,24 @@ void CDynamixelMotor::set_torque(float torque_ratio)
   }
   else
   {
-    if(this->torque_control)
-    {
-      if(torque_ratio>100.0 || torque_ratio<-100.0)
-      {
-        /* handle exceptions */
-        throw CDynamixelMotorException(_HERE_,"Invalid torque ratio.");
-      }
-      else
-      {
-        if(torque_ratio<0.0)
-          torque+=0x0400;
-        torque+=((unsigned short int)(fabs(torque_ratio)*1023.0/100.0))&0x03FF;
-        this->dynamixel_dev->write_word_register(goal_speed,torque);
-      }
-    }
-    else
-    {
-      if(torque_ratio>100.0 || torque_ratio<0.0)
-      {
-        /* handle exceptions */
-        throw CDynamixelMotorException(_HERE_,"Invalid torque ratio.");
-      }
-      else
-      {
-        // set the maximum torque of the servo
-        torque=((unsigned short int)(fabs(torque_ratio)*1023.0/100.0))&0x03FF;
-        // save the value to EEPROM 
-        this->dynamixel_dev->write_word_register(max_torque,torque);
-        // update the current value
-        this->dynamixel_dev->write_word_register(torque_limit,torque);
-      }
+    try{
+      this->dynamixel_dev->read_word_register(current_speed,&data);
+      c_speed = this->to_speeds(data);
+    }catch(CDynamixelAlarmException &e){
+      /* handle dynamixel exception */
+      if(e.get_alarm()&this->alarms)
+	this->reset_motor();
+      throw;
     }
   }
+
+  return c_speed;
 }
 
-float CDynamixelMotor::get_torque(void)
+double CDynamixelMotor::get_current_temperature(void)
 {
-  unsigned short int load;
-  float torque;
+  unsigned char data;
+  double c_temp;
 
   if(this->dynamixel_dev==NULL)
   {
@@ -1439,19 +1223,24 @@ float CDynamixelMotor::get_torque(void)
   }
   else
   {
-    this->dynamixel_dev->read_word_register(current_load,&load);
-    torque=(load&0x3FF)*100.0/1023;
-    if(load>0x3FF)
-      torque=-1*torque;
+    try{
+      this->dynamixel_dev->read_byte_register(current_temp,&data);
+      c_temp = (double)data;
+    }catch(CDynamixelAlarmException &e){
+      /* handle dynamixel exception */
+      if(e.get_alarm()&this->alarms)
+	this->reset_motor();
+      throw;
+    }
   }
 
-  return torque;
+  return c_temp;
 }
 
-float CDynamixelMotor::get_max_torque(void)
+double CDynamixelMotor::get_current_voltage(void)
 {
-  unsigned short int load;
-  float torque;
+  unsigned char data;
+  double c_voltage;
 
   if(this->dynamixel_dev==NULL)
   {
@@ -1460,19 +1249,24 @@ float CDynamixelMotor::get_max_torque(void)
   }
   else
   {
-    this->dynamixel_dev->read_word_register(max_torque,&load);
-    torque=(load&0x3FF)*100.0/1023;
-    if(load>0x3FF)
-      torque=-1*torque;
+    try{
+      this->dynamixel_dev->read_byte_register(current_voltage,&data);
+      c_voltage = (double)data/10;
+    }catch(CDynamixelAlarmException &e){
+      /* handle dynamixel exception */
+      if(e.get_alarm()&this->alarms)
+	this->reset_motor();
+      throw;
+    }
   }
 
-  return torque;
+  return c_voltage;
 }
 
-float CDynamixelMotor::get_limit_torque(void)
+double CDynamixelMotor::get_current_effort(void)
 {
-  unsigned short int load;
-  float torque;
+  unsigned char data;
+  double c_effort;
 
   if(this->dynamixel_dev==NULL)
   {
@@ -1481,29 +1275,59 @@ float CDynamixelMotor::get_limit_torque(void)
   }
   else
   {
-    this->dynamixel_dev->read_word_register(torque_limit,&load);
-    torque=(load&0x3FF)*100.0/1023;
-    if(load>0x3FF)
-      torque=-1*torque;
+    try{
+      this->dynamixel_dev->read_byte_register(current_load,&data);
+      c_effort = (double)((data&0x3FF)*100.0/1023);
+      if (this->get_current_speed() < 0)
+      {
+	c_effort *= -1.0;
+      }
+    }catch(CDynamixelAlarmException &e){
+      /* handle dynamixel exception */
+      if(e.get_alarm()&this->alarms)
+	this->reset_motor();
+      throw;
+    }
   }
 
-  return torque;
+  return c_effort;
 }
 
 CDynamixelMotor::~CDynamixelMotor()
 {
-  this->close();
-  this->info.model="";
-  this->info.firmware_ver=0x00;
-  this->control.cw_compliance_margin=0x00;
-  this->control.ccw_compliance_margin=0x00;
-  this->control.cw_compliance_slope=0x20;
-  this->control.ccw_compliance_slope=0x20;
+  /* stop the motor */
+  this->stop();
+  /* disable the motor */
+  this->disable();
   if(this->dynamixel_dev!=NULL)
   {
     this->dyn_server->free_device(this->dynamixel_dev->get_id());
     delete this->dynamixel_dev;
     this->dynamixel_dev=NULL;
   }
+  this->info.model="";
+  this->info.firmware_ver=(unsigned char)-1;
+  this->info.gear_ratio=(unsigned int)-1;
+  this->info.encoder_resolution=(unsigned int)-1;
+  this->info.pid_control=false;
+  this->info.max_angle=-1;
+  this->info.center_angle=-1;
+  this->info.max_speed=-1;
+  this->info.bus_id="";
+  this->info.baudrate=(unsigned int)-1;
+  this->info.id=(unsigned char)-1;
+  this->compliance.cw_compliance_margin=0x00;
+  this->compliance.ccw_compliance_margin=0x00;
+  this->compliance.cw_compliance_slope=0x20;
+  this->compliance.ccw_compliance_slope=0x20;
+  this->pid.p=0x00;
+  this->pid.i=0x00;
+  this->pid.d=0x00;
+  this->config.max_angle=0.0;
+  this->config.min_angle=0.0;
+  this->config.max_temperature=0.0;
+  this->config.max_voltage=0.0;
+  this->config.min_voltage=0.0;
+  this->config.max_torque=0.0;
 }
 
diff --git a/src/dynamixel_motor.h b/src/dynamixel_motor.h
index 1245965a730db8226a2790ac9273ae95e2f10411..3d315201ce00e4af5b476f5c409d1824ba11d721 100644
--- a/src/dynamixel_motor.h
+++ b/src/dynamixel_motor.h
@@ -1,439 +1,395 @@
-#ifndef _DYNAMIXEL_MOTOR_H
-#define _DYNAMIXEL_MOTOR_H
-
-#include "dynamixelserver.h"
-#include "motor_control.h"
-#include "eventserver.h"
-#include "ftdimodule.h"
-#include "mutex.h"
-#include <stdio.h>
-#include <stdlib.h>
-#include <string>
-#include <vector>
-
-typedef enum {
-  model_number=0x00,
-  firmware_version=0x02,
-  id=0x03,
-  baudrate=0x04,
-  return_delay_time=0x05,
-  cw_angle_limit=0x06,
-  ccw_angle_limit=0x08,
-  temp_limit=0x0B,
-  low_voltage_limit=0x0C,
-  high_voltage_limit=0x0D,
-  max_torque=0x0E,
-  return_level=0x10,
-  alarm_led=0x11,
-  alarm_shtdwn=0x12,
-  down_cal=0x14,
-  up_cal=0x16,
-  torque_en=0x18,
-  led=0x19,
-  pid_p=0x1A,
-  pid_i=0x1B,
-  pid_d=0x1C,
-  cw_comp_margin=0x1A,
-  ccw_comp_margin=0x1B,
-  cw_comp_slope=0x1C,
-  ccw_comp_slope=0x1D,
-  goal_pos=0x1E,
-  goal_speed=0x20,
-  torque_limit=0x22,
-  current_pos=0x24,
-  current_speed=0x26,
-  current_load=0x28,
-  current_voltage=0x2A,
-  current_temp=0x2B,
-  reg_inst=0x2C,
-  moving=0x2E,
-  lock=0x2F,
-  punch=0x30
-} reg_id;
-
-typedef enum {
-  input_voltage_error=0x01,
-  angle_limit_error=0x02,
-  overheating_error=0x04,
-  range_error=0x08,
-  checksum_error=0x10,
-  overload_error=0x20,
-  instruction_error=0x40
-}dyn_alarm;
-
-typedef struct
-{
-  std::string model;
-  unsigned char firmware_ver;
-}TDynamixel_info;
-
-typedef struct
-{
-  unsigned char cw_compliance_margin;
-  unsigned char ccw_compliance_margin;
-  unsigned char cw_compliance_slope;
-  unsigned char ccw_compliance_slope;
-  unsigned char punch;
-}TDynamixel_control;
-
-/**
- * \brief 
- *
- */
-class CDynamixelMotor : public CMotorControl
-{
-  private:
-    CDynamixelServer *dyn_server;
-    /**
-     * \brief 
-     *
-     */
-    CDynamixel *dynamixel_dev;
-    /**
-     * \brief 
-     *
-     */   
-    TDynamixel_control control;
-    /**
-     * \brief 
-     *
-     */   
-    TDynamixel_info info;
-    /**
-     * \brief
-     *
-     */
-    unsigned char alarms;
-    /**
-     * \brief
-     *
-     */
-    bool torque_control;
-    /**
-     * \brief
-     *
-     */
-    long int current_position;
-    // model attributes
-    /**
-     * \brief
-     *
-     */
-    int dyn_enc_res;
-    /**
-     * \brief
-     *
-     */
-    int dyn_max_angle;
-    /**
-     * \brief
-     *
-     */
-    int dyn_max_speed;
-    /**
-     * \brief
-     *
-     */
-    int dyn_max_torque;
-  protected:
-    /**
-     * \brief
-     *
-     */
-    virtual void angles_to_controller(std::vector<float>& angles,std::vector<float>& counts); 
-    /**
-     * \brief
-     *
-     */
-    virtual void speeds_to_controller(std::vector<float>& angles,std::vector<float>& counts); 
-    /**
-    * \brief
-     *
-     */
-    virtual void accels_to_controller(std::vector<float>& angles,std::vector<float>& counts); 
-    /**
-     * \brief
-     *
-     */
-    virtual void controller_to_angles(std::vector<float>& counts,std::vector<float>& angles); 
-    /**
-     * \brief
-     *
-     */
-    virtual void controller_to_speeds(std::vector<float>& counts,std::vector<float>& angles); 
-    /**
-     * \brief
-     *
-     */
-    virtual void controller_to_accels(std::vector<float>& counts,std::vector<float>& angles); 
-    /**
-     * \brief 
-     *
-     */
-    virtual void cont_set_position_range(std::vector<float>& min, std::vector<float>& max);
-    /**
-     * \brief 
-     *
-     */ 
-    virtual void cont_get_position_range(std::vector<float>& min, std::vector<float>& max);
-    /**
-     * \brief 
-     *
-     */ 
-    virtual void cont_get_gear_factor(std::vector<float>& gear);
-    /**
-     * \brief 
-     *
-     */
-    virtual std::vector<float> cont_get_position(void);
-    /**
-     * \brief 
-     *
-     */
-    virtual std::vector<float> cont_get_velocity(void);
-    /**
-     * \brief 
-     *
-     */
-    virtual void cont_enable(std::vector<bool> &enable);
-    /**
-     * \brief 
-     *
-     */
-    virtual void cont_disable(std::vector<bool> &disable);
-    /**
-     * \brief 
-     *
-     */
-    virtual void cont_load(std::vector<float>& position, std::vector<float>& velocity, std::vector<float>& accel);
-    /**
-     * \brief 
-     *
-     */
-    virtual void cont_load(std::vector<float>& velocity, std::vector<float>& accel);
-    /**
-     * \brief 
-     *
-     */
-    virtual void cont_move(void);
-    /**
-     * \brief 
-     *
-     */
-    virtual void cont_stop(void);
-    /**
-     * \brief 
-     *
-     */
-    virtual void cont_close(void);
-#ifdef _HAVE_XSD
-    /**
-     * \brief 
-     *
-     */
-    virtual void cont_load_config(std::string &filename);
-    /**
-     * \brief 
-     *
-     */
-    virtual void cont_save_config(std::string &filename);
-#endif
-    /**
-     * \brief 
-     *
-     */
-    void reset_motor(void);
-  public:
-    /**
-     * \brief
-     *
-     */ 
-    CDynamixelMotor(std::string& cont_id,unsigned char bus_id,int baudrate,unsigned char dev_id);
-    /**
-     * \brief
-     *
-     */ 
-    CDynamixelMotor(std::string& cont_id,std::string &bus_id,int baudrate,unsigned char dev_id);
-    /**
-     * \brief 
-     *
-     */ 
-    int get_baudrate(void);
-    /**
-     * \brief
-     *
-     */ 
-    unsigned char get_node_address(void);
-    /**
-     * \brief
-     *
-     */ 
-    void set_node_address(unsigned char dev_id);
-    /**
-     * \brief 
-     *  
-     */ 
-    std::string get_model(void);
-    /**
-     * \brief 
-     *  
-     */ 
-    int get_id(void);
-    /**
-     * \brief 
-     *  
-     */
-    unsigned char get_firmware_version(void); 
-    /**
-     * \brief 
-     *  
-     */ 
-    int get_temperature_limit(void);
-    /**
-     * \brief 
-     *  
-     */ 
-    void set_temperature_limit(int limit);
-    /**
-     * \brief 
-     *  
-     */
-    int get_current_temperature(void); 
-    /**
-     * \brief 
-     *  
-     */ 
-    void get_voltage_limits(float *min, float *max);
-    /**
-     * \brief 
-     *  
-     */
-    void set_voltage_limits(float min, float max); 
-    /**
-     * \brief 
-     *  
-     */ 
-    float get_current_voltage(void);
-    /**
-     * \brief 
-     *  
-     */ 
-    unsigned char get_led_alarms(void);
-    /**
-     * \brief 
-     *  
-     */ 
-    void set_led_alarms(unsigned char alarms);
-    /**
-     * \brief 
-     *  
-     */
-    unsigned char get_turn_off_alarms(void); 
-    /**
-     * \brief 
-     *  
-     */
-    void set_turn_off_alarms(unsigned char alarms); 
-    /**
-     * \brief 
-     *  
-     */ 
-    void turn_led_on(void);
-    /**
-     * \brief 
-     *  
-     */ 
-    void turn_led_off(void);
-    /**
-     * \brief 
-     *  
-     */ 
-    void get_compliance_margin(unsigned char *cw_margin, unsigned char *ccw_margin);
-    /**
-     * \brief 
-     *  
-     */ 
-    void set_compliance_margin(unsigned char cw_margin, unsigned char ccw_margin);
-    /**
-     * \brief 
-     *  
-     */ 
-    void get_compliance_slope(unsigned char *cw_slope, unsigned char *ccw_margin);
-    /**
-     * \brief 
-     *  
-     */ 
-    void set_compliance_slope(unsigned char cw_slope, unsigned char ccw_slope);
-    /**
-     * \brief 
-     *  
-     */ 
-    short int get_punch(void);
-    /**
-     * \brief 
-     *  
-     */ 
-    void set_punch(short int punch_value);
-    /**
-     * \brief 
-     *  
-     */
-    void get_pid(unsigned char *p,unsigned char *i,unsigned char *d);
-    /**
-     * \brief 
-     *  
-     */
-    void set_pid(unsigned char p,unsigned char i,unsigned char d);
-    /**
-     * \brief 
-     *  
-     */
-    bool is_locked(void);
-    /**
-     * \brief 
-     *  
-     */ 
-    void lock(void);
-    /**
-     * \brief 
-     *  
-     */ 
-    void enable_torque_control(void);
-    /**
-     * \brief 
-     *  
-     */ 
-    void disable_torque_control(void);
-    /**
-     * \brief 
-     *  
-     */ 
-    bool is_torque_control_enabled(void);
-    /**
-     * \brief 
-     *  
-     */ 
-    void set_torque(float torque_ratio);
-    /**
-     * \brief 
-     *  
-     */ 
-    float get_torque(void);
-    /**
-     * \brief 
-     *  
-     */ 
-    float get_max_torque(void);
-    /**
-     * \brief 
-     *  
-     */ 
-    float get_limit_torque(void);
-    /**
-     * \brief 
-     *  
-     */ 
-    virtual ~CDynamixelMotor(); 
-};
-
-#endif 
+#ifndef _DYNAMIXEL_MOTOR_H
+#define _DYNAMIXEL_MOTOR_H
+
+#include "dynamixelserver.h"
+#include "threadserver.h"
+#include "eventserver.h"
+#include "ftdimodule.h"
+#include "mutex.h"
+#include <stdio.h>
+#include <stdlib.h>
+#include <string>
+#include <vector>
+#include <memory>
+
+typedef enum {
+  //                           [Access] [Description]
+  // EEPROM Area 
+  model_number=0x00,        //   (R)     Model Number
+  firmware_version=0x02,    //   (R)     Version of the Firmware
+  id=0x03,                  //   (RW)    ID of Dynamixel
+  baudrate=0x04,            //   (RW)    Baud Rate of Dynamixel
+  return_delay_time=0x05,   //   (RW)    Return Delay Time 
+  cw_angle_limit=0x06,      //   (RW)    Clockwise Angle Limit
+  ccw_angle_limit=0x08,     //   (RW)    Counterclockwise Angle Limit 
+  temp_limit=0x0B,          //   (RW)    Internal Temperature Limit
+  low_voltage_limit=0x0C,   //   (RW)    Lowest Voltage Limit
+  high_voltage_limit=0x0D,  //   (RW)    Highest Voltage Limit
+  max_torque=0x0E,          //   (RW)    Maximum Torque 
+  return_level=0x10,        //   (RW)    Status Return Level
+  alarm_led=0x11,           //   (RW)    LED for Alarm 
+  alarm_shtdwn=0x12,        //   (RW)    Shutdown for Alarm 
+  down_cal=0x14,            //   (RW)     
+  up_cal=0x16,              //   (RW)    
+  // RAM Area 
+  torque_en=0x18,           //   (RW)    Torque On/Off 
+  led=0x19,                 //   (RW)    LED On/Off 
+  pid_p=0x1A,               //   (RW)     
+  pid_i=0x1B,               //   (RW)     
+  pid_d=0x1C,               //   (RW)     
+  cw_comp_margin=0x1A,      //   (RW)    CW Compliance Margin
+  ccw_comp_margin=0x1B,     //   (RW)    CCW Compliance Margin
+  cw_comp_slope=0x1C,       //   (RW)    CW Compliance Slope
+  ccw_comp_slope=0x1D,      //   (RW)    CCW Compliance Slope 
+  goal_pos=0x1E,            //   (RW)    Goal Position 
+  goal_speed=0x20,          //   (RW)    Moving Speed 
+  torque_limit=0x22,        //   (RW)    Torque Limit 
+  current_pos=0x24,         //   (R)     Current Position 
+  current_speed=0x26,       //   (R)     Current Speed 
+  current_load=0x28,        //   (R)     Current Load 
+  current_voltage=0x2A,     //   (R)     Current Voltage 
+  current_temp=0x2B,        //   (RW)    Current Temperature 
+  reg_inst=0x2C,            //   (RW)    Means if Instruction is registered 
+  moving=0x2E,              //   (R)     Means if there is any movement 
+  lock=0x2F,                //   (RW)    Locking EEPROM 
+  punch=0x30                //   (RW)    Punch 
+} reg_id;
+
+typedef enum
+{
+  input_voltage_error=0x01,
+  angle_limit_error=0x02,
+  overheating_error=0x04,
+  range_error=0x08,
+  checksum_error=0x10,
+  overload_error=0x20,
+  instruction_error=0x40
+}dyn_alarm;
+
+typedef struct
+{
+  std::string model;
+  unsigned char firmware_ver;
+  unsigned int gear_ratio;
+  unsigned int encoder_resolution;
+  bool pid_control;
+  double max_angle;
+  double center_angle;
+  double max_speed;
+  std::string bus_id;
+  unsigned int baudrate;
+  unsigned char id;
+}TDynamixel_info;
+
+typedef struct
+{
+  unsigned char cw_compliance_margin;
+  unsigned char ccw_compliance_margin;
+  unsigned char cw_compliance_slope;
+  unsigned char ccw_compliance_slope;
+  unsigned char punch;
+}TDynamixel_compliance;
+
+typedef struct
+{
+  unsigned char p;
+  unsigned char i;
+  unsigned char d;
+}TDynamixel_pid;
+
+typedef struct
+{
+  double max_angle;
+  double min_angle;
+  double max_temperature;
+  double max_voltage;
+  double min_voltage;
+  double max_torque;
+}TDynamixel_config;
+
+typedef enum{angle_ctrl=0,torque_ctrl=1} control_mode;
+
+/**
+ * \brief 
+ *
+ */
+class CDynamixelMotor 
+{
+  private:
+    CDynamixelServer *dyn_server;
+    /**
+     * \brief 
+     *
+     */
+    CDynamixel *dynamixel_dev;
+    /**
+     * \brief 
+     *
+     */   
+    TDynamixel_compliance compliance;
+    /**
+     * \brief 
+     *
+     */   
+    TDynamixel_pid pid;
+    /**
+     * \brief 
+     *
+     */   
+    TDynamixel_config config;
+    /**
+     * \brief 
+     *
+     */   
+    TDynamixel_info info;
+    /**
+     * \brief
+     *
+     */
+    unsigned char alarms;
+    /**
+     * \brief
+     *
+     */
+    control_mode mode;
+
+  protected:
+    /**
+     * \brief
+     *
+     */
+    unsigned int from_angles(double angle); 
+    /**
+     * \brief
+     *
+     */
+    unsigned int from_speeds(double speed); 
+    /**
+     * \brief
+     *
+     */
+    double to_angles(unsigned short int counts); 
+    /**
+     * \brief
+     *
+     */
+    double to_speeds(unsigned short int counts); 
+    /**
+     * \brief 
+     *
+     */
+    void reset_motor(void);
+    /**
+     * \brief 
+     *
+     */
+    void get_model(void);
+
+  public:
+    /**
+     * \brief
+     *
+     */ 
+    CDynamixelMotor(std::string& cont_id,unsigned char bus_id,int baudrate,unsigned char dev_id);
+    /**
+     * \brief
+     *
+     */ 
+    CDynamixelMotor(std::string& cont_id,std::string &bus_id,int baudrate,unsigned char dev_id);
+    /**
+     * \brief
+     *
+     */
+    void get_servo_info(TDynamixel_info &info);
+    /* configuration functions */
+    /**
+     * \brief
+     *
+     */
+    void load_config(TDynamixel_config &config);
+#ifdef _HAVE_XSD
+    /**
+     * \brief 
+     *
+     */
+    void load_config(std::string &filename);
+    /**
+     * \brief 
+     *
+     */
+    void save_config(std::string &filename);
+#endif
+    /**
+     * \brief
+     *
+     */
+    void set_position_range(double min,double max);
+    /**
+     * \brief 
+     *
+     */ 
+    void get_position_range(double *min, double *max);
+    /**
+     * \brief 
+     *  
+     */ 
+    int get_temperature_limit(void);
+    /**
+     * \brief 
+     *  
+     */ 
+    void set_temperature_limit(int limit);
+    /**
+     * \brief 
+     *  
+     */ 
+    void get_voltage_limits(double *min, double *max);
+    /**
+     * \brief 
+     *  
+     */
+    void set_voltage_limits(double min, double max); 
+    /**
+     * \brief 
+     *  
+     */ 
+    unsigned char get_led_alarms(void);
+    /**
+     * \brief 
+     *  
+     */ 
+    void set_led_alarms(unsigned char alarms);
+    /**
+     * \brief 
+     *  
+     */
+    unsigned char get_turn_off_alarms(void); 
+    /**
+     * \brief 
+     *  
+     */
+    void set_turn_off_alarms(unsigned char alarms); 
+    /**
+     * \brief 
+     *  
+     */ 
+    double get_max_torque(void);
+    /**
+     * \brief 
+     *  
+     */ 
+    double get_limit_torque(void);
+    /**
+     * \brief 
+     *  
+     */ 
+    void set_max_torque(double torque_ratio);
+    /**
+     * \brief 
+     *  
+     */ 
+    void set_limit_torque(double torque_ratio);
+    /**
+     * \brief 
+     *  
+     */ 
+    void get_compliance_control(TDynamixel_compliance &config);
+    /**
+     * \brief 
+     *  
+     */ 
+    void set_compliance_control(TDynamixel_compliance &config);
+    /**
+     * \brief 
+     *  
+     */ 
+    void get_pid_control(TDynamixel_pid &config);
+    /**
+     * \brief 
+     *  
+     */ 
+    void set_pid_control(TDynamixel_pid &config);
+    /* control functions */
+    /**
+     * \brief 
+     *  
+     */ 
+    void turn_led_on(void);
+    /**
+     * \brief 
+     *  
+     */ 
+    void turn_led_off(void);
+    /**
+     * \brief 
+     *  
+     */
+    bool is_locked(void);
+    /**
+     * \brief 
+     *  
+     */ 
+    void lock(void);
+    /**
+     * \brief 
+     *
+     */
+    void enable(void);
+    /**
+     * \brief 
+     *
+     */
+    void disable(void);
+    /**
+     * \brief 
+     *
+     */
+    void move_absolute_angle(double angle,double speed);
+    /**
+     * \brief 
+     *
+     */
+    void move_relative_angle(double angle,double speed);
+    /**
+     * \brief 
+     *
+     */
+    void move_torque(double torque_ratio);
+    /**
+     * \brief 
+     *
+     */
+    void stop(void);
+    /**
+     * \brief 
+     *  
+     */
+    double get_current_angle(void); 
+    /**
+     * \brief 
+     *  
+     */
+    double get_current_speed(void); 
+    /**
+     * \brief 
+     *  
+     */ 
+    double get_current_effort(void);
+    /**
+     * \brief 
+     *  
+     */ 
+    double get_current_voltage(void);
+    /**
+     * \brief 
+     *  
+     */ 
+    double get_current_temperature(void);
+    /**
+     * \brief 
+     *  
+     */ 
+    virtual ~CDynamixelMotor(); 
+};
+
+#endif
diff --git a/src/dynamixel_motor_exceptions.cpp b/src/dynamixel_motor_exceptions.cpp
index 60fab00e51a23b8c7521a8221dabb2318eba2065..00402baa89c395af55945aa47a0f5712c6aa7aaa 100755
--- a/src/dynamixel_motor_exceptions.cpp
+++ b/src/dynamixel_motor_exceptions.cpp
@@ -5,6 +5,7 @@
 
 const std::string dynamixel_motor_error_message="DynamixelMotor error - ";
 const std::string dynamixel_motor_group_error_message="DynamixelMotorGroup error - ";
+const std::string dynamixel_motion_sequence_error_message="DynamixelMotionSeq error - ";
 
 CDynamixelMotorException::CDynamixelMotorException(const std::string& where,const std::string &error_msg):CException(where,dynamixel_motor_error_message)
 {
@@ -20,3 +21,9 @@ CDynamixelMotorGroupException::CDynamixelMotorGroupException(const std::string&
   this->error_msg+=error_msg;
 }
 
+CDynamixelMotionSequenceException::CDynamixelMotionSequenceException(const std::string& where,const std::string &error_msg):CException(where,dynamixel_motion_sequence_error_message)
+{
+  std::stringstream text;
+ 
+  this->error_msg+=error_msg;
+}
diff --git a/src/dynamixel_motor_exceptions.h b/src/dynamixel_motor_exceptions.h
index 0ee478e56e7097f0c5f7e74e5e1c044fc8577cfb..25487eedb5b253853b257fb4eafc4f371757ce67 100755
--- a/src/dynamixel_motor_exceptions.h
+++ b/src/dynamixel_motor_exceptions.h
@@ -33,4 +33,16 @@ class CDynamixelMotorGroupException : public CException
     CDynamixelMotorGroupException(const std::string& where,const std::string &error_msg);
 };
 
+/**
+ * \brief 
+ */
+class CDynamixelMotionSequenceException : public CException
+{
+  public:
+    /**
+     * \brief
+     *
+     */
+    CDynamixelMotionSequenceException(const std::string& where,const std::string &error_msg);
+};
 #endif
diff --git a/src/dynamixel_motor_group.cpp b/src/dynamixel_motor_group.cpp
index 98fb2efb0cdc7bb394efabc762a971ee76e31166..d383bd2cd826ca2679476bf1ae019feb442d36b8 100644
--- a/src/dynamixel_motor_group.cpp
+++ b/src/dynamixel_motor_group.cpp
@@ -1,4 +1,5 @@
 #include "dynamixel_motor_exceptions.h"
+#include "dynamixelexceptions.h"
 #include "dynamixelserver.h"
 #include "eventexceptions.h"
 #include "dynamixel_motor_group.h"
@@ -6,8 +7,14 @@
 #include "ftdiserver.h"
 #include <math.h>
 #include <iostream>
+#include <fstream>
+#ifdef _HAVE_XSD
+#include "xml/dynamixel_motor_cfg_file.hxx"
+#include "xml/dynamixel_motor_group_cfg_file.hxx"
+#include "xml/dyn_motion_seq_file.hxx"
+#endif
 
-CDynamixelMotorGroup::CDynamixelMotorGroup(std::string &group_id):CMotorGroup(group_id)
+CDynamixelMotorGroup::CDynamixelMotorGroup(std::string &group_id)
 {
   if(group_id.size()==0)
   {
@@ -16,122 +23,1799 @@ CDynamixelMotorGroup::CDynamixelMotorGroup(std::string &group_id):CMotorGroup(gr
   }
   else 
   {
+    this->group_id=group_id;
     this->dyn_server=CDynamixelServer::instance();
+    this->clear();
+    this->mode=angle_ctrl;
+    /* initialize motion sequence attributes */
+    this->sequence_state=mtn_empty;
+    this->sequence_current_step=-1;
+    this->sequence_error_msg="Motion sequence ended successfully";
+    this->init_events();
+    this->init_threads();
   }
 }
 
-void CDynamixelMotorGroup::move(std::vector<float> &position,std::vector<float> &velocity,std::vector<float> &acceleration)
+CDynamixelMotorGroup::CDynamixelMotorGroup(std::string &group_id,unsigned bus_id,int baudrate,std::vector<unsigned char> &ids)
 {
-  std::vector<float> pos_count,vel_count,accel_count,tmp_pos;
-  std::vector< std::vector<unsigned char> > data;
-  std::vector<short int> count_value;
-  std::vector<bool> absolute;
   unsigned int i=0;
 
-  if(position.size()!=this->servo_id.size())
+  if(group_id.size()==0)
   {
-    /* handle errors */
-    throw CDynamixelMotorGroupException(_HERE_,"The number of position commands does not coincide with the total number of motors in the group");
+    /* handle exceptions */
+    throw CDynamixelMotorGroupException(_HERE_,"Invalid group identifier - empty string");
   }
-  else if(velocity.size()!=this->servo_id.size())
+  else 
   {
-    /* handle exceptions */
-    throw CDynamixelMotorGroupException(_HERE_,"The number of velocity commands does not coincide with the total number of motors in the group");
+    this->group_id=group_id;
+    this->dyn_server=CDynamixelServer::instance();
+    this->clear();
+    this->mode=angle_ctrl;
+    /* initialize motion sequence attributes */
+    this->sequence_state=mtn_empty;
+    this->sequence_current_step=-1;
+    this->sequence_error_msg="Motion sequence ended successfully";
+    if(ids.size()==0)
+    {
+      /* handle exceptions */
+      throw CDynamixelMotorGroupException(_HERE_,"Impossible to create an empty group");
+    }
+    try{
+      this->dyn_server->config_bus(bus_id,baudrate);
+      for(i=0;i<ids.size();i++)
+	this->init_motor(ids[i]);
+      if(this->config[0].min_angle==-this->info[0].center_angle && this->config[0].max_angle==-this->info[0].center_angle)
+      {
+	this->mode=torque_ctrl;
+	for(i=1;i<ids.size();i++)
+	  this->set_position_range(i,-this->info[i].center_angle,-this->info[i].center_angle);
+      }
+      else
+      {
+	this->mode=angle_ctrl;
+	for(i=1;i<ids.size();i++)
+	  this->set_position_range(i,-this->info[i].center_angle,this->info[i].max_angle-this->info[i].center_angle);
+      }
+      this->init_events();
+      this->init_threads();
+    }catch(CException &e){
+      /* handle exceptions */
+      this->clear();
+      throw;
+    }
   }
-  else if(acceleration.size()!=this->servo_id.size())
+}
+
+CDynamixelMotorGroup::CDynamixelMotorGroup(std::string &group_id,std::string &bus_id,int baudrate,std::vector<unsigned char> &ids)
+{
+  unsigned int i=0;
+
+  if(group_id.size()==0)
   {
     /* handle exceptions */
-    throw CDynamixelMotorGroupException(_HERE_,"The number of acceleration commands does not coincide with the total number of motors in the group");
+    throw CDynamixelMotorGroupException(_HERE_,"Invalid group identifier - empty string");
   }
-  else
+  else 
   {
+    this->group_id=group_id;
+    this->dyn_server=CDynamixelServer::instance();
+    this->clear();
+    if(ids.size()==0)
+    {
+      /* handle exceptions */
+      throw CDynamixelMotorGroupException(_HERE_,"Impossible to create an empty group");
+    }
     try{
-      // call the base class function 
-      CMotorGroup::move(position,velocity,acceleration);
-      data.resize(servo_id.size());
-      for(i=0;i<servo_id.size();i++)
-      {
-	/* Number of instructions in bytes:
-	   - goal_pos: 2 bytes
-	   - goal_speed: 2 bytes */
-	data[i].resize(4);	
-      }
-      absolute=this->is_motion_absolute();
-      for(i=0;i<servo_id.size();i++)
-      {
-        if(!absolute[i])
-          tmp_pos.push_back(position[i]+this->current_pos[i]);
-        else
-          tmp_pos.push_back(position[i]);
-      }
-      this->current_pos=tmp_pos;
-      // convert the input data
-      this->angles_to_controller(tmp_pos,pos_count);
-      this->speeds_to_controller(velocity,vel_count);
-      this->accels_to_controller(acceleration,accel_count);
-      for(i=0;i<servo_id.size();i++)
-      {
-	data[i][0]=((int)(pos_count[i])%256);
-	data[i][1]=(int)(pos_count[i]/256);
-	data[i][2]=((int)(vel_count[i])%256);
-	data[i][3]=(int)(vel_count[i]/256);
-      }
-      dyn_server->write_sync(servo_id,goal_pos,data);
+      this->dyn_server->config_bus(bus_id,baudrate);
+      for(i=0;i<ids.size();i++)
+	this->init_motor(ids[i]);
+      if(this->config[0].min_angle==-this->info[0].center_angle && this->config[0].max_angle==-this->info[0].center_angle)
+      {
+	this->mode=torque_ctrl;
+	for(i=1;i<ids.size();i++)
+	  this->set_position_range(i,-this->info[i].center_angle,-this->info[i].center_angle);
+      }
+      else
+      {
+	this->mode=angle_ctrl;
+	for(i=1;i<ids.size();i++)
+	  this->set_position_range(i,-this->info[i].center_angle,this->info[i].max_angle-this->info[i].center_angle);
+      }
+      this->init_events();
+      this->init_threads();
     }catch(CException &e){
       /* handle exceptions */
-      throw; 
-    }	
-  }  
+      this->clear();
+      throw;
+    }
+  }
+}
+
+unsigned int CDynamixelMotorGroup::from_angles(unsigned int index,double angle)
+{
+  unsigned int counts;
+
+  counts=(angle+this->info[index].center_angle)*this->info[index].encoder_resolution/this->info[index].max_angle;
+
+  return counts;
+}
+
+unsigned int CDynamixelMotorGroup::from_speeds(unsigned int index,double speed)
+{
+  unsigned int counts;
+
+  if(speed>this->info[index].max_speed)
+    speed=this->info[index].max_speed;
+  counts=fabs(speed)/0.666;
+
+  return counts;
 }
 
-std::string CDynamixelMotorGroup::add_motor_control(CDynamixelMotor *controller)
+double CDynamixelMotorGroup::to_angles(unsigned int index,int unsigned counts)
 {
-  std::vector<float> current_position;
-  std::string cont_id;
+  double angle;
+
+  angle=counts*this->info[index].max_angle/this->info[index].encoder_resolution-this->info[index].center_angle;
+
+  return angle;
+}
+
+double CDynamixelMotorGroup::to_speeds(unsigned int index,int unsigned counts)
+{
+  double speed;
+
+  speed=counts*0.666;
+
+  return speed;
+}
+
+void CDynamixelMotorGroup::reset_motor(unsigned int index)
+{
+  unsigned short int current_position;
+  unsigned short int maximum_torque;
 
   try{
-    cont_id=CMotorGroup::add_motor_control(controller);
-    // if the controller is successfully added
-    this->servo_id.push_back(((CDynamixelMotor *)controller)->get_id());
-    current_position=controller->get_position();
-    this->current_pos.push_back(current_position[0]);
-  }catch(CException &e){
+    this->dynamixel_dev[index]->read_word_register(current_pos,&current_position);
+  }catch(CDynamixelAlarmException &e){
+    /* do nothing - expected exception */
+  }
+  try{
+    this->dynamixel_dev[index]->write_word_register(goal_pos,current_position);
+  }catch(CDynamixelAlarmException &e){
+    /* do nothing - expected exception */
+  }
+  try{
+    this->dynamixel_dev[index]->read_word_register(max_torque,&maximum_torque);
+  }catch(CDynamixelAlarmException &e){
+    /* do nothing - expected exception */
+  }
+  try{
+    this->dynamixel_dev[index]->write_word_register(torque_limit,maximum_torque);
+  }catch(CDynamixelAlarmException &e){
+    /* do nothing - expected exception */
+  }
+  try{
+    this->dynamixel_dev[index]->write_byte_register(led,0x00);
+  }catch(CDynamixelAlarmException &e){
+    /* do nothing - expected exception */
+  }
+}
+
+void CDynamixelMotorGroup::get_model(unsigned int index)
+{
+  unsigned short int model;
+
+  if(this->dynamixel_dev[index]==NULL)
+  {
     /* handle exceptions */
-    throw;
+    throw CDynamixelMotorException(_HERE_,"The dynamixel device is not properly configured.");
+  }
+  else
+  {
+    try{
+      this->dynamixel_dev[index]->read_byte_register(firmware_version,&this->info[index].firmware_ver);
+      this->dynamixel_dev[index]->read_word_register(model_number,&model);
+      switch(model)
+      {
+	case 0x000C: this->info[index].model="AX-12A";
+		     this->info[index].max_angle=300.0;
+		     this->info[index].center_angle=150.0;
+		     this->info[index].max_speed=354.0;
+		     this->info[index].encoder_resolution=1023;
+		     this->info[index].gear_ratio=254;
+		     this->info[index].pid_control=false;
+		     break;
+	case 0x012C: this->info[index].model="AX-12W";
+		     this->info[index].max_angle=300.0;
+		     this->info[index].center_angle=150.0;
+		     this->info[index].max_speed=2830;
+		     this->info[index].encoder_resolution=1023;
+		     this->info[index].gear_ratio=32;
+		     this->info[index].pid_control=false;
+		     break;
+	case 0x0012: this->info[index].model="AX-18A";
+		     this->info[index].max_angle=300.0;
+		     this->info[index].center_angle=150.0;
+		     this->info[index].max_speed=582;
+		     this->info[index].encoder_resolution=1023;
+		     this->info[index].gear_ratio=254;
+		     this->info[index].pid_control=false;
+		     break;
+	case 0x001D: this->info[index].model="MX-28";
+		     this->info[index].max_angle=360.0;
+		     this->info[index].center_angle=180.0;
+		     this->info[index].max_speed=330;
+		     this->info[index].encoder_resolution=4095;
+		     this->info[index].gear_ratio=193;
+		     this->info[index].pid_control=true;
+		     break;
+	case 0x0018: this->info[index].model="RX-24F";
+		     this->info[index].max_angle=300.0;
+		     this->info[index].center_angle=150.0;
+		     this->info[index].max_speed=756;
+		     this->info[index].encoder_resolution=1023;
+		     this->info[index].gear_ratio=193;
+		     this->info[index].pid_control=false;
+		     break;
+	case 0x001C: this->info[index].model="RX-28";
+		     this->info[index].max_angle=300.0;
+		     this->info[index].center_angle=150.0;
+		     this->info[index].max_speed=402;
+		     this->info[index].encoder_resolution=1023;
+		     this->info[index].gear_ratio=193;
+		     this->info[index].pid_control=false;
+		     break;
+	case 0x0136: this->info[index].model="MX-64";
+		     this->info[index].max_angle=360.0;
+		     this->info[index].center_angle=180.0;
+		     this->info[index].max_speed=378;
+		     this->info[index].encoder_resolution=4095;
+		     this->info[index].gear_ratio=200;
+		     this->info[index].pid_control=true;
+		     break;
+	case 0x0040: this->info[index].model="Rx-64";
+		     this->info[index].max_angle=300.0;
+		     this->info[index].center_angle=150.0;
+		     this->info[index].max_speed=294;
+		     this->info[index].encoder_resolution=1023;
+		     this->info[index].gear_ratio=200;
+		     this->info[index].pid_control=false;
+		     break;
+	case 0x0140: this->info[index].model="MX-106";
+		     this->info[index].max_angle=360.0;
+		     this->info[index].center_angle=180.0;
+		     this->info[index].max_speed=270;
+		     this->info[index].encoder_resolution=4095;
+		     this->info[index].gear_ratio=225;
+		     this->info[index].pid_control=true;
+		     break;
+	case 0x006B: this->info[index].model="Ex-106+";
+		     this->info[index].max_angle=251.0;
+		     this->info[index].center_angle=125.5;
+		     this->info[index].max_speed=414;
+		     this->info[index].encoder_resolution=4095;
+		     this->info[index].gear_ratio=184;
+		     this->info[index].pid_control=false;
+		     break;
+	default: this->info[index].model="unknown";
+		 break;
+      }
+    }catch(CDynamixelAlarmException &e){
+      /* handle dynamixel exception */
+      if(e.get_alarm()&this->alarms[index])
+	this->reset_motor(index);
+      throw;
+    }
   }
+}
+
+void CDynamixelMotorGroup::set_position_range(unsigned int index,double min, double max)
+{
+  unsigned short int max_pos,min_pos;
 
-  return cont_id;
+  if(this->dynamixel_dev[index]==NULL)
+  {
+    /* handle exceptions */
+    throw CDynamixelMotorException(_HERE_,"The dynamixel device is not properly configured.");
+  }
+  else
+  {
+    max_pos=this->from_angles(index,max);
+    min_pos=this->from_angles(index,min);
+    if(min_pos<0.0 || max_pos>(this->info[index].encoder_resolution))
+    {
+      /* handle exceptions */
+      throw CDynamixelMotorException(_HERE_,"The desired range is outside the valid range of the servo.");
+    }
+    else
+    {
+      try{
+	this->config[index].max_angle=max;
+	this->config[index].min_angle=min;
+	this->dynamixel_dev[index]->write_word_register(ccw_angle_limit,max_pos);
+	this->dynamixel_dev[index]->write_word_register(cw_angle_limit,min_pos);
+      }catch(CDynamixelAlarmException &e){
+	/* handle dynamixel exception */
+	if(e.get_alarm()&this->alarms[index])
+	  this->reset_motor(index);
+	throw;
+      }
+    }
+  }
 }
 
-void CDynamixelMotorGroup::remove_motor_control(std::string &cont_id)
+void CDynamixelMotorGroup::get_position_range(unsigned int index,double *min, double *max)
 {
-  std::vector<TMotorInfo>::iterator old_cont;
-  std::vector<unsigned char> new_servo_id;
-  std::vector<float> new_current_pos;
-  unsigned int i,old_id;
+  unsigned short int angle_limit;
 
-  try{
-    if((old_cont=this->search_controller(cont_id))==(std::vector<TMotorInfo>::iterator)NULL)
+  if(this->dynamixel_dev[index]==NULL)
+  {
+    /* handle exceptions */
+    throw CDynamixelMotorException(_HERE_,"The dynamixel device is not properly configured.");
+  }
+  else
+  {
+    try{
+      this->dynamixel_dev[index]->read_word_register(ccw_angle_limit,&angle_limit);
+      (*max)=this->to_angles(index,angle_limit);
+      this->dynamixel_dev[index]->read_word_register(cw_angle_limit,&angle_limit);
+      (*min)=this->to_angles(index,angle_limit);
+    }catch(CDynamixelAlarmException &e){
+      /* handle dynamixel exception */
+      if(e.get_alarm()&this->alarms[index])
+	this->reset_motor(index);
+      throw;
+    }
+  }
+}
+
+void CDynamixelMotorGroup::set_temperature_limit(unsigned int index,int limit)
+{
+  if(limit<0 && limit>255)
+  {
+    /* handle exceptions */
+    throw CDynamixelMotorException(_HERE_,"The desired temperatura limit is out of range.");
+  }
+  else
+  {
+    if(this->dynamixel_dev[index]==NULL)
     {
       /* handle exceptions */
-      throw CMotorGroupException(_HERE_,"Impossible to remove the CMotorControl object, no object exist with the given identifier");
+      throw CDynamixelMotorException(_HERE_,"The dynamixel device is not properly configured.");
     }
-    old_id=((CDynamixelMotor *)old_cont->controller)->get_id();
-    for(i=0;i<this->servo_id.size();i++)
-      if(this->servo_id[i]!=old_id)
+    else
+    {
+      try{
+	this->config[index].max_temperature=limit;
+	this->dynamixel_dev[index]->write_byte_register(temp_limit,(unsigned char)limit);
+      }catch(CDynamixelAlarmException &e){
+	/* handle dynamixel exception */
+	if(e.get_alarm()&this->alarms[index])
+	  this->reset_motor(index);
+	throw;
+      }
+    }
+  } 
+}
+
+int CDynamixelMotorGroup::get_temperature_limit(unsigned int index)
+{
+  unsigned char limit;
+
+  if(this->dynamixel_dev[index]==NULL)
+  {
+    /* handle exceptions */
+    throw CDynamixelMotorException(_HERE_,"The dynamixel device is not properly configured.");
+  }
+  else
+  {
+    try{
+      this->dynamixel_dev[index]->read_byte_register(temp_limit,&limit);
+    }catch(CDynamixelAlarmException &e){
+      /* handle dynamixel exception */
+      if(e.get_alarm()&this->alarms[index])
+	this->reset_motor(index);
+      throw;
+    }
+  }
+
+  return limit;
+}
+
+void CDynamixelMotorGroup::set_voltage_limits(unsigned int index,double min, double max)
+{
+  unsigned char min_voltage,max_voltage;
+
+  if(this->dynamixel_dev[index]==NULL)
+  {
+    /* handle exceptions */
+    throw CDynamixelMotorException(_HERE_,"The dynamixel device is not properly configured.");
+  }
+  else
+  {
+    if(min>max)
+    {
+      /* handle exceptions */
+      throw CDynamixelMotorException(_HERE_,"The maximum voltage is lower than the minimum voltage.");
+    }
+    else
+    {
+      if(min<5.0 || min>25.0 || max<5.0 || max>25.0)
       {
-        new_servo_id.push_back(servo_id[i]);
-        new_current_pos.push_back(this->current_pos[i]);
+	/* handle exceptions */
+	throw CDynamixelMotorException(_HERE_,"The desired voltage range is outside the valid range.");
       }
-    this->servo_id=new_servo_id;
-    CMotorGroup::remove_motor_control(cont_id);
-  }catch(CException &e){
+      else
+      {
+	try{
+	  this->config[index].min_voltage=min;
+	  this->config[index].max_voltage=max;
+	  min_voltage=min*10;
+	  max_voltage=max*10;
+	  this->dynamixel_dev[index]->write_byte_register(low_voltage_limit,min_voltage);
+	  this->dynamixel_dev[index]->write_byte_register(high_voltage_limit,max_voltage);
+	}catch(CDynamixelAlarmException &e){
+	  /* handle dynamixel exception */
+	  if(e.get_alarm()&this->alarms[index])
+	    this->reset_motor(index);
+	  throw;
+	}
+      }
+    }
+  }
+}
+
+void CDynamixelMotorGroup::get_voltage_limits(unsigned int index,double *min, double *max)
+{
+  unsigned char min_voltage,max_voltage;
+
+  if(this->dynamixel_dev[index]==NULL)
+  {
     /* handle exceptions */
-    throw;
+    throw CDynamixelMotorException(_HERE_,"The dynamixel device is not properly configured.");
+  }
+  else
+  {
+    try{
+      this->dynamixel_dev[index]->read_byte_register(low_voltage_limit,&min_voltage);
+      this->dynamixel_dev[index]->read_byte_register(high_voltage_limit,&max_voltage);
+      *min=((double)min_voltage/10.0);
+      *max=((double)max_voltage/10.0);
+    }catch(CDynamixelAlarmException &e){
+      /* handle dynamixel exception */
+      if(e.get_alarm()&this->alarms[index])
+	this->reset_motor(index);
+      throw;
+    }
   }
 }
 
-CDynamixelMotorGroup::~CDynamixelMotorGroup()
+unsigned char CDynamixelMotorGroup::get_turn_off_alarms(unsigned int index)
+{
+  unsigned char shutdown_alarms=0x00;
+
+  if(this->dynamixel_dev[index]==NULL)
+  {
+    /* handle exceptions */
+    throw CDynamixelMotorException(_HERE_,"The dynamixel device is not properly configured.");
+  }
+  else
+  {
+    try{
+      this->dynamixel_dev[index]->read_byte_register(alarm_shtdwn,&shutdown_alarms);
+    }catch(CDynamixelAlarmException &e){
+      /* handle dynamixel exception */
+      if(e.get_alarm()&this->alarms[index])
+	this->reset_motor(index);
+      throw;
+    }
+  }
+
+  return shutdown_alarms;
+}
+
+void CDynamixelMotorGroup::set_max_torque(unsigned int index,double torque_ratio)
+{
+  unsigned short int load;
+
+  if(this->dynamixel_dev[index]==NULL)
+  {
+    /* handle exceptions */
+    throw CDynamixelMotorException(_HERE_,"The dynamixel device is not properly configured.");
+  }
+  else
+  {
+    if(torque_ratio<0.0 || torque_ratio>100.0)
+    {
+      throw CDynamixelMotorException(_HERE_,"The desired torque ratio is outside the valid range.");
+    }
+    else
+    {
+      load=torque_ratio*1023/100.0;
+      try{
+	this->config[index].max_torque=torque_ratio;
+	this->dynamixel_dev[index]->write_word_register(max_torque,load);
+      }catch(CDynamixelAlarmException &e){
+	/* handle dynamixel exception */
+	if(e.get_alarm()&this->alarms[index])
+	  this->reset_motor(index);
+	throw;
+      }
+    }
+  }
+}
+
+void CDynamixelMotorGroup::set_limit_torque(unsigned int index,double torque_ratio)
+{
+  unsigned short int load;
+
+  if(this->dynamixel_dev[index]==NULL)
+  {
+    /* handle exceptions */
+    throw CDynamixelMotorException(_HERE_,"The dynamixel device is not properly configured.");
+  }
+  else
+  {
+    if(torque_ratio<0.0 || torque_ratio>100.0)
+    {
+      throw CDynamixelMotorException(_HERE_,"The desired torque ratio is outside the valid range.");
+    }
+    else
+    {
+      load=torque_ratio*1023/100.0;
+      try{
+	this->dynamixel_dev[index]->write_word_register(torque_limit,load);
+      }catch(CDynamixelAlarmException &e){
+	/* handle dynamixel exception */
+	if(e.get_alarm()&this->alarms[index])
+	  this->reset_motor(index);
+	throw;
+      }
+    }
+  }
+}
+
+double CDynamixelMotorGroup::get_max_torque(unsigned int index)
+{
+  unsigned short int load;
+  double torque;
+
+  if(this->dynamixel_dev[index]==NULL)
+  {
+    /* handle exceptions */
+    throw CDynamixelMotorException(_HERE_,"The dynamixel device is not properly configured.");
+  }
+  else
+  {
+    try{
+      this->dynamixel_dev[index]->read_word_register(max_torque,&load);
+      torque=(load&0x3FF)*100.0/1023;
+      if(load>0x3FF)
+	torque=-1*torque;
+    }catch(CDynamixelAlarmException &e){
+      /* handle dynamixel exception */
+      if(e.get_alarm()&this->alarms[index])
+	this->reset_motor(index);
+      throw;
+    }
+  }
+
+  return torque;
+}
+
+void CDynamixelMotorGroup::get_compliance_control(unsigned int index,TDynamixel_compliance &config)
+{
+  if(this->dynamixel_dev[index]==NULL)
+  {
+    /* handle exceptions */
+    throw CDynamixelMotorException(_HERE_,"The dynamixel device is not properly configured.");
+  }
+  else
+  {
+    if(!this->info[index].pid_control)
+    {
+      try{
+	this->dynamixel_dev[index]->read_byte_register(cw_comp_margin,&config.cw_compliance_margin);
+	this->dynamixel_dev[index]->read_byte_register(ccw_comp_margin,&config.ccw_compliance_margin);
+	this->dynamixel_dev[index]->read_byte_register(cw_comp_slope,&config.cw_compliance_slope);
+	this->dynamixel_dev[index]->read_byte_register(ccw_comp_slope,&config.ccw_compliance_slope);
+	this->dynamixel_dev[index]->read_byte_register(punch,&config.punch);
+      }catch(CDynamixelAlarmException &e){
+	/* handle dynamixel exception */
+	if(e.get_alarm()&this->alarms[index])
+	  this->reset_motor(index);
+	throw;
+      }
+    }
+  }
+}
+
+void CDynamixelMotorGroup::get_pid_control(unsigned int index,TDynamixel_pid &config)
+{
+  if(this->dynamixel_dev[index]==NULL)
+  {
+    /* handle exceptions */
+    throw CDynamixelMotorException(_HERE_,"The dynamixel device is not properly configured.");
+  }
+  else
+  {
+    if(this->info[index].pid_control)
+    {
+      try{
+	this->dynamixel_dev[index]->read_byte_register(pid_p,&config.p);
+	this->dynamixel_dev[index]->read_byte_register(pid_i,&config.i);
+	this->dynamixel_dev[index]->read_byte_register(pid_d,&config.d);
+      }catch(CDynamixelAlarmException &e){
+	/* handle dynamixel exception */
+	if(e.get_alarm()&this->alarms[index])
+	  this->reset_motor(index);
+	throw;
+      }
+    }
+  }
+}
+
+void *CDynamixelMotorGroup::sequence_thread(void *param)
 {
+  CDynamixelMotorGroup *mtn_seq=(CDynamixelMotorGroup *)param;
+  std::list<std::string> events;
+  int event_id=0,to=-1;
+  bool end=false;
 
+  // initialize the motion events
+  events.push_back(mtn_seq->finish_thread_event_id);
+  events.push_back(mtn_seq->start_sequence_event_id);
+  events.push_back(mtn_seq->stop_sequence_event_id);
+  events.push_back(mtn_seq->resume_sequence_event_id);
+
+  while(!end)
+  {
+    try{
+      try{
+	event_id=mtn_seq->event_server->wait_first(events,to);
+	mtn_seq->motion_access.enter();
+	switch(event_id)
+	{
+	  case -1: mtn_seq->sequence_current_step++;
+		   to=mtn_seq->load_motion(mtn_seq->sequence_current_step);
+		   break;
+	  case 0: /* finish the thread */
+		   end=true;
+		   break;
+	  case 1: /* start sequence */
+		   to=mtn_seq->load_motion(mtn_seq->sequence_current_step);
+		   break; 
+	  case 2: /* stop sequence */
+		   mtn_seq->stop();
+		   mtn_seq->sequence_error_msg="Motion sequence stopped by user";
+		   mtn_seq->sequence_current_step=0;
+		   break; 
+	  case 3: /* resume sequence */
+		   mtn_seq->sequence_current_step++;
+		   to=mtn_seq->load_motion(mtn_seq->sequence_current_step);
+		   break;
+	}
+	mtn_seq->motion_access.exit();
+      }catch(CEventTimeoutException &e){
+	if(!mtn_seq->event_server->event_is_set(mtn_seq->pause_sequence_event_id))
+	{
+	  /* load and execute the next step */
+	  mtn_seq->motion_access.enter();
+	  mtn_seq->sequence_current_step++;
+	  to=mtn_seq->load_motion(mtn_seq->sequence_current_step);
+	  mtn_seq->motion_access.exit();
+	}
+	else
+	{
+	  mtn_seq->event_server->reset_event(mtn_seq->pause_sequence_event_id);
+	  to=-1;
+	}
+      }
+    }catch(CException &e){
+      mtn_seq->motion_access.exit();
+      mtn_seq->stop();
+      mtn_seq->sequence_state=mtn_loaded;
+      mtn_seq->sequence_error_msg=e.what();
+      // signal the user
+      if(!mtn_seq->event_server->event_is_set(mtn_seq->sequence_error_event_id))
+	mtn_seq->event_server->set_event(mtn_seq->sequence_error_event_id);
+      if(!mtn_seq->event_server->event_is_set(mtn_seq->sequence_complete_event_id))
+	mtn_seq->event_server->set_event(mtn_seq->sequence_complete_event_id);
+    }
+  }
+
+  pthread_exit(NULL);
+}
+
+void CDynamixelMotorGroup::init_motor(unsigned int id)
+{
+  TDynamixel_info info;
+  TDynamixel_config config;
+  TDynamixel_pid pid;
+  TDynamixel_compliance compliance;
+  CDynamixel *dynamixel_dev=NULL;
+
+  info.baudrate=this->dyn_server->get_baudrate();
+  info.bus_id=this->dyn_server->get_bus_serial();
+  dynamixel_dev=this->dyn_server->get_device(id);
+  this->dynamixel_dev.push_back(dynamixel_dev);
+  info.id=id;
+  this->info.push_back(info);
+  this->get_model(this->servo_id.size());
+  this->get_position_range(this->servo_id.size(),&config.min_angle,&config.max_angle);
+  config.max_temperature=this->get_temperature_limit(this->servo_id.size());
+  this->get_voltage_limits(this->servo_id.size(),&config.min_voltage,&config.max_voltage);
+  config.max_torque=this->get_max_torque(this->servo_id.size());
+  this->config.push_back(config);
+  this->get_compliance_control(this->servo_id.size(),compliance);
+  this->compliance.push_back(compliance);
+  this->get_pid_control(this->servo_id.size(),pid);
+  this->pid.push_back(pid);
+  this->alarms.push_back(this->get_turn_off_alarms(this->servo_id.size()));
+  this->servo_id.push_back(id);
+}
+
+void CDynamixelMotorGroup::init_threads(void)
+{
+  this->thread_server=CThreadServer::instance();
+  this->sequence_thread_id=this->group_id + "sequence_thread";
+  this->thread_server->create_thread(this->sequence_thread_id);
+  this->thread_server->attach_thread(this->sequence_thread_id,this->sequence_thread,this);
+  this->thread_server->start_thread(this->sequence_thread_id);
+}
+
+void CDynamixelMotorGroup::init_events(void)
+{
+  this->event_server=CEventServer::instance();
+  this->finish_thread_event_id=this->group_id + "_finish_thread_event";
+  this->event_server->create_event(this->finish_thread_event_id);
+  this->sequence_complete_event_id=this->group_id + "_sequence_complete_event";
+  this->event_server->create_event(this->sequence_complete_event_id);
+  this->event_server->set_event(this->sequence_complete_event_id);
+  this->sequence_error_event_id=this->group_id + "_sequence_error_event";
+  this->event_server->create_event(this->sequence_error_event_id);
+  this->start_sequence_event_id=this->group_id + "_start_sequence_event";
+  this->event_server->create_event(this->start_sequence_event_id);
+  this->stop_sequence_event_id=this->group_id + "_stop_sequence_event";
+  this->event_server->create_event(this->stop_sequence_event_id);
+  this->pause_sequence_event_id=this->group_id + "_pause_sequence_event";
+  this->event_server->create_event(this->pause_sequence_event_id);
+  this->resume_sequence_event_id=this->group_id + "_resume_sequence_event";
+  this->event_server->create_event(this->resume_sequence_event_id);
+}
+
+void CDynamixelMotorGroup::clear(void)
+{
+  unsigned int i=0;
+
+  for(i=0;i<this->servo_id.size();i++)
+  {
+    if(this->dynamixel_dev[i]!=NULL)
+    {
+      this->dyn_server->free_device(this->dynamixel_dev[i]->get_id());
+      delete this->dynamixel_dev[i];
+    }
+    this->dynamixel_dev[i]=NULL;
+  }
+  this->dynamixel_dev.clear();
+  this->compliance.clear();
+  this->pid.clear();
+  this->config.clear();
+  this->info.clear();
+  this->alarms.clear();
+  this->servo_id.clear();
+  /* clear any motion attribute */
+  this->sequence_state=mtn_empty;
+  this->sequence_current_step=-1;
+  this->sequence_error_msg="Motion sequence ended successfully";
+  this->seq.clear();
+}
+
+int CDynamixelMotorGroup::load_motion(unsigned int step_id)
+{
+  static std::vector<int> time(this->get_num_motors());
+  std::vector<double> current_position;
+  unsigned int i=0;
+  double distance;
+  int max=0;
+
+  if(step_id<0)
+  {
+    /* handle errors */
+    throw CDynamixelMotionSequenceException(_HERE_,"Invalid step index");
+  }
+  else if(step_id>=this->seq.size())
+  {
+    this->sequence_state=mtn_loaded;
+    this->sequence_error_msg="Motion sequence completed successfully";
+    /* signal the completion of the sequence */
+    if(!this->event_server->event_is_set(this->sequence_complete_event_id))
+      this->event_server->set_event(this->sequence_complete_event_id);
+    return -1;
+  }
+  else
+  {
+    this->get_current_angle(current_position);
+    for(i=0;i<this->get_num_motors();i++)
+    {
+      if(this->seq[step_id].absolute_motion)// absolute motion
+	distance=fabs(current_position[i]-this->seq[step_id].position[i]);
+      else// relative motion
+	distance=fabs(this->seq[step_id].position[i]);
+      time[i]=distance/this->seq[step_id].velocity[i]*1000;// time in ms
+    }
+    if(this->seq[step_id].absolute_motion)
+      this->move_absolute_angle(this->seq[step_id].position,this->seq[step_id].velocity);
+    else
+      this->move_relative_angle(this->seq[step_id].position,this->seq[step_id].velocity);
+    max=time[0];
+    for(i=1;i<this->get_num_motors();i++)
+      if(time[i]>max)
+	max=time[i];
+    return max+this->seq[step_id].delay;
+  }
+}
+
+void CDynamixelMotorGroup::load_config(TDynamixelGroup_config &config)
+{
+  std::vector<TDynamixel_compliance> compliance;
+  std::vector<TDynamixel_pid> pid;
+  unsigned int i=0;
+
+  this->clear();
+  try{
+    this->dyn_server->config_bus(config.bus_id,config.baudrate);
+    pid.resize(config.id.size());
+    compliance.resize(config.id.size());
+    for(i=0;i<config.id.size();i++)
+    {
+      this->init_motor(config.id[i]);
+      // load the configuration file
+      std::auto_ptr<dynamixel_motor_config_t> motor(dynamixel_motor_config(config.config_files[i].c_str(),xml_schema::flags::dont_validate));
+      this->set_position_range(i,motor->min_angle(),motor->max_angle());
+      this->set_temperature_limit(i,motor->temp_limit());
+      this->set_voltage_limits(i,motor->min_voltage(),motor->max_voltage());
+      if(this->info[i].pid_control)
+      {
+	pid[i].p=motor->kp();
+	pid[i].i=motor->ki();
+	pid[i].d=motor->kd();
+      }
+      else
+      {
+	compliance[i].cw_compliance_margin=motor->cw_comp_margin();
+	compliance[i].ccw_compliance_margin=motor->ccw_comp_margin();
+	compliance[i].cw_compliance_slope=motor->cw_comp_slope();
+	compliance[i].ccw_compliance_slope=motor->ccw_comp_slope();
+	compliance[i].punch=motor->punch();
+      }
+      this->set_max_torque(i,motor->max_torque());
+      this->set_limit_torque(i,motor->max_torque());
+    }
+    if(this->config[0].min_angle==-this->info[0].center_angle && this->config[0].max_angle==-this->info[0].center_angle)
+    {
+      this->mode=torque_ctrl;
+      for(i=1;i<this->servo_id.size();i++)
+	this->set_position_range(i,-this->info[i].center_angle,-this->info[i].center_angle);
+    }
+    else
+    {
+      this->mode=angle_ctrl;
+      for(i=1;i<this->servo_id.size();i++)
+	this->set_position_range(i,-this->info[i].center_angle,this->info[i].max_angle-this->info[i].center_angle);
+    }
+    this->set_pid_control(pid);
+    this->set_compliance_control(compliance);
+  }catch (const xml_schema::exception& e){
+    std::ostringstream os;
+    os << e;
+    this->clear();
+    /* handle exceptions */
+    throw CDynamixelMotorException(_HERE_,os.str());
+  }catch(CException &e){
+    this->clear();
+    throw e;
+  }
+}
+
+#ifdef _HAVE_XSD
+void CDynamixelMotorGroup::load_config(std::string &filename)
+{
+  dyn_motor_group_config_t::dyn_motor_config_iterator iterator;
+  std::vector<TDynamixel_compliance> compliance;
+  std::vector<TDynamixel_pid> pid;
+  unsigned int i=0;
+
+  this->clear();
+
+  // try to open the specified file
+  try{
+    std::auto_ptr<dyn_motor_group_config_t> cfg(dyn_motor_group_config(filename.c_str(), xml_schema::flags::dont_validate));
+    this->dyn_server->config_bus(cfg->bus_id(),cfg->baudrate());
+    pid.resize(cfg->dyn_motor_config().size());
+    compliance.resize(cfg->dyn_motor_config().size());
+    for(iterator=cfg->dyn_motor_config().begin(),i=0;iterator!=cfg->dyn_motor_config().end();iterator++,i++)
+    {
+      this->init_motor(iterator->id());
+      // load the configuration file
+      std::auto_ptr<dynamixel_motor_config_t> motor(dynamixel_motor_config(iterator->config_file().c_str(),xml_schema::flags::dont_validate));
+      this->set_position_range(i,motor->min_angle(),motor->max_angle());
+      this->set_temperature_limit(i,motor->temp_limit());
+      this->set_voltage_limits(i,motor->min_voltage(),motor->max_voltage());
+      if(this->info[i].pid_control)
+      {
+	pid[i].p=motor->kp();
+	pid[i].i=motor->ki();
+	pid[i].d=motor->kd();
+      }
+      else
+      {
+	compliance[i].cw_compliance_margin=motor->cw_comp_margin();
+	compliance[i].ccw_compliance_margin=motor->ccw_comp_margin();
+	compliance[i].cw_compliance_slope=motor->cw_comp_slope();
+	compliance[i].ccw_compliance_slope=motor->ccw_comp_slope();
+	compliance[i].punch=motor->punch();
+      }
+      this->set_max_torque(i,motor->max_torque());
+      this->set_limit_torque(i,motor->max_torque());
+    }
+    if(this->config[0].min_angle==-this->info[0].center_angle && this->config[0].max_angle==-this->info[0].center_angle)
+    {
+      this->mode=torque_ctrl;
+      for(i=1;i<this->servo_id.size();i++)
+	this->set_position_range(i,-this->info[i].center_angle,-this->info[i].center_angle);
+    }
+    else
+    {
+      this->mode=angle_ctrl;
+      for(i=1;i<this->servo_id.size();i++)
+	this->set_position_range(i,-this->info[i].center_angle,this->info[i].max_angle-this->info[i].center_angle);
+    }
+    this->set_pid_control(pid);
+    this->set_compliance_control(compliance);
+  }catch (const xml_schema::exception& e){
+    std::ostringstream os;
+    os << e;
+    this->clear();
+    /* handle exceptions */
+    throw CDynamixelMotorException(_HERE_,os.str());
+  }catch(CException &e){
+    this->clear();
+    throw e;
+  }
+}
+
+void CDynamixelMotorGroup::save_config(std::string &filename)
+{
+
+}
+
+void CDynamixelMotorGroup::load_sequence(std::string &filename)
+{
+  dyn_sequence_t::step_iterator iterator;
+  TDynamixelMotionStep step;
+
+  // try to open the specified file
+  try{
+    // stop any current motion
+    this->motion_access.enter();
+    if(this->sequence_state==mtn_started || this->sequence_state==mtn_paused)
+    {
+      this->motion_access.exit();
+      this->stop_sequence();
+      this->motion_access.enter();
+      this->sequence_state=mtn_loaded;
+    }
+    // load the new sequence
+    std::auto_ptr<dyn_sequence_t> seq(dyn_motion_seq(filename.c_str(),xml_schema::flags::dont_validate));
+    if(seq->num_motors()!=this->get_num_motors())
+    {
+      this->motion_access.exit();
+      /* handle exceptions */
+      throw CDynamixelMotionSequenceException(_HERE_,"The number of motors in the loaded sequence does not coincide with the number of motors in the associated motor group");
+    }
+    else
+    {
+      // erase the previous sequence
+      this->seq.clear(); 
+      for(iterator=seq->step().begin();iterator!=seq->step().end();iterator++)
+      {
+	if(iterator->mode()=="absolute")
+	  step.absolute_motion=true;
+	else
+	  step.absolute_motion=false;
+	step.delay=iterator->delay();
+	step.position.clear();
+	step.position=iterator->position();
+	step.velocity.clear();
+	step.velocity=iterator->velocity();
+	this->seq.push_back(step);
+      }
+      this->sequence_state=mtn_loaded;
+      this->sequence_current_step=0;
+    }
+    this->motion_access.exit();
+  }catch (const xml_schema::exception& e){
+    this->sequence_state=mtn_empty;
+    this->motion_access.exit();
+    /* handle exceptions */
+    std::ostringstream os;
+    os << e;
+    throw CDynamixelMotionSequenceException(_HERE_,os.str());
+  }
+}
+
+void CDynamixelMotorGroup::save_sequence(std::string &filename)
+{
+  xml_schema::namespace_infomap map;
+  unsigned int i=0,j=0;
+  std::string mode;
+
+  try{
+    // save the base class parameters
+    std::ofstream output_file(filename.c_str(),std::ios_base::out);
+    dyn_sequence_t sequence_file(this->get_num_motors());
+    dyn_sequence_t::step_sequence& motion_sequence(sequence_file.step());
+
+    for(i=0;i<this->seq.size();i++)
+    {
+      if(this->seq[i].absolute_motion)
+	mode="absolute";
+      else
+	mode="relative";
+      step_t step(mode,this->seq[i].delay);
+      step_t::position_sequence& position(step.position());
+      step_t::velocity_sequence& velocity(step.velocity());
+      for(j=0;j<this->get_num_motors();j++)
+      {
+	position.push_back(this->seq[i].position[j]);
+	velocity.push_back(this->seq[i].velocity[j]);
+      }
+      motion_sequence.push_back(step);
+    }
+    map[""].name="";
+    map[""].schema="motion_sequence.xsd";
+    dyn_motion_seq(output_file,sequence_file,map);
+  }catch (const xml_schema::exception& e){
+    std::ostringstream os;
+    os << e;
+    /* handle exceptions */
+    throw CDynamixelMotorException(_HERE_,os.str());
+  }
+}
+#endif
+
+void CDynamixelMotorGroup::set_compliance_control(std::vector<TDynamixel_compliance> &config)
+{
+  unsigned int i=0;
+
+  for(i=0;i<this->servo_id.size();i++)
+  {
+    if(this->dynamixel_dev[i]==NULL)
+    {
+      /* handle exceptions */
+      throw CDynamixelMotorException(_HERE_,"The dynamixel device is not properly configured.");
+    }
+    else
+    {
+      if(!this->info[i].pid_control)
+      {
+	if(config[i].cw_compliance_margin>254)
+	{
+	  /* handle exceptions */
+	  throw CDynamixelMotorException(_HERE_,"Invalid clockwise compliance margin.");
+	}
+	if(config[i].ccw_compliance_margin>254)
+	{
+	  /*  handle exceptions */
+	  throw CDynamixelMotorException(_HERE_,"Invalid counterclockwise compliance margin.");
+	}
+	if(config[i].cw_compliance_slope>=1 && config[i].cw_compliance_slope<=5) config[i].cw_compliance_slope=4;
+	else if(config[i].cw_compliance_slope>=6 && config[i].cw_compliance_slope<=11) config[i].cw_compliance_slope=8;
+	else if(config[i].cw_compliance_slope>=12 && config[i].cw_compliance_slope<=23) config[i].cw_compliance_slope=16;
+	else if(config[i].cw_compliance_slope>=24 && config[i].cw_compliance_slope<=47) config[i].cw_compliance_slope=32;
+	else if(config[i].cw_compliance_slope>=48 && config[i].cw_compliance_slope<=95) config[i].cw_compliance_slope=64;
+	else if(config[i].cw_compliance_slope>=96 && config[i].cw_compliance_slope<=191) config[i].cw_compliance_slope=128;
+	else if(config[i].cw_compliance_slope>=192 && config[i].cw_compliance_slope<=254) config[i].cw_compliance_slope=254;
+	else
+	{
+	  /* handle exceptions */
+	  throw CDynamixelMotorException(_HERE_,"Invalid clockwise compliance slope.");
+	}
+	if(config[i].ccw_compliance_slope>=1 && config[i].ccw_compliance_slope<=5) config[i].ccw_compliance_slope=4;
+	else if(config[i].ccw_compliance_slope>=6 && config[i].ccw_compliance_slope<=11) config[i].ccw_compliance_slope=8;
+	else if(config[i].ccw_compliance_slope>=12 && config[i].ccw_compliance_slope<=23) config[i].ccw_compliance_slope=16;
+	else if(config[i].ccw_compliance_slope>=24 && config[i].ccw_compliance_slope<=47) config[i].ccw_compliance_slope=32;
+	else if(config[i].ccw_compliance_slope>=48 && config[i].ccw_compliance_slope<=95) config[i].ccw_compliance_slope=64;
+	else if(config[i].ccw_compliance_slope>=96 && config[i].ccw_compliance_slope<=191) config[i].ccw_compliance_slope=128;
+	else if(config[i].ccw_compliance_slope>=192 && config[i].ccw_compliance_slope<=254) config[i].ccw_compliance_slope=254;
+	else
+	{
+	  /* handle exceptions */
+	  throw CDynamixelMotorException(_HERE_,"Invalid counterclockwise compliance slope.");
+	}
+	if(config[i].punch<0 || config[i].punch>1023)
+	{
+	  /* handle exceptions */
+	  throw CDynamixelMotorException(_HERE_,"Invalid punch value.");
+	}
+	try{
+	  this->compliance[i].cw_compliance_margin=config[i].cw_compliance_margin;
+	  this->compliance[i].ccw_compliance_margin=config[i].ccw_compliance_margin;
+	  this->compliance[i].cw_compliance_slope=config[i].cw_compliance_slope;
+	  this->compliance[i].ccw_compliance_slope=config[i].ccw_compliance_slope;
+	  this->dynamixel_dev[i]->write_byte_register(cw_comp_margin,config[i].cw_compliance_margin);
+	  this->dynamixel_dev[i]->write_byte_register(ccw_comp_margin,config[i].ccw_compliance_margin);
+	  this->dynamixel_dev[i]->write_byte_register(cw_comp_slope,config[i].cw_compliance_slope);
+	  this->dynamixel_dev[i]->write_byte_register(ccw_comp_slope,config[i].ccw_compliance_slope);
+	  this->dynamixel_dev[i]->write_word_register(punch,config[i].punch);
+	}catch(CDynamixelAlarmException &e){
+	  /* handle dynamixel exception */
+	  if(e.get_alarm()&this->alarms[i])
+	    this->reset_motor(i);
+	  throw;
+	}
+      }
+    }
+  }
+}
+
+void CDynamixelMotorGroup::set_pid_control(std::vector<TDynamixel_pid> &config)
+{
+  unsigned int i=0;
+
+  for(i=0;i<this->servo_id.size();i++)
+  {
+    if(this->dynamixel_dev[i]==NULL)
+    {
+      /* handle exceptions */
+      throw CDynamixelMotorException(_HERE_,"The dynamixel device is not properly configured.");
+    }
+    else
+    {
+      if(this->info[i].pid_control)
+      {
+	this->pid[i].p=config[i].p;
+	this->pid[i].i=config[i].i;
+	this->pid[i].d=config[i].d;
+	this->dynamixel_dev[i]->write_byte_register(pid_p,config[i].p);
+	this->dynamixel_dev[i]->write_byte_register(pid_i,config[i].i);
+	this->dynamixel_dev[i]->write_byte_register(pid_d,config[i].d);
+      }
+    }
+  }
+}
+
+void CDynamixelMotorGroup::enable(void)
+{
+  unsigned int i=0;
+
+  for(i=0;i<this->servo_id.size();i++)
+  {
+    if(this->dynamixel_dev[i]==NULL)
+    {
+      /* handle exceptions */
+      throw CDynamixelMotorException(_HERE_,"The dynamixel device is not properly configured.");
+    }
+    else
+    {
+      try{
+	this->dynamixel_dev[i]->write_byte_register(torque_en,1);
+      }catch(CDynamixelAlarmException &e){
+	/* handle dynamixel exception */
+	if(e.get_alarm()&this->alarms[i])
+	  this->reset_motor(i);
+	throw;
+      }
+    }
+  }
+}
+
+void CDynamixelMotorGroup::disable(void)
+{
+  unsigned int i=0;
+
+  for(i=0;i<this->servo_id.size();i++)
+  {
+    if(this->dynamixel_dev[i]==NULL)
+    {
+      /* handle exceptions */
+      throw CDynamixelMotorException(_HERE_,"The dynamixel device is not properly configured.");
+    }
+    else
+    {
+      try{
+	this->dynamixel_dev[i]->write_byte_register(torque_en,0);
+      }catch(CDynamixelAlarmException &e){
+	/* handle dynamixel exception */
+	if(e.get_alarm()&this->alarms[i])
+	  this->reset_motor(i);
+	throw;
+      }
+    }
+  }
+}
+
+void CDynamixelMotorGroup::move_absolute_angle(std::vector<double> &angles,std::vector<double> &speeds)
+{
+  std::vector< std::vector<unsigned char> > data;
+  unsigned short int cmd[2];
+  unsigned int i=0;
+
+  try{
+    if(this->mode==torque_ctrl)
+    {
+      for(i=0;i<this->servo_id.size();i++)
+	this->set_position_range(i,-this->info[i].center_angle,this->info[i].max_angle-this->info[i].center_angle);
+      this->mode=angle_ctrl;
+    }
+    data.resize(this->servo_id.size());
+    for(i=0;i<this->servo_id.size();i++)
+    {
+      data[i].resize(4);
+      cmd[0]=this->from_angles(i,angles[i]);
+      cmd[1]=this->from_speeds(i,speeds[i]);
+      data[i][0]=((int)(cmd[0])%256);
+      data[i][1]=(int)(cmd[0]/256);
+      data[i][2]=((int)(cmd[1])%256);
+      data[i][3]=(int)(cmd[1]/256);
+    }
+    this->dyn_server->write_sync(this->servo_id, goal_pos, data);
+  }catch(CDynamixelAlarmException &e){
+    /* handle dynamixel exception */
+    if(e.get_alarm()&this->alarms[i])
+      this->reset_motor(i);
+    throw;
+  }
+}
+
+void CDynamixelMotorGroup::move_relative_angle(std::vector<double> &angles,std::vector<double> &speeds)
+{
+  std::vector< std::vector<unsigned char> > data;
+  unsigned short int cmd[2],pos;
+  unsigned int i=0;
+
+  try{
+    if(this->mode==torque_ctrl)
+    {
+      for(i=0;i<this->servo_id.size();i++)
+	this->set_position_range(i,-this->info[i].center_angle,this->info[i].max_angle-this->info[i].center_angle);
+      this->mode=angle_ctrl;
+    }
+    data.resize(this->servo_id.size());
+    for(i=0;i<this->servo_id.size();i++)
+    {
+      if(this->dynamixel_dev[i]==NULL)
+      {
+	/* handle exceptions */
+	throw CDynamixelMotorException(_HERE_,"The dynamixel device is not properly configured.");
+      }
+      else
+      {
+	this->dynamixel_dev[i]->read_word_register(current_pos,&pos);
+	data[i].resize(4);
+	cmd[0]=this->from_angles(i,angles[i]+this->to_angles(i,pos));
+	cmd[1]=this->from_speeds(i,speeds[i]);
+	data[i][0]=((int)(cmd[0])%256);
+	data[i][1]=(int)(cmd[0]/256);
+	data[i][2]=((int)(cmd[1])%256);
+	data[i][3]=(int)(cmd[1]/256);
+      }
+    }
+    this->dyn_server->write_sync(this->servo_id,goal_pos,data);
+  }catch(CDynamixelAlarmException &e){
+    /* handle dynamixel exception */
+    if(e.get_alarm()&this->alarms[i])
+      this->reset_motor(i);
+    throw;
+  }
+}
+
+void CDynamixelMotorGroup::move_torque(std::vector<double> &torque_ratios)
+{
+  std::vector< std::vector<unsigned char> > data;
+  unsigned short int torque=0;
+  unsigned int i=0;
+
+  try{
+    if(this->mode==angle_ctrl)
+    {
+      for(i=0;i<this->servo_id.size();i++)
+	this->set_position_range(i,-this->info[i].center_angle,-this->info[i].center_angle);
+      this->mode=torque_ctrl;
+    }
+    data.resize(this->servo_id.size());
+    for(i=0;i<this->servo_id.size();i++)
+    {
+      if(this->dynamixel_dev[i]==NULL)
+      {
+	/* handle exceptions */
+	throw CDynamixelMotorException(_HERE_,"The dynamixel device is not properly configured.");
+      }
+      else
+      {
+	torque=0;
+	data[i].resize(2);
+	if(torque_ratios[i]<0.0)
+	  torque+=0x0400;
+	torque+=((unsigned short int)(fabs(torque_ratios[i])*1023.0/100.0))&0x03FF;
+	data[i][0]=((int)(torque)%256);
+	data[i][1]=(int)(torque/256);
+      }
+    }
+    this->dyn_server->write_sync(this->servo_id,goal_speed,data);
+  }catch(CDynamixelAlarmException &e){
+    /* handle dynamixel exception */
+    if(e.get_alarm()&this->alarms[i])
+      this->reset_motor(i);
+    throw;
+  }
+}
+
+void CDynamixelMotorGroup::stop(void)
+{
+  unsigned short int current_position;
+  unsigned int i=0;
+
+  try{
+    for(i=0;i<this->servo_id.size();i++)
+    {
+      if(this->dynamixel_dev[i]==NULL)
+      {
+	/* handle exceptions */
+	throw CDynamixelMotorException(_HERE_,"The dynamixel device is not properly configured.");
+      }
+      else
+      {
+	if(this->mode==angle_ctrl)
+	{
+	  this->dynamixel_dev[i]->read_word_register(current_pos,&current_position);
+	  this->dynamixel_dev[i]->write_word_register(goal_pos,current_position);
+	}
+	else
+	  this->dynamixel_dev[i]->write_word_register(goal_speed,0);
+      }
+    }
+  }catch(CDynamixelAlarmException &e){
+    /* handle dynamixel exception */
+    if(e.get_alarm()&this->alarms[i])
+      this->reset_motor(i);
+    throw;
+  }
+}
+
+void CDynamixelMotorGroup::get_current_angle(std::vector<double> &angles)
+{
+  unsigned short int data;
+
+  angles.resize(this->servo_id.size());
+
+  for(unsigned int i=0; i<this->servo_id.size(); i++)
+  {
+    if(this->dynamixel_dev[i]==NULL)
+    {
+      /* handle exceptions */
+      throw CDynamixelMotorException(_HERE_,"The dynamixel device is not properly configured.");
+    }
+    else
+    {
+      try{
+	this->dynamixel_dev[i]->read_word_register(current_pos,&data);
+	angles[i] = this->to_angles(i, data);
+      }catch(CDynamixelAlarmException &e){
+	/* handle dynamixel exception */
+	if(e.get_alarm()&this->alarms[i])
+	  this->reset_motor(i);
+	throw;
+      }
+    }
+  }
+}
+
+void CDynamixelMotorGroup::get_current_speed(std::vector<double> &speeds)
+{
+  unsigned short int data;
+
+  speeds.resize(this->servo_id.size());
+
+  for(unsigned int i=0; i<this->servo_id.size(); i++)
+  {
+    if(this->dynamixel_dev[i]==NULL)
+    {
+      /* handle exceptions */
+      throw CDynamixelMotorException(_HERE_,"The dynamixel device is not properly configured.");
+    }
+    else
+    {
+      try{
+	this->dynamixel_dev[i]->read_word_register(current_speed,&data);
+	speeds[i] = this->to_speeds(i, data);
+      }catch(CDynamixelAlarmException &e){
+	/* handle dynamixel exception */
+	if(e.get_alarm()&this->alarms[i])
+	  this->reset_motor(i);
+	throw;
+      }
+    }
+  }
+}
+
+void CDynamixelMotorGroup::get_current_effort(std::vector<double> &efforts)
+{
+  unsigned short int c_effort;
+  unsigned short int c_speed;
+
+  efforts.resize(this->servo_id.size());
+
+  for(unsigned int i=0; i<this->servo_id.size(); i++)
+  {
+    if(this->dynamixel_dev[i]==NULL)
+    {
+      /* handle exceptions */
+      throw CDynamixelMotorException(_HERE_,"The dynamixel device is not properly configured.");
+    }
+    else
+    {
+      try{
+	this->dynamixel_dev[i]->read_word_register(current_load,&c_effort);
+	this->dynamixel_dev[i]->read_word_register(current_speed,&c_speed);
+	efforts[i] = (double)((c_effort&0x3FF)*100.0/1023);
+	if (this->to_speeds(i, c_speed) < 0)
+	{
+	  efforts[i] *= -1.0;
+	}
+      }catch(CDynamixelAlarmException &e){
+	/* handle dynamixel exception */
+	if(e.get_alarm()&this->alarms[i])
+	  this->reset_motor(i);
+	throw;
+      }
+    }
+  }
+}
+
+void CDynamixelMotorGroup::get_current_voltage(std::vector<double> &voltages)
+{
+  unsigned char data;
+
+  voltages.resize(this->servo_id.size());
+
+  for(unsigned int i=0; i<this->servo_id.size(); i++)
+  {
+    if(this->dynamixel_dev[i]==NULL)
+    {
+      /* handle exceptions */
+      throw CDynamixelMotorException(_HERE_,"The dynamixel device is not properly configured.");
+    }
+    else
+    {
+      try{
+	this->dynamixel_dev[i]->read_byte_register(current_voltage,&data);
+	voltages[i] = (double)data/10;
+      }catch(CDynamixelAlarmException &e){
+	/* handle dynamixel exception */
+	if(e.get_alarm()&this->alarms[i])
+	  this->reset_motor(i);
+	throw;
+      }
+    }
+  }
+}
+
+void CDynamixelMotorGroup::get_current_temperature(std::vector<double> &temperatures)
+{
+  unsigned char data;
+
+  temperatures.resize(this->servo_id.size());
+
+  for(unsigned int i=0; i<this->servo_id.size(); i++)
+  {
+    if(this->dynamixel_dev[i]==NULL)
+    {
+      /* handle exceptions */
+      throw CDynamixelMotorException(_HERE_,"The dynamixel device is not properly configured.");
+    }
+    else
+    {
+      try{
+	this->dynamixel_dev[i]->read_byte_register(current_temp,&data);
+	temperatures[i] = (double)data;
+      }catch(CDynamixelAlarmException &e){
+	/* handle dynamixel exception */
+	if(e.get_alarm()&this->alarms[i])
+	  this->reset_motor(i);
+	throw;
+      }
+    }
+  }
+}
+
+unsigned int CDynamixelMotorGroup::get_num_motors(void)
+{
+  return this->servo_id.size();
+}
+
+TDynamixelMotionStates CDynamixelMotorGroup::get_sequence_current_state(void)
+{
+  return this->sequence_state;
+}
+
+void CDynamixelMotorGroup::add_sequence_step(std::vector<double> &pos,std::vector<double> &vel, double delay, bool abs_motion)
+{
+  TDynamixelMotionStep step;
+
+  if(pos.size()!=this->get_num_motors())
+  {
+    /* handle exceptions */
+    throw CDynamixelMotionSequenceException(_HERE_,"The position vector has a wrong length");
+  }
+  if(vel.size()!=this->get_num_motors())
+  {
+    /* handle exceptions */
+    throw CDynamixelMotionSequenceException(_HERE_,"The velocity vector has a wrong length");
+  }
+  if(delay<0.0)
+  {
+    /* handle exceptions */
+    throw CDynamixelMotionSequenceException(_HERE_,"Negative delay time");
+  }
+  this->motion_access.enter();
+  step.position=pos;
+  step.velocity=vel;
+  step.delay=delay;
+  step.absolute_motion=abs_motion;
+  this->seq.push_back(step);
+  if(this->sequence_state!=mtn_loaded)
+  {
+    this->sequence_state=mtn_loaded;
+    this->sequence_current_step=0;
+  }
+  this->motion_access.exit();
+}
+
+void CDynamixelMotorGroup::insert_sequence_step(unsigned int index,std::vector<double> &pos,std::vector<double> &vel, double delay, bool abs_motion)
+{
+  std::vector<TDynamixelMotionStep> sequence;
+  TDynamixelMotionStep step;
+  unsigned int i;
+
+  if(index < 0 || index > this->seq.size())
+  {
+    /* handle exceptions */
+    throw CDynamixelMotionSequenceException(_HERE_,"The index is out of range");
+  }
+  if(pos.size()!=this->get_num_motors())
+  {
+    /* handle exceptions */
+    throw CDynamixelMotionSequenceException(_HERE_,"The position vector has a wrong length");
+  }
+  if(vel.size()!=this->get_num_motors())
+  {
+    /* handle exceptions */
+    throw CDynamixelMotionSequenceException(_HERE_,"The velocity vector has a wrong length");
+  }
+  if(delay<0.0)
+  {
+    /* handle exceptions */
+    throw CDynamixelMotionSequenceException(_HERE_,"Negative delay time");
+  }
+  this->motion_access.enter();
+  step.position=pos;
+  step.velocity=vel;
+  step.delay=delay;
+  step.absolute_motion=abs_motion;
+  sequence=this->seq;
+  this->seq.clear();
+  for(i=0;i<sequence.size();i++)
+  {
+    if(i==index)
+      this->seq.push_back(step);
+    this->seq.push_back(sequence[i]);
+  }
+  if(this->sequence_state!=mtn_loaded)
+  {
+    this->sequence_state=mtn_loaded;
+    this->sequence_current_step=0;
+  }
+  this->motion_access.exit();
+}
+
+void CDynamixelMotorGroup::delete_sequence_step(unsigned int index)
+{
+  std::vector<TDynamixelMotionStep> sequence;
+  unsigned int i;
+
+  if(index < 0 || index > this->seq.size())
+  {
+    /* handle exceptions */
+    throw CDynamixelMotionSequenceException(_HERE_,"The index is out of range");
+  }
+  this->motion_access.enter();
+  sequence=this->seq;
+  this->seq.clear();
+  for(i=0;i<sequence.size();i++)
+  {
+    if(i!=index)
+      this->seq.push_back(sequence[i]);
+  }
+  if(this->seq.size()==0)
+    this->sequence_state=mtn_empty;
+  this->motion_access.exit();
+}
+
+void CDynamixelMotorGroup::clear_sequence(void)
+{
+  this->stop_sequence();
+  this->motion_access.enter();
+  this->seq.clear();
+  this->sequence_state=mtn_empty;
+  this->motion_access.exit();
+}
+
+void CDynamixelMotorGroup::start_sequence(void)
+{
+  this->motion_access.enter();  
+  switch(this->sequence_state)
+  {
+    case mtn_empty: /* handle exceptions */
+      //this->motion_access.exit();  
+      //throw CMotionSequenceException(_HERE_,"There is no motion sequence loaded");
+      break;
+    case mtn_loaded: // enable the motors
+      this->enable();
+      this->sequence_current_step=0;
+      if(this->event_server->event_is_set(this->sequence_complete_event_id))
+	this->event_server->reset_event(this->sequence_complete_event_id);
+      if(this->event_server->event_is_set(this->sequence_error_event_id))
+	this->event_server->reset_event(this->sequence_error_event_id);
+      if(!this->event_server->event_is_set(this->start_sequence_event_id))
+	this->event_server->set_event(this->start_sequence_event_id);
+      this->sequence_state=mtn_started;
+      break;
+    case mtn_started: /* do nothing */
+      break;
+    case mtn_paused: /* handle exceptions */
+      //this->motion_access.exit();  
+      //throw CMotionSequenceException(_HERE_,"A sequence is currently pause, stop it before starting a new one.");
+      break;
+  }
+  this->motion_access.exit();
+}
+
+void CDynamixelMotorGroup::pause_sequence(void)
+{
+  this->motion_access.enter();  
+  switch(this->sequence_state)
+  {
+    case mtn_empty: /* handle exceptions */
+      //this->motion_access.exit();  
+      //throw CMotionSequenceException(_HERE_,"There is no motion sequence loaded");
+      break;
+    case mtn_loaded: /* handle exceptions */
+      //this->motion_access.exit();  
+      //throw CMotionSequenceException(_HERE_,"There is no motion sequence currently being executed");
+      break;
+    case mtn_started: if(!this->event_server->event_is_set(this->pause_sequence_event_id))
+			this->event_server->set_event(this->pause_sequence_event_id);
+		      this->sequence_state=mtn_paused;
+		      break;
+    case mtn_paused: /* do nothing */
+		      break;
+  }
+  this->motion_access.exit();
+}
+
+void CDynamixelMotorGroup::resume_sequence(void)
+{
+  this->motion_access.enter();  
+  switch(this->sequence_state)
+  {
+    case mtn_empty: /* handle exceptions */
+      //this->motion_access.exit();  
+      //throw CMotionSequenceException(_HERE_,"There is no motion sequence loaded");
+      break;
+    case mtn_loaded: /* handle exceptions */
+      //this->motion_access.exit();  
+      //throw CMotionSequenceException(_HERE_,"There is no motion sequence currently being executed");
+      break;
+    case mtn_started: /* do nothing */ 
+      break;
+    case mtn_paused: if(!this->event_server->event_is_set(this->resume_sequence_event_id))
+		       this->event_server->set_event(this->resume_sequence_event_id);
+		     this->sequence_state=mtn_started;
+		     break;
+  }
+  this->motion_access.exit();
+}
+
+void CDynamixelMotorGroup::stop_sequence(void)
+{
+  this->motion_access.enter();  
+  switch(this->sequence_state)
+  {
+    case mtn_empty: /* handle exceptions */
+      //this->motion_access.exit();  
+      //throw CMotionSequenceException(_HERE_,"There is no motion sequence loaded");
+      break;
+    case mtn_loaded: /* handle exceptions */
+      //this->motion_access.exit();  
+      //throw CMotionSequenceException(_HERE_,"There is no motion sequence currently being executed");
+      break;
+    case mtn_started: if(!this->event_server->event_is_set(this->stop_sequence_event_id))
+			this->event_server->set_event(this->stop_sequence_event_id);
+		      this->sequence_state=mtn_loaded;
+		      break;
+    case mtn_paused: if(!this->event_server->event_is_set(this->stop_sequence_event_id))
+		       this->event_server->set_event(this->stop_sequence_event_id);
+		     this->sequence_state=mtn_loaded;
+		     break;
+  }
+  this->motion_access.exit();
+}
+
+std::string CDynamixelMotorGroup::get_sequence_complete_event_id(void)
+{
+  return this->sequence_complete_event_id;
+}
+
+std::string CDynamixelMotorGroup::get_sequence_error_event_id(void)
+{
+  return this->sequence_error_event_id;
+}
+
+std::string CDynamixelMotorGroup::get_sequence_error_message(void)
+{
+  return this->sequence_error_msg;
+}
+
+int CDynamixelMotorGroup::get_sequence_current_step(void)
+{
+  return this->sequence_current_step;
+}
+
+double CDynamixelMotorGroup::get_sequence_completed_percentage(void)
+{
+  double ratio;
+
+  if(this->sequence_state!=mtn_empty)
+    ratio=((double)this->sequence_current_step*100.0)/(this->seq.size());
+  else
+  {
+    /* handle errors */
+    throw CDynamixelMotionSequenceException(_HERE_,"There is no motion sequence loaded");
+  }
+
+  return ratio;
+}
+
+CDynamixelMotorGroup::~CDynamixelMotorGroup()
+{
+  /* stop the motor */
+  this->stop();
+  /* stop any active sequence */
+  if(!this->event_server->event_is_set(this->sequence_complete_event_id))
+    this->stop_sequence();
+  /* stop the internal trhead */
+  this->event_server->set_event(this->finish_thread_event_id);
+  this->thread_server->end_thread(this->sequence_thread_id);
+  this->thread_server->detach_thread(this->sequence_thread_id);
+  this->thread_server->delete_thread(this->sequence_thread_id);
+  this->sequence_thread_id="";
+  this->event_server->set_event(this->finish_thread_event_id);
+  this->event_server->delete_event(this->finish_thread_event_id);
+  this->finish_thread_event_id="";
+  this->event_server->delete_event(this->start_sequence_event_id);
+  this->start_sequence_event_id="";
+  this->event_server->delete_event(this->stop_sequence_event_id);
+  this->stop_sequence_event_id="";
+  this->event_server->delete_event(this->pause_sequence_event_id);
+  this->pause_sequence_event_id="";
+  this->event_server->delete_event(this->resume_sequence_event_id);
+  this->resume_sequence_event_id="";
+  this->event_server->delete_event(this->sequence_complete_event_id);
+  this->sequence_complete_event_id="";
+  this->event_server->delete_event(this->sequence_error_event_id);
+  this->sequence_error_event_id="";
+  this->disable();
+  this->clear();
 }
diff --git a/src/dynamixel_motor_group.h b/src/dynamixel_motor_group.h
index b4c66067e0fcf293f34d65b95085defa0d192456..f9329a18cfbbdb7fa05e4d25edf77f3da5f0bc9e 100644
--- a/src/dynamixel_motor_group.h
+++ b/src/dynamixel_motor_group.h
@@ -2,26 +2,473 @@
 #define _DYNAMIXEL_MOTOR_GROUP_H
 
 #include "dynamixel_motor.h"
-#include "threadserver.h"
-#include "eventserver.h"
-#include "motor_group.h"
 #include "mutex.h"
 #include <vector>
 
-class CDynamixelMotorGroup  : public CMotorGroup
+typedef enum {mtn_empty,mtn_loaded,mtn_started,mtn_paused} TDynamixelMotionStates;
+
+typedef struct
+{
+  std::string bus_id;
+  unsigned int baudrate;
+  std::vector<unsigned char> id;
+  std::vector<std::string> config_files;
+}TDynamixelGroup_config;
+
+typedef struct
+{
+  std::vector<double> position;
+  std::vector<double> velocity;
+  bool absolute_motion;
+  double delay;
+}TDynamixelMotionStep;
+
+class CDynamixelMotorGroup 
 {
 
   private:
-    std::vector<unsigned char> servo_id;
-    std::vector<float> current_pos;
+    /**
+     * \brief 
+     *
+     */
+    std::string group_id;
+    /**
+     * \brief 
+     *
+     */
     CDynamixelServer *dyn_server;
+    /**
+     * \brief 
+     *
+     */
+    std::vector<CDynamixel *> dynamixel_dev;
+    /**
+     * \brief 
+     *
+     */   
+    std::vector<TDynamixel_compliance> compliance;
+    /**
+     * \brief 
+     *
+     */   
+    std::vector<TDynamixel_pid> pid;
+    /**
+     * \brief 
+     *
+     */   
+    std::vector<TDynamixel_config> config;
+    /**
+     * \brief 
+     *
+     */   
+    std::vector<TDynamixel_info> info;
+    /**
+     * \brief
+     *
+     */
+    std::vector<unsigned char> alarms;
+    /**
+     * \brief
+     *
+     */
+    control_mode mode;
+    /* thread attributes */
+    /**
+     * \brief
+     *
+     */
+    CThreadServer *thread_server;
+    /**
+     * \brief 
+     *
+     */
+    std::string sequence_thread_id;
+    /* event attributes */
+    /**
+     * \brief
+     *
+     */
+    CEventServer *event_server;
+    /**
+     * \brief
+     *
+     */
+    std::string finish_thread_event_id;
+    /**
+     * \brief 
+     *
+     */
+    std::string sequence_complete_event_id;
+    /**
+     * \brief 
+     *
+     */
+    std::string sequence_error_event_id;
+    /**
+     * \brief 
+     *
+     */
+    std::string start_sequence_event_id;
+    /**
+     * \brief 
+     *
+     */
+    std::string stop_sequence_event_id;
+    /**
+     * \brief 
+     *
+     */
+    std::string pause_sequence_event_id;
+    /**
+     * \brief 
+     *
+     */
+    std::string resume_sequence_event_id;
+    /**
+     * \brief
+     *
+     */
+    std::vector<unsigned char> servo_id;
+    /* Motion sequence attributes */
+    /**
+     * \brief 
+     *
+     */
+    TDynamixelMotionStates sequence_state;
+    /**
+     * \brief 
+     *
+     */
+    std::vector<TDynamixelMotionStep> seq;
+    /**
+     * \brief 
+     *
+     */
+    int sequence_current_step;
+    /**
+     * \brief 
+     *
+     */
+    std::string sequence_error_msg; 
+    /**
+     * \brief 
+     *
+     */
+    CMutex motion_access;
+  protected:
+    /**
+     * \brief
+     *
+     */
+    unsigned int from_angles(unsigned int index,double angle); 
+    /**
+     * \brief
+     *
+     */
+    unsigned int from_speeds(unsigned int index,double speed); 
+    /**
+     * \brief
+     *
+     */
+    double to_angles(unsigned int index,int unsigned counts); 
+    /**
+     * \brief
+     *
+     */
+    double to_speeds(unsigned int index,int unsigned counts); 
+    /**
+     * \brief 
+     *
+     */
+    void reset_motor(unsigned int index);
+    /**
+     * \brief 
+     *
+     */
+    void get_model(unsigned int index);
+    /**
+     * \brief 
+     *  
+     */ 
+    void set_position_range(unsigned int index,double min, double max);
+    /**
+     * \brief 
+     *
+     */ 
+    void get_position_range(unsigned int index,double *min, double *max);
+    /**
+     * \brief 
+     *  
+     */ 
+    void set_temperature_limit(unsigned int index,int limit);
+    /**
+     * \brief 
+     *  
+     */ 
+    int get_temperature_limit(unsigned int index);
+    /**
+     * \brief 
+     *  
+     */
+    void set_voltage_limits(unsigned int index,double min, double max);
+    /**
+     * \brief 
+     *  
+     */ 
+    void get_voltage_limits(unsigned int index,double *min, double *max);
+    /**
+     * \brief 
+     *  
+     */
+    unsigned char get_turn_off_alarms(unsigned int index); 
+    /**
+     * \brief 
+     *  
+     */
+    void set_max_torque(unsigned int index,double torque_ratio);
+    /**
+     * \brief 
+     *  
+     */
+    void set_limit_torque(unsigned int index,double torque_ratio);
+    /**
+     * \brief 
+     *  
+     */ 
+    double get_max_torque(unsigned int index);
+    /**
+     * \brief 
+     *  
+     */ 
+    void get_compliance_control(unsigned int index,TDynamixel_compliance &config);
+    /**
+     * \brief 
+     *  
+     */ 
+    void get_pid_control(unsigned int index,TDynamixel_pid &config);
+    /**
+     * \brief 
+     *
+     */
+    void init_motor(unsigned int id);
+    /**
+     * \brief 
+     *
+     */
+    void init_threads(void);
+    /**
+     * \brief 
+     *
+     */
+    void init_events(void);
+    /**
+     * \brief 
+     *
+     */
+    void clear(void);
+    /* motion sequence protected functions */
+    /**
+     * \brief 
+     *
+     */
+    static void *sequence_thread(void *param);
+    /**
+     * \brief 
+     *
+     */
+    int load_motion(unsigned int step_id);
   public: 
+    /**
+     * \brief
+     *
+     */
     CDynamixelMotorGroup(std::string &group_id);
-    void move(std::vector<float> &position,std::vector<float> &velocity,std::vector<float> &acceleration);	
-    std::string add_motor_control(CDynamixelMotor *controller);
-    void remove_motor_control(std::string &cont_id);    
+    /**
+     * \brief
+     *
+     */
+    CDynamixelMotorGroup(std::string &group_id,unsigned bus_id,int baudrate,std::vector<unsigned char> &ids);
+    /**
+     * \brief
+     *
+     */
+    CDynamixelMotorGroup(std::string &group_id,std::string &bus_id,int baudrate,std::vector<unsigned char> &ids);
+    /* configuration functions */
+    /**
+     * \brief
+     *
+     */
+    void load_config(TDynamixelGroup_config &config);
+#ifdef _HAVE_XSD
+    /**
+     * \brief 
+     *
+     */
+    void load_config(std::string &filename);
+    /**
+     * \brief 
+     *
+     */
+    void save_config(std::string &filename);
+#endif
+    /**
+     * \brief 
+     *  
+     */ 
+    void set_compliance_control(std::vector<TDynamixel_compliance> &config);
+    /**
+     * \brief 
+     *  
+     */ 
+    void set_pid_control(std::vector<TDynamixel_pid> &config);
+    /**
+     * \brief 
+     *
+     */
+    void enable(void);
+    /**
+     * \brief 
+     *
+     */
+    void disable(void);
+    /**
+     * \brief 
+     *
+     */ 
+    void move_absolute_angle(std::vector<double> &angles, std::vector<double> &speeds);
+    /**
+     * \brief 
+     *
+     */
+    void move_relative_angle(std::vector<double> &angles, std::vector<double> &speeds);
+    /**
+     * \brief 
+     *
+     */
+    void move_torque(std::vector<double> &torque_ratios);
+    /**
+     * \brief 
+     *
+     */
+    void stop(void);
+    /**
+     * \brief 
+     *  
+     */
+    void get_current_angle(std::vector<double> &angles); 
+    /**
+     * \brief 
+     *  
+     */
+    void get_current_speed(std::vector<double> &speeds); 
+    /**
+     * \brief 
+     *  
+     */ 
+    void get_current_effort(std::vector<double> &efforts);
+    /**
+     * \brief 
+     *  
+     */ 
+    void get_current_voltage(std::vector<double> &voltages);
+    /**
+     * \brief 
+     *  
+     */ 
+    void get_current_temperature(std::vector<double> &temperatures);
+    /**
+     * \brief 
+     *
+     */
+    unsigned int get_num_motors(void);
+    /* motion sequence public functions */
+    /**
+     * \brief 
+     *
+     */
+    TDynamixelMotionStates get_sequence_current_state(void);
+#ifdef _HAVE_XSD
+    /**
+     * \brief 
+     *
+     */
+    void load_sequence(std::string &filename);
+    /**
+     * \brief 
+     *
+     */
+    void save_sequence(std::string &filename);
+#endif
+    /**
+     * \brief 
+     *
+     */
+    void add_sequence_step(std::vector<double> &pos,std::vector<double> &vel,double delay=0.0,bool abs_motion=true);
+    /**
+     * \brief 
+     *
+     */
+    void insert_sequence_step(unsigned int index,std::vector<double> &pos,std::vector<double> &vel,double delay=0.0,bool abs_motion=true);
+    /**
+     * \brief 
+     *
+     */
+    void delete_sequence_step(unsigned int index);
+    /**
+     * \brief 
+     *
+     */
+    void clear_sequence(void);
+    /**
+     * \brief 
+     *
+     */
+    void start_sequence(void);
+    /**
+     * \brief 
+     *
+     */
+    void pause_sequence(void);
+    /**
+     * \brief 
+     *
+     */
+    void resume_sequence(void);
+    /**
+     * \brief 
+     *
+     */
+    void stop_sequence(void);
+    /**
+     * \brief 
+     *
+     */
+    std::string get_sequence_complete_event_id(void);
+    /**
+     * \brief 
+     *
+     */
+    std::string get_sequence_error_event_id(void);
+    /**
+     * \brief 
+     *
+     */
+    std::string get_sequence_error_message(void);
+    /**
+     * \brief 
+     *
+     */
+    int get_sequence_current_step(void);
+    /**
+     * \brief 
+     *
+     */
+    double get_sequence_completed_percentage(void);
+    /**
+     * \brief 
+     *  
+     */ 
     virtual ~CDynamixelMotorGroup();
 };
 
-
 #endif
diff --git a/src/examples/CMakeLists.txt b/src/examples/CMakeLists.txt
index f9d55000831510d397cdd77bca238071c1bdc62a..d9cd6210087bde801f80bb1799652b5129eb4830 100644
--- a/src/examples/CMakeLists.txt
+++ b/src/examples/CMakeLists.txt
@@ -2,40 +2,16 @@
 ADD_EXECUTABLE(test_dynamixel_motor test_dynamixel_motor.cpp)
 
 # edit the following line to add the necessary libraries
-TARGET_LINK_LIBRARIES(test_dynamixel_motor dynamixel_motor_cont ${comm_LIBRARY} ${motor_control_LIBRARY})
-
-# edit the following line to add the source code for the example and the name of the executable
-ADD_EXECUTABLE(test_dynamixel_motor_scan test_dynamixel_motor_scan.cpp)
-
-# edit the following line to add the necessary libraries
-TARGET_LINK_LIBRARIES(test_dynamixel_motor_scan dynamixel_motor_cont ${comm_LIBRARY} ${motor_control_LIBRARY})
-
-# edit the following line to add the source code for the example and the name of the executable
-ADD_EXECUTABLE(test_sequence test_sequence.cpp)
-
-# edit the following line to add the necessary libraries
-TARGET_LINK_LIBRARIES(test_sequence dynamixel_motor_cont ${comm_LIBRARY} ${motor_control_LIBRARY})
+TARGET_LINK_LIBRARIES(test_dynamixel_motor dynamixel_motor_cont ${comm_LIBRARY})
 
 # edit the following line to add the source code for the example and the name of the executable
 ADD_EXECUTABLE(test_dynamixel_motor_group test_dynamixel_motor_group.cpp)
 
 # edit the following line to add the necessary libraries
-TARGET_LINK_LIBRARIES(test_dynamixel_motor_group dynamixel_motor_cont ${comm_LIBRARY} ${motor_control_LIBRARY})
-
-# edit the following line to add the source code for the example and the name of the executable
-ADD_EXECUTABLE(test_dynamixel_motor_open_loop test_dynamixel_motor_open_loop.cpp)
-
-# edit the following line to add the necessary libraries
-TARGET_LINK_LIBRARIES(test_dynamixel_motor_open_loop dynamixel_motor_cont ${comm_LIBRARY} ${motor_control_LIBRARY})
-
-# edit the following line to add the source code for the example and the name of the executable
-ADD_EXECUTABLE(test_dynamixel_motor_group_open_loop test_dynamixel_motor_group_open_loop.cpp)
-
-# edit the following line to add the necessary libraries
-TARGET_LINK_LIBRARIES(test_dynamixel_motor_group_open_loop dynamixel_motor_cont ${comm_LIBRARY} ${motor_control_LIBRARY})
+TARGET_LINK_LIBRARIES(test_dynamixel_motor_group dynamixel_motor_cont ${comm_LIBRARY})
 
 # edit the following line to add the source code for the example and the name of the executable
-ADD_EXECUTABLE(test_sequence_open_loop test_sequence_open_loop.cpp)
+ADD_EXECUTABLE(test_dynamixel_motion_seq test_dynamixel_motion_seq.cpp)
 
 # edit the following line to add the necessary libraries
-TARGET_LINK_LIBRARIES(test_sequence_open_loop dynamixel_motor_cont ${comm_LIBRARY} ${motor_control_LIBRARY})
+TARGET_LINK_LIBRARIES(test_dynamixel_motion_seq dynamixel_motor_cont ${comm_LIBRARY})
diff --git a/src/examples/test_dynamixel_motion_seq.cpp b/src/examples/test_dynamixel_motion_seq.cpp
new file mode 100755
index 0000000000000000000000000000000000000000..c7266485269dfe2f1401f1d3c498c9c31dffccb1
--- /dev/null
+++ b/src/examples/test_dynamixel_motion_seq.cpp
@@ -0,0 +1,40 @@
+#include "dynamixelexceptions.h"
+#include "dynamixelserver.h"
+#include "eventserver.h"
+#include "exceptions.h"
+#include "dynamixel_motor_group.h"
+#include "dynamixel_motor.h"
+#include <iostream>
+#include <math.h>
+
+std::string sequence_filename="../src/xml/sequence1.xml";
+
+std::string group_name="GROUP1";
+
+std::string config_file="../src/xml/dyn_group_config.xml";
+
+int main(int argc, char *argv[])
+{
+  CDynamixelServer *dyn_server=CDynamixelServer::instance();
+  CEventServer *event_server=CEventServer::instance();
+  std::vector<double> angles,speeds;
+  CDynamixelMotorGroup group(group_name);
+
+  try{
+    if(dyn_server->get_num_buses()>0)
+    {
+      group.load_config(config_file);
+      group.load_sequence(sequence_filename);
+      group.start_sequence();
+      while(!event_server->event_is_set(group.get_sequence_complete_event_id()))
+      {
+        std::cout << group.get_sequence_completed_percentage() << "% of sequence completed" << std::endl;
+        usleep(200000);
+      }
+    }
+  }catch(CException &e){
+    std::cout << e.what() << std::endl;
+  }
+}
+
+
diff --git a/src/examples/test_dynamixel_motor.cpp b/src/examples/test_dynamixel_motor.cpp
index 20e81b32cf50724a585c0b22640a626fdaac9b41..df7663f3349fbc1524449d977a3e4a82d71ee699 100755
--- a/src/examples/test_dynamixel_motor.cpp
+++ b/src/examples/test_dynamixel_motor.cpp
@@ -1,102 +1,108 @@
 #include "dynamixelexceptions.h"
 #include "dynamixelserver.h"
-#include "eventserver.h"
 #include "exceptions.h"
 #include "dynamixel_motor.h"
 #include <iostream>
 
-std::string cont2_name="AX-12+_2";
-std::string cont3_name="AX-12+_3";
-std::string cont_config_file="../src/xml/base_dyn_config.xml";
+std::string cont_name="RX-28";
+std::string config_file="../src/xml/dyn_config.xml";
 
 int main(int argc, char *argv[])
 {
   CDynamixelServer *dyn_server=CDynamixelServer::instance();
-  CEventServer *event_server=CEventServer::instance();
-  std::list<std::string> events1,events2,events3;
-  CDynamixelMotor *cont2,*cont3;
-  std::vector<float> pos1(1),vel1(1),acc1(1),pos0(1);
-  std::vector<float> pos2(1),max(1),min(1);
-  std::vector<float> position(1);
-  std::vector<bool> enable(1);
-  std::string serial="A400gaIt";
+  CDynamixelMotor *cont;
+  std::string serial="A4012B3G";
+  TDynamixel_info info;
+  double max_angle,min_angle;
+  unsigned char led_alarms,sd_alarms;
+  TDynamixel_compliance compliance;
+  TDynamixel_pid pid;
 
-  try{
+  try
+  {
     if(dyn_server->get_num_buses()>0)
     {
-      cont2=new CDynamixelMotor(cont2_name,serial,1000000,1);
-      cont2->close();
-      delete cont2;
-      cont2=new CDynamixelMotor(cont2_name,serial,1000000,1);
-      enable[0]=true;
-      cont2->enable(enable);
-#ifdef _HAVE_XSD
-      cont2->load_config(cont_config_file);
-      events2.push_back(cont2->get_position_feedback_event());
-#else
-      events2.push_back(cont2->config_position_feedback(fb_polling,100.0));
-#endif
-      cont2->set_torque(100.0);
-//      cont3=new CDynamixelMotor(cont3_name,serial,1000000,21);
-//      enable[0]=true;
-//      cont3->enable(enable);
-//#ifdef _HAVE_XSD
-//      cont3->load_config(cont_config_file);
-//      events3.push_back(cont3->get_position_feedback_event());
-//#else
-//      events3.push_back(cont3->config_position_feedback(fb_polling,100.0));
-//#endif
-      position=cont2->get_position();
-      std::cout << "Current position of device 1: " << position[0] << std::endl;
-//      position=cont3->get_position();
-//      std::cout << "Current position of device 15: " << position[0] << std::endl;
-      vel1[0]=40.0;
-      pos0[0]=150.0;
-      acc1[0]=vel1[0]*vel1[0]/(0.05*pos0[0]);
-      event_server->wait_all(events2); 
-      std::cout << "centering ..." << std::endl;
-      cont2->load(pos0,vel1,acc1);
-      cont2->move();
-//      event_server->wait_all(events3); 
-//      std::cout << "centering ..." << std::endl;
-//      cont3->load(pos0,vel1,acc1);
-//      cont3->move();
-      sleep(2);
+      cont = new CDynamixelMotor(cont_name, serial, 1000000, 23);
 
-      pos1[0]=170.0;
-      pos2[0]=125.0;
-      for(;;) 
+      cont->get_servo_info(info);
+      std::cout << "[INFO]: Servo model: " << info.model << std::endl;
+      std::cout << "[INFO]: Firmware version: " << (int)info.firmware_ver << std::endl;
+      std::cout << "[INFO]: Gear ratio: " << info.gear_ratio << std::endl;
+      std::cout << "[INFO]: Encoder resolution: " << info.encoder_resolution << " counts" << std::endl;
+      if(info.pid_control)
       {
-        event_server->wait_all(events2); 
-        std::cout << "servo 1 moving left ..." << std::endl;
-        cont2->load(pos1,vel1,acc1);
-        cont2->move();
-        event_server->wait_all(events2); 
-        std::cout << "servo 1 moving right ..." << std::endl;
-        cont2->load(pos2,vel1,acc1);
-        cont2->move();
-        event_server->wait_all(events2); 
-        std::cout << "servo 1 centering ..." << std::endl;
-        cont2->load(pos0,vel1,acc1);
-        cont2->move();
-        sleep(1);
-//        event_server->wait_all(events3); 
-//        std::cout << "servo 2 moving left ..." << std::endl;
-//        cont3->load(pos1,vel1,acc1);
-//        cont3->move();
-//        event_server->wait_all(events3); 
-//        std::cout << "servo 2 moving right ..." << std::endl;
-//        cont3->load(pos2,vel1,acc1);
-//        cont3->move();
-//        event_server->wait_all(events3); 
-//        std::cout << "servo 2 centering ..." << std::endl;
-//        cont3->load(pos0,vel1,acc1);
-//        cont3->move();
-//        sleep(1);
+	std::cout << "[INFO]: PID control capable" << std::endl;
+	pid.p=10;
+	pid.i=20;
+	pid.d=30;
+	cont->set_pid_control(pid);
+	cont->get_pid_control(pid);
+	std::cout << "[INFO]: PID control: (" << (int)pid.p << "," << (int)pid.i << "," << (int)pid.d << ")" << std::endl;
+      }
+      else
+      {
+	std::cout << "[INFO]: Compliance control capable" << std::endl;
+	cont->get_compliance_control(compliance);
+	std::cout << "[INFO]: Compliance margin: (" << std::dec << (int)compliance.cw_compliance_margin << "," << (int)compliance.ccw_compliance_margin << ")" << std::endl;
+	std::cout << "[INFO]: Compliance slope: (" << std::dec << (int)compliance.cw_compliance_slope << "," << (int)compliance.ccw_compliance_slope << ")" << std::endl;
+      }
+      std::cout << "[INFO]: Maximum angle: " << info.max_angle << " degrees" << std::endl;
+      std::cout << "[INFO]: Center angle: " << info.center_angle << " degrees" << std::endl;
+      std::cout << "[INFO]: Maximum speed: " << info.max_speed << " degress/s" << std::endl;
+      std::cout << "[INFO]: Bus identifier: " << info.bus_id << std::endl;
+      std::cout << "[INFO]: Bus baudrate: " << info.baudrate << " bps" << std::endl;
+      std::cout << "[INFO]: Servo identifier: " << (int)info.id << std::endl;
+      cont->get_position_range(&min_angle,&max_angle);
+      std::cout << "[INFO]: Angle range: (" << min_angle << "," << max_angle << ")" << std::endl;
+      sd_alarms = cont->get_turn_off_alarms();
+      std::cout << "[INFO]: Shutdown alarm flags: " << std::hex << (int)sd_alarms << std::endl;
+      std::cout << "[INFO]: - Input Voltage Error:\t" << bool(sd_alarms&0x01) << std::endl;
+      std::cout << "[INFO]: - Angle Limit Error:\t"   << bool(sd_alarms&0x02) << std::endl;
+      std::cout << "[INFO]: - OverHeating Error:\t"   << bool(sd_alarms&0x04) << std::endl;
+      std::cout << "[INFO]: - Range Error:\t\t"       << bool(sd_alarms&0x08) << std::endl;
+      std::cout << "[INFO]: - CheckSum Error:\t"    << bool(sd_alarms&0x10) << std::endl;
+      std::cout << "[INFO]: - Overload Error:\t"    << bool(sd_alarms&0x20) << std::endl;
+      std::cout << "[INFO]: - Instruction Error:\t"   << bool(sd_alarms&0x40) << std::endl;
+      led_alarms=cont->get_led_alarms();
+      std::cout << "[INFO]: LED alarm flags: " << std::hex << (int)led_alarms << std::endl;
+      std::cout << "[INFO]: Punch: " << std::dec << (int)compliance.punch << std::endl;
+      cont->turn_led_on();
+      sleep(1);
+      cont->turn_led_off();
+      //      cont->move_absolute_angle(-90,300);
+      //      sleep(2);
+      //      cont->move_absolute_angle(90,100);
+      //      sleep(2);
+      //      cont->move_relative_angle(-5,100);
+      //      sleep(1);
+      //      cont->move_relative_angle(-5,100);
+      //      sleep(1);
+      //      cont->move_relative_angle(-5,100);
+      //      sleep(1);
+      //      cont->move_relative_angle(-5,100);
+      //      sleep(1);
+      //      cont->move_relative_angle(-5,100);
+      //      sleep(1);
+      //      cont->move_relative_angle(-5,100);
+      //      sleep(1);
+      //      cont->move_torque(50);
+      //      sleep(5);
+      //      cont->move_torque(-50);
+      //      sleep(5);
+      for (size_t aa = 0; aa < 100; ++aa)
+      {
+	try
+	{
+	  cont->move_absolute_angle(125.0, 250);
+	  sleep(2);
+	  cont->move_absolute_angle(-125.0, 250);
+	  sleep(2);
+	}catch(CDynamixelAlarmException &e){
+	  std::cout << "[Alarm exception]: " << e.what() << std::endl;
+	}
       }
     }
   }catch(CException &e){
-    std::cout << e.what() << std::endl;
-  }
+    std::cout << "[Genereal exception]: " << e.what() << std::endl; }
   return 0; 
 }
diff --git a/src/examples/test_dynamixel_motor_group.cpp b/src/examples/test_dynamixel_motor_group.cpp
index 10bcd592f9a69272a81cd492e3a547264a1220bf..0f026e88f4bb78291f2d217f0e4db2d5db26f41a 100644
--- a/src/examples/test_dynamixel_motor_group.cpp
+++ b/src/examples/test_dynamixel_motor_group.cpp
@@ -7,71 +7,49 @@
 #include <iostream>
 #include <math.h>
 
-std::string cont1_name="AX-12+_1";
-std::string cont2_name="AX-12+_2";
-std::string cont3_name="AX-12+_3";
-std::string cont4_name="AX-12+_4";
 std::string group_name="GROUP1";
 
-std::string config_file="../src/xml/base_dyn_config.xml";
+std::string config_file="../src/xml/dyn_group_config.xml";
 
 int main(int argc, char *argv[])
 {
   CDynamixelServer *dyn_server=CDynamixelServer::instance();
-  CEventServer *event_server=CEventServer::instance();
-  std::vector<float> pos(2),vel(2),acc(2);
-  std::vector<bool> enable(2,true);
-  std::list<std::string> events;
-  CDynamixelMotor *cont1,*cont2;
-  CDynamixelMotorGroup *group;
+  std::vector<double> angles,speeds,torques;
+  CDynamixelMotorGroup group(group_name);
   unsigned int i=0;
-  std::string name;
 
   try{
     if(dyn_server->get_num_buses()>0)
     {
-      cont1=new CDynamixelMotor(cont1_name,0,1000000,21);
-      cont2=new CDynamixelMotor(cont2_name,0,1000000,11);
-      cont1->set_compliance_slope(254,254);
-      cont1->set_punch(4);
-      cont1->set_compliance_margin(1,1);
-      cont2->set_compliance_slope(254,254);
-      cont2->set_punch(16);
-      cont2->set_compliance_margin(1,1);
-
-      group=new CDynamixelMotorGroup(group_name);
-      name=group->add_motor_control(cont1);
-      #ifdef _HAVE_XSD
-      group->config_motor_control(name,config_file);
-      #endif
-      name=group->add_motor_control(cont2);
-      #ifdef _HAVE_XSD
-      group->config_motor_control(name,config_file);
-      #endif
-
-      group->get_position(pos);
-      group->enable(enable);
-      group->use_closed_loop_control();
-      events.push_back(group->get_position_reached_event_id());
-      pos[0]=150.0;
-      pos[1]=150.0;
-      vel[0]=100.0;
-      vel[1]=100.0;
-      acc[0]=vel[0]*vel[0]/(0.2*50);
-      acc[1]=vel[1]*vel[1]/(0.2*50);
-      event_server->wait_all(events);
-      group->move(pos,vel,acc);
+      group.load_config(config_file);
+      angles.resize(2);
+      angles[0]=90;
+      angles[1]=-90;
+      speeds.resize(2);
+      speeds[0]=100;
+      speeds[1]=50;
+      group.move_absolute_angle(angles,speeds);
+      sleep(5);      
+      angles.resize(2);
+      angles[0]=-90;
+      angles[1]=90;
+      group.move_absolute_angle(angles,speeds);
+      sleep(5);      
+      // relative motion
+      angles[0]=10;
+      angles[1]=-10;
       for(i=0;i<10;i++)
       {
-        pos[0]=100;
-        pos[1]=100;
-        event_server->wait_all(events);
-        group->move(pos,vel,acc);
-        pos[0]=200;
-        pos[1]=200;
-        event_server->wait_all(events);
-        group->move(pos,vel,acc);
-      } 
+        group.move_relative_angle(angles,speeds);
+        sleep(1);
+      }
+      // torque motion
+      torques.resize(2);
+      torques[0]=100.0;
+      torques[1]=-50;
+      group.move_torque(torques);
+      sleep(4);
+      group.stop();
     }
   }catch(CException &e){
     std::cout << e.what() << std::endl;
diff --git a/src/examples/test_dynamixel_motor_group_open_loop.cpp b/src/examples/test_dynamixel_motor_group_open_loop.cpp
deleted file mode 100755
index 59d4266495d78b130fa1505239ab0c5c83e51705..0000000000000000000000000000000000000000
--- a/src/examples/test_dynamixel_motor_group_open_loop.cpp
+++ /dev/null
@@ -1,88 +0,0 @@
-#include "dynamixelexceptions.h"
-#include "dynamixelserver.h"
-#include "eventserver.h"
-#include "exceptions.h"
-#include "dynamixel_motor_group.h"
-#include "dynamixel_motor.h"
-#include <iostream>
-#include <math.h>
-
-std::string cont1_name="AX-12+_1";
-std::string cont2_name="AX-12+_2";
-std::string group_name="GROUP1";
-
-int main(int argc, char *argv[])
-{
-  CDynamixelServer *dyn_server=CDynamixelServer::instance();
-  CEventServer *event_server=CEventServer::instance();
-  std::vector<float> pos(2),vel(2),acc(2);
-  std::vector<bool> enable(2,true);
-  std::list<std::string> events;
-  CDynamixelMotor *cont1,*cont2;
-  CDynamixelMotorGroup *group;
-  unsigned int i=0,j=0;
-  int dir=1;
-
-  try{
-    if(dyn_server->get_num_buses()>0)
-    {
-      cont1=new CDynamixelMotor(cont1_name,0,1000000,21);
-      cont2=new CDynamixelMotor(cont2_name,0,1000000,11);
-      cont1->set_compliance_slope(254,254);
-      cont1->set_punch(4);
-      cont1->set_compliance_margin(1,1);
-      cont2->set_compliance_slope(254,254);
-      cont2->set_punch(16);
-      cont2->set_compliance_margin(1,1);
-
-      group=new CDynamixelMotorGroup(group_name);
-      group->add_motor_control(cont1);
-      group->add_motor_control(cont2);
-      group->enable(enable);
-      group->use_open_loop_control();
-      pos[0]=150.0;
-      pos[1]=150.0;
-      group->move(pos,vel,acc);
-      sleep(2);
-      for(j=0;j<1000;j++)
-      {
-	if(pos[0]>=290)
-	  dir=-1;
-	else if(pos[0]<=10)
-	  dir=1;	  
-	for(i=0;i<pos.size();i++)
-	{
-	  pos[i]+=1.5*dir;      
-	}
-	group->move(pos,vel,acc);
-	usleep(20000);
-      }
-      group->use_closed_loop_control();
-      events.push_back(group->get_position_reached_event_id());
-      pos[0]=150.0;
-      pos[1]=150.0;
-      vel[0]=100.0;
-      vel[1]=100.0;
-      acc[0]=vel[0]*vel[0]/(0.2*50);
-      acc[1]=vel[1]*vel[1]/(0.2*50);
-      event_server->wait_all(events);
-      group->move(pos,vel,acc);
-      for(i=0;i<10;i++)
-      {
-        pos[0]=100;
-        pos[1]=100;
-        event_server->wait_all(events);
-        group->move(pos,vel,acc);
-        pos[0]=200;
-        pos[1]=200;
-        event_server->wait_all(events);
-        group->move(pos,vel,acc);
-      }
-
-    }
-  }catch(CException &e){
-    std::cout << e.what() << std::endl;
-  }
-}
-
-
diff --git a/src/examples/test_dynamixel_motor_open_loop.cpp b/src/examples/test_dynamixel_motor_open_loop.cpp
deleted file mode 100755
index 6bf2c8b1e12e54059fc44c414bbf3956cfa851ad..0000000000000000000000000000000000000000
--- a/src/examples/test_dynamixel_motor_open_loop.cpp
+++ /dev/null
@@ -1,146 +0,0 @@
-#include "dynamixelexceptions.h"
-#include "dynamixelserver.h"
-#include "eventserver.h"
-#include "exceptions.h"
-#include "dynamixel_motor.h"
-#include <iostream>
-
-std::string cont2_name="AX-12+_2";
-std::string cont3_name="AX-12+_3";
-std::string cont_config_file="../src/xml/base_dyn_config.xml";
-
-int main(int argc, char *argv[])
-{
-  CDynamixelServer *dyn_server=CDynamixelServer::instance();
-  CEventServer *event_server=CEventServer::instance();
-  std::list<std::string> events1,events2,events3;
-  CDynamixelMotor *cont2,*cont3;
-  std::vector<float> pos1(1),vel1(1),acc1(1),pos0(1);
-  std::vector<float> pos2(1),max(1),min(1);
-  std::vector<float> position(1);
-  std::vector<bool> enable(1);
-  int i=0;
-
-  try{
-    if(dyn_server->get_num_buses()>0)
-    {
-      cont2=new CDynamixelMotor(cont2_name,0,1000000,11);
-      cont2->close();
-      delete cont2;
-      cont2=new CDynamixelMotor(cont2_name,0,1000000,11);
-      enable[0]=true;
-      cont2->enable(enable);
-#ifdef _HAVE_XSD
-      cont2->load_config(cont_config_file);
-      events2.push_back(cont2->get_position_feedback_event());
-#else
-      events2.push_back(cont2->config_position_feedback(fb_polling,100.0));
-#endif
-      cont2->set_torque(100.0);
-      cont3=new CDynamixelMotor(cont3_name,0,1000000,21);
-      enable[0]=true;
-      cont3->enable(enable);
-#ifdef _HAVE_XSD
-      cont3->load_config(cont_config_file);
-      events3.push_back(cont3->get_position_feedback_event());
-#else
-      events3.push_back(cont3->config_position_feedback(fb_polling,100.0));
-#endif
-      position=cont2->get_position();
-      std::cout << "Current position of device 1: " << position[0] << std::endl;
-      position=cont3->get_position();
-      std::cout << "Current position of device 15: " << position[0] << std::endl;
-      vel1[0]=40.0;
-      pos0[0]=150.0;
-      acc1[0]=vel1[0]*vel1[0]/(0.05*pos0[0]);
-      event_server->wait_all(events2); 
-      std::cout << "centering ..." << std::endl;
-      cont2->load(pos0,vel1,acc1);
-      cont2->move();
-      event_server->wait_all(events3); 
-      std::cout << "centering ..." << std::endl;
-      cont3->load(pos0,vel1,acc1);
-      cont3->move();
-      sleep(2);
-      // set open loop mode
-
-      pos1[0]=190.0;
-      pos2[0]=110.0;
-      for(;;)
-      {
-      std::cout << "open loop control" << std::endl;
-      cont2->use_open_loop_control();
-      cont3->use_open_loop_control();
-      for(;;) 
-      {
-//        event_server->wait_all(events2); 
-        std::cout << "servo 1 moving left ..." << std::endl;
-        cont2->load(pos1,vel1,acc1);
-        cont2->move();
-        sleep(1);
-//        event_server->wait_all(events2); 
-        std::cout << "servo 1 moving right ..." << std::endl;
-        cont2->load(pos2,vel1,acc1);
-        cont2->move();
-        sleep(2);
-//        event_server->wait_all(events2); 
-        std::cout << "servo 1 centering ..." << std::endl;
-        cont2->load(pos0,vel1,acc1);
-        cont2->move();
-        sleep(1);
-//        event_server->wait_all(events3); 
-        std::cout << "servo 2 moving left ..." << std::endl;
-        cont3->load(pos1,vel1,acc1);
-        cont3->move();
-        sleep(1);
-//        event_server->wait_all(events3); 
-        std::cout << "servo 2 moving right ..." << std::endl;
-        cont3->load(pos2,vel1,acc1);
-        cont3->move();
-        sleep(2);
-//        event_server->wait_all(events3); 
-        std::cout << "servo 2 centering ..." << std::endl;
-        cont3->load(pos0,vel1,acc1);
-        cont3->move();
-        sleep(1);
-      }
-
-      std::cout << "closed loop control" << std::endl;
-      cont2->use_closed_loop_control();
-      cont3->use_closed_loop_control();
-
-      for(i=0;i<1;i++)
-      {
-        event_server->wait_all(events2); 
-        std::cout << "servo 1 moving left ..." << std::endl;
-        cont2->load(pos1,vel1,acc1);
-        cont2->move();
-        event_server->wait_all(events2); 
-        std::cout << "servo 1 moving right ..." << std::endl;
-        cont2->load(pos2,vel1,acc1);
-        cont2->move();
-        event_server->wait_all(events2); 
-        std::cout << "servo 1 centering ..." << std::endl;
-        cont2->load(pos0,vel1,acc1);
-        cont2->move();
-        event_server->wait_all(events3); 
-        std::cout << "servo 2 moving left ..." << std::endl;
-        cont3->load(pos1,vel1,acc1);
-        cont3->move();
-        event_server->wait_all(events3); 
-        std::cout << "servo 2 moving right ..." << std::endl;
-        cont3->load(pos2,vel1,acc1);
-        cont3->move();
-        event_server->wait_all(events3); 
-        std::cout << "servo 2 centering ..." << std::endl;
-        cont3->load(pos0,vel1,acc1);
-        cont3->move();
-      }
-      sleep(1);
-      }
-    }
-  }catch(CException &e){
-    std::cout << e.what() << std::endl;
-  }
-  return 0; 
-}
diff --git a/src/examples/test_dynamixel_motor_scan.cpp b/src/examples/test_dynamixel_motor_scan.cpp
deleted file mode 100755
index 04d54e29ff82691340fdd0f6430af974017a8aba..0000000000000000000000000000000000000000
--- a/src/examples/test_dynamixel_motor_scan.cpp
+++ /dev/null
@@ -1,52 +0,0 @@
-#include "dynamixelexceptions.h"
-#include "dynamixelserver.h"
-#include "eventserver.h"
-#include "exceptions.h"
-#include "dynamixel_motor.h"
-#include <iostream>
-
-std::string cont1_name="AX-12+_1";
-std::string cont2_name="AX-12+_2";
-
-int main(int argc, char *argv[])
-{
-  CDynamixelServer *dyn_server=CDynamixelServer::instance();
-  CEventServer *event_server=CEventServer::instance();
-  std::vector<std::string> motion_done_1;
-  std::vector<int> ids;
-  std::list<std::string> events;
-  CDynamixelMotor *cont1;
-  std::vector<float> pos1(1),vel1(1),acc1(1),pos0(1);
-  std::vector<float> pos2(1),max(1),min(1);
-  std::vector<float> position(1);
-  std::vector<bool> enable(1);
-  int i=0;
-
-  try{
-    if(dyn_server->get_num_buses()>0)
-    {
-      events.push_back(dyn_server->get_scan_done_event_id());
-      dyn_server->config_bus(0,1000000);
-      dyn_server->start_scan();
-      event_server->wait_first(events);
-      std::cout << "Found " << dyn_server->get_num_devices() << " devices" << std::endl;
-      ids=dyn_server->get_device_ids();
-      for(i=0;i<dyn_server->get_num_devices();i++)
-        std::cout << "Device " << i << " -> id: " << ids[i] << std::endl;
-      cont1=new CDynamixelMotor(cont1_name,0,dyn_server->get_baudrate(),ids[0]);
-      cont1->enable(enable);
-      cont1->enable_torque_control();
-      position=cont1->get_position();
-      std::cout << "Current position of device " << ids[0] << ": " << position[0] << std::endl;
-      cont1->set_torque(100.0);
-      sleep(2);
-      cont1->set_torque(-100.0);
-      sleep(2);
-      cont1->set_torque(0.0);
-    }
-  }catch(CException &e){
-    std::cout << e.what() << std::endl;
-  }
-
-  return 0;
-}
diff --git a/src/examples/test_sequence.cpp b/src/examples/test_sequence.cpp
deleted file mode 100755
index 6b446da0e653170d5478edb51d03aa16f044299e..0000000000000000000000000000000000000000
--- a/src/examples/test_sequence.cpp
+++ /dev/null
@@ -1,92 +0,0 @@
-#include "motion_sequence.h"
-#include "eventserver.h"
-#include "exceptions.h"
-#include "dynamixel_motor.h"
-#include "motor_group.h"
-#include <math.h>
-
-std::string cont_name1="AX-12+_1";
-std::string cont_name2="AX-12+_2";
-std::string cont_name3="AX-12+_3";
-std::string seq_name="test_sequence";
-std::string seq_file="../src/xml/test_motion.xml";
-std::string seq_file2="../src/xml/test_motion2.xml";
-std::string seq_file3="../src/xml/test_motion3.xml";
-std::string group_name="test";
-std::string cont_config_file="../src/xml/base_dyn_config.xml";
-
-int main(int argc, char * argv[])
-{
-  try{
-#ifdef _HAVE_XSD
-    CEventServer *event_server=CEventServer::instance();
-#endif
-    std::list<std::string> events;
-    CMotorGroup group(group_name);
-    CMotionSequence sequence(seq_name);
-    CDynamixelMotor cont1(cont_name1,0,1000000,1);
-    CDynamixelMotor cont2(cont_name2,0,1000000,12);
-    CDynamixelMotor cont3(cont_name3,0,1000000,15);
-    std::vector<float> position(3);
-    std::vector<float> velocity(3);
-
-    events.push_back(sequence.get_sequence_complete_event_id());
-#ifdef _HAVE_XSD
-    cont1.load_config(cont_config_file);
-    cont2.load_config(cont_config_file);
-    cont3.load_config(cont_config_file);
-#endif
-    group.add_motor_control(&cont1);
-    group.add_motor_control(&cont2);
-    group.add_motor_control(&cont3);
-    sequence.set_motor_group(&group);
-#ifdef _HAVE_XSD
-    sequence.load_sequence(seq_file);
-    sequence.set_timeout_factor(1.5);
-    sequence.start_sequence();
-    while(!event_server->event_is_set(sequence.get_sequence_complete_event_id()))
-    {
-      std::cout << sequence.get_completed_percentage() << "% of sequence completed" << std::endl;
-      usleep(200000);
-    }
-    sequence.start_sequence();
-    while(!event_server->event_is_set(sequence.get_sequence_complete_event_id()))
-    {
-      std::cout << sequence.get_completed_percentage() << "% of sequence completed" << std::endl;
-      usleep(200000);
-    }
-    sequence.load_sequence(seq_file2);
-    position[0]=100;
-    position[1]=200;
-    position[2]=100;
-    velocity[0]=50;
-    velocity[1]=50;
-    velocity[2]=50;
-    sequence.add_step(position,velocity,0);
-    position[0]=200;
-    position[1]=100;
-    position[2]=200;
-    sequence.add_step(position,velocity,2000);
-    position[0]=100;
-    position[1]=200;
-    position[2]=100;
-    sequence.add_step(position,velocity,0);
-    position[0]=0;
-    position[1]=0;
-    position[2]=0;
-    sequence.insert_step(0,position,velocity,0);
-    sequence.start_sequence();
-    while(!event_server->event_is_set(sequence.get_sequence_complete_event_id()))
-    {
-      std::cout << sequence.get_completed_percentage() << "% of sequence completed" << std::endl;
-      usleep(200000);
-    }
-    sequence.save_sequence(seq_file3);
-#else
-    std::cout << "Impossible to execute sequence because the XML library is not available" << std::endl;
-#endif
-
-  }catch(CException &e){
-    std::cout << e.what() << std::endl;
-  }
-}
diff --git a/src/examples/test_sequence_open_loop.cpp b/src/examples/test_sequence_open_loop.cpp
deleted file mode 100755
index 820797c5092c18e47d2790be8934489ad7769ebf..0000000000000000000000000000000000000000
--- a/src/examples/test_sequence_open_loop.cpp
+++ /dev/null
@@ -1,89 +0,0 @@
-#include "motion_sequence.h"
-#include "eventserver.h"
-#include "exceptions.h"
-#include "dynamixel_motor.h"
-#include "dynamixel_motor_group.h"
-#include "motor_group.h"
-#include <math.h>
-
-std::string cont_name1="AX-12+_1";
-std::string cont_name2="AX-12+_2";
-std::string seq_name="test_sequence";
-std::string seq_file="../src/xml/test_motion.xml";
-std::string seq_file2="../src/xml/test_motion2.xml";
-std::string seq_file3="../src/xml/test_motion3.xml";
-std::string group_name="test";
-std::string cont_config_file="../src/xml/base_dyn_config.xml";
-
-int main(int argc, char * argv[])
-{
-  try{
-#ifdef _HAVE_XSD
-    CEventServer *event_server=CEventServer::instance();
-#endif
-    std::list<std::string> events;
-    CDynamixelMotorGroup group(group_name);
-    CMotionSequence sequence(seq_name);
-    CDynamixelMotor cont1(cont_name1,0,1000000,11);
-    CDynamixelMotor cont2(cont_name2,0,1000000,21);
-    std::vector<float> position(2);
-    std::vector<float> velocity(2);
-
-    events.push_back(sequence.get_sequence_complete_event_id());
-#ifdef _HAVE_XSD
-    cont1.load_config(cont_config_file);
-    cont2.load_config(cont_config_file);
-#endif
-    group.add_motor_control(&cont1);
-    group.add_motor_control(&cont2);
-    sequence.set_motor_group(&group);
-#ifdef _HAVE_XSD
-    sequence.load_sequence(seq_file);
-    sequence.set_timeout_factor(1.5);
-    sequence.start_sequence();
-    while(!event_server->event_is_set(sequence.get_sequence_complete_event_id()))
-    {
-      std::cout << sequence.get_completed_percentage() << "% of sequence completed" << std::endl;
-      usleep(200000);
-    }
-    sequence.start_sequence();
-    while(!event_server->event_is_set(sequence.get_sequence_complete_event_id()))
-    {
-      std::cout << sequence.get_completed_percentage() << "% of sequence completed" << std::endl;
-      usleep(200000);
-    }
-    sequence.load_sequence(seq_file2);
-    position[0]=100;
-    position[1]=200;
-    position[2]=100;
-    velocity[0]=50;
-    velocity[1]=50;
-    velocity[2]=50;
-    sequence.add_step(position,velocity,0);
-    position[0]=200;
-    position[1]=100;
-    position[2]=200;
-    sequence.add_step(position,velocity,2000);
-    position[0]=100;
-    position[1]=200;
-    position[2]=100;
-    sequence.add_step(position,velocity,0);
-    position[0]=0;
-    position[1]=0;
-    position[2]=0;
-    sequence.insert_step(0,position,velocity,0);
-    sequence.start_sequence();
-    while(!event_server->event_is_set(sequence.get_sequence_complete_event_id()))
-    {
-      std::cout << sequence.get_completed_percentage() << "% of sequence completed" << std::endl;
-      usleep(200000);
-    }
-    sequence.save_sequence(seq_file3);
-#else
-    std::cout << "Impossible to execute sequence because the XML library is not available" << std::endl;
-#endif
-
-  }catch(CException &e){
-    std::cout << e.what() << std::endl;
-  }
-}
diff --git a/src/xml/CMakeLists.txt b/src/xml/CMakeLists.txt
index 5112a622d9a4079523b6d3ffd162dbd8a57381bf..72bb23ab1f278fb9b59f512758b393baaa5733ba 100755
--- a/src/xml/CMakeLists.txt
+++ b/src/xml/CMakeLists.txt
@@ -13,7 +13,7 @@ ENDIF(EXISTS "/usr/include/xsd/cxx")
 
 IF(XSD_FOUND)
    SET(XSD_LIBRARY ${XSD_LIBRARY} PARENT_SCOPE)
-   SET(XSD_FILES dynamixel_motor_cfg_file.xsd)
+   SET(XSD_FILES dynamixel_motor_cfg_file.xsd dynamixel_motor_group_cfg_file.xsd dyn_motion_seq_file.xsd)
 
    IF(XSD_FILES)
       SET(XSD_PATH ${CMAKE_CURRENT_SOURCE_DIR})
@@ -34,7 +34,7 @@ IF(XSD_FOUND)
       ADD_CUSTOM_TARGET(xsd_files_gen DEPENDS ${XSD_SOURCES_INT})
       ADD_CUSTOM_COMMAND(
          OUTPUT ${XSD_SOURCES_INT}
-         COMMAND xsd cxx-tree --generate-serialization ${XSD_FILES}
+         COMMAND xsdcxx cxx-tree --generate-serialization ${XSD_FILES}
          WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
          DEPENDS ${XSD_PATH_FILES}
          COMMENT "Parsing the xml template file ${XSD_FILES}")
diff --git a/src/xml/base_dyn_config.xml b/src/xml/base_dyn_config.xml
deleted file mode 100755
index 401aa3e9255fca4993c338778c4272919c496442..0000000000000000000000000000000000000000
--- a/src/xml/base_dyn_config.xml
+++ /dev/null
@@ -1,38 +0,0 @@
-<?xml version="1.0"?>
-
-<motor_config>
-  <num_axis>1</num_axis>
-  <axis_config>
-    <accel_range>
-      <max>0</max>
-      <min>0</min>
-    </accel_range>
-    <velocity_range>
-      <max>0</max>
-      <min>0</min>
-    </velocity_range>
-    <position_range>
-      <max>300</max>
-      <min>0</min>
-    </position_range>
-    <encoder_res>1</encoder_res>
-    <gear_factor>1.0</gear_factor>
-  </axis_config>
-  <config_file>dyn_config.xml</config_file>
-  <position_feedback>
-    <enabled>1</enabled>
-    <mode>polling</mode>
-    <rate>100.0</rate>
-  </position_feedback>
-  <velocity_feedback>
-    <enabled>0</enabled>
-    <mode>polling</mode>
-    <rate>100.0</rate>
-  </velocity_feedback>
-  <limits_feedback>
-    <enabled>0</enabled>
-    <mode>polling</mode>
-    <rate>1.0</rate>
-  </limits_feedback>
-  <open_loop>0</open_loop>
-</motor_config>
diff --git a/src/xml/dyn_config.xml b/src/xml/dyn_config.xml
index d8eb131954c553e430490392d030efa9ea4c455e..6f8a57d8d99081e3b8ce8f53334d4cef36a499bf 100755
--- a/src/xml/dyn_config.xml
+++ b/src/xml/dyn_config.xml
@@ -3,12 +3,19 @@
 <dynamixel_motor_config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xsi:noNamespaceSchemaLocation="dynamixel_motor_cfg_file.xsd">
 
+  <alarm_shtdwn>4</alarm_shtdwn>
+  <min_angle>-125</min_angle>
+  <max_angle>125</max_angle>
   <temp_limit>85</temp_limit>
   <max_voltage>19</max_voltage>
   <min_voltage>6</min_voltage>
-  <cw_comp_margin>2</cw_comp_margin>
-  <ccw_comp_margin>2</ccw_comp_margin>
-  <cw_comp_slope>16</cw_comp_slope>
-  <ccw_comp_slope>16</ccw_comp_slope>
-  <punch>0</punch>
+  <max_torque>100</max_torque>
+  <cw_comp_margin>0</cw_comp_margin>
+  <ccw_comp_margin>0</ccw_comp_margin>
+  <cw_comp_slope>32</cw_comp_slope>
+  <ccw_comp_slope>32</ccw_comp_slope>
+  <punch>32</punch>
+  <kp>0</kp>
+  <ki>0</ki>
+  <kd>0</kd>
 </dynamixel_motor_config>
diff --git a/src/xml/dyn_group_config.xml b/src/xml/dyn_group_config.xml
new file mode 100755
index 0000000000000000000000000000000000000000..48864feed344cf19b166a902c2977495ac6b025b
--- /dev/null
+++ b/src/xml/dyn_group_config.xml
@@ -0,0 +1,16 @@
+<?xml version="1.0"?>
+
+<dyn_motor_group_config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+       xsi:noNamespaceSchemaLocation="dyn_motor_group_cfg_file.xsd">
+
+  <bus_id>A4012B3G</bus_id>
+  <baudrate>1000000</baudrate>
+  <dyn_motor_config>
+    <id>1</id>
+    <config_file>../src/xml/dyn_config.xml</config_file>
+  </dyn_motor_config>
+  <dyn_motor_config>
+    <id>3</id>
+    <config_file>../src/xml/dyn_config.xml</config_file>
+  </dyn_motor_config>
+</dyn_motor_group_config>
diff --git a/src/xml/dyn_motion_seq_file.xsd b/src/xml/dyn_motion_seq_file.xsd
new file mode 100755
index 0000000000000000000000000000000000000000..43fe9d61c1b418ec0725af8b330ce61e3ddff067
--- /dev/null
+++ b/src/xml/dyn_motion_seq_file.xsd
@@ -0,0 +1,44 @@
+<?xml version="1.0"?>
+
+<!--
+
+file      : dyn_motion_seq_file.xsd 
+author    : Sergi Hernandez Juan (shernand@iri.upc.edu)
+copyright : not copyrighted - public domain
+
+-->
+
+<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema">
+  <xsd:simpleType name="motion_t">
+     <xsd:restriction base="xsd:string">
+        <xsd:enumeration value="absolute"/>
+        <xsd:enumeration value="relative"/>
+     </xsd:restriction>
+  </xsd:simpleType>
+
+  <xsd:complexType name="step_t">
+    <xsd:sequence>
+      <xsd:element name="position" type="xsd:double" maxOccurs="unbounded">
+      </xsd:element>
+      <xsd:element name="velocity" type="xsd:double" maxOccurs="unbounded">
+      </xsd:element>
+      <xsd:element name="mode" type="motion_t">
+      </xsd:element>
+      <xsd:element name="delay" type="xsd:double">
+      </xsd:element>
+    </xsd:sequence>
+  </xsd:complexType>
+
+  <xsd:complexType name="dyn_sequence_t">
+    <xsd:sequence>
+      <xsd:element name="num_motors" type="xsd:unsignedInt">
+      </xsd:element>
+      <xsd:element name="step" type="step_t" maxOccurs="unbounded">
+      </xsd:element>
+    </xsd:sequence>
+  </xsd:complexType>
+
+  <xsd:element name="dyn_motion_seq" type="dyn_sequence_t">
+  </xsd:element>
+
+</xsd:schema>
diff --git a/src/xml/dynamixel_motor_cfg_file.xsd b/src/xml/dynamixel_motor_cfg_file.xsd
index 7d6b76c150f2602fbbaa5755b3a1d7cab4a944ed..d813b05bce3f0162a932da2ec32705ae08f1229b 100755
--- a/src/xml/dynamixel_motor_cfg_file.xsd
+++ b/src/xml/dynamixel_motor_cfg_file.xsd
@@ -24,15 +24,19 @@ copyright : not copyrighted - public domain
 
   <xsd:complexType name="dynamixel_motor_config_t">
     <xsd:sequence>
+      <xsd:element name="alarm_shtdwn" type="xsd:unsignedByte">
+      </xsd:element>
+      <xsd:element name="max_angle" type="xsd:float">
+      </xsd:element>
+      <xsd:element name="min_angle" type="xsd:float">
+      </xsd:element>
       <xsd:element name="temp_limit" type="xsd:int">
       </xsd:element>
       <xsd:element name="max_voltage" type="xsd:float">
       </xsd:element>
       <xsd:element name="min_voltage" type="xsd:float">
       </xsd:element>
-      <xsd:element name="led_alarms" type="alarm_t" minOccurs="0" maxOccurs="unbounded">
-      </xsd:element>
-      <xsd:element name="off_alarms" type="alarm_t" minOccurs="0" maxOccurs="unbounded">
+      <xsd:element name="max_torque" type="xsd:float">
       </xsd:element>
       <xsd:element name="cw_comp_margin" type="xsd:unsignedByte">
       </xsd:element>
@@ -44,6 +48,12 @@ copyright : not copyrighted - public domain
       </xsd:element>
       <xsd:element name="punch" type="xsd:unsignedByte">
       </xsd:element>
+      <xsd:element name="kp" type="xsd:unsignedByte">
+      </xsd:element>
+      <xsd:element name="ki" type="xsd:unsignedByte">
+      </xsd:element>
+      <xsd:element name="kd" type="xsd:unsignedByte">
+      </xsd:element>
     </xsd:sequence>
   </xsd:complexType>
 
diff --git a/src/xml/dynamixel_motor_group_cfg_file.xsd b/src/xml/dynamixel_motor_group_cfg_file.xsd
new file mode 100755
index 0000000000000000000000000000000000000000..6b416ce9f6eafb7d149af2d534c4ab60652c5c0e
--- /dev/null
+++ b/src/xml/dynamixel_motor_group_cfg_file.xsd
@@ -0,0 +1,36 @@
+<?xml version="1.0"?>
+
+<!--
+
+file      : dynamixel_motor_group_cfg_file.xsd 
+author    : Sergi Hernandez Juan (shernand@iri.upc.edu)
+copyright : not copyrighted - public domain
+
+-->
+
+<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema">
+
+  <xsd:complexType name="dyn_motor_config_t">
+    <xsd:sequence>
+      <xsd:element name="id" type="xsd:int">
+      </xsd:element>
+      <xsd:element name="config_file" type="xsd:string">
+      </xsd:element>
+    </xsd:sequence>
+  </xsd:complexType>
+
+  <xsd:complexType name="dyn_motor_group_config_t">
+    <xsd:sequence>
+      <xsd:element name="bus_id" type="xsd:string">
+      </xsd:element>
+      <xsd:element name="baudrate" type="xsd:int">
+      </xsd:element>
+      <xsd:element name="dyn_motor_config" type="dyn_motor_config_t" maxOccurs="unbounded">
+      </xsd:element>
+    </xsd:sequence>
+  </xsd:complexType>
+
+  <xsd:element name="dyn_motor_group_config" type="dyn_motor_group_config_t">
+  </xsd:element>
+
+</xsd:schema>
diff --git a/src/xml/sequence1.xml b/src/xml/sequence1.xml
new file mode 100755
index 0000000000000000000000000000000000000000..01f634145cd92e8e987c2aed40c1bb5b62986898
--- /dev/null
+++ b/src/xml/sequence1.xml
@@ -0,0 +1,63 @@
+<?xml version="1.0"?>
+
+<dyn_motion_seq xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+       xsi:noNamespaceSchemaLocation="dyn_motion_seq_file.xsd">
+   <num_motors>2</num_motors>
+   <step>
+     <position>0.0</position>
+     <position>0.0</position>
+     <velocity>100.0</velocity>
+     <velocity>100.0</velocity>
+     <mode>absolute</mode>
+     <delay>0</delay>
+   </step>
+   <step>
+     <position>30.0</position>
+     <position>30.0</position>
+     <velocity>100.0</velocity>
+     <velocity>100.0</velocity>
+     <mode>absolute</mode>
+     <delay>0</delay>
+   </step>
+   <step>
+     <position>-30.0</position>
+     <position>-30.0</position>
+     <velocity>100.0</velocity>
+     <velocity>100.0</velocity>
+     <mode>absolute</mode>
+     <delay>0</delay>
+   </step>
+   <step>
+     <position>20.0</position>
+     <position>20.0</position>
+     <velocity>20.0</velocity>
+     <velocity>20.0</velocity>
+     <mode>relative</mode>
+     <delay>0</delay>
+   </step>
+   <step>
+     <position>20.0</position>
+     <position>20.0</position>
+     <velocity>20.0</velocity>
+     <velocity>20.0</velocity>
+     <mode>relative</mode>
+     <delay>0</delay>
+   </step>
+   <step>
+     <position>20.0</position>
+     <position>20.0</position>
+     <velocity>20.0</velocity>
+     <velocity>20.0</velocity>
+     <mode>relative</mode>
+     <delay>0</delay>
+   </step>
+   <step>
+     <position>-30.0</position>
+     <position>-30.0</position>
+     <velocity>100.0</velocity>
+     <velocity>100.0</velocity>
+     <mode>absolute</mode>
+     <delay>0</delay>
+   </step>
+</dyn_motion_seq>
+
diff --git a/src/xml/test_motion.xml b/src/xml/test_motion.xml
deleted file mode 100755
index 95e982aaab8d3eb5647b331cfae45c487da8e83a..0000000000000000000000000000000000000000
--- a/src/xml/test_motion.xml
+++ /dev/null
@@ -1,17 +0,0 @@
-<?xml version="1.0"?>
-
-<motion_seq xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-       xsi:noNamespaceSchemaLocation="motion_sequence_file.xsd">
-   <num_motors>2</num_motors>
-   <num_steps>1</num_steps>
-   <control>position</control>
-   <motion>absolute</motion>
-   <loop>open</loop>
-   <step>
-     <position>150.0</position>
-     <position>150.0</position>
-     <velocity>100.0</velocity>
-     <velocity>100.0</velocity>
-     <delay>0</delay>
-   </step>
-</motion_seq>
diff --git a/src/xml/test_motion2.xml b/src/xml/test_motion2.xml
deleted file mode 100755
index 0b474af49661caca00f551e629600034ffd2f2ee..0000000000000000000000000000000000000000
--- a/src/xml/test_motion2.xml
+++ /dev/null
@@ -1,17 +0,0 @@
-<?xml version="1.0"?>
-
-<motion_seq xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-       xsi:noNamespaceSchemaLocation="motion_sequence_file.xsd">
-   <num_motors>2</num_motors>
-   <num_steps>1</num_steps>
-   <control>position</control>
-   <motion>absolute</motion>
-   <loop>open</loop>
-   <step>
-     <position>150.0</position>
-     <position>150.0</position>
-     <velocity>150.0</velocity>
-     <velocity>150.0</velocity>
-     <delay>0</delay>
-   </step>
-</motion_seq>