diff --git a/ur_driver/src/ur_driver/deserialize.py b/ur_driver/src/ur_driver/deserialize.py old mode 100644 new mode 100755 index 253a5fe891e29a3c589ed0d7ee15517ecae35b66..aeb446f7d249100692342de089266e5c680f4ea6 --- a/ur_driver/src/ur_driver/deserialize.py +++ b/ur_driver/src/ur_driver/deserialize.py @@ -50,7 +50,7 @@ class ToolMode(object): BOOTLOADER = 249 RUNNING = 253 IDLE = 255 - + class MasterSafetyState(object): UNDEFINED = 0 BOOTLOADER = 1 @@ -68,14 +68,29 @@ class MasterOnOffState(object): ON = 2 TURNING_OFF = 3 +#this class handles different protocol versions class RobotModeData(object): + @staticmethod + def unpack(buf): + rmd = RobotModeData() + (plen, ptype) = struct.unpack_from("!IB", buf) + if plen == 29: + return RobotModeData_V18.unpack(buf) + elif plen == 38: + return RobotModeData_V30.unpack(buf) + else: + print "RobotModeData has wrong length: " + str(plen) + return rmd + +#this parses RobotModeData for versions <= v1.8 (i.e. 1.6, 1.7, 1.8) +class RobotModeData_V18(object): __slots__ = ['timestamp', 'robot_connected', 'real_robot_enabled', 'power_on_robot', 'emergency_stopped', 'security_stopped', 'program_running', 'program_paused', 'robot_mode', 'speed_fraction'] @staticmethod def unpack(buf): - rmd = RobotModeData() + rmd = RobotModeData_V18() (_, _, rmd.timestamp, rmd.robot_connected, rmd.real_robot_enabled, rmd.power_on_robot, rmd.emergency_stopped, rmd.security_stopped, @@ -83,7 +98,24 @@ class RobotModeData(object): rmd.speed_fraction) = struct.unpack_from("!IBQ???????Bd", buf) return rmd -# Don't use T_micro (obsolete). For retrocompatibility purposes. +#this parses RobotModeData for versions >=3.0 (i.e. 3.0) +class RobotModeData_V30(object): + __slots__ = ['timestamp', 'robot_connected', 'real_robot_enabled', + 'power_on_robot', 'emergency_stopped', + 'security_stopped', 'program_running', 'program_paused', + 'robot_mode', 'control_mode', 'target_speed_fraction', + 'speed_scaling'] + @staticmethod + def unpack(buf): + rmd = RobotModeData_V30() + (_, _, + rmd.timestamp, rmd.robot_connected, rmd.real_robot_enabled, + rmd.power_on_robot, rmd.emergency_stopped, rmd.security_stopped, + rmd.program_running, rmd.program_paused, rmd.robot_mode, rmd.control_mode, + rmd.target_speed_fraction, rmd.speed_scaling) = struct.unpack_from("!IBQ???????BBdd", buf) + return rmd + +#this parses JointData for all versions (i.e. 1.6, 1.7, 1.8, 3.0) class JointData(object): __slots__ = ['q_actual', 'q_target', 'qd_actual', 'I_actual', 'V_actual', 'T_motor', 'T_micro', 'joint_mode'] @@ -94,12 +126,13 @@ class JointData(object): for i in range(6): jd = JointData() (jd.q_actual, jd.q_target, jd.qd_actual, jd.I_actual, jd.V_actual, - jd.T_motor, jd.T_micro, + jd.T_motor, jd.T_micro, jd.joint_mode) = struct.unpack_from("!dddffffB", buf, offset) offset += 41 all_joints.append(jd) return all_joints +#this parses JointData for all versions (i.e. 1.6, 1.7, 1.8, 3.0) class ToolData(object): __slots__ = ['analog_input_range2', 'analog_input_range3', 'analog_input2', 'analog_input3', @@ -115,7 +148,23 @@ class ToolData(object): td.tool_temperature, td.tool_mode) = struct.unpack_from("!IBbbddfBffB", buf) return td +#this class handles different protocol versions class MasterboardData(object): + @staticmethod + def unpack(buf): + md = MasterboardData() + (plen, ptype) = struct.unpack_from("!IB", buf) + if (plen == 64) or (plen == 76): # Euromap67 interface = 12 bytes + return MasterboardData_V18.unpack(buf) + elif (plen == 72) or (plen == 92): # Euromap67 interface = 20 bytes + return MasterboardData_V30.unpack(buf) + else: + print "MasterboardData has wrong length: " + str(plen) + print "Euromap67Interface is ignored" + return md + +#this parses MasterboardData for versions <= v1.8 (i.e. 1.6, 1.7, 1.8) +class MasterboardData_V18(object): __slots__ = ['digital_input_bits', 'digital_output_bits', 'analog_input_range0', 'analog_input_range1', 'analog_input0', 'analog_input1', @@ -124,10 +173,10 @@ class MasterboardData(object): 'masterboard_temperature', 'robot_voltage_48V', 'robot_current', 'master_io_current', 'master_safety_state', - 'master_onoff_state'] + 'master_onoff_state']#subsequent slots related to 'euromap' ignored @staticmethod def unpack(buf): - md = MasterboardData() + md = MasterboardData_V18() (_, _, md.digital_input_bits, md.digital_output_bits, md.analog_input_range0, md.analog_input_range1, @@ -140,6 +189,33 @@ class MasterboardData(object): md.master_onoff_state) = struct.unpack_from("!IBhhbbddbbddffffBB", buf) return md +#this parses MasterboardData for versions >=3.0 (i.e. 3.0) +class MasterboardData_V30(object): + __slots__ = ['digital_input_bits', 'digital_output_bits', + 'analog_input_range0', 'analog_input_range1', + 'analog_input0', 'analog_input1', + 'analog_output_domain0', 'analog_output_domain1', + 'analog_output0', 'analog_output1', + 'masterboard_temperature', + 'robot_voltage_48V', 'robot_current', + 'master_io_current', 'safety_mode', + 'in_reduced_mode']#subsequent slots related to 'euromap' ignored + @staticmethod + def unpack(buf): + md = MasterboardData_V30() + (_, _, _UNDOCUMENTED_, + md.digital_input_bits, md.digital_output_bits, + md.analog_input_range0, md.analog_input_range1, + md.analog_input0, md.analog_input1, + md.analog_output_domain0, md.analog_output_domain1, + md.analog_output0, md.analog_output1, + md.masterboard_temperature, + md.robot_voltage_48V, md.robot_current, + md.master_io_current, md.safety_mode, + md.in_reduced_mode) = struct.unpack_from("!IBIiibbddbbddffffBB", buf) + return md + +#this parses JointData for all versions (i.e. 1.6, 1.7, 1.8, 3.0) class CartesianInfo(object): __slots__ = ['x', 'y', 'z', 'rx', 'ry', 'rz'] @staticmethod @@ -149,21 +225,26 @@ class CartesianInfo(object): ci.x, ci.y, ci.z, ci.rx, ci.ry, ci.rz) = struct.unpack_from("!IB6d", buf) return ci +#this parses KinematicsInfo for versions (i.e. 1.8, 3.0) +#KinematicsInfo is not available in 1.6 and 1.7 class KinematicsInfo(object): @staticmethod def unpack(buf): return KinematicsInfo() +#helper class for ConfigurationData class JointLimitData(object): __slots__ = ['min_limit', 'max_limit', 'max_speed', 'max_acceleration'] +#this parses ConfigurationData for versions (i.e. 1.8, 3.0) +#ConfigurationData is not available in 1.6 and 1.7 class ConfigurationData(object): __slots__ = ['joint_limit_data', - 'v_joint_default', 'a_joint_default', + 'v_joint_default', 'a_joint_default', 'v_tool_default', 'a_tool_default', 'eq_radius', 'dh_a', 'dh_d', 'dh_alpha', 'dh_theta', 'masterboard_version', 'controller_box_type', - 'robot_type', 'robot_subtype'] + 'robot_type', 'robot_subtype']#in v1.8 there is an additional slot 'motor_type' for each joint, which currently is ignored! @staticmethod def unpack(buf): cd = ConfigurationData() @@ -179,6 +260,8 @@ class ConfigurationData(object): cd.robot_subtype) = struct.unpack_from("!iiii", buf, 5+32*6+5*8+6*32) return cd +#this parses KinematicsInfo for versions (i.e. 1.8, 3.0) +#KinematicsInfo is not available in 1.6 and 1.7 class ForceModeData(object): __slots__ = ['x', 'y', 'z', 'rx', 'ry', 'rz', 'robot_dexterity'] @staticmethod @@ -188,6 +271,20 @@ class ForceModeData(object): fmd.robot_dexterity) = struct.unpack_from("!IBddddddd", buf) return fmd +#this class handles different protocol versions +class AdditionalInfo(object): + @staticmethod + def unpack(buf): + ai = AdditionalInfo() + (plen, ptype) = struct.unpack_from("!IB", buf) + if plen == 10: + return AdditionalInfoOld.unpack(buf) + elif plen == 7: + return AdditionalInfoNew.unpack(buf) + else: + print "AdditionalInfo has wrong length: " + str(plen) + return ai + class AdditionalInfoOld(object): __slots__ = ['ctrl_bits', 'teach_button'] @staticmethod @@ -195,7 +292,7 @@ class AdditionalInfoOld(object): ai = AdditionalInfoOld() (_,_,ai.ctrl_bits, ai.teach_button) = struct.unpack_from("!IBIB", buf) return ai - + class AdditionalInfoNew(object): __slots__ = ['teach_button_enabled','teach_button_pressed'] @staticmethod @@ -203,16 +300,7 @@ class AdditionalInfoNew(object): ai = AdditionalInfoNew() (_,_,ai.teach_button_enabled, ai.teach_button_pressed) = struct.unpack_from("!IBBB", buf) return ai - -class AdditionalInfo(object): - @staticmethod - def unpack(buf): - ai = AdditionalInfo() - (plen, ptype) = struct.unpack_from("!IB", buf) - if plen == 10: - return AdditionalInfoOld.unpack(buf) - else: - return AdditionalInfoNew.unpack(buf) + class RobotState(object): __slots__ = ['robot_mode_data', 'joint_data', 'tool_data', diff --git a/ur_driver/src/ur_driver/deserializeRT.py b/ur_driver/src/ur_driver/deserializeRT.py index 5fe97d779d67613fa47eb55d44668b228a66bb68..fc083e8574fd516fddd5e0152342615be8cca2d8 100644 --- a/ur_driver/src/ur_driver/deserializeRT.py +++ b/ur_driver/src/ur_driver/deserializeRT.py @@ -1,7 +1,22 @@ import struct import copy +#this class handles different protocol versions class RobotStateRT(object): + @staticmethod + def unpack(buf): + rs = RobotStateRT() + (plen, ptype) = struct.unpack_from("!IB", buf) + if plen == 812: + return RobotStateRT_V18.unpack(buf) + elif plen == 1044: + return RobotStateRT_V30.unpack(buf) + else: + print "RobotStateRT has wrong length: " + str(plen) + return rs + +#this parses RobotStateRT for versions <= v1.8 (i.e. 1.6, 1.7, 1.8) +class RobotStateRT_V18(object): __slots__ = ['time', 'q_target', 'qd_target', 'qdd_target', 'i_target', 'm_target', 'q_actual', 'qd_actual', 'i_actual', 'tool_acc_values', @@ -20,7 +35,7 @@ class RobotStateRT(object): print("MessageSize: ", message_size, "; BufferSize: ", len(buf)) raise Exception("Could not unpack RobotStateRT packet: length field is incorrect") - rs = RobotStateRT() + rs = RobotStateRT_V18() #time: 1x double (1x 8byte) rs.time = struct.unpack_from("!d",buf, offset)[0] offset+=8 @@ -116,3 +131,175 @@ class RobotStateRT(object): rs.joint_modes = copy.deepcopy(all_values) return rs + +#this parses RobotStateRT for versions >=3.0 (i.e. 3.0) +class RobotStateRT_V30(object): + __slots__ = ['time', + 'q_target', 'qd_target', 'qdd_target', 'i_target', 'm_target', + 'q_actual', 'qd_actual', 'i_actual', 'i_control', + 'tool_vector_actual', 'tcp_speed_actual', 'tcp_force', + 'tool_vector_target', 'tcp_speed_target', + 'digital_input_bits', 'motor_temperatures', 'controller_timer', + 'test_value', + 'robot_mode', 'joint_modes', 'safety_mode', + #6xd: unused + 'tool_acc_values', + #6xd: unused + 'speed_scaling', 'linear_momentum_norm', + #2xd: unused + 'v_main', 'v_robot', 'i_robot', 'v_actual'] + + @staticmethod + def unpack(buf): + offset = 0 + message_size = struct.unpack_from("!i", buf, offset)[0] + offset+=4 + if message_size != len(buf): + print("MessageSize: ", message_size, "; BufferSize: ", len(buf)) + raise Exception("Could not unpack RobotStateRT packet: length field is incorrect") + + rs = RobotStateRT_V30() + #time: 1x double (1x 8byte) + rs.time = struct.unpack_from("!d",buf, offset)[0] + offset+=8 + + #q_target: 6x double (6x 8byte) + all_values = list(struct.unpack_from("!dddddd",buf, offset)) + offset+=6*8 + rs.q_target = copy.deepcopy(all_values) + + #qd_target: 6x double (6x 8byte) + all_values = list(struct.unpack_from("!dddddd",buf, offset)) + offset+=6*8 + rs.qd_target = copy.deepcopy(all_values) + + #qdd_target: 6x double (6x 8byte) + all_values = list(struct.unpack_from("!dddddd",buf, offset)) + offset+=6*8 + rs.qdd_target = copy.deepcopy(all_values) + + #i_target: 6x double (6x 8byte) + all_values = list(struct.unpack_from("!dddddd",buf, offset)) + offset+=6*8 + rs.i_target = copy.deepcopy(all_values) + + #m_target: 6x double (6x 8byte) + all_values = list(struct.unpack_from("!dddddd",buf, offset)) + offset+=6*8 + rs.m_target = copy.deepcopy(all_values) + + #q_actual: 6x double (6x 8byte) + all_values = list(struct.unpack_from("!dddddd",buf, offset)) + offset+=6*8 + rs.q_actual = copy.deepcopy(all_values) + + #qd_actual: 6x double (6x 8byte) + all_values = list(struct.unpack_from("!dddddd",buf, offset)) + offset+=6*8 + rs.qd_actual = copy.deepcopy(all_values) + + #i_actual: 6x double (6x 8byte) + all_values = list(struct.unpack_from("!dddddd",buf, offset)) + offset+=6*8 + rs.i_actual = copy.deepcopy(all_values) + + #i_control: 6x double (6x 8byte) + all_values = list(struct.unpack_from("!dddddd",buf, offset)) + offset+=6*8 + rs.i_control = copy.deepcopy(all_values) + + #tool_vector_actual: 6x double (6x 8byte) + all_values = list(struct.unpack_from("!dddddd",buf, offset)) + offset+=6*8 + rs.tool_vector_actual = copy.deepcopy(all_values) + + #tcp_speed_actual: 6x double (6x 8byte) + all_values = list(struct.unpack_from("!dddddd",buf, offset)) + offset+=6*8 + rs.tcp_speed_actual = copy.deepcopy(all_values) + + #tcp_force: 6x double (6x 8byte) + all_values = list(struct.unpack_from("!dddddd",buf, offset)) + offset+=6*8 + rs.tcp_force = copy.deepcopy(all_values) + + #tool_vector_target: 6x double (6x 8byte) + all_values = list(struct.unpack_from("!dddddd",buf, offset)) + offset+=6*8 + rs.tool_vector_target = copy.deepcopy(all_values) + + #tcp_speed_target: 6x double (6x 8byte) + all_values = list(struct.unpack_from("!dddddd",buf, offset)) + offset+=6*8 + rs.tcp_speed_target = copy.deepcopy(all_values) + + #digital_input_bits: 1x double (1x 8byte) ? + rs.digital_input_bits = struct.unpack_from("!d",buf, offset)[0] + offset+=8 + + #motor_temperatures: 6x double (6x 8byte) + all_values = list(struct.unpack_from("!dddddd",buf, offset)) + offset+=6*8 + rs.motor_temperatures = copy.deepcopy(all_values) + + #controller_timer: 1x double (1x 8byte) + rs.controller_timer = struct.unpack_from("!d",buf, offset)[0] + offset+=8 + + #test_value: 1x double (1x 8byte) + rs.test_value = struct.unpack_from("!d",buf, offset)[0] + offset+=8 + + #robot_mode: 1x double (1x 8byte) + rs.robot_mode = struct.unpack_from("!d",buf, offset)[0] + offset+=8 + + #joint_modes: 6x double (6x 8byte) + all_values = list(struct.unpack_from("!dddddd",buf, offset)) + offset+=6*8 + rs.joint_modes = copy.deepcopy(all_values) + + #safety_mode: 1x double (1x 8byte) + rs.safety_mode = struct.unpack_from("!d",buf, offset)[0] + offset+=8 + + #unused: 6x double (6x 8byte) + offset+=48 + + #tool_acc_values: 3x double (3x 8byte) + all_values = list(struct.unpack_from("!ddd",buf, offset)) + offset+=3*8 + rs.tool_acc_values = copy.deepcopy(all_values) + + #unused: 6x double (6x 8byte) + offset+=48 + + #speed_scaling: 1x double (1x 8byte) + rs.speed_scaling = struct.unpack_from("!d",buf, offset)[0] + offset+=8 + + #linear_momentum_norm: 1x double (1x 8byte) + rs.linear_momentum_norm = struct.unpack_from("!d",buf, offset)[0] + offset+=8 + + #unused: 2x double (2x 8byte) + offset+=16 + + #v_main: 1x double (1x 8byte) + rs.v_main = struct.unpack_from("!d",buf, offset)[0] + offset+=8 + + #v_robot: 1x double (1x 8byte) + rs.v_robot = struct.unpack_from("!d",buf, offset)[0] + offset+=8 + + #i_robot: 1x double (1x 8byte) + rs.i_robot = struct.unpack_from("!d",buf, offset)[0] + offset+=8 + + #v_actual: 6x double (6x 8byte) + all_values = list(struct.unpack_from("!dddddd",buf, offset)) + offset+=6*8 + rs.v_actual = copy.deepcopy(all_values) + + return rs