Skip to content

Commit 59184d3

Browse files
committed
Add getSubscriptionsInfo to Node class (osrf#27)
Signed-off-by: Ivan Santiago Paunovic <ivanpauno@ekumenlabs.com>
1 parent 2bd1e56 commit 59184d3

File tree

5 files changed

+117
-13
lines changed

5 files changed

+117
-13
lines changed

rcljava/include/org_ros2_rcljava_node_NodeImpl.h

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -119,6 +119,15 @@ JNIEXPORT void
119119
JNICALL Java_org_ros2_rcljava_node_NodeImpl_nativeGetPublishersInfo(
120120
JNIEnv *, jclass, jlong, jstring, jobject);
121121

122+
/*
123+
* Class: org_ros2_rcljava_node_NodeImpl
124+
* Method: nativeGetSubscriptionsInfo
125+
* Signature: (JLjava/lang/String;Ljava/util/List;)V
126+
*/
127+
JNIEXPORT void
128+
JNICALL Java_org_ros2_rcljava_node_NodeImpl_nativeGetSubscriptionsInfo(
129+
JNIEnv *, jclass, jlong, jstring, jobject);
130+
122131
#ifdef __cplusplus
123132
}
124133
#endif

rcljava/src/main/cpp/org_ros2_rcljava_node_NodeImpl.cpp

Lines changed: 29 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -379,9 +379,10 @@ Java_org_ros2_rcljava_node_NodeImpl_nativeGetTopicNamesAndTypes(
379379
}
380380
}
381381

382-
JNIEXPORT void JNICALL
383-
Java_org_ros2_rcljava_node_NodeImpl_nativeGetPublishersInfo(
384-
JNIEnv * env, jclass, jlong handle, jstring jtopic_name, jobject jpublishers_info)
382+
template<typename FunctorT>
383+
void
384+
get_endpoint_info_common(
385+
JNIEnv * env, jlong handle, jstring jtopic_name, jobject jendpoints_info, FunctorT get_info)
385386
{
386387
rcl_node_t * node = reinterpret_cast<rcl_node_t *>(handle);
387388
if (!node) {
@@ -391,7 +392,7 @@ Java_org_ros2_rcljava_node_NodeImpl_nativeGetPublishersInfo(
391392
}
392393

393394
rcutils_allocator_t allocator = rcutils_get_default_allocator();
394-
rcl_topic_endpoint_info_array_t publishers_info =
395+
rcl_topic_endpoint_info_array_t endpoints_info =
395396
rcl_get_zero_initialized_topic_endpoint_info_array();
396397

397398
const char * topic_name = env->GetStringUTFChars(jtopic_name, NULL);
@@ -401,26 +402,26 @@ Java_org_ros2_rcljava_node_NodeImpl_nativeGetPublishersInfo(
401402
return;
402403
}
403404

404-
rcl_ret_t ret = rcl_get_publishers_info_by_topic(
405+
rcl_ret_t ret = get_info(
405406
node,
406407
&allocator,
407408
topic_name,
408409
false, // use ros mangling conventions
409-
&publishers_info);
410+
&endpoints_info);
410411

411412
env->ReleaseStringUTFChars(jtopic_name, topic_name);
412413

413414
RCLJAVA_COMMON_THROW_FROM_RCL(env, ret, "failed to get publisher info");
414415
auto cleanup_info_array = rcpputils::make_scope_exit(
415-
[info_ptr = &publishers_info, allocator_ptr = &allocator, env]() {
416+
[info_ptr = &endpoints_info, allocator_ptr = &allocator, env]() {
416417
rcl_ret_t ret = rcl_topic_endpoint_info_array_fini(info_ptr, allocator_ptr);
417418
if (!env->ExceptionCheck() && RCL_RET_OK != ret) {
418-
rcljava_throw_rclexception(env, ret, "failed to destroy rcl publisher info");
419+
rcljava_throw_rclexception(env, ret, "failed to destroy rcl endpoints info");
419420
}
420421
}
421422
);
422423

423-
jclass list_clazz = env->GetObjectClass(jpublishers_info);
424+
jclass list_clazz = env->GetObjectClass(jendpoints_info);
424425
jmethodID list_add_mid = env->GetMethodID(list_clazz, "add", "(Ljava/lang/Object;)Z");
425426
RCLJAVA_COMMON_CHECK_FOR_EXCEPTION(env);
426427
jclass endpoint_info_clazz = env->FindClass("org/ros2/rcljava/graph/EndpointInfo");
@@ -431,13 +432,29 @@ Java_org_ros2_rcljava_node_NodeImpl_nativeGetPublishersInfo(
431432
endpoint_info_clazz, "nativeFromRCL", "(J)V");
432433
RCLJAVA_COMMON_CHECK_FOR_EXCEPTION(env);
433434

434-
for (size_t i = 0; i < publishers_info.size; i++) {
435+
for (size_t i = 0; i < endpoints_info.size; i++) {
435436
jobject item = env->NewObject(endpoint_info_clazz, endpoint_info_init_mid);
436437
RCLJAVA_COMMON_CHECK_FOR_EXCEPTION(env);
437-
env->CallVoidMethod(item, endpoint_info_from_rcl_mid, &publishers_info.info_array[i]);
438+
env->CallVoidMethod(item, endpoint_info_from_rcl_mid, &endpoints_info.info_array[i]);
438439
RCLJAVA_COMMON_CHECK_FOR_EXCEPTION(env);
439-
env->CallBooleanMethod(jpublishers_info, list_add_mid, item);
440+
env->CallBooleanMethod(jendpoints_info, list_add_mid, item);
440441
RCLJAVA_COMMON_CHECK_FOR_EXCEPTION(env);
441442
env->DeleteLocalRef(item);
442443
}
443444
}
445+
446+
JNIEXPORT void JNICALL
447+
Java_org_ros2_rcljava_node_NodeImpl_nativeGetPublishersInfo(
448+
JNIEnv * env, jclass, jlong handle, jstring jtopic_name, jobject jpublishers_info)
449+
{
450+
get_endpoint_info_common(
451+
env, handle, jtopic_name, jpublishers_info, rcl_get_publishers_info_by_topic);
452+
}
453+
454+
JNIEXPORT void JNICALL
455+
Java_org_ros2_rcljava_node_NodeImpl_nativeGetSubscriptionsInfo(
456+
JNIEnv * env, jclass, jlong handle, jstring jtopic_name, jobject jsubscriptions_info)
457+
{
458+
get_endpoint_info_common(
459+
env, handle, jtopic_name, jsubscriptions_info, rcl_get_subscriptions_info_by_topic);
460+
}

rcljava/src/main/java/org/ros2/rcljava/node/Node.java

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -578,4 +578,16 @@ <T extends ServiceDefinition> Client<T> createClient(final Class<T> serviceType,
578578
* passed topic.
579579
*/
580580
Collection<EndpointInfo> getPublishersInfo(final String topicName);
581+
582+
/**
583+
* Get information of all subscriptions in a topic.
584+
*
585+
* The queried information includes the node that created the publisher, its qos, etc.
586+
* For more info, see @{link EndpointInfo}.
587+
*
588+
* @param topicName The topic name of interest.
589+
* @return A collection of `EndpointInfo` instances, describing all subscriptions in the
590+
* passed topic.
591+
*/
592+
Collection<EndpointInfo> getSubscriptionsInfo(final String topicName);
581593
}

rcljava/src/main/java/org/ros2/rcljava/node/NodeImpl.java

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -782,4 +782,13 @@ public final Collection<EndpointInfo> getPublishersInfo(final String topicName)
782782

783783
private native static final void nativeGetPublishersInfo(
784784
final long handle, final String topicName, ArrayList<EndpointInfo> endpointInfo);
785+
786+
public final Collection<EndpointInfo> getSubscriptionsInfo(final String topicName) {
787+
ArrayList<EndpointInfo> returnValue = new ArrayList();
788+
nativeGetSubscriptionsInfo(this.handle, topicName, returnValue);
789+
return returnValue;
790+
}
791+
792+
private native static final void nativeGetSubscriptionsInfo(
793+
final long handle, final String topicName, ArrayList<EndpointInfo> endpointInfo);
785794
}

rcljava/src/test/java/org/ros2/rcljava/node/NodeTest.java

Lines changed: 58 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1064,4 +1064,61 @@ public void accept(final Collection<EndpointInfo> info) {
10641064
publisher.dispose();
10651065
publisher2.dispose();
10661066
}
1067-
}
1067+
1068+
@Test
1069+
public final void testGetSubscriptionsInfo() {
1070+
Subscription<rcljava.msg.UInt32> subscription = node.<rcljava.msg.UInt32>createSubscription(
1071+
rcljava.msg.UInt32.class, "test_get_subscriptions_info", new Consumer<rcljava.msg.UInt32>() {
1072+
public void accept(final rcljava.msg.UInt32 msg) {}
1073+
});
1074+
Subscription<rcljava.msg.UInt32> subscription2 = node.<rcljava.msg.UInt32>createSubscription(
1075+
rcljava.msg.UInt32.class, "test_get_subscriptions_info", new Consumer<rcljava.msg.UInt32>() {
1076+
public void accept(final rcljava.msg.UInt32 msg) {}
1077+
}, QoSProfile.sensorData());
1078+
1079+
Consumer<Collection<EndpointInfo>> validateEndpointInfo =
1080+
new Consumer<Collection<EndpointInfo>>() {
1081+
public void accept(final Collection<EndpointInfo> info) {
1082+
assertEquals(info.size(), 2);
1083+
Iterator<EndpointInfo> it = info.iterator();
1084+
EndpointInfo item = it.next();
1085+
assertEquals("test_node", item.nodeName);
1086+
assertEquals("/", item.nodeNamespace);
1087+
assertEquals("rcljava/msg/UInt32", item.topicType);
1088+
assertEquals(item.endpointType, EndpointInfo.EndpointType.SUBSCRIPTION);
1089+
assertEquals(item.qos.getReliability(), Reliability.RELIABLE);
1090+
item = it.next();
1091+
assertEquals("test_node", item.nodeName);
1092+
assertEquals("/", item.nodeNamespace);
1093+
assertEquals("rcljava/msg/UInt32", item.topicType);
1094+
assertEquals(item.endpointType, EndpointInfo.EndpointType.SUBSCRIPTION);
1095+
assertEquals(item.qos.getReliability(), Reliability.BEST_EFFORT);
1096+
assertFalse(it.hasNext());
1097+
}
1098+
};
1099+
1100+
long start = System.currentTimeMillis();
1101+
boolean ok = false;
1102+
Collection<EndpointInfo> subscriptionsInfo = null;
1103+
do {
1104+
subscriptionsInfo = node.getSubscriptionsInfo("/test_get_subscriptions_info");
1105+
try {
1106+
validateEndpointInfo.accept(subscriptionsInfo);
1107+
ok = true;
1108+
} catch (AssertionError err) {
1109+
// ignore here, it's going to be validated again at the end.
1110+
}
1111+
// TODO(ivanpauno): We could wait for the graph guard condition to be triggered if that
1112+
// would be available.
1113+
try {
1114+
TimeUnit.MILLISECONDS.sleep(100);
1115+
} catch (InterruptedException err) {
1116+
// ignore
1117+
}
1118+
} while (!ok && System.currentTimeMillis() < start + 1000);
1119+
assertNotNull(subscriptionsInfo);
1120+
validateEndpointInfo.accept(subscriptionsInfo);
1121+
subscription.dispose();
1122+
subscription2.dispose();
1123+
}
1124+
}

0 commit comments

Comments
 (0)