diff --git a/dynamixel_manager/Makefile b/dynamixel_manager/Makefile
index ab1e59b5b6dea777f90b49ffc73ebf51ef73e345..9058279e15f2830c3a5dacd9dc8e7721fcd4e70b 100755
--- a/dynamixel_manager/Makefile
+++ b/dynamixel_manager/Makefile
@@ -15,7 +15,7 @@ COMM_PATH = ../comm
 UTILS_PATH = ../utils
 DYN_BASE_PATH = ../dynamixel_base
 
-INCLUDE_DIRS = -I./include/ -I$(COMM_PATH)/include -I$(UTILS_PATH)/include -I$(DYN_BASE_PATH)/include
+INCLUDE_DIRS = -I./include/ -I./include/modules -I$(COMM_PATH)/include -I$(UTILS_PATH)/include -I$(DYN_BASE_PATH)/include
 
 TCHAIN_PREFIX=arm-none-eabi-
 
@@ -32,6 +32,8 @@ DYNAMIXEL_OUT_M3 = ./lib/dynamixel_manager_m3.a
 
 SRC_DIR=./src/
 SRC=$(wildcard $(SRC_DIR)*.c)
+SRC_DIR_MODULES=./src/modules/
+SRC+=$(wildcard $(SRC_DIR_MODULES)*.c)
 
 DYNAMIXEL_M4_FPU_OBJ_DIR=build/m4_fpu/
 DYNAMIXEL_M4_FPU_OBJS_TMP = $(notdir $(SRC:.c=.o))
@@ -52,12 +54,20 @@ DYNAMIXEL_M3_OBJS = $(patsubst %,$(DYNAMIXEL_M3_OBJ_DIR)%,$(DYNAMIXEL_M3_OBJS_TM
 all: $(DYNAMIXEL_OUT_M4_FPU) $(DYNAMIXEL_OUT_M0) $(DYNAMIXEL_OUT_M0plus) $(DYNAMIXEL_OUT_M3)
 $(DYNAMIXEL_M4_FPU_OBJ_DIR)%.o: $(SRC_DIR)%.c
 	$(CC) -c $(CFLAGS) $(COMPILE_OPTS_M4_FPU) -o $@ $<
+$(DYNAMIXEL_M4_FPU_OBJ_DIR)%.o: $(SRC_DIR_MODULES)%.c
+	$(CC) -c $(CFLAGS) $(COMPILE_OPTS_M4_FPU) -o $@ $<
 $(DYNAMIXEL_M0_OBJ_DIR)%.o: $(SRC_DIR)%.c
 	$(CC) -c $(CFLAGS) $(COMPILE_OPTS_M0) -o $@ $<
+$(DYNAMIXEL_M0_OBJ_DIR)%.o: $(SRC_DIR_MODULES)%.c
+	$(CC) -c $(CFLAGS) $(COMPILE_OPTS_M0) -o $@ $<
 $(DYNAMIXEL_M0plus_OBJ_DIR)%.o: $(SRC_DIR)%.c
 	$(CC) -c $(CFLAGS) $(COMPILE_OPTS_M0plus) -o $@ $<
+$(DYNAMIXEL_M0plus_OBJ_DIR)%.o: $(SRC_DIR_MODULES)%.c
+	$(CC) -c $(CFLAGS) $(COMPILE_OPTS_M0plus) -o $@ $<
 $(DYNAMIXEL_M3_OBJ_DIR)%.o: $(SRC_DIR)%.c
 	$(CC) -c $(CFLAGS) $(COMPILE_OPTS_M3) -o $@ $<
+$(DYNAMIXEL_M3_OBJ_DIR)%.o: $(SRC_DIR_MODULES)%.c
+	$(CC) -c $(CFLAGS) $(COMPILE_OPTS_M3) -o $@ $<
 mkdir_build: 
 	mkdir -p build/m4_fpu
 	mkdir -p build/m0
diff --git a/dynamixel_manager/include/dyn_devices.h b/dynamixel_manager/include/dyn_devices.h
index c10582ff5b9f007c2e6aaf3538290bacaa46489d..e6bbe5225e1497dcd79d05c746a5c2e88e136077 100644
--- a/dynamixel_manager/include/dyn_devices.h
+++ b/dynamixel_manager/include/dyn_devices.h
@@ -19,9 +19,13 @@
 #define       SERVO_MX106     0x0140
 #define       SERVO_XL320     0x015E
 
-#define       IS_SERVO(model) (model==SERVO_DX113 || model==SERVO_DX116 || model==SERVO_DX117 || model==SERVO_AX12A \
-                               model==SERVO_AX12W || model==SERVO_AX18A || model==SERVO_RX10 || model==SERVO_MX12W \
-                               model==SERVO_MX28 || model==SERVO_RX24F || model==SERVO_RX28 || model==SERVO_RX64 \
+#define       IS_SERVO(model) (model==SERVO_DX113 || model==SERVO_DX116 || model==SERVO_DX117 || model==SERVO_AX12A || \
+                               model==SERVO_AX12W || model==SERVO_AX18A || model==SERVO_RX10 || model==SERVO_MX12W || \
+                               model==SERVO_MX28 || model==SERVO_RX24F || model==SERVO_RX28 || model==SERVO_RX64 || \
                                model==SERVO_MX64 || model==SERVO_EX106 || model==SERVO_MX106 || model==SERVO_XL320)
 
+#define       HAS_BULK_READ(model) (model==SERVO_MX12W || model==SERVO_MX28 || model==SERVO_MX64 || model==SERVO_MX106 || model==SERVO_XL320)
+#define       HAS_BULK_WRITE(model) (model==SERVO_XL320)
+#define       HAS_SYNC_READ(model) (model==SERVO_XL320)
+
 #endif
diff --git a/dynamixel_manager/include/dyn_manager.h b/dynamixel_manager/include/dyn_manager.h
index ab0c336134eb7f4993ff6633da608afb789247ed..241c7231d719a0fb3cc74d12055cfde76e7d533b 100644
--- a/dynamixel_manager/include/dyn_manager.h
+++ b/dynamixel_manager/include/dyn_manager.h
@@ -23,6 +23,8 @@
 #define    DYN_MANAGER_BULK                  0x40
 #define    DYN_MANAGER_NONE                  0x00
 
+#define    DYN_MANAGER_DEFAULT_PERIOD_US     7800
+
 typedef enum {single_rd_op=DYN_MANAGER_SINGLE|DYN_MANAGER_READ,
               single_wr_op=DYN_MANAGER_SINGLE|DYN_MANAGER_WRITE,
               sync_rd_op=DYN_MANAGER_SYNC|DYN_MANAGER_READ,
@@ -58,7 +60,7 @@ typedef struct{
   unsigned char ids[DYN_MANAGER_MAX_NUM_DEVICES];
   unsigned short int address;
   unsigned short int length;
-  TWriteData data[DYN_MANAGER_MAX_NUM_DEVICES];
+  unsigned char *data[DYN_MANAGER_MAX_NUM_DEVICES];
 }TDynManagerSyncOp;
 
 typedef struct{
@@ -67,7 +69,7 @@ typedef struct{
   unsigned char ids[DYN_MANAGER_MAX_NUM_DEVICES];
   unsigned short int address[DYN_MANAGER_MAX_NUM_DEVICES];
   unsigned short int length[DYN_MANAGER_MAX_NUM_DEVICES];
-  TWriteData data[DYN_MANAGER_MAX_NUM_DEVICES];
+  unsigned char *data[DYN_MANAGER_MAX_NUM_DEVICES];
 }TDynManagerBulkOp;
 
 typedef struct{
@@ -96,13 +98,20 @@ typedef struct{
   unsigned char num_devices;
   OP_HANDLE op_handles[DYN_MANAGER_MAX_NUM_OP];
   unsigned char num_ops;
+  unsigned short int period_us;
+  void (*init_timer)(void);
+  void (*set_period)(unsigned short int period_us);
 }TDynManager;
 
 // public functions
 void dyn_manager_init(TDynManager *manager);
+void dyn_manager_set_period(TDynManager *manager,unsigned short int period_us);
+unsigned short int dyn_manager_get_period(TDynManager *manager);
 void dyn_manager_scan(TDynManager *manager);
 void dyn_manager_add_master(TDynManager *manager,TDynamixelMaster *master);
 unsigned char dyn_manager_get_num_masters(TDynManager *manager);
+TDynamixelMaster *dyn_manager_get_device_master(TDynManager *manager,unsigned char device_id);
+unsigned short int dyn_manager_get_device_model(TDynManager *manager,unsigned char device_id);
 void dyn_manager_add_module(TDynManager *manager,struct TDynModule *module);
 unsigned char dyn_manager_get_num_modules(TDynManager *manager);
 void dyn_manager_delete_op(TDynManager *manager,OP_HANDLE *op);
@@ -117,19 +126,19 @@ void dyn_manager_single_op_change_address(TDynManager *manager,OP_HANDLE *op,uns
 void dyn_manager_single_op_change_length(TDynManager *manager,OP_HANDLE *op,unsigned short int length);
 void dyn_manager_single_op_change_data(TDynManager *manager,OP_HANDLE *op,unsigned char *data);
 // sync operation functions
-OP_HANDLE *dyn_manager_sync_op_new(TDynManager *manager,unsigned char mode,unsigned char num,unsigned char *ids,unsigned short int address, unsigned short int length, TWriteData *data);
-void dyn_manager_sync_op_add_devices(TDynManager *manager,OP_HANDLE *op,unsigned char num,unsigned char *ids,TWriteData *data);
+OP_HANDLE *dyn_manager_sync_op_new(TDynManager *manager,unsigned char mode,unsigned char num,unsigned char *ids,unsigned short int address, unsigned short int length, unsigned char * const data[]);
+void dyn_manager_sync_op_add_devices(TDynManager *manager,OP_HANDLE *op,unsigned char num,unsigned char *ids,unsigned char * const data[]);
 void dyn_manager_sync_op_remove_devices(TDynManager *manager,OP_HANDLE *op,unsigned char num,unsigned char *ids);
 void dyn_manager_sync_op_change_address(TDynManager *manager,OP_HANDLE *op,unsigned short int address);
 void dyn_manager_sync_op_change_length(TDynManager *manager,OP_HANDLE *op,unsigned short int length);
-void dyn_manager_sync_op_change_data(TDynManager *manager,OP_HANDLE *op,unsigned char num,unsigned char *ids,TWriteData *data);
+void dyn_manager_sync_op_change_data(TDynManager *manager,OP_HANDLE *op,unsigned char num,unsigned char *ids,unsigned char * const data[]);
 // bulk operation functions
-OP_HANDLE *dyn_manager_bulk_op_new(TDynManager *manager,unsigned char mode,unsigned char num,unsigned char *ids,unsigned short int *address, unsigned short int *length, TWriteData *data);
-void dyn_manager_bulk_op_add_devices(TDynManager *manager,OP_HANDLE *op,unsigned char num,unsigned char *ids,unsigned short int *address, unsigned short int *length,TWriteData *data);
+OP_HANDLE *dyn_manager_bulk_op_new(TDynManager *manager,unsigned char mode,unsigned char num,unsigned char *ids,unsigned short int *address, unsigned short int *length, unsigned char * const data[]);
+void dyn_manager_bulk_op_add_devices(TDynManager *manager,OP_HANDLE *op,unsigned char num,unsigned char *ids,unsigned short int *address, unsigned short int *length,unsigned char * const data[]);
 void dyn_manager_bulk_op_remove_devices(TDynManager *manager,OP_HANDLE *op,unsigned char num,unsigned char *ids);
 void dyn_manager_bulk_op_change_address(TDynManager *manager,OP_HANDLE *op,unsigned char num,unsigned char *ids,unsigned short int *address);
 void dyn_manager_bulk_op_change_length(TDynManager *manager,OP_HANDLE *op,unsigned char num,unsigned char *ids,unsigned short int *length);
-void dyn_manager_bulk_op_change_data(TDynManager *manager,OP_HANDLE *op,unsigned char num,unsigned char *ids,TWriteData *data);
+void dyn_manager_bulk_op_change_data(TDynManager *manager,OP_HANDLE *op,unsigned char num,unsigned char *ids,unsigned char * const data[]);
 void dyn_manager_loop(TDynManager *manager);
 
 #endif 
diff --git a/dynamixel_manager/include/dyn_module.h b/dynamixel_manager/include/dyn_module.h
index 95ba55eaba912bb0d4f2c8dbbed74f7635f91caf..3da912ac704ae0d5623d954bb045585a79cee1cc 100644
--- a/dynamixel_manager/include/dyn_module.h
+++ b/dynamixel_manager/include/dyn_module.h
@@ -12,26 +12,26 @@ typedef struct TDynModule{
   unsigned char assigned_ids[DYN_MANAGER_MAX_NUM_DEVICES];
   unsigned char num_assigned_ids;
   unsigned char period_count;
-  void (*init)(void);
-  void (*add_device)(unsigned char id,unsigned short int model);
-  void (*setup)(void);
-  void (*pre_process)(void);
-  void (*post_process)(void);
+  unsigned char enabled;
+  void (*add_device)(void *module_data,unsigned char id,unsigned short int model);
+  void (*set_period)(void *module_data,unsigned short int period_us);
+  void (*setup)(void *module_data);
+  void (*pre_process)(void *module_data);
+  void (*post_process)(void *module_data);
+  void *data;
 }TDynModule;
 
 //public functions
 void dyn_module_init(TDynModule *module);
+inline void dyn_module_enable(TDynModule *module);
+inline void dyn_module_disable(TDynModule *module);
+inline unsigned char dyn_module_is_enabled(TDynModule *module);
 void dyn_module_add_model(TDynModule *module,unsigned short int model);
-unsigned char dyn_module_get_num_models(TDynModule *module);
+inline unsigned char dyn_module_get_num_models(TDynModule *module);
 void dyn_module_add_device(TDynModule *module,unsigned char id, unsigned short int model);
-unsigned char dyn_module_get_num_assigned_devices(TDynModule *module);
-unsigned char dyn_moudle_device_is_assigned(TDynModule *module,unsigned char id);
+inline unsigned char dyn_module_get_num_assigned_devices(TDynModule *module);
+unsigned char dyn_module_device_is_assigned(TDynModule *module,unsigned char id);
 void dyn_module_set_period(TDynModule *module,unsigned char period);
-unsigned char dyn_module_get_period(TDynModule *module);
-void dyn_module_set_init_fctn(TDynModule *module,void (*init)(void));
-void dyn_module_set_add_device_fctn(TDynModule *module,void (*add_device)(unsigned char id,unsigned short int model));
-void dyn_module_set_setup_fctn(TDynModule *module,void (*setup)(void));
-void dyn_module_set_pre_process_fctn(TDynModule *module,void (*pre_process)(void));
-void dyn_module_set_post_process_fctn(TDynModule *module,void (*post_process)(void));
+inline unsigned char dyn_module_get_period(TDynModule *module);
 
 #endif
diff --git a/dynamixel_manager/include/modules/action.h b/dynamixel_manager/include/modules/action.h
new file mode 100755
index 0000000000000000000000000000000000000000..506b11d5ab837a58f7d08b45041c49cf0994aeb2
--- /dev/null
+++ b/dynamixel_manager/include/modules/action.h
@@ -0,0 +1,25 @@
+#ifndef _ACTION_H
+#define _ACTION_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include "motion_pages.h"
+#include "motion_module.h"
+
+// public functions
+void action_init(void);
+TMotionModule *action_get_module(void);
+unsigned char action_load_page(unsigned char page_id);
+void action_start_page(void);
+void action_stop_page(void);
+unsigned char action_is_running(void);
+unsigned char action_get_current_page(void);
+unsigned char action_get_current_step(void);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/dynamixel_manager/include/modules/dyn_servos.h b/dynamixel_manager/include/modules/dyn_servos.h
new file mode 100755
index 0000000000000000000000000000000000000000..07d4e55521b0279fda66c9fe001c91c7623ce551
--- /dev/null
+++ b/dynamixel_manager/include/modules/dyn_servos.h
@@ -0,0 +1,125 @@
+#ifndef _DYN_SERVOS_H
+#define _DYN_SERVOS_H
+
+// Servo register map
+typedef enum{
+  P_MODEL_NUMBER_L            = 0,
+  P_MODEL_NUMBER_H            = 1,
+  P_VERSION                   = 2,
+  P_ID                        = 3,
+  P_BAUD_RATE                 = 4,
+  P_RETURN_DELAY_TIME         = 5,
+  P_CW_ANGLE_LIMIT_L          = 6,
+  P_CW_ANGLE_LIMIT_H          = 7,
+  P_CCW_ANGLE_LIMIT_L         = 8,
+  P_CCW_ANGLE_LIMIT_H         = 9,
+  P_SYSTEM_DATA2              = 10,
+  P_HIGH_LIMIT_TEMPERATURE    = 11,
+  P_LOW_LIMIT_VOLTAGE         = 12,
+  P_HIGH_LIMIT_VOLTAGE        = 13,
+  P_MAX_TORQUE_L              = 14,
+  P_MAX_TORQUE_H              = 15,
+  P_RETURN_LEVEL              = 16,
+  P_ALARM_LED                 = 17,
+  P_ALARM_SHUTDOWN            = 18,
+  P_OPERATING_MODE            = 19,
+  P_LOW_CALIBRATION_L         = 20,
+  P_LOW_CALIBRATION_H         = 21,
+  P_HIGH_CALIBRATION_L        = 22,
+  P_HIGH_CALIBRATION_H        = 23,
+  P_TORQUE_ENABLE             = 24,
+  P_LED                       = 25,
+  P_CW_COMPLIANCE_MARGIN      = 26,
+  P_CCW_COMPLIANCE_MARGIN     = 27,
+  P_CW_COMPLIANCE_SLOPE       = 28,
+  P_CCW_COMPLIANCE_SLOPE      = 29,
+  P_D_GAIN                    = 26,
+  P_I_GAIN                    = 27,
+  P_P_GAIN                    = 28,
+  P_RESERVED                  = 29,
+  P_GOAL_POSITION_L           = 30,
+  P_GOAL_POSITION_H           = 31,
+  P_MOVING_SPEED_L            = 32,
+  P_MOVING_SPEED_H            = 33,
+  P_TORQUE_LIMIT_L            = 34,
+  P_TORQUE_LIMIT_H            = 35,
+  P_PRESENT_POSITION_L        = 36,
+  P_PRESENT_POSITION_H        = 37,
+  P_PRESENT_SPEED_L           = 38,
+  P_PRESENT_SPEED_H           = 39,
+  P_PRESENT_LOAD_L            = 40,
+  P_PRESENT_LOAD_H            = 41,
+  P_PRESENT_VOLTAGE           = 42,
+  P_PRESENT_TEMPERATURE       = 43,
+  P_REGISTERED_INSTRUCTION    = 44,
+  P_PAUSE_TIME                = 45,
+  P_MOVING                    = 46,
+  P_LOCK                      = 47,
+  P_PUNCH_L                   = 48,
+  P_PUNCH_H                   = 49,
+  P_RESERVED4                 = 50,
+  P_RESERVED5                 = 51,
+  P_POT_L                     = 52,
+  P_POT_H                     = 53,
+  P_PWM_OUT_L                 = 54,
+  P_PWM_OUT_H                 = 55,
+  P_P_ERROR_L                 = 56,
+  P_P_ERROR_H                 = 57,
+  P_I_ERROR_L                 = 58,
+  P_I_ERROR_H                 = 59,
+  P_D_ERROR_L                 = 60,
+  P_D_ERROR_H                 = 61,
+  P_P_ERROR_OUT_L             = 62,
+  P_P_ERROR_OUT_H             = 63,
+  P_I_ERROR_OUT_L             = 64,
+  P_I_ERROR_OUT_H             = 65,
+  P_D_ERROR_OUT_L             = 66,
+  P_D_ERROR_OUT_H             = 67}TDynServo;
+
+typedef enum{
+  XL_MODEL_NUMBER_L            = 0,
+  XL_MODEL_NUMBER_H            = 1,
+  XL_VERSION                   = 2,
+  XL_ID                        = 3,
+  XL_BAUD_RATE                 = 4,
+  XL_RETURN_DELAY_TIME         = 5,
+  XL_CW_ANGLE_LIMIT_L          = 6,
+  XL_CW_ANGLE_LIMIT_H          = 7,
+  XL_CCW_ANGLE_LIMIT_L         = 8,
+  XL_CCW_ANGLE_LIMIT_H         = 9,
+  XL_SYSTEM_DATA2              = 10,
+  XL_CONTROL_MODE              = 11,
+  XL_HIGH_LIMIT_TEMPERATURE    = 12,
+  XL_LOW_LIMIT_VOLTAGE         = 13,
+  XL_HIGH_LIMIT_VOLTAGE        = 14,
+  XL_MAX_TORQUE_L              = 15,
+  XL_MAX_TORQUE_H              = 16,
+  XL_RETURN_LEVEL              = 17,
+  XL_ALARM_SHUTDOWN            = 18,
+  XL_TORQUE_ENABLE             = 24,
+  XL_LED                       = 25,
+  XL_D_GAIN                    = 27,
+  XL_I_GAIN                    = 28,
+  XL_P_GAIN                    = 29,
+  XL_GOAL_POSITION_L           = 30,
+  XL_GOAL_POSITION_H           = 31,
+  XL_MOVING_SPEED_L            = 32,
+  XL_MOVING_SPEED_H            = 33,
+  XL_TORQUE_LIMIT_L            = 35,
+  XL_TORQUE_LIMIT_H            = 36,
+  XL_PRESENT_POSITION_L        = 37,
+  XL_PRESENT_POSITION_H        = 38,
+  XL_PRESENT_SPEED_L           = 39,
+  XL_PRESENT_SPEED_H           = 40,
+  XL_PRESENT_LOAD_L            = 41,
+  XL_PRESENT_LOAD_H            = 42,
+  XL_PRESENT_VOLTAGE           = 45,
+  XL_PRESENT_TEMPERATURE       = 46,
+  XL_REGISTERED_INSTRUCTION    = 47,
+  XL_MOVING                    = 49,
+  XL_HARDWARE_ERROR_STATUS     = 50,
+  XL_PUNCH_L                   = 51,
+  XL_PUNCH_H                   = 51}TXLServo;
+
+
+#endif
diff --git a/dynamixel_manager/include/modules/motion_manager.h b/dynamixel_manager/include/modules/motion_manager.h
new file mode 100644
index 0000000000000000000000000000000000000000..74a12817c1752533f3b7e12ee1acca72fd900180
--- /dev/null
+++ b/dynamixel_manager/include/modules/motion_manager.h
@@ -0,0 +1,65 @@
+#ifndef _MOTION_MANAGER_H
+#define _MOTION_MANAGER_H
+
+#include "dyn_module.h"
+
+#define MAX_NUM_MOTION_MODULES        8
+
+typedef enum {MM_NONE          = -1,
+              MM_ACTION        = 0,
+              MM_WALKING       = 1,
+              MM_JOINTS        = 2,
+              MM_HEAD          = 3} TModules;
+
+typedef struct{
+  unsigned short int model;
+  unsigned short int encoder_resolution;
+  unsigned char gear_ratio;
+  unsigned short int max_angle;
+  unsigned short int center_angle;
+  unsigned short int max_speed;
+  long long int cw_angle_limit;
+  long long int ccw_angle_limit;
+}TServoConfig;
+
+typedef struct{
+  unsigned char cw_compliance;
+  unsigned char ccw_compliance;
+  unsigned short int target_value;
+  long long int target_angle;
+  unsigned short int current_value;
+  long long int current_angle;
+  TModules module;
+  unsigned char enabled;
+  char offset;
+}TServoValues;
+
+struct TMotionModule;
+
+typedef struct {
+  TDynModule dyn_module;
+  struct TMotionModule *modules[MAX_NUM_MOTION_MODULES];
+  unsigned char num_modules;
+  TServoConfig servo_configs[DYN_MANAGER_MAX_NUM_DEVICES];
+  TServoValues servo_values[DYN_MANAGER_MAX_NUM_DEVICES];
+  OP_HANDLE *enable_op;
+  OP_HANDLE *motion_op;
+  OP_HANDLE *feedback_op;
+  unsigned char balance_enabled;
+  void (*balance)(short int offsets[DYN_MANAGER_MAX_NUM_DEVICES]);
+}TMotionManager;  
+
+void mmanager_init(TMotionManager *mmanager);
+TDynModule *mmanager_get_dyn_module(TMotionManager *mmanager);
+void mmanager_enable_balance(TMotionManager *mmanager);
+void mmanager_disable_balance(TMotionManager *mmanager);
+unsigned char mmanager_is_balance_enabled(TMotionManager *mmanager);
+void mmanager_set_module(TMotionManager *mmanager,unsigned char servo_id,TModules module);
+TModules mmanager_get_module(TMotionManager *mmanager,unsigned char servo_id);
+void mmanager_enable_servo(TMotionManager *mmanager,unsigned char servo_id);
+void mmanager_disable_servo(TMotionManager *mmanager,unsigned char servo_id);
+unsigned char mmanager_is_servo_enabled(TMotionManager *mmanager,unsigned char servo_id);
+void mmanager_set_offset(TMotionManager *mmanager,unsigned char servo_id,char offset);
+void mmanager_add_module(TMotionManager *mmanager,struct TMotionModule *module);
+
+#endif
diff --git a/dynamixel_manager/include/modules/motion_module.h b/dynamixel_manager/include/modules/motion_module.h
new file mode 100644
index 0000000000000000000000000000000000000000..bb4c6136e19f3992691d9fdf120627bfedd99aed
--- /dev/null
+++ b/dynamixel_manager/include/modules/motion_module.h
@@ -0,0 +1,18 @@
+#ifndef _MOTION_MODULE_H
+#define _MOTION_MODULE_H
+
+#include "motion_manager.h"
+
+typedef struct TMotionModule{
+  TModules id;
+  TMotionManager *manager;
+  void (*set_period)(void *module,unsigned short int period_us);
+  void (*set_module)(void *module,unsigned char servo_id);  
+  void (*pre_process)(void *module);
+  void (*post_process)(void *module);
+  void *data;
+}TMotionModule;
+
+void mmodule_init(TMotionModule *module);
+
+#endif 
diff --git a/dynamixel_manager/include/modules/motion_pages.h b/dynamixel_manager/include/modules/motion_pages.h
new file mode 100755
index 0000000000000000000000000000000000000000..a0dd2151b09d5a8cc44255152613555900050bf6
--- /dev/null
+++ b/dynamixel_manager/include/modules/motion_pages.h
@@ -0,0 +1,58 @@
+#ifndef _MOTION_PAGES_H
+#define _MOTION_PAGES_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define MAX_PAGES                     256 
+#define PAGE_MAX_NUM_SERVOS           31
+#define POSE_NUMBER_OF_POSES_PER_PAGE 7
+
+typedef struct // Header Structure (total 64unsigned char)
+{
+  unsigned char name[14];         // Name             0~13
+  unsigned char reserved1;        // Reserved1        14
+  unsigned char repeat;           // Repeat count     15
+  unsigned char schedule;         // schedule         16
+  unsigned char reserved2[3];     // reserved2        17~19
+  unsigned char stepnum;          // Number of step   20
+  unsigned char reserved3;        // reserved3        21
+  unsigned char speed;            // Speed            22
+  unsigned char reserved4;        // reserved4        23
+  unsigned char accel;            // Acceleration time 24
+  unsigned char next;             // Link to next     25
+  unsigned char exit;             // Link to exit     26
+  unsigned char reserved5[4];     // reserved5        27~30
+  unsigned char checksum;         // checksum         31
+  unsigned char slope[PAGE_MAX_NUM_SERVOS];        // CW/CCW compliance slope  32~62
+  unsigned char reserved6;        // reserved6        63
+}TPageHeader;
+
+typedef struct // Step Structure (total 64unsigned char)
+{
+  short int position[PAGE_MAX_NUM_SERVOS];    // Joint position   0~61
+  unsigned char pause;            // Pause time       62
+  unsigned char time;             // Time             63
+}TStep;
+
+typedef struct // Page Structure (total 512unsigned char)
+{
+  TPageHeader header;       // Page header  0~64
+  TStep steps[POSE_NUMBER_OF_POSES_PER_PAGE];           // Page step    65~511
+}TPage;
+
+extern TPage motion_pages[MAX_PAGES];
+
+// public functions
+void pages_get_page(unsigned char page_id,TPage *page);
+unsigned char pages_check_checksum(TPage *page);
+void pages_clear_page(TPage *page);
+void pages_copy_page(TPage *src,TPage *dst);
+inline unsigned char pages_get_slope(TPage *page,unsigned char servo_id);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/dynamixel_manager/src/dyn_manager.c b/dynamixel_manager/src/dyn_manager.c
index e304245b98bdaefc501864f3bc7e186bafd651ee..9a29a8cf4222aa5ddbbd932f71723710701262a5 100644
--- a/dynamixel_manager/src/dyn_manager.c
+++ b/dynamixel_manager/src/dyn_manager.c
@@ -5,14 +5,14 @@ extern unsigned char dyn_master_start_read_table(TDynamixelMaster *master,unsign
 extern unsigned char dyn_master_is_read_table_done(TDynamixelMaster *master,unsigned char id,unsigned short int address,unsigned short int length,unsigned char *data);
 extern unsigned char dyn_master_start_write_table(TDynamixelMaster *master,unsigned char id,unsigned short int address,unsigned short int length,unsigned char *data);
 extern unsigned char dyn_master_is_write_table_done(TDynamixelMaster *master,unsigned char id,unsigned short int address,unsigned short int length,unsigned char *data);
-extern unsigned char dyn_master_start_sync_write(TDynamixelMaster *master,unsigned char num,unsigned char *ids,unsigned short int address, unsigned short int length, TWriteData *data);
-extern unsigned char dyn_master_is_sync_write_done(TDynamixelMaster *master,unsigned char num,unsigned char *ids,unsigned short int address, unsigned short int length, TWriteData *data);
-extern unsigned char dyn_master_start_sync_read(TDynamixelMaster *master,unsigned char num,unsigned char *ids,unsigned short int address, unsigned short int length, TWriteData *data);
-extern unsigned char dyn_master_is_sync_read_done(TDynamixelMaster *master,unsigned char num,unsigned char *ids,unsigned short int address, unsigned short int length, TWriteData *data);
-extern unsigned char dyn_master_start_bulk_write(TDynamixelMaster *master,unsigned char num,unsigned char *ids,unsigned short int *address, unsigned short int *length, TWriteData *data);
-extern unsigned char dyn_master_is_bulk_write_done(TDynamixelMaster *master,unsigned char num,unsigned char *ids,unsigned short int *address, unsigned short int *length, TWriteData *data);
-extern unsigned char dyn_master_start_bulk_read(TDynamixelMaster *master,unsigned char num,unsigned char *ids,unsigned short int *address, unsigned short int *length, TWriteData *data);
-extern unsigned char dyn_master_is_bulk_read_done(TDynamixelMaster *master,unsigned char num,unsigned char *ids,unsigned short int *address, unsigned short int *length, TWriteData *data);
+extern unsigned char dyn_master_start_sync_write(TDynamixelMaster *master,unsigned char num,unsigned char *ids,unsigned short int address, unsigned short int length, unsigned char * const data[]);
+extern unsigned char dyn_master_is_sync_write_done(TDynamixelMaster *master,unsigned char num,unsigned char *ids,unsigned short int address, unsigned short int length, unsigned char * const data[]);
+extern unsigned char dyn_master_start_sync_read(TDynamixelMaster *master,unsigned char num,unsigned char *ids,unsigned short int address, unsigned short int length, unsigned char * const data[]);
+extern unsigned char dyn_master_is_sync_read_done(TDynamixelMaster *master,unsigned char num,unsigned char *ids,unsigned short int address, unsigned short int length, unsigned char * const data[]);
+extern unsigned char dyn_master_start_bulk_write(TDynamixelMaster *master,unsigned char num,unsigned char *ids,unsigned short int *address, unsigned short int *length, unsigned char * const data[]);
+extern unsigned char dyn_master_is_bulk_write_done(TDynamixelMaster *master,unsigned char num,unsigned char *ids,unsigned short int *address, unsigned short int *length, unsigned char * const data[]);
+extern unsigned char dyn_master_start_bulk_read(TDynamixelMaster *master,unsigned char num,unsigned char *ids,unsigned short int *address, unsigned short int *length, unsigned char * const data[]);
+extern unsigned char dyn_master_is_bulk_read_done(TDynamixelMaster *master,unsigned char num,unsigned char *ids,unsigned short int *address, unsigned short int *length, unsigned char * const data[]);
 
 typedef enum {start_single_ops,wait_single_ops,start_sync_ops,wait_sync_ops,start_bulk_ops,wait_bulk_ops,ops_done} dyn_manager_states_t;
 
@@ -115,7 +115,7 @@ void dyn_manager_delete_op_single_master(TDynManager *manager,unsigned char mast
                                  for(k=0;k<manager->operations[master_index].sync_op[j].num_devices;k++)
                                  {
                                    manager->operations[master_index].sync_op[j].ids[k]=manager->operations[master_index].sync_op[j+1].ids[k];
-                                   manager->operations[master_index].sync_op[j].data[k].data_addr=manager->operations[master_index].sync_op[j+1].data[k].data_addr;
+                                   manager->operations[master_index].sync_op[j].data[k]=manager->operations[master_index].sync_op[j+1].data[k];
                                  }
                                }
                              }
@@ -131,7 +131,7 @@ void dyn_manager_delete_op_single_master(TDynManager *manager,unsigned char mast
                                for(k=0;k<manager->operations[master_index].sync_op[op->op_index[master_index]].num_devices;k++)
                                {
                                  manager->operations[master_index].sync_op[op->op_index[master_index]].ids[k]=0xFF;
-                                 manager->operations[master_index].sync_op[op->op_index[master_index]].data[k].data_addr=0x00000000;
+                                 manager->operations[master_index].sync_op[op->op_index[master_index]].data[k]=0x00000000;
                                }
                              }
                              manager->operations[master_index].num_sync_op--;
@@ -150,7 +150,7 @@ void dyn_manager_delete_op_single_master(TDynManager *manager,unsigned char mast
                                    manager->operations[master_index].bulk_op[j].address[k]=manager->operations[master_index].bulk_op[j+1].address[k];
                                    manager->operations[master_index].bulk_op[j].length[k]=manager->operations[master_index].bulk_op[j+1].length[k];
                                    manager->operations[master_index].bulk_op[j].ids[k]=manager->operations[master_index].bulk_op[j+1].ids[k];
-                                   manager->operations[master_index].bulk_op[j].data[k].data_addr=manager->operations[master_index].bulk_op[j+1].data[k].data_addr;
+                                   manager->operations[master_index].bulk_op[j].data[k]=manager->operations[master_index].bulk_op[j+1].data[k];
                                  }
                                }
                              }
@@ -166,7 +166,7 @@ void dyn_manager_delete_op_single_master(TDynManager *manager,unsigned char mast
                                  manager->operations[master_index].bulk_op[op->op_index[master_index]].address[k]=0x0000;
                                  manager->operations[master_index].bulk_op[op->op_index[master_index]].length[k]=0x0000;
                                  manager->operations[master_index].bulk_op[op->op_index[master_index]].ids[k]=0xFF;
-                                 manager->operations[master_index].bulk_op[op->op_index[master_index]].data[k].data_addr=0x00000000;
+                                 manager->operations[master_index].bulk_op[op->op_index[master_index]].data[k]=0x00000000;
                                }
                              }
                              manager->operations[master_index].num_bulk_op--;
@@ -217,7 +217,7 @@ void dyn_manager_init(TDynManager *manager)
       for(k=0;k<DYN_MANAGER_MAX_NUM_DEVICES;k++)
       {
         manager->operations[i].sync_op[j].ids[k]=0xFF;
-        manager->operations[i].sync_op[j].data[k].data_addr=0x00000000;
+        manager->operations[i].sync_op[j].data[k]=0x00000000;
       }
       manager->operations[i].sync_op[j].address=0x0000;
       manager->operations[i].sync_op[j].length=0x0000;
@@ -235,7 +235,7 @@ void dyn_manager_init(TDynManager *manager)
         manager->operations[i].bulk_op[j].ids[k]=0xFF;
         manager->operations[i].bulk_op[j].address[k]=0x0000;
         manager->operations[i].bulk_op[j].length[k]=0x0000;
-        manager->operations[i].bulk_op[j].data[k].data_addr=0x00000000;
+        manager->operations[i].bulk_op[j].data[k]=0x00000000;
       }
     }
     manager->operations[i].num_bulk_op=0;
@@ -258,6 +258,29 @@ void dyn_manager_init(TDynManager *manager)
     manager->op_handles[i].handle_index=i;
   }
   manager->num_ops=0x00;
+  /* initialize timer */
+  if(manager->init_timer!=0x00000000)
+    manager->init_timer();
+  dyn_manager_set_period(manager,DYN_MANAGER_DEFAULT_PERIOD_US);
+}
+
+void dyn_manager_set_period(TDynManager *manager,unsigned short int period_us)
+{
+  unsigned char i;
+
+  if(manager->set_period!=0x00000000)
+  {
+    manager->set_period(period_us);
+    for(i=0;i<DYN_MANAGER_MAX_NUM_MODULES;i++)
+      if(manager->modules[i]!=0x00000000 && manager->modules[i]->set_period!=0x00000000)
+         manager->modules[i]->set_period(manager->modules[i]->data,period_us);
+    manager->period_us=period_us;
+  }
+}
+
+unsigned short int dyn_manager_get_period(TDynManager *manager)
+{
+  return manager->period_us;
 }
 
 void dyn_manager_scan(TDynManager *manager)
@@ -266,11 +289,6 @@ void dyn_manager_scan(TDynManager *manager)
   unsigned char i,j,k,num=0;
   unsigned short int model;
 
-  // call all the modules init function
-  for(i=0;i<manager->num_modules;i++)
-    if(manager->modules[i]->init!=0x00000000)
-      manager->modules[i]->init();
-
   // scan all dynamixel buses
   for(i=0;i<manager->num_masters;i++)
   {
@@ -287,8 +305,9 @@ void dyn_manager_scan(TDynManager *manager)
         manager->devices[servo_ids[j]].master_index=i;
         manager->num_devices++;
         // pass the infor to each of the modules
-        for(k=0;k<manager->num_modules;k++)
-          dyn_module_add_device(manager->modules[k],servo_ids[j],model); 
+        for(k=0;k<DYN_MANAGER_MAX_NUM_MODULES;k++)
+          if(manager->modules[k]!=0x00000000)
+            dyn_module_add_device(manager->modules[k],servo_ids[j],model); 
       }
       // else ignore device
     }
@@ -296,7 +315,7 @@ void dyn_manager_scan(TDynManager *manager)
   // configure the operations
   for(i=0;i<manager->num_modules;i++)
     if(manager->modules[i]->setup!=0x00000000)
-      manager->modules[i]->setup();
+      manager->modules[i]->setup(manager->modules[i]->data);
 }
 
 void dyn_manager_add_master(TDynManager *manager,TDynamixelMaster *master)
@@ -318,6 +337,19 @@ unsigned char dyn_manager_get_num_masters(TDynManager *manager)
   return manager->num_masters;
 }
 
+TDynamixelMaster *dyn_manager_get_device_master(TDynManager *manager,unsigned char device_id)
+{
+  if(dyn_manager_check_id(manager,device_id)!=0xFF)
+    return manager->masters[dyn_manager_check_id(manager,device_id)];
+  else
+    return 0x00000000;
+}
+
+unsigned short int dyn_manager_get_device_model(TDynManager *manager,unsigned char device_id)
+{
+  return manager->devices[device_id].model;
+}
+
 void dyn_manager_add_module(TDynManager *manager,TDynModule *module)
 {
   unsigned char i;
@@ -489,7 +521,7 @@ void dyn_manager_single_op_change_data(TDynManager *manager,OP_HANDLE *op,unsign
 }
 
 // sync operation functions
-OP_HANDLE *dyn_manager_sync_op_new(TDynManager *manager,unsigned char mode,unsigned char num,unsigned char *ids,unsigned short int address, unsigned short int length, TWriteData *data)
+OP_HANDLE *dyn_manager_sync_op_new(TDynManager *manager,unsigned char mode,unsigned char num,unsigned char *ids,unsigned short int address, unsigned short int length, unsigned char * const data[])
 {
   unsigned char i,master_index,current_op_index;
   TDynManagerSyncOp *current_op;
@@ -522,7 +554,7 @@ OP_HANDLE *dyn_manager_sync_op_new(TDynManager *manager,unsigned char mode,unsig
           current_op->address=address;
           current_op->length=length;
           current_op->ids[current_op->num_devices]=ids[i];
-          current_op->data[current_op->num_devices].data_addr=data[i].data_addr;
+          current_op->data[current_op->num_devices]=data[i];
           current_op->num_devices++;
           manager->operations[master_index].num_sync_op++;
         }
@@ -540,7 +572,7 @@ OP_HANDLE *dyn_manager_sync_op_new(TDynManager *manager,unsigned char mode,unsig
       if(dyn_manager_id_present(current_op->num_devices,current_op->ids,ids[i])==0x00)
       {
         current_op->ids[current_op->num_devices]=ids[i];
-        current_op->data[current_op->num_devices].data_addr=data[i].data_addr;
+        current_op->data[current_op->num_devices]=data[i];
         current_op->num_devices++;
       }
     }
@@ -549,7 +581,7 @@ OP_HANDLE *dyn_manager_sync_op_new(TDynManager *manager,unsigned char mode,unsig
   return op_handle;
 }
 
-void dyn_manager_sync_op_add_devices(TDynManager *manager,OP_HANDLE *op,unsigned char num,unsigned char *ids,TWriteData *data)
+void dyn_manager_sync_op_add_devices(TDynManager *manager,OP_HANDLE *op,unsigned char num,unsigned char *ids,unsigned char * const data[])
 {
   TDynManagerSyncOp *current_op;
   unsigned char i,j;
@@ -566,7 +598,7 @@ void dyn_manager_sync_op_add_devices(TDynManager *manager,OP_HANDLE *op,unsigned
           if(current_op->num_devices<DYN_MANAGER_MAX_NUM_DEVICES)
           {
             current_op->ids[current_op->num_devices]=ids[i];
-            current_op->data[current_op->num_devices].data_addr=data[i].data_addr;
+            current_op->data[current_op->num_devices]=data[i];
             current_op->num_devices++;
           }
         }
@@ -594,13 +626,13 @@ void dyn_manager_sync_op_remove_devices(TDynManager *manager,OP_HANDLE *op,unsig
             for(k=device_index;k<current_op->num_devices;k++)
             {
               current_op->ids[k]=current_op->ids[k+1];
-              current_op->data[k].data_addr=current_op->data[k+1].data_addr;
+              current_op->data[k]=current_op->data[k+1];
             }
           }
           else
           {
             current_op->ids[device_index]=0xFF;
-            current_op->data[device_index].data_addr=0x00000000;
+            current_op->data[device_index]=0x00000000;
           }
           current_op->num_devices--;
         }
@@ -633,7 +665,7 @@ void dyn_manager_sync_op_change_length(TDynManager *manager,OP_HANDLE *op,unsign
   }
 }
 
-void dyn_manager_sync_op_change_data(TDynManager *manager,OP_HANDLE *op,unsigned char num,unsigned char *ids,TWriteData *data)
+void dyn_manager_sync_op_change_data(TDynManager *manager,OP_HANDLE *op,unsigned char num,unsigned char *ids,unsigned char * const data[])
 {
   TDynManagerSyncOp *current_op;
   unsigned char i,j,device_index;
@@ -646,14 +678,14 @@ void dyn_manager_sync_op_change_data(TDynManager *manager,OP_HANDLE *op,unsigned
       for(j=0;j<num;j++)
       {
         if((device_index=dyn_manager_id_present(current_op->num_devices,current_op->ids,ids[j]))!=0x00)
-          current_op->data[device_index].data_addr=data[j].data_addr;
+          current_op->data[device_index]=data[j];
       }
     }
   }
 }
 
 // bulk operation functions
-OP_HANDLE *dyn_manager_bulk_op_new(TDynManager *manager,unsigned char mode,unsigned char num,unsigned char *ids,unsigned short int *address, unsigned short int *length, TWriteData *data)
+OP_HANDLE *dyn_manager_bulk_op_new(TDynManager *manager,unsigned char mode,unsigned char num,unsigned char *ids,unsigned short int *address, unsigned short int *length, unsigned char * const data[])
 {
   unsigned char i,master_index,current_op_index;
   TDynManagerBulkOp *current_op;
@@ -686,7 +718,7 @@ OP_HANDLE *dyn_manager_bulk_op_new(TDynManager *manager,unsigned char mode,unsig
           current_op->address[current_op->num_devices]=address[i];
           current_op->length[current_op->num_devices]=length[i];
           current_op->ids[current_op->num_devices]=ids[i];
-          current_op->data[current_op->num_devices].data_addr=data[i].data_addr;
+          current_op->data[current_op->num_devices]=data[i];
           current_op->num_devices++;
           manager->operations[master_index].num_bulk_op++;
         }
@@ -706,7 +738,7 @@ OP_HANDLE *dyn_manager_bulk_op_new(TDynManager *manager,unsigned char mode,unsig
         current_op->address[current_op->num_devices]=address[i];
         current_op->length[current_op->num_devices]=length[i];
         current_op->ids[current_op->num_devices]=ids[i];
-        current_op->data[current_op->num_devices].data_addr=data[i].data_addr;
+        current_op->data[current_op->num_devices]=data[i];
         current_op->num_devices++;
       }
     }
@@ -715,7 +747,7 @@ OP_HANDLE *dyn_manager_bulk_op_new(TDynManager *manager,unsigned char mode,unsig
   return op_handle;
 }
 
-void dyn_manager_bulk_op_add_devices(TDynManager *manager,OP_HANDLE *op,unsigned char num,unsigned char *ids,unsigned short int *address, unsigned short int *length,TWriteData *data)
+void dyn_manager_bulk_op_add_devices(TDynManager *manager,OP_HANDLE *op,unsigned char num,unsigned char *ids,unsigned short int *address, unsigned short int *length,unsigned char * const data[])
 {
   TDynManagerBulkOp *current_op;
   unsigned char i,j;
@@ -734,7 +766,7 @@ void dyn_manager_bulk_op_add_devices(TDynManager *manager,OP_HANDLE *op,unsigned
             current_op->ids[current_op->num_devices]=ids[i];
             current_op->address[current_op->num_devices]=address[i];
             current_op->length[current_op->num_devices]=length[i];
-            current_op->data[current_op->num_devices].data_addr=data[i].data_addr;
+            current_op->data[current_op->num_devices]=data[i];
             current_op->num_devices++;
           }
         }
@@ -764,7 +796,7 @@ void dyn_manager_bulk_op_remove_devices(TDynManager *manager,OP_HANDLE *op,unsig
               current_op->ids[k]=current_op->ids[k+1];
               current_op->address[k]=current_op->address[k+1];
               current_op->length[k]=current_op->length[k+1];
-              current_op->data[k].data_addr=current_op->data[k+1].data_addr;
+              current_op->data[k]=current_op->data[k+1];
             }
           }
           else
@@ -772,7 +804,7 @@ void dyn_manager_bulk_op_remove_devices(TDynManager *manager,OP_HANDLE *op,unsig
             current_op->ids[device_index]=0xFF;
             current_op->address[device_index]=0x0000;
             current_op->length[device_index]=0x0000;
-            current_op->data[device_index].data_addr=0x00000000;
+            current_op->data[device_index]=0x00000000;
           }
           current_op->num_devices--;
         }
@@ -821,7 +853,7 @@ void dyn_manager_bulk_op_change_length(TDynManager *manager,OP_HANDLE *op,unsign
   }
 }
 
-void dyn_manager_bulk_op_change_data(TDynManager *manager,OP_HANDLE *op,unsigned char num,unsigned char *ids,TWriteData *data)
+void dyn_manager_bulk_op_change_data(TDynManager *manager,OP_HANDLE *op,unsigned char num,unsigned char *ids,unsigned char * const data[])
 {
   TDynManagerBulkOp *current_op;
   unsigned char i,j,device_index;
@@ -834,7 +866,7 @@ void dyn_manager_bulk_op_change_data(TDynManager *manager,OP_HANDLE *op,unsigned
       for(j=0;j<num;j++)
       {
         if((device_index=dyn_manager_id_present(current_op->num_devices,current_op->ids,ids[j]))!=0x00)
-          current_op->data[device_index].data_addr=data[j].data_addr;
+          current_op->data[device_index]=data[j];
       }
     }
   }
@@ -867,11 +899,14 @@ void dyn_manager_loop(TDynManager *manager)
   // execute the pre_process functions for all modules
   for(i=0;i<manager->num_modules;i++)
   {
-    modules_period_count[i]++;
-    if(modules_period_count[i]==manager->modules[i]->period_count)
+    if(manager->modules[i]->enabled) 
     {
-      if(manager->modules[i]->pre_process!=0x00000000)
-        manager->modules[i]->pre_process();
+      modules_period_count[i]++;
+      if(modules_period_count[i]==manager->modules[i]->period_count)
+      {
+        if(manager->modules[i]->pre_process!=0x00000000)
+          manager->modules[i]->pre_process(manager->modules[i]->data);
+      }
     }
   }
 
@@ -882,7 +917,7 @@ void dyn_manager_loop(TDynManager *manager)
       switch(states[i])
       {
         case start_single_ops: if(current_single_op[i]>=manager->operations[i].num_single_op)
-                                 states[i]=start_sync_ops;
+                                 states[i]=start_bulk_ops;
                                else
                                {
                                  single_op_period_count[current_single_op[i]]++;
@@ -921,7 +956,10 @@ void dyn_manager_loop(TDynManager *manager)
                               }
                               break;
         case start_sync_ops: if(current_sync_op[i]>=manager->operations[i].num_sync_op)
-                               states[i]=start_bulk_ops;
+                             {
+                               states[i]=ops_done;
+                               loop_done--;
+                             }
                              else
                              {
                                sync_op_period_count[current_sync_op[i]]++;
@@ -960,10 +998,7 @@ void dyn_manager_loop(TDynManager *manager)
                             }
                             break;
         case start_bulk_ops: if(current_bulk_op[i]>=manager->operations[i].num_bulk_op)
-                             {
-                               states[i]=ops_done;
-                               loop_done--;
-                             }
+                               states[i]=start_sync_ops;
                              else
                              {
                                bulk_op_period_count[current_bulk_op[i]]++;
@@ -1010,11 +1045,14 @@ void dyn_manager_loop(TDynManager *manager)
   // execute the pre_process functions for all modules
   for(i=0;i<manager->num_modules;i++)
   {
-    if(modules_period_count[i]==manager->modules[i]->period_count)
+    if(manager->modules[i]->enabled)
     {
-      if(manager->modules[i]->post_process!=0x00000000)
-        manager->modules[i]->post_process();
-      modules_period_count[i]=0;
+      if(modules_period_count[i]==manager->modules[i]->period_count)
+      {
+        if(manager->modules[i]->post_process!=0x00000000)
+          manager->modules[i]->post_process(manager->modules[i]->data);
+        modules_period_count[i]=0;
+      }
     }
   }
 }
diff --git a/dynamixel_manager/src/dyn_module.c b/dynamixel_manager/src/dyn_module.c
index a84e3451ca878eb4b5f45860ad27cda97a92f04e..8f2e76b2ab3f6e8d5312ca344b5b5e3e313cd017 100644
--- a/dynamixel_manager/src/dyn_module.c
+++ b/dynamixel_manager/src/dyn_module.c
@@ -11,11 +11,27 @@ void dyn_module_init(TDynModule *module)
     module->assigned_ids[i]=0x00;
   module->num_assigned_ids=0x00;
   module->period_count=0x00;
-  module->init=0x00000000;
+  module->enabled=0x00;
   module->add_device=0x00000000;
   module->setup=0x00000000;
   module->pre_process=0x00000000;
   module->post_process=0x00000000;
+  module->data=0x00000000;
+}
+
+inline void dyn_module_enable(TDynModule *module)
+{
+  module->enabled=0x01;
+}
+
+inline void dyn_module_disable(TDynModule *module)
+{
+  module->enabled=0x00;
+}
+
+inline unsigned char dyn_module_is_enabled(TDynModule *module)
+{
+  return module->enabled;
 }
 
 void dyn_module_add_model(TDynModule *module,unsigned short int model)
@@ -32,7 +48,7 @@ void dyn_module_add_model(TDynModule *module,unsigned short int model)
   }
 }
 
-unsigned char dyn_module_get_num_models(TDynModule *module)
+inline unsigned char dyn_module_get_num_models(TDynModule *module)
 {
   return module->num_models;
 }
@@ -45,17 +61,16 @@ void dyn_module_add_device(TDynModule *module,unsigned char id, unsigned short i
   {
     if(model==module->models[i])
     {
+      module->assigned_ids[id]=0x01;
+      module->num_assigned_ids++;
       if(module->add_device!=0x00000000)
-      {
-        module->assigned_ids[id]=0x01;
-        module->num_assigned_ids++;
-        module->add_device(id,model);
-      }
+        module->add_device(module->data,id,model);
+      break;
     }
   }
 }
 
-unsigned char dyn_module_get_num_assigned_devices(TDynModule *module)
+inline unsigned char dyn_module_get_num_assigned_devices(TDynModule *module)
 {
   return module->num_assigned_ids;
 }
@@ -76,33 +91,9 @@ void dyn_module_set_period(TDynModule *module,unsigned char period)
     module->period_count=period;
 }
 
-unsigned char dyn_module_get_period(TDynModule *module)
+inline unsigned char dyn_module_get_period(TDynModule *module)
 {
   return module->period_count;
 }
 
-void dyn_module_set_init_fctn(TDynModule *module,void (*init)(void))
-{
-  module->init=init;
-}
-
-void dyn_module_set_add_device_fctn(TDynModule *module,void (*add_device)(unsigned char id,unsigned short int model))
-{
-  module->add_device=add_device;
-}
-
-void dyn_module_set_setup_fctn(TDynModule *module,void (*setup)(void))
-{
-  module->setup=setup;
-}
-
-void dyn_module_set_pre_process_fctn(TDynModule *module,void (*pre_process)(void))
-{
-  module->pre_process=pre_process;
-}
-
-void dyn_module_set_post_process_fctn(TDynModule *module,void (*post_process)(void))
-{
-  module->post_process=post_process;
-}
 
diff --git a/dynamixel_manager/src/modules/action.c b/dynamixel_manager/src/modules/action.c
new file mode 100755
index 0000000000000000000000000000000000000000..ea816ab70fd8b5fb941a6d98c1ecd37825016141
--- /dev/null
+++ b/dynamixel_manager/src/modules/action.c
@@ -0,0 +1,556 @@
+#include "action.h"
+#include "motion_pages.h"
+
+#define SPEED_BASE_SCHEDULE 0x00
+#define TIME_BASE_SCHEDULE  0x0A
+
+// private variables
+typedef enum {ACTION_PRE,ACTION_MAIN,ACTION_POST,ACTION_PAUSE} action_states;
+TMotionModule action_module;
+
+TPage action_next_page;
+TPage action_current_page;
+unsigned char action_current_step_index;
+unsigned char action_current_page_index;
+// angle variables
+long long int action_moving_angles[PAGE_MAX_NUM_SERVOS];// fixed point 48|16 format
+long long int action_start_angles[PAGE_MAX_NUM_SERVOS];// fixed point 48|16 format
+// speed variables
+long long int action_start_speed[PAGE_MAX_NUM_SERVOS];// fixed point 48|16 format
+long long int action_main_speed[PAGE_MAX_NUM_SERVOS];// fixed point 48|16 format
+// control variables
+unsigned char action_end,action_stop;
+unsigned char action_zero_speed_finish[PAGE_MAX_NUM_SERVOS];
+unsigned char action_next_index;
+unsigned char action_running;
+// time variables (in time units (7.8 ms each time unit))
+long long int action_total_time;// fixed point 48|16 format
+long long int action_pre_time;// fixed point 48|16 format
+long long int action_main_time;// fixed point 48|16 format
+long long int action_step_time;// fixed point 48|16 format
+long long int action_pause_time;// fixed point 48|16 format
+long long int action_current_time;// fixed point 48|16 format
+long long int action_section_time;// fixed point 48|16 format
+long long int action_period;
+
+// private functions
+void action_load_next_step(void)
+{
+  // page and step information
+  static char num_repetitions=0;
+  // angle variables
+  short int next_angle;// information from the flash memory (fixed point 9|7 format)
+  long long int max_angle;// fixed point format 48|16 format
+  long long int tmp_angle;// fixed point format 48|16 format
+  long long int angle;// fixed point format 48|16 format
+  long long int target_angles;// fixed point 48|16 format
+  long long int next_angles;// fixed point 48|16 format
+  long long int action_pre_time_initial_speed_angle;// fixed point 48|16 format
+  long long int moving_angle;// fixed point 48|16 format
+  // time variables
+  long long int accel_time_num;// fixed point 48|16 format
+  long long int zero_speed_divider;// fixed point 48|16 format
+  long long int non_zero_speed_divider;// fixed point 48|16 format
+  // control variables
+  unsigned char dir_change;
+  // control information
+  unsigned char i=0;
+
+  action_current_step_index++;
+  if(action_current_step_index>=action_current_page.header.stepnum)// the last step has been executed
+  {
+    if(action_current_page.header.stepnum==1)
+    {
+      if(action_stop)
+        action_next_index=action_current_page.header.exit;
+      else
+      {
+        num_repetitions--;
+        if(num_repetitions>0)
+          action_next_index=action_current_page_index;
+        else
+          action_next_index=action_current_page.header.next;
+      }
+      if(action_next_index==0)
+        action_end=0x01;
+      else
+      {
+        if(action_next_index!=action_current_page_index)
+        {
+          pages_get_page(action_next_index,&action_next_page);
+          if(!pages_check_checksum(&action_next_page))
+            action_end=0x01;
+        }
+        if(action_next_page.header.repeat==0 || action_next_page.header.stepnum==0)
+          action_end=0x01;
+      }
+    }
+    pages_copy_page(&action_next_page,&action_current_page);// make the next page active
+    if(action_current_page_index!=action_next_index)
+      num_repetitions=action_current_page.header.repeat;
+    action_current_step_index=0;
+    action_current_page_index=action_next_index;
+  }
+  else if(action_current_step_index==action_current_page.header.stepnum-1)// it is the last step
+  {
+    if(action_stop)
+      action_next_index=action_current_page.header.exit;
+    else
+    {
+      num_repetitions--;
+      if(num_repetitions>0)
+        action_next_index=action_current_page_index;
+      else
+        action_next_index=action_current_page.header.next;
+    }
+    if(action_next_index==0)
+      action_end=0x01;
+    else
+    {
+      if(action_next_index!=action_current_page_index)
+      {
+        pages_get_page(action_next_index,&action_next_page);
+        if(!pages_check_checksum(&action_next_page))
+          action_end=0x01;
+      }
+      if(action_next_page.header.repeat==0 || action_next_page.header.stepnum==0)
+        action_end=0x01;
+    }
+  }
+  // compute trajectory
+  action_pause_time=(action_current_page.steps[action_current_step_index].pause*action_current_page.header.speed)>>5;
+  action_pause_time=action_pause_time<<9;
+  action_step_time=(action_current_page.steps[action_current_step_index].time*action_current_page.header.speed)>>5;
+  action_step_time=action_step_time<<9;
+  if(action_step_time<action_period)
+    action_step_time=action_period;// 0.078 in 16|16 format
+  max_angle=0;
+  for(i=0;i<PAGE_MAX_NUM_SERVOS;i++)
+  {
+    if(mmanager_get_module(action_module.manager,i)==MM_ACTION)
+    {
+      angle=action_current_page.steps[action_current_step_index].position[i];
+      if(angle==0x5A00)// bigger than 180
+        target_angles=action_module.manager->servo_values[i].target_angle;
+      else
+        target_angles=angle<<9;
+      action_moving_angles[i]=target_angles-action_module.manager->servo_values[i].target_angle;
+      if(action_end)
+        next_angles=target_angles;
+      else
+      {
+        if(action_current_step_index==action_current_page.header.stepnum-1)
+          next_angle=action_next_page.steps[0].position[i];
+        else
+          next_angle=action_current_page.steps[action_current_step_index+1].position[i];
+        if(next_angle==0x5A00)
+          next_angles=target_angles;
+        else
+          next_angles=next_angle<<9;
+      }
+      // check changes in direction
+      if(((action_module.manager->servo_values[i].target_angle < target_angles) && (target_angles < next_angles)) ||
+         ((action_module.manager->servo_values[i].target_angle > target_angles) && (target_angles > next_angles)))
+        dir_change=0x00;
+      else
+        dir_change=0x01;
+      // check the type of ending
+      if(dir_change || action_pause_time>0 || action_end)
+        action_zero_speed_finish[i]=0x01;
+      else
+        action_zero_speed_finish[i]=0x00;
+      // find the maximum angle of motion in speed base schedule
+      if(action_current_page.header.schedule==SPEED_BASE_SCHEDULE)// speed base schedule
+      {
+        // fer el valor absolut
+        if(action_moving_angles[i]<0)
+          tmp_angle=-action_moving_angles[i];
+        else
+          tmp_angle=action_moving_angles[i];
+        if(tmp_angle>max_angle)
+          max_angle=tmp_angle;
+      }
+      action_module.manager->servo_values[i].cw_compliance=(1<<(action_current_page.header.slope[i]&0x0F));
+      action_module.manager->servo_values[i].ccw_compliance=(1<<((action_current_page.header.slope[i]&0xF0)>>4));
+    }
+  }
+  if(action_current_page.header.schedule==SPEED_BASE_SCHEDULE)
+    action_step_time=(max_angle*256)/(action_current_page.steps[action_current_step_index].time*720);
+  accel_time_num=action_current_page.header.accel;
+  accel_time_num=accel_time_num<<9;
+  if(action_step_time<=(accel_time_num<<1))
+  {
+    if(action_step_time==0)
+      accel_time_num=0;
+    else
+    {
+      accel_time_num=(action_step_time-action_period)>>1;
+      if(accel_time_num==0)
+        action_step_time=0;
+    }
+  }
+  action_total_time=action_step_time;
+  action_pre_time=accel_time_num;
+  action_main_time=action_total_time-action_pre_time;
+  non_zero_speed_divider=(action_pre_time>>1)+action_main_time;
+  if(non_zero_speed_divider<action_period)
+    non_zero_speed_divider=action_period;
+  zero_speed_divider=action_main_time;
+  if(zero_speed_divider<action_period)
+    zero_speed_divider=action_period;
+  for(i=0;i<PAGE_MAX_NUM_SERVOS;i++)
+  {
+    if(mmanager_get_module(action_module.manager,i)==MM_ACTION)
+    {
+      action_pre_time_initial_speed_angle=(action_start_speed[i]*action_pre_time)>>1;
+      moving_angle=action_moving_angles[i]<<16;
+      if(action_zero_speed_finish[i])
+        action_main_speed[i]=(moving_angle-action_pre_time_initial_speed_angle)/zero_speed_divider;
+      else
+        action_main_speed[i]=(moving_angle-action_pre_time_initial_speed_angle)/non_zero_speed_divider;
+//      if((action_main_speed[i]>>16)>info.max_speed)
+//        action_main_speed[i]=(info.max_speed*65536);
+//      else if((action_main_speed[i]>>16)<-info.max_speed)
+//        action_main_speed[i]=-(info.max_speed*65536);
+    }
+  }
+}
+
+void action_finish(void)
+{
+  // set the internal state machine to the idle state
+  action_end=0x00;
+  // change the internal state 
+  action_running=0x00;
+}
+
+void action_set_period(void *module,unsigned short int period_us)
+{
+  // load the current period 
+  action_period=(period_us<<16)/1000000;
+}
+
+void action_set_module(void *module,unsigned char servo_id)
+{
+
+}
+
+void action_pre_process(void *module)
+{
+  unsigned char i;
+  // angle variables 
+  static long long int accel_angles[PAGE_MAX_NUM_SERVOS];// fixed point 48|16 format
+  static long long int main_angles[PAGE_MAX_NUM_SERVOS];// fixed point 48|16 format
+  // speed variables (in controller units)
+  static long long int current_speed[PAGE_MAX_NUM_SERVOS]={0};// fixed point 48|16 format
+  long long int delta_speed;
+  // control variables 
+  static action_states state=ACTION_PAUSE;
+
+  if(action_running==0x01)
+  {
+    action_current_time+=action_period;
+    switch(state)
+    {
+      case ACTION_PRE: if(action_current_time>action_section_time)
+                       {
+                         for(i=0;i<PAGE_MAX_NUM_SERVOS;i++)
+                         {
+                           if(mmanager_get_module(action_module.manager,i)==MM_ACTION)
+                           {
+                             /* the last segment of the pre section */
+                             delta_speed=(action_main_speed[i]-action_start_speed[i]);
+                             current_speed[i]=action_start_speed[i]+delta_speed;
+                             accel_angles[i]=(action_start_speed[i]*action_section_time+((delta_speed*action_section_time)>>1))>>16;
+                             action_module.manager->servo_values[i].target_angle=action_start_angles[i]+accel_angles[i];
+                             /* update of the state */
+                             if(!action_zero_speed_finish[i])
+                             {
+                               if((action_step_time-action_pre_time)==0)
+                                 main_angles[i]=0;
+                               else
+                                 main_angles[i]=((action_moving_angles[i]-accel_angles[i])*(action_step_time-(action_pre_time<<1)))/(action_step_time-action_pre_time);
+                               action_start_angles[i]=action_module.manager->servo_values[i].target_angle;
+                             }
+                             else
+                             {
+                               main_angles[i]=action_moving_angles[i]-accel_angles[i]-(((action_main_speed[i]*action_pre_time)>>1)>>16);
+                               action_start_angles[i]=action_module.manager->servo_values[i].target_angle;
+                             }
+                             /* the first step of the main section */
+                             action_module.manager->servo_values[i].target_angle=action_start_angles[i]+(main_angles[i]*(action_current_time-action_section_time))/(action_step_time-(action_pre_time<<1));
+                             current_speed[i]=action_main_speed[i];
+                           }
+                         }
+                         action_current_time=action_current_time-action_section_time;
+                         action_section_time=action_step_time-(action_pre_time<<1);
+                         state=ACTION_MAIN;
+                       }
+                       else
+                       {
+                         for(i=0;i<PAGE_MAX_NUM_SERVOS;i++)
+                         {
+                           if(mmanager_get_module(action_module.manager,i)==MM_ACTION)
+                           {
+                             delta_speed=((action_main_speed[i]-action_start_speed[i])*action_current_time)/action_section_time;
+                             current_speed[i]=action_start_speed[i]+delta_speed;
+                             accel_angles[i]=((action_start_speed[i]*action_current_time)+((delta_speed*action_current_time)>>1))>>16;
+                             action_module.manager->servo_values[i].target_angle=action_start_angles[i]+accel_angles[i];
+                           }
+                         }
+                         state=ACTION_PRE;
+                       }
+                       break;
+      case ACTION_MAIN: if(action_current_time>action_section_time)
+                        {
+                          for(i=0;i<PAGE_MAX_NUM_SERVOS;i++)
+                          {
+                            if(mmanager_get_module(action_module.manager,i)==MM_ACTION)
+                            {
+                              /* last segment of the main section */
+                              action_module.manager->servo_values[i].target_angle=action_start_angles[i]+main_angles[i];
+                              current_speed[i]=action_main_speed[i];
+                              /* update state */
+                              action_start_angles[i]=action_module.manager->servo_values[i].target_angle;
+                              main_angles[i]=action_moving_angles[i]-main_angles[i]-accel_angles[i];
+                              /* first segment of the post section */
+                              if(action_zero_speed_finish[i])
+                              {
+                                delta_speed=((0.0-action_main_speed[i])*(action_current_time-action_section_time))/action_pre_time;
+                                current_speed[i]=action_main_speed[i]+delta_speed;
+                                action_module.manager->servo_values[i].target_angle=action_start_angles[i]+(((action_main_speed[i]*(action_current_time-action_section_time))+((delta_speed*(action_current_time-action_section_time))>>1))>>16);
+                              }
+                              else
+                              {
+                                action_module.manager->servo_values[i].target_angle=action_start_angles[i]+((main_angles[i]*(action_current_time-action_section_time))/action_pre_time);
+                                current_speed[i]=action_main_speed[i];
+                              }
+                            }
+                          }
+                          action_current_time=action_current_time-action_section_time;
+                          action_section_time=action_pre_time;
+                          state=ACTION_POST;
+                        }
+                        else
+                        {
+                          for(i=0;i<PAGE_MAX_NUM_SERVOS;i++)
+                          {
+                            if(mmanager_get_module(action_module.manager,i)==MM_ACTION)
+                            {
+                              action_module.manager->servo_values[i].target_angle=action_start_angles[i]+(main_angles[i]*action_current_time)/action_section_time;
+                              current_speed[i]=action_main_speed[i];
+                            }
+                          }
+                          state=ACTION_MAIN;
+                        }
+                        break;
+      case ACTION_POST: if(action_current_time>action_section_time)
+                        {
+                          for(i=0;i<PAGE_MAX_NUM_SERVOS;i++)
+                          {
+                            if(mmanager_get_module(action_module.manager,i)==MM_ACTION)
+                            {
+                              /* last segment of the post section */
+                              if(action_zero_speed_finish[i])
+                              {
+                                delta_speed=-action_main_speed[i];
+                                current_speed[i]=action_main_speed[i]+delta_speed;
+                                action_module.manager->servo_values[i].target_angle=action_start_angles[i]+(((action_main_speed[i]*action_section_time)+((delta_speed*action_section_time)>>1))>>16);
+                              }
+                              else
+                              {
+                                action_module.manager->servo_values[i].target_angle=action_start_angles[i]+main_angles[i];
+                                current_speed[i]=action_main_speed[i];
+                              }
+                              /* update state */
+                              action_start_angles[i]=action_module.manager->servo_values[i].target_angle;
+                              action_start_speed[i]=current_speed[i];
+                            }
+                          }
+                          /* load the next step */
+                          if(action_pause_time==0)
+                          {
+                            if(action_end)
+                            {
+                              state=ACTION_PAUSE;
+                              action_finish();
+                            }
+                            else
+                            {
+                              action_load_next_step();
+                              /* first step of the next section */
+                              for(i=0;i<PAGE_MAX_NUM_SERVOS;i++)
+                              {
+                                if(mmanager_get_module(action_module.manager,i)==MM_ACTION)
+                                {
+                                  delta_speed=((action_main_speed[i]-action_start_speed[i])*(action_current_time-action_section_time))/action_pre_time;
+                                  current_speed[i]=action_start_speed[i]+delta_speed;
+                                  accel_angles[i]=(((action_start_speed[i]*(action_current_time-action_section_time))+((delta_speed*(action_current_time-action_section_time))>>1))>>16);
+                                  action_module.manager->servo_values[i].target_angle=action_start_angles[i]+accel_angles[i];
+                                }
+                              }
+                              action_current_time=action_current_time-action_section_time;
+                              action_section_time=action_pre_time;
+                              state=ACTION_PRE;
+                            }
+                          }
+                          else
+                          {
+                            action_current_time=action_current_time-action_section_time;
+                            action_section_time=action_pause_time;
+                            state=ACTION_PAUSE;
+                          }
+                        }
+                        else
+                        {
+                          for(i=0;i<PAGE_MAX_NUM_SERVOS;i++)
+                          {
+                            if(mmanager_get_module(action_module.manager,i)==MM_ACTION)
+                            {
+                              if(action_zero_speed_finish[i])
+                              {
+                                delta_speed=((0.0-action_main_speed[i])*action_current_time)/action_section_time;
+                                current_speed[i]=action_main_speed[i]+delta_speed;
+                                action_module.manager->servo_values[i].target_angle=action_start_angles[i]+(((action_main_speed[i]*action_current_time)+((delta_speed*action_current_time)>>1))>>16);
+                              }
+                              else
+                              {
+                                action_module.manager->servo_values[i].target_angle=action_start_angles[i]+(main_angles[i]*action_current_time)/action_section_time;
+                                current_speed[i]=action_main_speed[i];
+                              }
+                            }
+                          }
+                          state=ACTION_POST;
+                        }
+                        break;
+      case ACTION_PAUSE: if(action_current_time>action_section_time)
+                         {
+                           if(action_end)
+                           {
+                             state=ACTION_PAUSE;
+                             action_finish();
+                           }
+                           else
+                           {
+                             // find next page to execute
+                             action_load_next_step();
+                             /* first step of the next section */
+                             for(i=0;i<PAGE_MAX_NUM_SERVOS;i++)
+                             {
+                               if(mmanager_get_module(action_module.manager,i)==MM_ACTION)
+                               {
+                                 delta_speed=((action_main_speed[i]-action_start_speed[i])*(action_current_time-action_section_time))/action_pre_time;
+                                 current_speed[i]=action_start_speed[i]+delta_speed;
+                                 accel_angles[i]=(((action_start_speed[i]*(action_current_time-action_section_time))+((delta_speed*(action_current_time-action_section_time))>>1))>>16);
+                                 action_module.manager->servo_values[i].target_angle=action_start_angles[i]+accel_angles[i];
+                               }
+                             }
+                             action_current_time=action_current_time-action_section_time;
+                             action_section_time=action_pre_time;
+                             state=ACTION_PRE;
+                           }
+                         }
+                         else// pause section still active
+                           state=ACTION_PAUSE;
+                         break;
+      default: break;
+    }
+  }
+}
+
+// public functions
+void action_init(void)
+{
+  unsigned char i;
+
+  /* initialize the motion module */
+  mmodule_init(&action_module);
+  action_module.id=MM_ACTION;
+  action_module.set_period=action_set_period;
+  action_module.set_module=action_set_module;
+  action_module.pre_process=action_pre_process;
+
+  // init manager_current_angles with the current position of the servos
+  for(i=0;i<PAGE_MAX_NUM_SERVOS;i++)
+  {
+    // angle variables
+    action_moving_angles[i]=0;// fixed point 48|16 format
+    action_start_angles[i]=0;
+    // speed variables
+    action_start_speed[i]=0;// fixed point 48|16 format
+    action_main_speed[i]=0;// fixed point 48|16 format
+    // control variables
+    action_zero_speed_finish[i]=0x00;
+  }
+  // clear the contents of the next page
+  pages_clear_page(&action_next_page);
+  pages_clear_page(&action_current_page);
+  action_current_page_index=0;
+  action_current_step_index=-1;
+  // control variables
+  action_end=0x00;
+  action_stop=0x00;
+  action_running=0x00;
+  action_next_index=0;
+  // time variables (in time units (7.8 ms each time unit))
+  action_total_time=0;// fixed point 48|16 format
+  action_pre_time=0;// fixed point 48|16 format
+  action_main_time=0;// fixed point 48|16 format
+  action_step_time=0;// fixed point 48|16 format
+  action_pause_time=0;// fixed point 48|16 format
+  action_current_time=0;// fixed point 48|16 format
+  action_section_time=0;// fixed point 48|16 format
+  action_period=(DYN_MANAGER_DEFAULT_PERIOD_US<<16)/1000000;
+}
+
+TMotionModule *action_get_module(void)
+{
+  return &action_module;
+}
+
+unsigned char action_load_page(unsigned char page_id)
+{
+  action_next_index=page_id;
+  pages_get_page(action_next_index,&action_current_page);
+  pages_get_page(action_current_page.header.next,&action_next_page);
+  if(!pages_check_checksum(&action_current_page))
+    return 0x00;
+  if(!pages_check_checksum(&action_next_page))
+    return 0x00;
+
+  return 0x01;
+}
+
+void action_start_page(void)
+{
+  unsigned char i;
+
+  for(i=0;i<PAGE_MAX_NUM_SERVOS;i++)
+    action_start_angles[i]=action_module.manager->servo_values[i].target_angle;
+  action_stop=0x00;
+  action_current_time=0;
+  action_section_time=0; 
+  action_current_step_index=-1;
+  /* clear the interrupt flag */
+  action_running=0x01;
+}
+
+void action_stop_page(void)
+{
+  action_stop=0x01;
+}
+
+unsigned char action_is_running(void)
+{
+  return action_running;
+}
+
+unsigned char action_get_current_page(void)
+{
+  return action_current_page_index;
+}
+
+unsigned char action_get_current_step(void)
+{
+  return action_current_step_index;
+}
diff --git a/dynamixel_manager/src/modules/motion_manager.c b/dynamixel_manager/src/modules/motion_manager.c
new file mode 100644
index 0000000000000000000000000000000000000000..bbcca07ee8d43db53294443c0cf49723ccad98df
--- /dev/null
+++ b/dynamixel_manager/src/modules/motion_manager.c
@@ -0,0 +1,420 @@
+#include "motion_manager.h"
+#include "motion_module.h"
+#include "dyn_devices.h"
+#include "dyn_servos.h"
+
+/* private functions */
+inline unsigned short int mmanager_angle_to_value(TMotionManager *mmanager,unsigned char servo_id,short int angle)
+{
+  return ((angle+mmanager->servo_configs[servo_id].center_angle)*mmanager->servo_configs[servo_id].encoder_resolution)/mmanager->servo_configs[servo_id].max_angle;
+}
+
+inline short int mmanager_value_to_angle(TMotionManager *mmanager,unsigned char servo_id,unsigned short int value)
+{
+  return (((short int)((value*mmanager->servo_configs[servo_id].max_angle)/mmanager->servo_configs[servo_id].encoder_resolution))-mmanager->servo_configs[servo_id].center_angle);
+}
+
+void mmanager_compute_targets(TMotionManager *mmanager)
+{
+  short int offsets[DYN_MANAGER_MAX_NUM_DEVICES]={0};
+  unsigned char i;
+  short int angle;
+
+  // compute the balance offsets
+  if(mmanager->balance_enabled==0x01)
+    mmanager->balance(offsets);
+  // convert the angles to digital values
+  for(i=0;i<DYN_MANAGER_MAX_NUM_DEVICES;i++)
+  {
+    if(mmanager->servo_values[i].enabled)// servo is enabled and present
+    {
+      angle=(mmanager->servo_values[i].target_angle>>9)+offsets[i]+(mmanager->servo_values[i].offset<<3);
+      //>>16 from the action codification, <<7 from the manager codification
+      mmanager->servo_values[i].target_value=mmanager_angle_to_value(mmanager,i,angle);
+    }
+  }
+}
+
+void mmanager_compute_angles(TMotionManager *mmanager)
+{
+  unsigned char i;
+
+  // convert the digital values to angles
+  for(i=0;i<DYN_MANAGER_MAX_NUM_DEVICES;i++)
+  {
+    if(mmanager->servo_values[i].enabled)// servo is enabled and present
+      mmanager->servo_values[i].current_angle=mmanager_value_to_angle(mmanager,i,mmanager->servo_values[i].current_value);
+  }
+}
+
+void mmanager_add_device(TMotionManager *mmanager,unsigned char id,unsigned short int model)
+{
+  unsigned short int cw_value,ccw_value;
+
+  if(id<DYN_MANAGER_MAX_NUM_DEVICES)
+  {
+    switch(model)
+    {
+      case SERVO_DX113: mmanager->servo_configs[id].encoder_resolution=1023;
+                        mmanager->servo_configs[id].gear_ratio=193;
+                        mmanager->servo_configs[id].max_angle=300<<7;
+                        mmanager->servo_configs[id].center_angle=150<<7;
+                        mmanager->servo_configs[id].max_speed=324;
+                        break;
+      case SERVO_DX116: mmanager->servo_configs[id].encoder_resolution=1023;
+                        mmanager->servo_configs[id].gear_ratio=143;
+                        mmanager->servo_configs[id].max_angle=300<<7;
+                        mmanager->servo_configs[id].center_angle=150<<7;
+                        mmanager->servo_configs[id].max_speed=354;
+                        break;
+      case SERVO_DX117: mmanager->servo_configs[id].encoder_resolution=1023;
+                        mmanager->servo_configs[id].gear_ratio=193;
+                        mmanager->servo_configs[id].max_angle=300<<7;
+                        mmanager->servo_configs[id].center_angle=150<<7;
+                        mmanager->servo_configs[id].max_speed=510;
+                        break;
+      case SERVO_AX12A: mmanager->servo_configs[id].encoder_resolution=1023;
+                        mmanager->servo_configs[id].gear_ratio=254;
+                        mmanager->servo_configs[id].max_angle=300<<7;
+                        mmanager->servo_configs[id].center_angle=150<<7;
+                        mmanager->servo_configs[id].max_speed=354;
+                        break;
+      case SERVO_AX12W: mmanager->servo_configs[id].encoder_resolution=1023;
+                        mmanager->servo_configs[id].gear_ratio=32;
+                        mmanager->servo_configs[id].max_angle=300<<7;
+                        mmanager->servo_configs[id].center_angle=150<<7;
+                        mmanager->servo_configs[id].max_speed=2830;
+                        break;
+      case SERVO_AX18A: mmanager->servo_configs[id].encoder_resolution=1023;
+                        mmanager->servo_configs[id].gear_ratio=254;
+                        mmanager->servo_configs[id].max_angle=300<<7;
+                        mmanager->servo_configs[id].center_angle=150<<7;
+                        mmanager->servo_configs[id].max_speed=582;
+                        break;
+      case SERVO_RX10: mmanager->servo_configs[id].encoder_resolution=1023;
+                       mmanager->servo_configs[id].gear_ratio=193;
+                       mmanager->servo_configs[id].max_angle=300<<7;
+                       mmanager->servo_configs[id].center_angle=150<<7;
+                       mmanager->servo_configs[id].max_speed=324;
+                       break;
+      case SERVO_MX12W: mmanager->servo_configs[id].encoder_resolution=4095;
+                        mmanager->servo_configs[id].gear_ratio=32;
+                        mmanager->servo_configs[id].max_angle=360<<7;
+                        mmanager->servo_configs[id].center_angle=180<<7;
+                        mmanager->servo_configs[id].max_speed=2820;
+                        break;
+      case SERVO_MX28: mmanager->servo_configs[id].encoder_resolution=4095;
+                       mmanager->servo_configs[id].gear_ratio=193;
+                       mmanager->servo_configs[id].max_angle=360<<7;
+                       mmanager->servo_configs[id].center_angle=180<<7;
+                       mmanager->servo_configs[id].max_speed=330;
+                       break;
+      case SERVO_RX24F: mmanager->servo_configs[id].encoder_resolution=1023;
+                        mmanager->servo_configs[id].gear_ratio=193;
+                        mmanager->servo_configs[id].max_angle=300<<7;
+                        mmanager->servo_configs[id].center_angle=150<<7;
+                        mmanager->servo_configs[id].max_speed=756;
+                        break;
+      case SERVO_RX28: mmanager->servo_configs[id].encoder_resolution=1023;
+                       mmanager->servo_configs[id].gear_ratio=193;
+                       mmanager->servo_configs[id].max_angle=300<<7;
+                       mmanager->servo_configs[id].center_angle=150<<7;
+                       mmanager->servo_configs[id].max_speed=402;
+                       break;
+      case SERVO_RX64: mmanager->servo_configs[id].encoder_resolution=1023;
+                       mmanager->servo_configs[id].gear_ratio=200;
+                       mmanager->servo_configs[id].max_angle=300<<7;
+                       mmanager->servo_configs[id].center_angle=150<<7;
+                       mmanager->servo_configs[id].max_speed=294;
+                       break;
+      case SERVO_MX64: mmanager->servo_configs[id].encoder_resolution=4095;
+                       mmanager->servo_configs[id].gear_ratio=200;
+                       mmanager->servo_configs[id].max_angle=360<<7;
+                       mmanager->servo_configs[id].center_angle=180<<7;
+                       mmanager->servo_configs[id].max_speed=378;
+                       break;
+      case SERVO_EX106: mmanager->servo_configs[id].encoder_resolution=1023;
+                        mmanager->servo_configs[id].gear_ratio=184;
+                        mmanager->servo_configs[id].max_angle=250<<7;
+                        mmanager->servo_configs[id].center_angle=125<<7;
+                        mmanager->servo_configs[id].max_speed=414;
+                        break;
+      case SERVO_MX106: mmanager->servo_configs[id].encoder_resolution=4095;
+                        mmanager->servo_configs[id].gear_ratio=225;
+                        mmanager->servo_configs[id].max_angle=360<<7;
+                        mmanager->servo_configs[id].center_angle=180<<7;
+                        mmanager->servo_configs[id].max_speed=270;
+                        break;
+      case SERVO_XL320: mmanager->servo_configs[id].encoder_resolution=1023;
+                        mmanager->servo_configs[id].gear_ratio=238;
+                        mmanager->servo_configs[id].max_angle=300<<7;
+                        mmanager->servo_configs[id].center_angle=150<<7;
+                        mmanager->servo_configs[id].max_speed=684;
+                        break;
+      default: break;
+    }
+    // get the servo's current position
+    if(model==SERVO_XL320)
+    {
+      dyn_master_read_word(dyn_manager_get_device_master(mmanager->dyn_module.manager,id),id,XL_PRESENT_POSITION_L,&mmanager->servo_values[id].current_value);
+      dyn_master_read_word(dyn_manager_get_device_master(mmanager->dyn_module.manager,id),id,XL_CW_ANGLE_LIMIT_L,&cw_value);
+      dyn_master_read_word(dyn_manager_get_device_master(mmanager->dyn_module.manager,id),id,XL_CCW_ANGLE_LIMIT_L,&ccw_value);
+    }
+    else
+    {
+      dyn_master_read_word(dyn_manager_get_device_master(mmanager->dyn_module.manager,id),id,P_PRESENT_POSITION_L,&mmanager->servo_values[id].current_value);
+      dyn_master_read_word(dyn_manager_get_device_master(mmanager->dyn_module.manager,id),id,P_CW_ANGLE_LIMIT_L,&cw_value);
+      dyn_master_read_word(dyn_manager_get_device_master(mmanager->dyn_module.manager,id),id,P_CCW_ANGLE_LIMIT_L,&ccw_value);
+    }
+    mmanager->servo_values[id].target_value=mmanager->servo_values[id].current_value;
+    mmanager->servo_values[id].current_angle=(mmanager_value_to_angle(mmanager,id,mmanager->servo_values[id].current_value)<<9);
+    mmanager->servo_values[id].target_angle=mmanager->servo_values[id].current_angle;
+    // read the servo limits
+    mmanager->servo_configs[id].cw_angle_limit=(mmanager_value_to_angle(mmanager,id,cw_value)<<9);
+    mmanager->servo_configs[id].ccw_angle_limit=(mmanager_value_to_angle(mmanager,id,ccw_value)<<9);
+  }
+}
+
+void mmanager_setup(TMotionManager *mmanager)
+{
+  unsigned char * data[DYN_MANAGER_MAX_NUM_DEVICES];
+  unsigned char ids[DYN_MANAGER_MAX_NUM_DEVICES];
+  unsigned short int address[DYN_MANAGER_MAX_NUM_DEVICES];
+  unsigned short int length[DYN_MANAGER_MAX_NUM_DEVICES];
+  unsigned char i,num=0;
+
+  // initialize the motion operation
+  for(i=0;i<DYN_MANAGER_MAX_NUM_DEVICES;i++)
+  {
+    if(mmanager->dyn_module.assigned_ids[i]==0x01)
+    {
+      data[num]=&mmanager->servo_values[i].cw_compliance;
+      ids[num]=i;
+      num++;
+    }
+  }
+  mmanager->motion_op=dyn_manager_sync_op_new(mmanager->dyn_module.manager,DYN_MANAGER_WRITE,num,ids,P_CW_COMPLIANCE_SLOPE,4,(unsigned char * const*)&data);
+  /* create a feedback operation with the servos that support bulk read */
+  num=0;
+  for(i=0;i<DYN_MANAGER_MAX_NUM_DEVICES;i++)
+  {
+    if(mmanager->dyn_module.assigned_ids[i]==0x01)
+    {
+      if(HAS_BULK_READ(dyn_manager_get_device_model(mmanager->dyn_module.manager,i)))
+      {
+        if(dyn_manager_get_device_model(mmanager->dyn_module.manager,i)==SERVO_XL320)
+          address[num]=XL_PRESENT_POSITION_L;
+        else
+          address[num]=P_PRESENT_POSITION_L;
+        data[num]=(unsigned char *)&mmanager->servo_values[i].current_value;
+        length[num]=2;
+        ids[num]=i;
+        num++;
+      }
+    }
+  }
+  mmanager->feedback_op=dyn_manager_bulk_op_new(mmanager->dyn_module.manager,DYN_MANAGER_READ,num,ids,address,length,(unsigned char * const*)data);
+}
+
+void mmanager_set_period(TMotionManager *mmanager,unsigned short int period_us)
+{
+  unsigned char i;
+
+  for(i=0;i<MAX_NUM_MOTION_MODULES;i++)
+    if(mmanager->modules[i]->set_period!=0x00000000)
+      mmanager->modules[i]->set_period(mmanager->modules[i]->data,period_us*mmanager->dyn_module.period_count);
+}
+
+void mmanager_pre_process(TMotionManager *mmanager)
+{
+  unsigned char i;
+
+  for(i=0;i<MAX_NUM_MOTION_MODULES;i++)
+  {
+    if(mmanager->modules[i]!=0x00000000 && mmanager->modules[i]->pre_process!=0x00000000)
+      mmanager->modules[i]->pre_process(mmanager->modules[i]->data);
+  }
+  /* call the balance function */
+  mmanager_compute_targets(mmanager);
+}
+
+void mmanager_post_process(TMotionManager *mmanager)
+{
+  unsigned char i;
+
+  /* transform the current values to angles */
+  mmanager_compute_angles(mmanager);
+  for(i=0;i<MAX_NUM_MOTION_MODULES;i++)
+  {
+    if(mmanager->modules[i]!=0x00000000 && mmanager->modules[i]->post_process!=0x00000000)
+      mmanager->modules[i]->post_process(mmanager->modules[i]->data);
+  }
+}
+
+/* public functions */
+void mmanager_init(TMotionManager *mmanager)
+{
+  unsigned char i;
+
+  /* initialize the base module */
+  dyn_module_init(&mmanager->dyn_module);
+  /* add all known servo models */
+  dyn_module_add_model(&mmanager->dyn_module,SERVO_DX113);
+  dyn_module_add_model(&mmanager->dyn_module,SERVO_DX116);
+  dyn_module_add_model(&mmanager->dyn_module,SERVO_DX117);
+  dyn_module_add_model(&mmanager->dyn_module,SERVO_AX12A);
+  dyn_module_add_model(&mmanager->dyn_module,SERVO_AX12W);
+  dyn_module_add_model(&mmanager->dyn_module,SERVO_AX18A);
+  dyn_module_add_model(&mmanager->dyn_module,SERVO_RX10);
+  dyn_module_add_model(&mmanager->dyn_module,SERVO_MX12W);
+  dyn_module_add_model(&mmanager->dyn_module,SERVO_MX28);
+  dyn_module_add_model(&mmanager->dyn_module,SERVO_RX24F);
+  dyn_module_add_model(&mmanager->dyn_module,SERVO_RX28);
+  dyn_module_add_model(&mmanager->dyn_module,SERVO_RX64);
+  dyn_module_add_model(&mmanager->dyn_module,SERVO_MX64);
+  dyn_module_add_model(&mmanager->dyn_module,SERVO_EX106);
+  dyn_module_add_model(&mmanager->dyn_module,SERVO_MX106);
+  dyn_module_add_model(&mmanager->dyn_module,SERVO_XL320);
+  mmanager->dyn_module.data=mmanager;
+  mmanager->dyn_module.add_device=(void (*)(void *,unsigned char,unsigned short int))mmanager_add_device;
+  mmanager->dyn_module.setup=(void (*)(void *))mmanager_setup;
+  mmanager->dyn_module.set_period=(void (*)(void *,unsigned short int))mmanager_set_period;
+  mmanager->dyn_module.pre_process=(void (*)(void *))mmanager_pre_process;
+  mmanager->dyn_module.post_process=(void (*)(void *))mmanager_post_process;
+  /* initialize internal attributes */
+  mmanager->balance_enabled=0x00;
+  mmanager->num_modules=0x00;
+  /* initialize motion module base attributes */
+  for(i=0;i<MAX_NUM_MOTION_MODULES;i++)
+    mmanager->modules[i]=0x00000000;
+  for(i=0;i<DYN_MANAGER_MAX_NUM_DEVICES;i++)
+  {
+    /* servo configuration */
+    mmanager->servo_configs[i].model=0x0000;
+    mmanager->servo_configs[i].encoder_resolution=0x0000;
+    mmanager->servo_configs[i].gear_ratio=0x00;
+    mmanager->servo_configs[i].max_angle=0x0000;
+    mmanager->servo_configs[i].center_angle=0x0000;
+    mmanager->servo_configs[i].max_speed=0x0000;
+    mmanager->servo_configs[i].cw_angle_limit=0;
+    mmanager->servo_configs[i].ccw_angle_limit=0;
+    /* servo values */
+    mmanager->servo_values[i].cw_compliance=0x00;
+    mmanager->servo_values[i].ccw_compliance=0x00;
+    mmanager->servo_values[i].target_value=0x0000;
+    mmanager->servo_values[i].target_angle=0;
+    mmanager->servo_values[i].current_value=0x0000;
+    mmanager->servo_values[i].current_angle=0;
+    mmanager->servo_values[i].module=MM_NONE;
+    mmanager->servo_values[i].enabled=0x00;
+    mmanager->servo_values[i].offset=0x00;
+  }
+  mmanager->enable_op=0x00000000;
+  mmanager->motion_op=0x00000000;
+  mmanager->feedback_op=0x00000000;
+  mmanager->balance=0x00000000;
+}
+
+TDynModule *mmanager_get_dyn_module(TMotionManager *mmanager)
+{
+  return &mmanager->dyn_module;
+}
+
+void mmanager_enable_balance(TMotionManager *mmanager)
+{
+  if(mmanager->balance!=0x00000000)
+    mmanager->balance_enabled=0x01;
+}
+
+void mmanager_disable_balance(TMotionManager *mmanager)
+{
+  mmanager->balance_enabled=0x00;
+}
+
+unsigned char mmanager_is_balance_enabled(TMotionManager *mmanager)
+{
+  return mmanager->balance_enabled;
+}
+
+void mmanager_set_module(TMotionManager *mmanager,unsigned char servo_id,TModules module)
+{
+  if(servo_id<DYN_MANAGER_MAX_NUM_DEVICES)
+  {
+    if(module!=mmanager->servo_values[servo_id].module)
+    {
+      if(module!=MM_NONE && mmanager->modules[module]->set_module!=0x00000000)
+        mmanager->modules[module]->set_module(mmanager->modules[module]->data,servo_id);
+      mmanager->servo_values[servo_id].module=module;
+    }
+  }
+}
+
+TModules mmanager_get_module(TMotionManager *mmanager,unsigned char servo_id)
+{
+  if(servo_id<DYN_MANAGER_MAX_NUM_DEVICES)
+    return mmanager->servo_values[servo_id].module;
+  else
+    return MM_NONE;
+}
+
+void mmanager_enable_servo(TMotionManager *mmanager,unsigned char servo_id)
+{
+  unsigned char * const data=&(mmanager->servo_values[servo_id].enabled);
+
+  if(servo_id<DYN_MANAGER_MAX_NUM_DEVICES)
+  {
+    mmanager->servo_values[servo_id].enabled=0x01;
+    /* add an operation to enable the servo */
+    if(mmanager->enable_op==0x00000000 || mmanager->enable_op->op_type==no_op)
+    {
+      mmanager->enable_op=dyn_manager_sync_op_new(mmanager->dyn_module.manager,DYN_MANAGER_WRITE,1,&servo_id,P_TORQUE_ENABLE,1,&data);
+      dyn_manager_set_op_repetitions(mmanager->dyn_module.manager,mmanager->enable_op,1);
+    }
+    else
+      dyn_manager_sync_op_add_devices(mmanager->dyn_module.manager,mmanager->enable_op,1,&servo_id,&data);
+  }
+}
+
+void mmanager_disable_servo(TMotionManager *mmanager,unsigned char servo_id)
+{
+  unsigned char * const data=&(mmanager->servo_values[servo_id].enabled);
+
+  if(servo_id<DYN_MANAGER_MAX_NUM_DEVICES)
+  {
+    mmanager->servo_values[servo_id].enabled=0x00;
+    /* add an operation to enable the servo */
+    if(mmanager->enable_op==0x00000000 || mmanager->enable_op->op_type==no_op)
+    {
+      mmanager->enable_op=dyn_manager_sync_op_new(mmanager->dyn_module.manager,DYN_MANAGER_WRITE,1,&servo_id,P_TORQUE_ENABLE,1,&data);
+      dyn_manager_set_op_repetitions(mmanager->dyn_module.manager,mmanager->enable_op,1);
+    }
+    else
+      dyn_manager_sync_op_add_devices(mmanager->dyn_module.manager,mmanager->enable_op,1,&servo_id,&data);
+  }
+}
+
+unsigned char mmanager_is_servo_enabled(TMotionManager *mmanager,unsigned char servo_id)
+{
+  if(servo_id<DYN_MANAGER_MAX_NUM_DEVICES)
+    return mmanager->servo_values[servo_id].enabled;
+  else
+    return 0x00;
+}
+
+void mmanager_set_offset(TMotionManager *mmanager,unsigned char servo_id,char offset)
+{
+  if(servo_id<DYN_MANAGER_MAX_NUM_DEVICES)
+    mmanager->servo_values[servo_id].offset=offset;
+}
+
+void mmanager_add_module(TMotionManager *mmanager,TMotionModule *module)
+{
+  if(module->id!=MM_NONE)
+  {
+    if(mmanager->modules[module->id]==0x00000000)
+      mmanager->num_modules++;
+    mmanager->modules[module->id]=module;
+    module->manager=mmanager;
+  }
+}
+
diff --git a/dynamixel_manager/src/modules/motion_module.c b/dynamixel_manager/src/modules/motion_module.c
new file mode 100644
index 0000000000000000000000000000000000000000..96199bd032887d4f941f45a07651fc078ca7a27d
--- /dev/null
+++ b/dynamixel_manager/src/modules/motion_module.c
@@ -0,0 +1,12 @@
+#include "motion_module.h"
+
+void mmodule_init(TMotionModule *module)
+{
+  module->id=MM_NONE;
+  module->manager=0x00000000;
+  module->set_period=0x00000000;
+  module->set_module=0x00000000;
+  module->pre_process=0x00000000;
+  module->post_process=0x00000000;
+  module->data=0x00000000;
+}
diff --git a/dynamixel_manager/src/modules/motion_pages.c b/dynamixel_manager/src/modules/motion_pages.c
new file mode 100755
index 0000000000000000000000000000000000000000..bf4f7d8a10551d3545493e0aa698a5088e136666
--- /dev/null
+++ b/dynamixel_manager/src/modules/motion_pages.c
@@ -0,0 +1,45 @@
+#include "motion_pages.h"
+
+void pages_get_page(unsigned char page_id,TPage *page)
+{
+  unsigned short int i=0;
+
+  for(i=0;i<sizeof(TPage);i++)
+    ((unsigned char *)page)[i]=((unsigned char *)&motion_pages[page_id])[i];
+}
+
+unsigned char pages_check_checksum(TPage *page)
+{
+  unsigned char checksum=0x00;
+  unsigned short int i=0;
+
+  for(i=0;i<sizeof(TPage);i++)
+    checksum+=((unsigned char *)page)[i];
+  if(checksum==0x00)
+    return 0x01;
+  else
+    return 0x00;
+}
+
+void pages_clear_page(TPage *page)
+{
+  unsigned short int i=0;
+
+  for(i=0;i<sizeof(TPage);i++)
+    ((unsigned char *)page)[i]=0x00;
+}
+
+void pages_copy_page(TPage *src,TPage *dst)
+{
+  unsigned short int i=0;
+
+  for(i=0;i<sizeof(TPage);i++)
+    ((unsigned char *)dst)[i]=((unsigned char *)src)[i];
+}
+
+inline unsigned char pages_get_slope(TPage *page,unsigned char servo_id)
+{
+  return 0x01<<(page->header.slope[servo_id]&0x0F);
+}
+
+TPage motion_pages[MAX_PAGES] __attribute__ ((section (".pages"))) __attribute__((weak)) ;