Skip to content

Commit 29e3b84

Browse files
committed
Add MessageLost subscription event status
Signed-off-by: Ivan Santiago Paunovic <ivanpauno@ekumenlabs.com>
1 parent 434e6f5 commit 29e3b84

5 files changed

Lines changed: 233 additions & 0 deletions

File tree

rcljava/CMakeLists.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,7 @@ set(${PROJECT_NAME}_jni_sources
6969
"src/main/cpp/org_ros2_rcljava_service_ServiceImpl.cpp"
7070
"src/main/cpp/org_ros2_rcljava_subscription_SubscriptionImpl.cpp"
7171
"src/main/cpp/org_ros2_rcljava_subscription_statuses_LivelinessChanged.cpp"
72+
"src/main/cpp/org_ros2_rcljava_subscription_statuses_MessageLost.cpp"
7273
"src/main/cpp/org_ros2_rcljava_subscription_statuses_RequestedDeadlineMissed.cpp"
7374
"src/main/cpp/org_ros2_rcljava_subscription_statuses_RequestedQosIncompatible.cpp"
7475
"src/main/cpp/org_ros2_rcljava_time_Clock.cpp"
@@ -180,6 +181,7 @@ set(${PROJECT_NAME}_sources
180181
"src/main/java/org/ros2/rcljava/subscription/Subscription.java"
181182
"src/main/java/org/ros2/rcljava/subscription/SubscriptionImpl.java"
182183
"src/main/java/org/ros2/rcljava/subscription/statuses/LivelinessChanged.java"
184+
"src/main/java/org/ros2/rcljava/subscription/statuses/MessageLost.java"
183185
"src/main/java/org/ros2/rcljava/subscription/statuses/RequestedDeadlineMissed.java"
184186
"src/main/java/org/ros2/rcljava/subscription/statuses/RequestedQosIncompatible.java"
185187
"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_MessageLost */
17+
18+
#ifndef ORG_ROS2_RCLJAVA_SUBSCRIPTION_STATUSES_MESSAGELOST_H_
19+
#define ORG_ROS2_RCLJAVA_SUBSCRIPTION_STATUSES_MESSAGELOST_H_
20+
#ifdef __cplusplus
21+
extern "C" {
22+
#endif
23+
24+
/*
25+
* Class: org_ros2_rcljava_subscription_statuses_MessageLost
26+
* Method: nativeAllocateRCLStatusEvent
27+
* Signature: ()J
28+
*/
29+
JNIEXPORT jlong JNICALL
30+
Java_org_ros2_rcljava_subscription_statuses_MessageLost_nativeAllocateRCLStatusEvent(
31+
JNIEnv *, jclass);
32+
33+
/*
34+
* Class: org_ros2_rcljava_subscription_statuses_MessageLost
35+
* Method: nativeDeallocateRCLStatusEvent
36+
* Signature: (J)V
37+
*/
38+
JNIEXPORT void JNICALL
39+
Java_org_ros2_rcljava_subscription_statuses_MessageLost_nativeDeallocateRCLStatusEvent(
40+
JNIEnv *, jclass, jlong);
41+
42+
/*
43+
* Class: org_ros2_rcljava_subscription_statuses_MessageLost
44+
* Method: nativeFromRCLEvent
45+
* Signature: (J)V
46+
*/
47+
JNIEXPORT void JNICALL
48+
Java_org_ros2_rcljava_subscription_statuses_MessageLost_nativeFromRCLEvent(
49+
JNIEnv *, jobject, jlong);
50+
51+
/*
52+
* Class: org_ros2_rcljava_subscription_statuses_MessageLost
53+
* Method: nativeGetsubscriptionEventType
54+
* Signature: ()I
55+
*/
56+
JNIEXPORT jint JNICALL
57+
Java_org_ros2_rcljava_subscription_statuses_MessageLost_nativeGetSubscriptionEventType(
58+
JNIEnv *, jclass);
59+
60+
#ifdef __cplusplus
61+
}
62+
#endif
63+
#endif // ORG_ROS2_RCLJAVA_SUBSCRIPTION_STATUSES_MESSAGELOST_H_
Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
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_MessageLost.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_MessageLost_nativeAllocateRCL(
28+
JNIEnv * env, jclass)
29+
{
30+
void * p = malloc(sizeof(rmw_message_lost_status_t));
31+
if (!p) {
32+
rcljava_throw_exception(
33+
env, "java/lang/OutOfMemoryError", "failed to allocate missed deadline status");
34+
}
35+
return reinterpret_cast<jlong>(p);
36+
}
37+
38+
JNIEXPORT void JNICALL
39+
Java_org_ros2_rcljava_subscription_statuses_MessageLost_nativeDeallocateRCL(
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_MessageLost_nativeFromRCL(
47+
JNIEnv * env, jobject self, jlong handle)
48+
{
49+
auto * p = reinterpret_cast<rmw_message_lost_status_t *>(handle);
50+
if (!p) {
51+
rcljava_throw_exception(
52+
env, "java/lang/IllegalArgumentException", "passed rmw object handle is NULL");
53+
return;
54+
}
55+
// TODO(ivanpauno): class and field lookup could be done at startup time
56+
jclass clazz = env->GetObjectClass(self);
57+
jfieldID total_count_fid = env->GetFieldID(clazz, "totalCount", "I");
58+
if (env->ExceptionCheck()) {
59+
return;
60+
}
61+
jfieldID total_count_change_fid = env->GetFieldID(clazz, "totalCountChange", "I");
62+
if (env->ExceptionCheck()) {
63+
return;
64+
}
65+
env->SetIntField(self, total_count_fid, p->total_count);
66+
env->SetIntField(self, total_count_change_fid, p->total_count_change);
67+
}
68+
69+
JNIEXPORT jint JNICALL
70+
Java_org_ros2_rcljava_subscription_statuses_MessageLost_nativeGetEventType(
71+
JNIEnv *, jclass)
72+
{
73+
return RCL_SUBSCRIPTION_MESSAGE_LOST;
74+
}
Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
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 a rmw_message_lost_status_t and RCLJava.
27+
*/
28+
public class MessageLost implements SubscriptionEventStatus {
29+
public int totalCount;
30+
public int totalCountChange;
31+
32+
public final long allocateRCLStatusEvent() {
33+
return nativeAllocateRCL();
34+
}
35+
public final void deallocateRCLStatusEvent(long handle) {
36+
nativeDeallocateRCL(handle);
37+
}
38+
public final void fromRCLEvent(long handle) {
39+
nativeFromRCL(handle);
40+
}
41+
public final int getSubscriptionEventType() {
42+
return nativeGetEventType();
43+
}
44+
// TODO(ivanpauno): Remove this when -source 8 can be used (method references for the win)
45+
public static final Supplier<MessageLost> factory = new Supplier<MessageLost>() {
46+
public MessageLost get() {
47+
return new MessageLost();
48+
}
49+
};
50+
51+
private static final Logger logger = LoggerFactory.getLogger(MessageLost.class);
52+
static {
53+
try {
54+
JNIUtils.loadImplementation(MessageLost.class);
55+
} catch (UnsatisfiedLinkError ule) {
56+
logger.error("Native code library failed to load.\n" + ule);
57+
System.exit(1);
58+
}
59+
}
60+
61+
private static native long nativeAllocateRCL();
62+
private static native void nativeDeallocateRCL(long handle);
63+
private native void nativeFromRCL(long handle);
64+
private static native int nativeGetEventType();
65+
}

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

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@
2828
import org.ros2.rcljava.events.EventHandler;
2929
import org.ros2.rcljava.node.Node;
3030
import org.ros2.rcljava.subscription.statuses.LivelinessChanged;
31+
import org.ros2.rcljava.subscription.statuses.MessageLost;
3132
import org.ros2.rcljava.subscription.statuses.RequestedDeadlineMissed;
3233
import org.ros2.rcljava.subscription.statuses.RequestedQosIncompatible;
3334

@@ -149,4 +150,32 @@ public void accept(final RequestedQosIncompatible status) {
149150
RCLJava.shutdown();
150151
assertEquals(0, eventHandler.getHandle());
151152
}
153+
154+
@Test
155+
public final void testCreateMessageLost() {
156+
String identifier = RCLJava.getRMWIdentifier();
157+
if (identifier.equals("rmw_fastrtps_cpp") || identifier.equals("rmw_fastrtps_dynamic_cpp")) {
158+
// event not supported in these implementations
159+
return;
160+
}
161+
RCLJava.rclJavaInit();
162+
Node node = RCLJava.createNode("test_node");
163+
Subscription<std_msgs.msg.String> subscription = node.<std_msgs.msg.String>createSubscription(
164+
std_msgs.msg.String.class, "test_topic", new Consumer<std_msgs.msg.String>() {
165+
public void accept(final std_msgs.msg.String msg) {}
166+
});
167+
EventHandler eventHandler = subscription.createEventHandler(
168+
MessageLost.factory, new Consumer<MessageLost>() {
169+
public void accept(final MessageLost status) {
170+
assertEquals(status.totalCount, 0);
171+
assertEquals(status.totalCountChange, 0);
172+
}
173+
}
174+
);
175+
assertNotEquals(0, eventHandler.getHandle());
176+
// force executing the callback, so we check that taking an event works
177+
eventHandler.executeCallback();
178+
RCLJava.shutdown();
179+
assertEquals(0, eventHandler.getHandle());
180+
}
152181
}

0 commit comments

Comments
 (0)