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)) ;