Explanation
Within our zetabot robot, we use Robot Operating System (ROS) to control and communicate with our robot.
If we looked at what Topic and Node was within ROS and how to publish and subscribe to the said topic with nodes, we will look at general ROS command lines, as well as service server and client interactions.
ROS Command Line
1. rosnode command line tool
The rosnode is a command line that allows informations about the ROS Nodes to be displayed. There are few supported commands for the tool:
rosnode info: prints information about a node. For example: -rosnode info /node_namewould display information about a node, including publication and subscription.rosnode kill: kill a running node. Please be aware that nodes that are set to respawn will fail to die, or reappear. - Killing one or more nodes by their name:$ rosnode kill rosout add_two_ints_server add_threeints_server ...
Killing nodes by user input (interactive mode):
$ rosnode kill 1. /rosout Please enter the number of the node you wish to kill. >
Kill all nodes:
kill -a, kill --all
rosnode list: list active nodes - To display the current node list:$ rosnode list
To display all the current list inside a /namespace_topic:
$ rosnode list /example_topic_name
To display XML -RPC URIs of current nodes:
$ rosnode list -u
To display the name and XML -RPC URIs of all the current nodes (either
-aor--all):$ rosnode list -a
rosnode machine: list nodes runnning on a particular machine or list machines. For example, to see the nodes running on zetabot:$ rosnode machine zetabot.local /talker-zetabot.local-72266-1257921234733 /rosout /listener-zetabot.local-72615-1257921238320
rosnode The rostopic command-line tool displays information about ROS topics. Currently, it can display a list of active topics, the publishers and subscribers of a specific topic, the publishing rate of a topic, the bandwidth of a topic, and messages published to a topic. The display of messages is configurable to output in a plotting-friendly format.ping: test connectivity to a node by pinging them repeatedly. - You may ping the nodes either individually or in total by specifying a node namerosnode ping /node_nameor ping all the nodes byrosnode ping --all- You may also ping an individual node Count number of times.$ rosnode ping -c 4 rosout rosnode: node is [/rosnode] pinging /rosout with a timeout of 3.0s xmlrpc reply from http://ann:46635/ time=1.195908ms xmlrpc reply from http://ann:46635/ time=1.123905ms xmlrpc reply from http://ann:46635/ time=1.144886ms xmlrpc reply from http://ann:46635/ time=1.137018ms ping average: 1.150429ms
rosnode clearnup: purge registration information of unreachable nodes. This function was added as a cosmetic solution for the ros node display and should not be used for functional means. This is because it may terminate functioning nodes simply due to a delay.
2. rostopic command line tool
The rostopic command-line tool displays information about ROS topics. Currently, it can display a list of active topics, the publishers and subscribers of a specific topic, the publishing rate of a topic, the bandwidth of a topic, and messages published to a topic. The display of messages is configurable to output in a plotting-friendly format.
rostopic listdisplays all current topics. - To recieve information on a specific topic, use therostopic list /topic_namecommand. This is equivalent torostopic info `` command. - If you wish to save the topic lists in a bag file, add ``-bargument. - If you wish to only list the publishers of the said topic, add-pargument. - If you wish to only list the subscribers of the said topic, add-sargument. - You may also control the display output, by adding-vverbose argument.rostopic echodisplays the messages sent to a topic. - In order to specify which topic, add the topic name after the command line:$ rostopic echo /imu
3. pm2 command line tool
pm2 is a deamon process manager that helps the management of application and nodes within the system. For our application we can type
$ pm2 list
ROS Service
As we learned, the publish / subscribe model is a very flexible communication paradigm but it does not allow request / reply based interactions. Big example for this is sensors that has to recieve and send feedback inforamtions, rather than publishing every sensed information. We can implement request / reply based communication system with Service which is defined by a pair of messages; one for the request and one for the reply.
A providing ROS node offers a service under a string name, and a client calls the service by sending the request message and awaiting the reply.
As mentioned earlier the ROS Services are defined by srv (simplified service description language) files. With the usage of rospy (python library), we can convert the srv files into Python source code, and create three classes necessary for ROS Services:
Service Definition. Ex: (my_package/srv/Foo.srv -> my_package.srv.Foo)
Within a python file, the Service is defined as a container for the request and response type. It must be used whenever one creates or calls a service
add_two_ints = rospy.ServiceProxy('service_name', my_package.srv.Foo)
Request Messages. Ex: (my_package/srv/Foo.srv -> my_package.srv.FooRequest)
The resuest message is used to call the appropriate service.
Response Messages. Ex: (my_package/srv/Foo.srv -> my_package.srv.FooResponse)
The response message is used to contain the return value from the appropriate service. Hecne the Service handlers must return response messages instances of the correct type.
2. Service proxies
In most cases, you wish to set up a rospy.wait_for_service('service_name', timeout=None) to block until a service is available.
In order to use a Service, we need to create a rospy.ServiceProxy(name, service_class, persistent=False, headers=None) with the name of the service one wishes to call. The Service may return an error
in which case, we need to have a exception handler.
rospy.wait_for_service('add_two_ints')
try:
add_two_ints = rospy.ServiceProxy('add_two_ints', AddTwoInts)
resp1 = add_two_ints(x, y)
return resp1.sum
except rospy.ServiceException as e:
print("Service call failed: %s"%e)
3. Calling services
The rospy.ServiceProxy instances are callable. Within the python environment, you may call upon these instances similar to how a methos is called.
add_two_ints = rospy.ServiceProxy('add_two_ints', AddTwoInts)
add_two_ints(1, 2)
There are total of three ways to pass an argument to the ServiceProxy instance.
Explicit style:
The explicit style allows you to crewate your won * Request instance and pass it to publish. e.g:
request = rospy_tutorials.srv.AddTwoIntsRequest(1, 2) response = add_two_ints(request)
Implicit style with in-order arguments:
In the in-order style, a new Message instance will be created with the arguments provided, in order. With this style, all of the fields must be provided.
resp = add_two_ints(1, 2)
Implicit style with keyword arguments:
In the keyword style, you can only initialize the fields you wish to put into as a Message.
resp = add_two_ints(a = 1)
The above code will set the a as 1 and b as the default value (for our case it is 0)
4. Providing Services
In rospy, the rospy.Service instance with a callback to invoke when new requests are recieved is created to provide Service. Each inbound request is handled in its own thread, so services must be thread-safe.
rospy.Service(name, service_class, handler, buff_size=65536)
Create a new ROS Service with - Specified name - Service type - Handler
The handler is invoked with the service request and should invoke appropriate service response message.
def add_two_ints(req): return rospy_tutorials.srv.AddTowIntsResponse(req.a + req.b) def add_two_ints_server(): rospy.init_node('add_two_ints_server') s = rospy.Service('add_two_ints', rospy_tutorials.srv.AddTwoInts, add_two_ints) rospy.spin()
The handler return type may be:
None(failure)
ServiceResponse
tuple or list
dict
singe-arugment responses only: value of fields.