diff --git a/rcljava/CMakeLists.txt b/rcljava/CMakeLists.txt index 19d7ce8c..b2a09fac 100644 --- a/rcljava/CMakeLists.txt +++ b/rcljava/CMakeLists.txt @@ -61,6 +61,7 @@ set(${PROJECT_NAME}_jni_sources "src/main/cpp/org_ros2_rcljava_executors_BaseExecutor.cpp" "src/main/cpp/org_ros2_rcljava_events_EventHandlerImpl.cpp" "src/main/cpp/org_ros2_rcljava_publisher_statuses_LivelinessLost.cpp" + "src/main/cpp/org_ros2_rcljava_publisher_statuses_OfferedDeadlineMissed.cpp" "src/main/cpp/org_ros2_rcljava_publisher_statuses_OfferedQosIncompatible.cpp" "src/main/cpp/org_ros2_rcljava_node_NodeImpl.cpp" "src/main/cpp/org_ros2_rcljava_publisher_PublisherImpl.cpp" @@ -134,6 +135,7 @@ set(${PROJECT_NAME}_sources "src/main/java/org/ros2/rcljava/events/PublisherEventStatus.java" "src/main/java/org/ros2/rcljava/events/SubscriptionEventStatus.java" "src/main/java/org/ros2/rcljava/publisher/statuses/LivelinessLost.java" + "src/main/java/org/ros2/rcljava/publisher/statuses/OfferedDeadlineMissed.java" "src/main/java/org/ros2/rcljava/publisher/statuses/OfferedQosIncompatible.java" "src/main/java/org/ros2/rcljava/executors/AnyExecutable.java" "src/main/java/org/ros2/rcljava/executors/BaseExecutor.java" diff --git a/rcljava/include/org_ros2_rcljava_publisher_statuses_OfferedDeadlineMissed.h b/rcljava/include/org_ros2_rcljava_publisher_statuses_OfferedDeadlineMissed.h new file mode 100644 index 00000000..2f0575c9 --- /dev/null +++ b/rcljava/include/org_ros2_rcljava_publisher_statuses_OfferedDeadlineMissed.h @@ -0,0 +1,63 @@ +// Copyright 2020 Open Source Robotics Foundation, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include +/* Header for class org_ros2_rcljava_publisher_statuses_OfferedDeadlineMissed */ + +#ifndef ORG_ROS2_RCLJAVA_PUBLISHER_STATUSES_OFFEREDDEADLINEMISSED_H_ +#define ORG_ROS2_RCLJAVA_PUBLISHER_STATUSES_OFFEREDDEADLINEMISSED_H_ +#ifdef __cplusplus +extern "C" { +#endif + +/* + * Class: org_ros2_rcljava_publisher_statuses_OfferedDeadlineMissed + * Method: nativeAllocateRCLStatusEvent + * Signature: ()J + */ +JNIEXPORT jlong JNICALL +Java_org_ros2_rcljava_publisher_statuses_OfferedDeadlineMissed_nativeAllocateRCLStatusEvent( + JNIEnv *, jclass); + +/* + * Class: org_ros2_rcljava_publisher_statuses_OfferedDeadlineMissed + * Method: nativeDeallocateRCLStatusEvent + * Signature: (J)V + */ +JNIEXPORT void JNICALL +Java_org_ros2_rcljava_publisher_statuses_OfferedDeadlineMissed_nativeDeallocateRCLStatusEvent( + JNIEnv *, jclass, jlong); + +/* + * Class: org_ros2_rcljava_publisher_statuses_OfferedDeadlineMissed + * Method: nativeFromRCLEvent + * Signature: (J)V + */ +JNIEXPORT void JNICALL +Java_org_ros2_rcljava_publisher_statuses_OfferedDeadlineMissed_nativeFromRCLEvent( + JNIEnv *, jobject, jlong); + +/* + * Class: org_ros2_rcljava_publisher_statuses_OfferedDeadlineMissed + * Method: nativeGetPublisherEventType + * Signature: ()I + */ +JNIEXPORT jint JNICALL +Java_org_ros2_rcljava_publisher_statuses_OfferedDeadlineMissed_nativeGetPublisherEventType( + JNIEnv *, jclass); + +#ifdef __cplusplus +} +#endif +#endif // ORG_ROS2_RCLJAVA_PUBLISHER_STATUSES_OFFEREDDEADLINEMISSED_H_ diff --git a/rcljava/src/main/cpp/org_ros2_rcljava_publisher_statuses_OfferedDeadlineMissed.cpp b/rcljava/src/main/cpp/org_ros2_rcljava_publisher_statuses_OfferedDeadlineMissed.cpp new file mode 100644 index 00000000..4cdac4bf --- /dev/null +++ b/rcljava/src/main/cpp/org_ros2_rcljava_publisher_statuses_OfferedDeadlineMissed.cpp @@ -0,0 +1,73 @@ +// Copyright 2020 Open Source Robotics Foundation, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include "org_ros2_rcljava_publisher_statuses_OfferedDeadlineMissed.h" + +#include +#include + +#include "rmw/types.h" +#include "rcl/event.h" +#include "rcljava_common/exceptions.hpp" + +using rcljava_common::exceptions::rcljava_throw_exception; + +JNIEXPORT jlong JNICALL +Java_org_ros2_rcljava_publisher_statuses_OfferedDeadlineMissed_nativeAllocateRCLStatusEvent( + JNIEnv * env, jclass) +{ + void * p = malloc(sizeof(rmw_offered_deadline_missed_status_t)); + if (!p) { + rcljava_throw_exception( + env, "java/lang/OutOfMemoryError", "failed to allocate deadline missed status"); + } + return reinterpret_cast(p); +} + +JNIEXPORT void JNICALL +Java_org_ros2_rcljava_publisher_statuses_OfferedDeadlineMissed_nativeDeallocateRCLStatusEvent( + JNIEnv *, jclass, jlong handle) +{ + free(reinterpret_cast(handle)); +} + +JNIEXPORT void JNICALL +Java_org_ros2_rcljava_publisher_statuses_OfferedDeadlineMissed_nativeFromRCLEvent( + JNIEnv * env, jobject self, jlong handle) +{ + auto * p = reinterpret_cast(handle); + if (!p) { + rcljava_throw_exception( + env, "java/lang/IllegalArgumentException", "passed rmw object handle is NULL"); + } + // TODO(ivanpauno): class and field lookup could be done at startup time + jclass clazz = env->GetObjectClass(self); + jfieldID total_count_fid = env->GetFieldID(clazz, "totalCount", "I"); + if (env->ExceptionCheck()) { + return; + } + jfieldID total_count_change_fid = env->GetFieldID(clazz, "totalCountChange", "I"); + if (env->ExceptionCheck()) { + return; + } + env->SetIntField(self, total_count_fid, p->total_count); + env->SetIntField(self, total_count_change_fid, p->total_count_change); +} + +JNIEXPORT jint JNICALL +Java_org_ros2_rcljava_publisher_statuses_OfferedDeadlineMissed_nativeGetPublisherEventType( + JNIEnv *, jclass) +{ + return RCL_PUBLISHER_OFFERED_DEADLINE_MISSED; +} diff --git a/rcljava/src/main/java/org/ros2/rcljava/publisher/statuses/OfferedDeadlineMissed.java b/rcljava/src/main/java/org/ros2/rcljava/publisher/statuses/OfferedDeadlineMissed.java new file mode 100644 index 00000000..f4409806 --- /dev/null +++ b/rcljava/src/main/java/org/ros2/rcljava/publisher/statuses/OfferedDeadlineMissed.java @@ -0,0 +1,65 @@ +// Copyright 2020 Open Source Robotics Foundation, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package org.ros2.rcljava.publisher.statuses; + +import java.util.function.Supplier; + +import org.ros2.rcljava.common.JNIUtils; +import org.ros2.rcljava.events.PublisherEventStatus; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * This class serves as a bridge between a rmw_offered_deadline_missed_status_t and RCLJava. + */ +public class OfferedDeadlineMissed implements PublisherEventStatus { + public int totalCount; + public int totalCountChange; + + public final long allocateRCLStatusEvent() { + return nativeAllocateRCLStatusEvent(); + } + public final void deallocateRCLStatusEvent(long handle) { + nativeDeallocateRCLStatusEvent(handle); + } + public final void fromRCLEvent(long handle) { + nativeFromRCLEvent(handle); + } + public final int getPublisherEventType() { + return nativeGetPublisherEventType(); + } + // TODO(ivanpauno): Remove this when -source 8 can be used (method references for the win) + public static final Supplier factory = new Supplier() { + public OfferedDeadlineMissed get() { + return new OfferedDeadlineMissed(); + } + }; + + private static final Logger logger = LoggerFactory.getLogger(OfferedDeadlineMissed.class); + static { + try { + JNIUtils.loadImplementation(OfferedDeadlineMissed.class); + } catch (UnsatisfiedLinkError ule) { + logger.error("Native code library failed to load.\n" + ule); + System.exit(1); + } + } + + private static native long nativeAllocateRCLStatusEvent(); + private static native void nativeDeallocateRCLStatusEvent(long handle); + private native void nativeFromRCLEvent(long handle); + private static native int nativeGetPublisherEventType(); +} diff --git a/rcljava/src/test/java/org/ros2/rcljava/publisher/PublisherTest.java b/rcljava/src/test/java/org/ros2/rcljava/publisher/PublisherTest.java index 7ee84de8..2183df8a 100644 --- a/rcljava/src/test/java/org/ros2/rcljava/publisher/PublisherTest.java +++ b/rcljava/src/test/java/org/ros2/rcljava/publisher/PublisherTest.java @@ -25,6 +25,7 @@ import org.ros2.rcljava.consumers.Consumer; import org.ros2.rcljava.events.EventHandler; import org.ros2.rcljava.publisher.statuses.LivelinessLost; +import org.ros2.rcljava.publisher.statuses.OfferedDeadlineMissed; import org.ros2.rcljava.publisher.statuses.OfferedQosIncompatible; import org.ros2.rcljava.exceptions.RCLException; import org.ros2.rcljava.node.Node; @@ -95,4 +96,25 @@ public void accept(final OfferedQosIncompatible status) { RCLJava.shutdown(); assertEquals(0, eventHandler.getHandle()); } + + @Test + public final void testCreateOfferedDeadlineMissedEvent() { + RCLJava.rclJavaInit(); + Node node = RCLJava.createNode("test_node"); + Publisher publisher = + node.createPublisher(std_msgs.msg.String.class, "test_topic"); + EventHandler eventHandler = publisher.createEventHandler( + OfferedDeadlineMissed.factory, new Consumer() { + public void accept(final OfferedDeadlineMissed status) { + assertEquals(status.totalCount, 0); + assertEquals(status.totalCountChange, 0); + } + } + ); + assertNotEquals(0, eventHandler.getHandle()); + // force executing the callback, so we check that taking an event works + eventHandler.executeCallback(); + RCLJava.shutdown(); + assertEquals(0, eventHandler.getHandle()); + } }