前提・実現したいこと
ROSを使ってUR(universal robots)に取り付けたグリッパー(Hand-e)を動かしたい
発生している問題・エラーメッセージ
$ rosrun robotiq_2f_gripper_control Robotiq2FGripperRtuNode.py /tmp/ttyUR Traceback (most recent call last): File "/home/user/catkin_ws/src/robotiq-noetic-mods/robotiq_2f_gripper_control/nodes/Robotiq2FGripperRtuNode.py", line 89, in <module> mainLoop(sys.argv[1]) File "/home/user/catkin_ws/src/robotiq-noetic-mods/robotiq_2f_gripper_control/nodes/Robotiq2FGripperRtuNode.py", line 75, in mainLoop status = gripper.getStatus() File "/home/user/catkin_ws/src/robotiq-noetic-mods/robotiq_2f_gripper_control/src/robotiq_2f_gripper_control/baseRobotiq2FGripper.py", line 107, in getStatus status = self.client.getStatus(6); File "/home/user/catkin_ws/src/robotiq-noetic-mods/robotiq_modbus_rtu/src/robotiq_modbus_rtu/comModbusRtu.py", line 103, in getStatus output.append((response.getRegister(i) & 0xFF00) >> 8) AttributeError: 'ModbusIOException' object has no attribute 'getRegister' ```Python #実行したノード(Robotiq2FGripperRtuNode.py)
#!/usr/bin/env python3
import roslib; roslib.load_manifest('robotiq_2f_gripper_control')
roslib.load_manifest('robotiq_modbus_rtu')
import rospy
import robotiq_2f_gripper_control.baseRobotiq2FGripper
import robotiq_modbus_rtu.comModbusRtu
import os, sys
from robotiq_2f_gripper_control.msg import _Robotiq2FGripper_robot_input as inputMsg
from robotiq_2f_gripper_control.msg import _Robotiq2FGripper_robot_output as outputMsg
def mainLoop(device):
#Gripper is a 2F with a TCP connection gripper = robotiq_2f_gripper_control.baseRobotiq2FGripper.robotiqbaseRobotiq2FGripper() gripper.client = robotiq_modbus_rtu.comModbusRtu.communication() #We connect to the address received as an argument gripper.client.connectToDevice(device) rospy.init_node('robotiq2FGripper') #The Gripper status is published on the topic named 'Robotiq2FGripperRobotInput' pub = rospy.Publisher('Robotiq2FGripperRobotInput', inputMsg.Robotiq2FGripper_robot_input,queue_size=10) #The Gripper command is received from the topic named 'Robotiq2FGripperRobotOutput' rospy.Subscriber('Robotiq2FGripperRobotOutput', outputMsg.Robotiq2FGripper_robot_output, gripper.refreshCommand) #We loop while not rospy.is_shutdown(): #Get and publish the Gripper status status = gripper.getStatus() pub.publish(status) #Wait a little #rospy.sleep(0.05) #Send the most recent command gripper.sendCommand() #Wait a little #rospy.sleep(0.05)
if name == 'main':
try:
mainLoop(sys.argv[1])
except rospy.ROSInterruptException: pass
#参照したノード(comModbusRtu.py)
from future import print_function
from pymodbus.client.sync import ModbusSerialClient
from math import ceil
class communication:
def init(self):
self.client = None
def connectToDevice(self, device):
"""Connection to the client - the method takes the IP address (as a string, e.g. '192.168.1.11') as an argument."""
self.client = ModbusSerialClient(method='rtu',port=device,stopbits=1, bytesize=8, baudrate=115200, timeout=0.2)
if not self.client.connect():
print("Unable to connect to {}".format(device))
return False
return True
def disconnectFromDevice(self):
"""Close connection"""
self.client.close()
def sendCommand(self, data):
"""Send a command to the Gripper - the method takes a list of uint8 as an argument. The meaning of each variable depends on the Gripper model (see support.robotiq.com for more details)"""
#make sure data has an even number of elements
if(len(data) % 2 == 1):
data.append(0)
#Initiate message as an empty list message = [] #Fill message by combining two bytes in one register for i in range(0, len(data)//2): message.append((data[2*i] << 8) + data[2*i+1]) #To do!: Implement try/except self.client.write_registers(0x03E8, message, unit=0x0009)
def getStatus(self, numBytes):
"""Sends a request to read, wait for the response and returns the Gripper status. The method gets the number of bytes to read as an argument"""
numRegs = int(ceil(numBytes/2.0))
#To do!: Implement try/except #Get status from the device response = self.client.read_holding_registers(0x07D0, numRegs, unit=0x0009) if response is None: return [0,0,0,0,0,0] # print(response) #Instantiate output as an empty list output = [] #Fill the output with the bytes in the appropriate order for i in range(0, numRegs): output.append((response.getRegister(i) & 0xFF00) >> 8) output.append( response.getRegister(i) & 0x00FF) #Output the result return output
#参照したノード(baseRobotiq2FGripper.py)
from robotiq_2f_gripper_control.msg import _Robotiq2FGripper_robot_input as inputMsg
from robotiq_2f_gripper_control.msg import _Robotiq2FGripper_robot_output as outputMsg
class robotiqbaseRobotiq2FGripper:
"""Base class (communication protocol agnostic) for sending commands and receiving the status of the Robotic 2F gripper"""
def __init__(self): #Initiate output message as an empty list self.message = [] #Note: after the instantiation, a ".client" member must be added to the object def verifyCommand(self, command): """Function to verify that the value of each variable satisfy its limits.""" #Verify that each variable is in its correct range command.rACT = max(0, command.rACT) command.rACT = min(1, command.rACT) command.rGTO = max(0, command.rGTO) command.rGTO = min(1, command.rGTO) command.rATR = max(0, command.rATR) command.rATR = min(1, command.rATR) command.rPR = max(0, command.rPR) command.rPR = min(255, command.rPR) command.rSP = max(0, command.rSP) command.rSP = min(255, command.rSP) command.rFR = max(0, command.rFR) command.rFR = min(255, command.rFR) #Return the modified command return command def refreshCommand(self, command): """Function to update the command which will be sent during the next sendCommand() call.""" #Limit the value of each variable command = self.verifyCommand(command) #Initiate command as an empty list self.message = [] #Build the command with each output variable #To-Do: add verification that all variables are in their authorized range self.message.append(command.rACT + (command.rGTO << 3) + (command.rATR << 4)) self.message.append(0) self.message.append(0) self.message.append(command.rPR) self.message.append(command.rSP) self.message.append(command.rFR) def sendCommand(self): """Send the command to the Gripper.""" self.client.sendCommand(self.message) def getStatus(self): """Request the status from the gripper and return it in the Robotiq2FGripper_robot_input msg type.""" #Acquire status from the Gripper status = self.client.getStatus(6); #Message to output message = inputMsg.Robotiq2FGripper_robot_input() #Assign the values to their respective variables message.gACT = (status[0] >> 0) & 0x01; message.gGTO = (status[0] >> 3) & 0x01; message.gSTA = (status[0] >> 4) & 0x03; message.gOBJ = (status[0] >> 6) & 0x03; message.gFLT = status[2] message.gPR = status[3] message.gPO = status[4] message.gCU = status[5] return message
### 試したこと IPアドレスの重複やプロセスの重複など確認したが特になし そもそもUR自体はROSで動かすことができる なんとなくcomModbusRtu.pyのresponse = self.client.read_holding_registers(0x07D0, numRegs, unit=0x0009)が怪しい気がする ### 補足情報 Ubuntu 20.04 ROS noetic python 3.8.5
あなたの回答
tips
プレビュー