Skip to content

Commit b8ef52f

Browse files
committed
Add LivelinessChanged subscription event (osrf#18)
Signed-off-by: Ivan Santiago Paunovic <ivanpauno@ekumenlabs.com>
1 parent d72d1cd commit b8ef52f

File tree

5 files changed

+244
-0
lines changed

5 files changed

+244
-0
lines changed

rcljava/CMakeLists.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,7 @@ set(${PROJECT_NAME}_jni_sources
6868
"src/main/cpp/org_ros2_rcljava_publisher_PublisherImpl.cpp"
6969
"src/main/cpp/org_ros2_rcljava_service_ServiceImpl.cpp"
7070
"src/main/cpp/org_ros2_rcljava_subscription_SubscriptionImpl.cpp"
71+
"src/main/cpp/org_ros2_rcljava_subscription_statuses_LivelinessChanged.cpp"
7172
"src/main/cpp/org_ros2_rcljava_subscription_statuses_RequestedDeadlineMissed.cpp"
7273
"src/main/cpp/org_ros2_rcljava_subscription_statuses_RequestedQosIncompatible.cpp"
7374
"src/main/cpp/org_ros2_rcljava_time_Clock.cpp"
@@ -178,6 +179,7 @@ set(${PROJECT_NAME}_sources
178179
"src/main/java/org/ros2/rcljava/service/ServiceImpl.java"
179180
"src/main/java/org/ros2/rcljava/subscription/Subscription.java"
180181
"src/main/java/org/ros2/rcljava/subscription/SubscriptionImpl.java"
182+
"src/main/java/org/ros2/rcljava/subscription/statuses/LivelinessChanged.java"
181183
"src/main/java/org/ros2/rcljava/subscription/statuses/RequestedDeadlineMissed.java"
182184
"src/main/java/org/ros2/rcljava/subscription/statuses/RequestedQosIncompatible.java"
183185
"src/main/java/org/ros2/rcljava/time/Clock.java"
Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
// Copyright 2020 Open Source Robotics Foundation, Inc.
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License");
4+
// you may not use this file except in compliance with the License.
5+
// You may obtain a copy of the License at
6+
//
7+
// http://www.apache.org/licenses/LICENSE-2.0
8+
//
9+
// Unless required by applicable law or agreed to in writing, software
10+
// distributed under the License is distributed on an "AS IS" BASIS,
11+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
// See the License for the specific language governing permissions and
13+
// limitations under the License.
14+
15+
#include <jni.h>
16+
/* Header for class org_ros2_rcljava_subscription_statuses_LivelinessChanged */
17+
18+
#ifndef ORG_ROS2_RCLJAVA_SUBSCRIPTION_STATUSES_LIVELINESSCHANGED_H_
19+
#define ORG_ROS2_RCLJAVA_SUBSCRIPTION_STATUSES_LIVELINESSCHANGED_H_
20+
#ifdef __cplusplus
21+
extern "C" {
22+
#endif
23+
24+
/*
25+
* Class: org_ros2_rcljava_subscription_statuses_LivelinessChanged
26+
* Method: nativeAllocateRCLStatusEvent
27+
* Signature: ()J
28+
*/
29+
JNIEXPORT jlong JNICALL
30+
Java_org_ros2_rcljava_subscription_statuses_LivelinessChanged_nativeAllocateRCLStatusEvent(
31+
JNIEnv *, jclass);
32+
33+
/*
34+
* Class: org_ros2_rcljava_subscription_statuses_LivelinessChanged
35+
* Method: nativeDeallocateRCLStatusEvent
36+
* Signature: (J)V
37+
*/
38+
JNIEXPORT void JNICALL
39+
Java_org_ros2_rcljava_subscription_statuses_LivelinessChanged_nativeDeallocateRCLStatusEvent(
40+
JNIEnv *, jclass, jlong);
41+
42+
/*
43+
* Class: org_ros2_rcljava_subscription_statuses_LivelinessChanged
44+
* Method: nativeFromRCLEvent
45+
* Signature: (J)V
46+
*/
47+
JNIEXPORT void JNICALL
48+
Java_org_ros2_rcljava_subscription_statuses_LivelinessChanged_nativeFromRCLEvent(
49+
JNIEnv *, jobject, jlong);
50+
51+
/*
52+
* Class: org_ros2_rcljava_subscription_statuses_LivelinessChanged
53+
* Method: nativeGetsubscriptionEventType
54+
* Signature: ()I
55+
*/
56+
JNIEXPORT jint JNICALL
57+
Java_org_ros2_rcljava_subscription_statuses_LivelinessChanged_nativeGetSubscriptionEventType(
58+
JNIEnv *, jclass);
59+
60+
#ifdef __cplusplus
61+
}
62+
#endif
63+
#endif // ORG_ROS2_RCLJAVA_SUBSCRIPTION_STATUSES_LIVELINESSCHANGED_H_
Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,83 @@
1+
// Copyright 2020 Open Source Robotics Foundation, Inc.
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License");
4+
// you may not use this file except in compliance with the License.
5+
// You may obtain a copy of the License at
6+
//
7+
// http://www.apache.org/licenses/LICENSE-2.0
8+
//
9+
// Unless required by applicable law or agreed to in writing, software
10+
// distributed under the License is distributed on an "AS IS" BASIS,
11+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
// See the License for the specific language governing permissions and
13+
// limitations under the License.
14+
15+
#include "org_ros2_rcljava_subscription_statuses_LivelinessChanged.h"
16+
17+
#include <jni.h>
18+
#include <stdlib.h>
19+
20+
#include "rmw/types.h"
21+
#include "rcl/event.h"
22+
#include "rcljava_common/exceptions.hpp"
23+
24+
using rcljava_common::exceptions::rcljava_throw_exception;
25+
26+
JNIEXPORT jlong JNICALL
27+
Java_org_ros2_rcljava_subscription_statuses_LivelinessChanged_nativeAllocateRCLStatusEvent(
28+
JNIEnv * env, jclass)
29+
{
30+
void * p = malloc(sizeof(rmw_liveliness_changed_status_t));
31+
if (!p) {
32+
rcljava_throw_exception(
33+
env, "java/lang/OutOfMemoryError", "failed to allocate liveliness changed status");
34+
}
35+
return reinterpret_cast<jlong>(p);
36+
}
37+
38+
JNIEXPORT void JNICALL
39+
Java_org_ros2_rcljava_subscription_statuses_LivelinessChanged_nativeDeallocateRCLStatusEvent(
40+
JNIEnv *, jclass, jlong handle)
41+
{
42+
free(reinterpret_cast<void *>(handle));
43+
}
44+
45+
JNIEXPORT void JNICALL
46+
Java_org_ros2_rcljava_subscription_statuses_LivelinessChanged_nativeFromRCLEvent(
47+
JNIEnv * env, jobject self, jlong handle)
48+
{
49+
auto * p = reinterpret_cast<rmw_liveliness_changed_status_t *>(handle);
50+
if (!p) {
51+
rcljava_throw_exception(
52+
env, "java/lang/IllegalArgumentException", "passed rmw object handle is NULL");
53+
}
54+
// TODO(ivanpauno): class and field lookup could be done at startup time
55+
jclass clazz = env->GetObjectClass(self);
56+
jfieldID alive_count_fid = env->GetFieldID(clazz, "aliveCount", "I");
57+
if (env->ExceptionCheck()) {
58+
return;
59+
}
60+
jfieldID not_alive_count_fid = env->GetFieldID(clazz, "notAliveCount", "I");
61+
if (env->ExceptionCheck()) {
62+
return;
63+
}
64+
jfieldID alive_count_change_fid = env->GetFieldID(clazz, "aliveCountChange", "I");
65+
if (env->ExceptionCheck()) {
66+
return;
67+
}
68+
jfieldID not_alive_count_change_fid = env->GetFieldID(clazz, "notAliveCountChange", "I");
69+
if (env->ExceptionCheck()) {
70+
return;
71+
}
72+
env->SetIntField(self, alive_count_fid, p->alive_count);
73+
env->SetIntField(self, not_alive_count_fid, p->not_alive_count);
74+
env->SetIntField(self, alive_count_change_fid, p->alive_count_change);
75+
env->SetIntField(self, not_alive_count_change_fid, p->not_alive_count_change);
76+
}
77+
78+
JNIEXPORT jint JNICALL
79+
Java_org_ros2_rcljava_subscription_statuses_LivelinessChanged_nativeGetSubscriptionEventType(
80+
JNIEnv *, jclass)
81+
{
82+
return RCL_SUBSCRIPTION_LIVELINESS_CHANGED;
83+
}
Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
// Copyright 2020 Open Source Robotics Foundation, Inc.
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License");
4+
// you may not use this file except in compliance with the License.
5+
// You may obtain a copy of the License at
6+
//
7+
// http://www.apache.org/licenses/LICENSE-2.0
8+
//
9+
// Unless required by applicable law or agreed to in writing, software
10+
// distributed under the License is distributed on an "AS IS" BASIS,
11+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
// See the License for the specific language governing permissions and
13+
// limitations under the License.
14+
15+
package org.ros2.rcljava.subscription.statuses;
16+
17+
import java.util.function.Supplier;
18+
19+
import org.ros2.rcljava.common.JNIUtils;
20+
import org.ros2.rcljava.events.SubscriptionEventStatus;
21+
22+
import org.slf4j.Logger;
23+
import org.slf4j.LoggerFactory;
24+
25+
/**
26+
* This class serves as a bridge between rmw_liveliness_changed_status_t
27+
* and RCLJava.
28+
*/
29+
public class LivelinessChanged implements SubscriptionEventStatus {
30+
public int aliveCount;
31+
public int notAliveCount;
32+
public int aliveCountChange;
33+
public int notAliveCountChange;
34+
35+
public final long allocateRCLStatusEvent() {
36+
return nativeAllocateRCLStatusEvent();
37+
}
38+
public final void deallocateRCLStatusEvent(long handle) {
39+
nativeDeallocateRCLStatusEvent(handle);
40+
}
41+
public final void fromRCLEvent(long handle) {
42+
nativeFromRCLEvent(handle);
43+
}
44+
public final int getSubscriptionEventType() {
45+
return nativeGetSubscriptionEventType();
46+
}
47+
// TODO(ivanpauno): Remove this when -source 8 can be used (method references for the win)
48+
public static final Supplier<LivelinessChanged>
49+
factory = new Supplier<LivelinessChanged>() {
50+
public LivelinessChanged get() {
51+
return new LivelinessChanged();
52+
}
53+
};
54+
55+
private static final Logger logger = LoggerFactory.getLogger(LivelinessChanged.class);
56+
static {
57+
try {
58+
JNIUtils.loadImplementation(LivelinessChanged.class);
59+
} catch (UnsatisfiedLinkError ule) {
60+
logger.error("Native code library failed to load.\n" + ule);
61+
System.exit(1);
62+
}
63+
}
64+
65+
private static native long nativeAllocateRCLStatusEvent();
66+
private static native void nativeDeallocateRCLStatusEvent(long handle);
67+
private native void nativeFromRCLEvent(long handle);
68+
private static native int nativeGetSubscriptionEventType();
69+
}

rcljava/src/test/java/org/ros2/rcljava/subscription/SubscriptionTest.java

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@
2727
import org.ros2.rcljava.consumers.Consumer;
2828
import org.ros2.rcljava.events.EventHandler;
2929
import org.ros2.rcljava.node.Node;
30+
import org.ros2.rcljava.subscription.statuses.LivelinessChanged;
3031
import org.ros2.rcljava.subscription.statuses.RequestedDeadlineMissed;
3132
import org.ros2.rcljava.subscription.statuses.RequestedQosIncompatible;
3233

@@ -70,6 +71,32 @@ public void accept(final std_msgs.msg.String msg) {}
7071
RCLJava.shutdown();
7172
}
7273

74+
@Test
75+
public final void testCreateLivelinessChangedEvent() {
76+
String identifier = RCLJava.getRMWIdentifier();
77+
RCLJava.rclJavaInit();
78+
Node node = RCLJava.createNode("test_node");
79+
Subscription<std_msgs.msg.String> subscription = node.<std_msgs.msg.String>createSubscription(
80+
std_msgs.msg.String.class, "test_topic", new Consumer<std_msgs.msg.String>() {
81+
public void accept(final std_msgs.msg.String msg) {}
82+
});
83+
EventHandler eventHandler = subscription.createEventHandler(
84+
LivelinessChanged.factory, new Consumer<LivelinessChanged>() {
85+
public void accept(final LivelinessChanged status) {
86+
assertEquals(status.aliveCount, 0);
87+
assertEquals(status.notAliveCount, 0);
88+
assertEquals(status.aliveCountChange, 0);
89+
assertEquals(status.notAliveCountChange, 0);
90+
}
91+
}
92+
);
93+
assertNotEquals(0, eventHandler.getHandle());
94+
// force executing the callback, so we check that taking an event works
95+
eventHandler.executeCallback();
96+
RCLJava.shutdown();
97+
assertEquals(0, eventHandler.getHandle());
98+
}
99+
73100
@Test
74101
public final void testCreateRequestedDeadlineMissedEvent() {
75102
String identifier = RCLJava.getRMWIdentifier();

0 commit comments

Comments
 (0)