I have a node that has a serial connection. I want to create a service so other nodes can send requests for it to write at the serial.
This is the server:
import rospy
import serial
from my_package.srv import SerialData
class SerialServer:
def __init__(self):
# Initialize the node and name it.
rospy.init_node('serial_server', anonymous=True)
# Services
rospy.Service('send_serial', SerialData, send_serial)
# Serial connection
self.ser = serial.Serial('/dev/ttyUSB0', baudrate=115200, timeout=1)
def send_serial(self, req):
try:
self.ser.write(req)
return 1
except:
rospy.loginfo('*** could not send ***')
return 0
def main():
try:
#Initialize
serial_server = SerialServer()
except rospy.ROSInterruptException: pass
#spin() simply keeps python from exiting until this node is stopped
rospy.spin()
if __name__ == '__main__':
main()
However, it needs self
as an argument, which causes an error when I try to call the service from the client because I have no access to the server object from the client node.
send_serial(initCondition)
"error processing request: send_serial() missing 1 required positional argument:
import rospy
from ros_igtl_bridge.msg import igtlstring
class SerialClient:
def __init__(self):
# ROS Topics
rospy.Subscriber('IGTL_STRING_IN', igtlstring, self.callbackString)
# Initialize the node and name it.
rospy.init_node('serial_client', anonymous=True)
def callbackString(self, msg):
if msg.name == 'INIT':
initCondition = msg.data[4] + msg.data[5]
rospy.wait_for_service('send_serial')
try:
send_serial = rospy.ServiceProxy('send_serial', SerialData)
if (send_serial(initCondition)):
rospy.loginfo("Initialization successful")
else:
rospy.loginfo("Could not initialize")
except rospy.ServiceException as e:
rospy.loginfo("Controller Service call failed: %s"%e)
def main():
try:
#Initialize
serial_client = SerialClient()
except rospy.ROSInterruptException: pass
#spin() simply keeps python from exiting until this node is stopped
rospy.spin()
if __name__ == '__main__':
main()
Which is the appropriate way to implement this type of service in ROS?
The indentation is wrong in your first file. send_serial
should be a attribute of the class; that way when it's called a reference to the instance(self
) will be passed in too. You will then have to also change the code where you set up the service such as:
rospy.Service('send_serial', SerialData, self.send_serial)