Note: This tutorial assumes that you have completed the previous tutorials: Installation, Creating Rosjava Packages. |
Please ask about problems and questions regarding this tutorial on answers.ros.org. Don't forget to include in your question the link to this page, the versions of your OS & ROS, and also add appropriate tags. |
A RosJava Service Client and Server (Catkin Style)
Description: It shows how to create, compile and execute a service (both server and client) in Rosjava.Keywords: Rosjava, service
Tutorial Level:
Next Tutorial: Building RosJava Libraries
Note: Tutorial under development
Creating and Compiling the Custom Service
In this tutorial we will generate the Java artifacts for a custom service inside a standard ROS package, and we will use them afterwards in a Rosjava package.
Creating the Service's package
In order to create a new package into a new Rosjava workspace, we open a terminal and typing the following commands:
mkdir -p ~/rosjava_srv_ws/src cd ~/rosjava_srv_ws/src catkin_create_pkg rosjava_custom_srv message_generation message_runtime std_msgs -V 0.1.0
Then we have to modify the CMakeLists.txt file in order to compile the custom Service Open the CMakeLists.txt from the previously created package and add the following:
find_package(catkin REQUIRED COMPONENTS message_generation message_runtime std_msgs ) add_service_files( DIRECTORY srv ) generate_messages(DEPENDENCIES std_msgs)
Creating the Service
We now create a new folders inside the rosjava_custom_srv package:
cd ~/rosjava_srv_ws/src/rosjava_custom_srv mkdir srv
And inside the srv folder we create the CustomService.srv file with the following content:
int32 size --- int64[] res
The service above sends as request an integer in order to create an array with this size. The service sends as a response this array which includes a numeric series to the size of the request. For example if the Client sends the number 5 as request, the Server will return the following array:
0 1 2 3 4
Finally we are able to compile the new service by executing the following in a new terminal:
cd ~/rosjava_srv_ws catkin_make
Creating the RosJava Client/Server
In the workspace we created above, we shall create a Rosjava package and a sub-project where the Service will be embedded. Remember to source your Rosjava installation workspace first to have the command line tools available (e.g. source ~/rosjava/devel/setup.bash). Then, execute the following commands from a command line:
cd ~/rosjava_srv_ws/src catkin_create_rosjava_pkg tutorial_custom_srv cd tutorial_custom_srv catkin_create_rosjava_project client_server cd ~/rosjava_srv_ws catkin_make
Add the Service into the rosjava_core package
Open the build.gradle from the client_server project (~/rosjava_srv_ws/src/tutorial_custom_srv/client_server/build.gradle) and add the following lines as dependencies:
dependencies { compile 'org.ros.rosjava_core:rosjava:[0.3,0.4)' compile 'org.ros.rosjava_messages:rosjava_custom_srv:[0.1, 0.2)' }
This way, we will be able to import the custom service into the sub-package. The [0.1, 0.2) from the rosjava_custom_srv is referred to the version of the package (package.xml). Finally in the rosjava_tutorial_custom_services, delete the src and create a new sub-directory with two java files, the Client.java and the Server.java inside of the rosjava_tutorial_services folder
cd rosjava_srv_ws/src/tutorial_custom_srv/client_server mkdir -p src/main/java/org/ros/rosjava_tutorial_services
Creating the Service/Server
The Server.java file will embed the following code:
1 /*
2 * Copyright (C) 2011 Google Inc.
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License"); you may not
5 * use this file except in compliance with the License. You may obtain a copy of
6 * the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
12 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
13 * License for the specific language governing permissions and limitations under
14 * the License.
15 */
16
17 package org.ros.rosjava_tutorial_custom_services;
18
19 import org.ros.namespace.GraphName;
20 import org.ros.node.AbstractNodeMain;
21 import org.ros.node.ConnectedNode;
22 import org.ros.node.NodeMain;
23 import org.ros.node.service.ServiceResponseBuilder;
24 import org.ros.node.service.ServiceServer;
25 import java.io.Console;
26 import rosjava_custom_srv.CustomService;
27 import rosjava_custom_srv.CustomServiceRequest;
28 import rosjava_custom_srv.CustomServiceResponse;
29 /**
30 * A simple {@link ServiceServer} {@link NodeMain}.
31 The original code is created by:
32 *
33 * @author damonkohler@google.com (Damon Kohler)
34 * The custom implementation is created by
35 v.s.moisiadis@gmail.com(Vasileios Moisiadis)
36 */
37 public class Server extends AbstractNodeMain {
38
39 @Override
40 public GraphName getDefaultNodeName() {
41 return GraphName.of("rosjava_tutorial_custom_services/server");
42 }
43
44 @Override
45 public void onStart(final ConnectedNode connectedNode) {
46 connectedNode.newServiceServer("CustomService", CustomService._TYPE,
47 new ServiceResponseBuilder<CustomServiceRequest, CustomServiceResponse>() {
48 @Override
49 public void
50 build(CustomServiceRequest request, CustomServiceResponse response) {
51 //Create an array with the size of request.getSize()
52 long[] tmpArray=new long[request.getSize()];
53 for(int i=0; i<request.getSize();i++){
54 tmpArray[i]=i;
55 }
56 response.setRes(tmpArray);
57 connectedNode.getLog().info(
58 String.format("The size of the array will be "+request.getSize()));
59
60 }
61 });
62 }
63 }
The Code Explained
The only difference with the original implementation is that we have imported our new custom service Error: No code_block found Also add the dynamic array creation Error: No code_block found
Creating the Service/Client
The Client.java file will embed the following code.
1 /*
2 * Copyright (C) 2011 Google Inc.
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License"); you may not
5 * use this file except in compliance with the License. You may obtain a copy of
6 * the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
12 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
13 * License for the specific language governing permissions and limitations under
14 * the License.
15 */
16
17 package org.ros.rosjava_tutorial_custom_services;
18
19 import org.ros.exception.RemoteException;
20 import org.ros.exception.RosRuntimeException;
21 import org.ros.exception.ServiceNotFoundException;
22 import org.ros.namespace.GraphName;
23 import org.ros.node.AbstractNodeMain;
24 import org.ros.node.ConnectedNode;
25 import org.ros.node.NodeMain;
26 import org.ros.node.service.ServiceClient;
27 import org.ros.node.service.ServiceResponseListener;
28 import rosjava_custom_srv.CustomServiceResponse;
29 import rosjava_custom_srv.CustomServiceRequest;
30 import rosjava_custom_srv.CustomService;
31
32 /**
33 * A simple {@link ServiceClient} {@link NodeMain}.
34 The original code is created by:
35 *
36 * @author damonkohler@google.com (Damon Kohler)
37 * The custom implementation is created by
38 v.s.moisiadis@gmail.com(Vasileios Moisiadis)
39 */
40 public class Client extends AbstractNodeMain {
41
42 @Override
43 public GraphName getDefaultNodeName() {
44 return GraphName.of("rosjava_tutorial_custom_custom_services/client");
45 }
46
47 @Override
48 public void onStart(final ConnectedNode connectedNode) {
49 ServiceClient<CustomServiceRequest, CustomServiceResponse> serviceClient;
50 try {
51 serviceClient = connectedNode.newServiceClient("CustomService", CustomService._TYPE);
52 } catch (ServiceNotFoundException e) {
53 throw new RosRuntimeException(e);
54 }
55 final CustomServiceRequest request = serviceClient.newMessage();
56 //set the request/size
57
58 request.setSize(10);
59
60 serviceClient.call(request, new ServiceResponseListener<CustomServiceResponse>() {
61 @Override
62 public void onSuccess(CustomServiceResponse response) {
63 connectedNode.getLog().info(
64 String.format("The response is : "));
65
66 for (long l : response.getRes()) {
67 connectedNode.getLog().info(l);
68 }
69 }
70
71 @Override
72 public void onFailure(RemoteException e) {
73 throw new RosRuntimeException(e);
74 }
75 });
76 }
77 }
The Code Explained
The only difference at the Service/Client is that we have to set a size to the requested array in order to receive it. Error: No code_block found Also we use a for loop to demonstrate the incoming data. Error: No code_block found
Running the Service
Before executing the service we have to build it first, and run the Master node. Open a new terminal and type the following commands (remember to source your rosjava installation workspace first!):
cd ~/rosjava_srv_ws catkin_make roscore
Then we open two more terminals and we execute separately. For the Server:
cd ~/rosjava_srv_ws source devel/setup.bash rosrun tutorial_custom_srv client_server org.ros.rosjava_tutorial_custom_services.Server # select option 2 when prompted
For the Client:
cd ~/rosjava_srv_ws source devel/setup.bash rosrun tutorial_custom_srv client_server org.ros.rosjava_tutorial_custom_services.Client # select option 2 when prompted