forked from CST-Group/cst-bindings
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathRosServiceClientCodelet.java
More file actions
157 lines (134 loc) · 5.22 KB
/
RosServiceClientCodelet.java
File metadata and controls
157 lines (134 loc) · 5.22 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
/***********************************************************************************************
* Copyright (c) 2012 DCA-FEEC-UNICAMP
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the GNU Lesser Public License v3
* which accompanies this distribution, and is available at
* http://www.gnu.org/licenses/lgpl.html
* <p>
* Contributors:
* K. Raizer, A. L. O. Paraense, E. M. Froes, R. R. Gudwin - initial API and implementation
* jrborelli - ROS2
***********************************************************************************************/
package br.unicamp.cst.bindings.ros2java;
import br.unicamp.cst.core.entities.Codelet;
import br.unicamp.cst.core.entities.Memory;
import br.unicamp.cst.core.exceptions.CodeletActivationBoundsException;
import id.jrosmessages.Message;
import id.jros2client.JRos2Client;
import id.jros2client.JRos2ClientFactory;
import pinorobotics.jros2services.JRos2ServiceClient;
import pinorobotics.jros2services.JRos2ServicesFactory;
import pinorobotics.jrosservices.msgs.ServiceDefinition;
import java.util.concurrent.Semaphore;
import java.util.concurrent.CompletableFuture;
public abstract class RosServiceClientCodelet<S extends Message, T extends Message> extends Codelet {
protected String serviceName;
protected ServiceDefinition<S, T> serviceDefinition;
protected Memory inputMemory;
protected S requestMessage;
protected JRos2ServiceClient<S, T> serviceClient;
protected JRos2Client ros2Client;
private final Semaphore callInProgressSemaphore = new Semaphore(1);
public RosServiceClientCodelet(String serviceName, ServiceDefinition<S, T> serviceDefinition) {
this.serviceName = serviceName;
this.serviceDefinition = serviceDefinition;
this.setName("Ros2Client:" + serviceName);
}
@Override
public synchronized void start() {
try {
ros2Client = new JRos2ClientFactory().createClient();
serviceClient = new JRos2ServicesFactory().createClient(ros2Client, serviceDefinition, serviceName);
} catch (Exception e) {
throw new RuntimeException("Failed to initialize ROS 2 client for service: " + serviceName, e);
}
super.start();
}
@Override
public synchronized void stop() {
try {
if (serviceClient != null) serviceClient.close();
if (ros2Client != null) ros2Client.close();
} catch (Exception e) {
e.printStackTrace();
}
super.stop();
}
@Override
public void accessMemoryObjects() {
if (inputMemory == null) {
inputMemory = this.getInput(serviceName, 0);
}
}
@Override
public void calculateActivation() {
try {
setActivation(1.0); // always ready to run
} catch (CodeletActivationBoundsException e) {
e.printStackTrace();
}
}
@Override
public void proc() {
if (inputMemory == null || inputMemory.getI() == null) return;
if (!callInProgressSemaphore.tryAcquire()) {
// Call in progress, skip this cycle
return;
}
try {
requestMessage = createNewRequest();
if (!formatServiceRequest(inputMemory, requestMessage)) {
callInProgressSemaphore.release();
return; // no need to send request
}
CompletableFuture<T> responseFuture = serviceClient.sendRequestAsync(requestMessage);
responseFuture.thenAccept(response -> {
if (response != null) processServiceResponse(response);
callInProgressSemaphore.release();
}).exceptionally(ex -> {
System.err.println("ROS 2 service call failed: " + ex.getMessage());
callInProgressSemaphore.release();
return null;
});
} catch (Exception e) {
System.err.println("Error in ROS 2 service call: " + e.getMessage());
callInProgressSemaphore.release();
}
}
/**
* Create a new empty request message instance.
*
*/
protected abstract S createNewRequest();
/*@Override //exemplo:
protected AddTwoIntsRequestMessage createNewRequest() {
return new AddTwoIntsRequestMessage();
} */
/**
* Fill the request message from input memory.
* Return true if the request should be sent.
*/
protected abstract boolean formatServiceRequest(Memory memory, S request);
/*
@Override //exemplo:
protected boolean formatServiceRequest(Memory memory, AddTwoIntsRequestMessage request) {
Integer[] inputs = (Integer[]) memory.getI(); // example cast
if (inputs == null || inputs.length < 2) return false;
request.setA(inputs[0]);
request.setB(inputs[1]);
return true;
}
*/
/**
* Handle the response message.
*/
protected abstract void processServiceResponse(T response);
/*
@Override
protected void processServiceResponse(AddTwoIntsResponseMessage response) {
int sum = response.getSum();
System.out.println("Sum received: " + sum);
// Update CST memory or state as needed
}
*/
}