From 94e53fb057b0482f08fcac8293d2d9fab36ffb2c Mon Sep 17 00:00:00 2001 From: Jacob Perron Date: Thu, 7 May 2020 05:28:38 -0700 Subject: [PATCH 1/6] Add Client methods for checking and waiting for service availability (#85) * Re-enable tests related to services Signed-off-by: Jacob Perron * Add Client methods for checking and waiting for service availability These methods are very useful for allowing a client to wait for a service to be available before making requests. Signed-off-by: Jacob Perron * Refactor ClientTest to avoid repeatedly sending requests Signed-off-by: Jacob Perron --- rcljava/CMakeLists.txt | 10 ++-- .../org_ros2_rcljava_client_ClientImpl.h | 10 ++++ .../org_ros2_rcljava_client_ClientImpl.cpp | 27 +++++++++ .../java/org/ros2/rcljava/client/Client.java | 30 ++++++++++ .../org/ros2/rcljava/client/ClientImpl.java | 56 +++++++++++++++++++ .../org/ros2/rcljava/client/ClientTest.java | 24 +++++--- 6 files changed, 145 insertions(+), 12 deletions(-) diff --git a/rcljava/CMakeLists.txt b/rcljava/CMakeLists.txt index 9fa10643..a2a5862f 100644 --- a/rcljava/CMakeLists.txt +++ b/rcljava/CMakeLists.txt @@ -264,14 +264,14 @@ if(BUILD_TESTING) "src/test/java/org/ros2/rcljava/RCLJavaTest.java" "src/test/java/org/ros2/rcljava/SpinTest.java" "src/test/java/org/ros2/rcljava/TimeTest.java" - # "src/test/java/org/ros2/rcljava/client/ClientTest.java" + "src/test/java/org/ros2/rcljava/client/ClientTest.java" "src/test/java/org/ros2/rcljava/contexts/ContextTest.java" "src/test/java/org/ros2/rcljava/node/NodeOptionsTest.java" "src/test/java/org/ros2/rcljava/node/NodeParametersTest.java" "src/test/java/org/ros2/rcljava/node/NodeUndeclaredParametersTest.java" "src/test/java/org/ros2/rcljava/node/NodeTest.java" - # "src/test/java/org/ros2/rcljava/parameters/AsyncParametersClientTest.java" - # "src/test/java/org/ros2/rcljava/parameters/SyncParametersClientTest.java" + "src/test/java/org/ros2/rcljava/parameters/AsyncParametersClientTest.java" + "src/test/java/org/ros2/rcljava/parameters/SyncParametersClientTest.java" "src/test/java/org/ros2/rcljava/publisher/PublisherTest.java" "src/test/java/org/ros2/rcljava/qos/QoSProfileTest.java" "src/test/java/org/ros2/rcljava/subscription/SubscriptionTest.java" @@ -283,13 +283,13 @@ if(BUILD_TESTING) "org.ros2.rcljava.RCLJavaTest" "org.ros2.rcljava.SpinTest" "org.ros2.rcljava.TimeTest" - # "org.ros2.rcljava.client.ClientTest" + "org.ros2.rcljava.client.ClientTest" "org.ros2.rcljava.contexts.ContextTest" "org.ros2.rcljava.node.NodeOptionsTest" "org.ros2.rcljava.node.NodeParametersTest" "org.ros2.rcljava.node.NodeUndeclaredParametersTest" "org.ros2.rcljava.node.NodeTest" - # "org.ros2.rcljava.parameters.SyncParametersClientTest" + "org.ros2.rcljava.parameters.SyncParametersClientTest" "org.ros2.rcljava.publisher.PublisherTest" "org.ros2.rcljava.qos.QoSProfileTest" "org.ros2.rcljava.subscription.SubscriptionTest" diff --git a/rcljava/include/org_ros2_rcljava_client_ClientImpl.h b/rcljava/include/org_ros2_rcljava_client_ClientImpl.h index ab71b022..c59635e0 100644 --- a/rcljava/include/org_ros2_rcljava_client_ClientImpl.h +++ b/rcljava/include/org_ros2_rcljava_client_ClientImpl.h @@ -37,6 +37,16 @@ JNICALL Java_org_ros2_rcljava_client_ClientImpl_nativeSendClientRequest( JNIEXPORT void JNICALL Java_org_ros2_rcljava_client_ClientImpl_nativeDispose(JNIEnv *, jclass, jlong, jlong); +/* + * Class: org_ros2_rcljava_client_ClientImpl + * Method: nativeIsServiceAvailable + * Signature: (JJ)Z + */ +JNIEXPORT jboolean +JNICALL Java_org_ros2_rcljava_client_ClientImpl_nativeIsServiceAvailable( + JNIEnv *, jclass, jlong, jlong); + + #ifdef __cplusplus } #endif diff --git a/rcljava/src/main/cpp/org_ros2_rcljava_client_ClientImpl.cpp b/rcljava/src/main/cpp/org_ros2_rcljava_client_ClientImpl.cpp index f950506f..33646342 100644 --- a/rcljava/src/main/cpp/org_ros2_rcljava_client_ClientImpl.cpp +++ b/rcljava/src/main/cpp/org_ros2_rcljava_client_ClientImpl.cpp @@ -19,6 +19,7 @@ #include #include "rcl/error_handling.h" +#include "rcl/graph.h" #include "rcl/node.h" #include "rcl/rcl.h" #include "rmw/rmw.h" @@ -96,3 +97,29 @@ Java_org_ros2_rcljava_client_ClientImpl_nativeDispose( rcljava_throw_rclexception(env, ret, msg); } } + +JNIEXPORT jboolean JNICALL +Java_org_ros2_rcljava_client_ClientImpl_nativeIsServiceAvailable( + JNIEnv * env, jclass, jlong node_handle, jlong client_handle) +{ + rcl_node_t * node = reinterpret_cast(node_handle); + assert(node != NULL); + rcl_client_t * client = reinterpret_cast(client_handle); + assert(client != NULL); + + bool is_ready; + rcl_ret_t ret = rcl_service_server_is_available(node, client, &is_ready); + if (RCL_RET_NODE_INVALID == ret) { + if (node && !rcl_context_is_valid(node->context)) { + // context is shutdown, do a soft failure + return false; + } + } + if (ret != RCL_RET_OK) { + std::string msg = + "Failed to check if service is available: " + std::string(rcl_get_error_string().str); + rcl_reset_error(); + rcljava_throw_rclexception(env, ret, msg); + } + return is_ready; +} diff --git a/rcljava/src/main/java/org/ros2/rcljava/client/Client.java b/rcljava/src/main/java/org/ros2/rcljava/client/Client.java index 79ef137e..774ecec6 100644 --- a/rcljava/src/main/java/org/ros2/rcljava/client/Client.java +++ b/rcljava/src/main/java/org/ros2/rcljava/client/Client.java @@ -15,6 +15,7 @@ package org.ros2.rcljava.client; +import java.time.Duration; import java.util.concurrent.Future; import org.ros2.rcljava.concurrent.RCLFuture; @@ -37,5 +38,34 @@ Future asyncSendRe Future asyncSendRequest( final U request, final Consumer> callback); + /** + * Check if the service server is available. + * + * @return true if the client can talk to the service, false otherwise. + */ + boolean isServiceAvailable(); + + /** + * Wait for the service server to be available. + * + * Blocks until the service is available or the ROS context is invalidated. + * + * @return true if the service is available, false if the ROS context was shutdown. + */ + boolean waitForService(); + + /** + * Wait for the service server to be available. + * + * Blocks until the service is available or a timeout occurs. + * Also returns if the ROS context is invalidated. + * + * @param timeout Time to wait for the service to be available. + * A zero value causes this method to check if the service is available and return immediately. + * A negative value is treated as an infinite timeout. + * @return true if the service is available, false otherwise. + */ + boolean waitForService(Duration timeout); + String getServiceName(); } diff --git a/rcljava/src/main/java/org/ros2/rcljava/client/ClientImpl.java b/rcljava/src/main/java/org/ros2/rcljava/client/ClientImpl.java index 1269de83..b8274cec 100644 --- a/rcljava/src/main/java/org/ros2/rcljava/client/ClientImpl.java +++ b/rcljava/src/main/java/org/ros2/rcljava/client/ClientImpl.java @@ -15,11 +15,15 @@ package org.ros2.rcljava.client; +import java.time.Duration; import java.lang.ref.WeakReference; +import java.lang.InterruptedException; +import java.lang.Long; import java.util.AbstractMap; import java.util.HashMap; import java.util.Map; import java.util.concurrent.Future; +import java.util.concurrent.TimeUnit; import org.ros2.rcljava.RCLJava; import org.ros2.rcljava.common.JNIUtils; @@ -142,6 +146,58 @@ public final long getHandle() { return this.handle; } + private static native boolean nativeIsServiceAvailable(long nodeHandle, long handle); + + /** + * {@inheritDoc} + */ + public boolean isServiceAvailable() { + Node node = this.nodeReference.get(); + if (node == null) { + return false; + } + return nativeIsServiceAvailable(node.getHandle(), this.handle); + } + + /** + * {@inheritDoc} + */ + public final boolean waitForService() { + return waitForService(Duration.ofNanos(-1)); + } + + /** + * {@inheritDoc} + */ + public final boolean waitForService(Duration timeout) { + long timeoutNano = timeout.toNanos(); + if (0L == timeoutNano) { + return isServiceAvailable(); + } + long startTime = System.nanoTime(); + long timeToWait = (timeoutNano >= 0L) ? timeoutNano : Long.MAX_VALUE; + while (RCLJava.ok() && timeToWait > 0L) { + // TODO(jacobperron): Wake up whenever graph changes instead of sleeping for a fixed duration + try { + TimeUnit.MILLISECONDS.sleep(10); + } catch (InterruptedException ex) { + Thread.currentThread().interrupt(); + return false; + } + + if (isServiceAvailable()) { + return true; + } + + // If timeout is negative, timeToWait will always be greater than zero + if (timeoutNano > 0L) { + timeToWait = timeoutNano - (System.nanoTime() - startTime); + } + } + + return false; + } + public String getServiceName() { return this.serviceName; } diff --git a/rcljava/src/test/java/org/ros2/rcljava/client/ClientTest.java b/rcljava/src/test/java/org/ros2/rcljava/client/ClientTest.java index dd41e228..df7d2a6c 100644 --- a/rcljava/src/test/java/org/ros2/rcljava/client/ClientTest.java +++ b/rcljava/src/test/java/org/ros2/rcljava/client/ClientTest.java @@ -26,9 +26,12 @@ import org.junit.Test; import java.lang.ref.WeakReference; +import java.time.Duration; import java.util.Arrays; import java.util.List; +import java.util.concurrent.Future; +import java.util.concurrent.TimeUnit; import org.ros2.rcljava.RCLJava; import org.ros2.rcljava.concurrent.RCLFuture; @@ -81,10 +84,10 @@ public static void tearDownOnce() { @Test public final void testAdd() throws Exception { - RCLFuture future = + RCLFuture consumerFuture = new RCLFuture(new WeakReference(node)); - TestClientConsumer clientConsumer = new TestClientConsumer(future); + TestClientConsumer clientConsumer = new TestClientConsumer(consumerFuture); Service service = node.createService( rcljava.srv.AddTwoInts.class, "add_two_ints", clientConsumer); @@ -96,12 +99,19 @@ public final void testAdd() throws Exception { Client client = node.createClient(rcljava.srv.AddTwoInts.class, "add_two_ints"); - while (RCLJava.ok() && !future.isDone()) { - client.asyncSendRequest(request); - RCLJava.spinOnce(node); - } + assertTrue(client.waitForService(Duration.ofSeconds(10))); + + Future responseFuture = client.asyncSendRequest(request); + + rcljava.srv.AddTwoInts_Response response = responseFuture.get(10, TimeUnit.SECONDS); + + // Check that the message was received by the service + assertTrue(consumerFuture.isDone()); + + // Check the contents of the response + assertEquals(5, response.getSum()); - assertEquals(5, future.get().getSum()); + // Cleanup client.dispose(); assertEquals(0, client.getHandle()); service.dispose(); From 77a1e2e1a441609da3b9b19852eb205bf059b61b Mon Sep 17 00:00:00 2001 From: Niels Tiben Date: Tue, 9 Jun 2020 11:49:38 +0200 Subject: [PATCH 2/6] Fix action generation (#108) Generate action code for: * `_SendGoal_Request` * `_SendGoal_Response` * `_GetResult_Request` * `_GetResult_Response` --- rosidl_generator_java/resource/action.cpp.em | 30 ++++++++++++++++++-- 1 file changed, 27 insertions(+), 3 deletions(-) diff --git a/rosidl_generator_java/resource/action.cpp.em b/rosidl_generator_java/resource/action.cpp.em index 0abc7138..266922e9 100644 --- a/rosidl_generator_java/resource/action.cpp.em +++ b/rosidl_generator_java/resource/action.cpp.em @@ -58,21 +58,45 @@ expand_template( data, output_file) +# Generate SendGoal message type +data.update({'msg': action.send_goal_service.request_message}) +output_file = os.path.join(output_dir, *namespaces[1:], '{0}.ep.{1}.cpp'.format(send_goal_type_name, typesupport_impl)) +expand_template( + 'msg.cpp.em', + data, + output_file) + +# Generate GetResult message type +data.update({'msg': action.get_result_service.request_message}) +output_file = os.path.join(output_dir, *namespaces[1:], '{0}.ep.{1}.cpp'.format(send_goal_type_name, typesupport_impl)) +expand_template( + 'msg.cpp.em', + data, + output_file) + +data = { + 'package_name': package_name, + 'interface_path': interface_path, + 'output_dir': output_dir, + 'template_basepath': template_basepath, + 'typesupport_impl': typesupport_impl, +} + # Generate SendGoal service type data.update({'service': action.send_goal_service}) output_file = os.path.join( output_dir, *namespaces[1:], '{0}.ep.{1}.cpp'.format(send_goal_type_name, typesupport_impl)) expand_template( - 'msg.cpp.em', + 'srv.cpp.em', data, output_file) -# Generate SendGoal service type +# Generate GetResult service type data.update({'service': action.get_result_service}) output_file = os.path.join( output_dir, *namespaces[1:], '{0}.ep.{1}.cpp'.format(get_result_type_name, typesupport_impl)) expand_template( - 'msg.cpp.em', + 'srv.cpp.em', data, output_file) }@ From b2859b68f84756c15edac2bba76cff1ed4c7ae4a Mon Sep 17 00:00:00 2001 From: sung-goo-kim <69021132+sung-goo-kim@users.noreply.github.com> Date: Thu, 1 Oct 2020 00:08:30 +0900 Subject: [PATCH 3/6] (RclJava) Fix Node.testPubUInt32MultipleNodes() error (#133) --- rcljava/src/test/java/org/ros2/rcljava/node/NodeTest.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rcljava/src/test/java/org/ros2/rcljava/node/NodeTest.java b/rcljava/src/test/java/org/ros2/rcljava/node/NodeTest.java index 21573efb..358c9e7f 100644 --- a/rcljava/src/test/java/org/ros2/rcljava/node/NodeTest.java +++ b/rcljava/src/test/java/org/ros2/rcljava/node/NodeTest.java @@ -858,7 +858,7 @@ public Node getNode() { executor.addNode(composableSubscriptionNodeOne); executor.addNode(composableSubscriptionNodeTwo); - while (RCLJava.ok() && !futureOne.isDone() && !futureTwo.isDone()) { + while (RCLJava.ok() && !(futureOne.isDone() && futureTwo.isDone())) { publisher.publish(msg); executor.spinSome(); } From 9ab541d7264842e5176f9f3bc1ab41c857b9a58f Mon Sep 17 00:00:00 2001 From: sung-goo-kim <69021132+sung-goo-kim@users.noreply.github.com> Date: Thu, 1 Oct 2020 00:08:58 +0900 Subject: [PATCH 4/6] clear node/context handle on RclJava.cleanup() (#130) * clear node/context handle on RclJava.cleanup() * clear publishers, subscriptions, clients, services and timers on Node.dispose() --- .../main/java/org/ros2/rcljava/RCLJava.java | 23 +++---------------- .../java/org/ros2/rcljava/node/NodeImpl.java | 17 ++++++++++++++ 2 files changed, 20 insertions(+), 20 deletions(-) diff --git a/rcljava/src/main/java/org/ros2/rcljava/RCLJava.java b/rcljava/src/main/java/org/ros2/rcljava/RCLJava.java index 87d7ebe8..6c820ed9 100644 --- a/rcljava/src/main/java/org/ros2/rcljava/RCLJava.java +++ b/rcljava/src/main/java/org/ros2/rcljava/RCLJava.java @@ -82,31 +82,14 @@ private RCLJava() {} private static void cleanup() { for (Node node : nodes) { - for (Subscription subscription : node.getSubscriptions()) { - subscription.dispose(); - } - - for (Publisher publisher : node.getPublishers()) { - publisher.dispose(); - } - - for (Timer timer : node.getTimers()) { - timer.dispose(); - } - - for (Service service : node.getServices()) { - service.dispose(); - } - - for (Client client : node.getClients()) { - client.dispose(); - } - node.dispose(); } + nodes.clear(); + for (Context context : contexts) { context.dispose(); } + contexts.clear(); } static { diff --git a/rcljava/src/main/java/org/ros2/rcljava/node/NodeImpl.java b/rcljava/src/main/java/org/ros2/rcljava/node/NodeImpl.java index 4e649913..5c11aed8 100644 --- a/rcljava/src/main/java/org/ros2/rcljava/node/NodeImpl.java +++ b/rcljava/src/main/java/org/ros2/rcljava/node/NodeImpl.java @@ -26,6 +26,7 @@ import org.ros2.rcljava.contexts.Context; import org.ros2.rcljava.graph.EndpointInfo; import org.ros2.rcljava.graph.NameAndTypes; +import org.ros2.rcljava.interfaces.Disposable; import org.ros2.rcljava.interfaces.MessageDefinition; import org.ros2.rcljava.interfaces.ServiceDefinition; import org.ros2.rcljava.node.NodeOptions; @@ -418,10 +419,26 @@ public final Collection getClients() { */ private static native void nativeDispose(long handle); + private void cleanupDisposables(Collection disposables) { + for (Disposable disposable : disposables) { + disposable.dispose(); + } + disposables.clear(); + } + + private void cleanup() { + cleanupDisposables(subscriptions); + cleanupDisposables(publishers); + cleanupDisposables(timers); + cleanupDisposables(services); + cleanupDisposables(clients); + } + /** * {@inheritDoc} */ public final void dispose() { + cleanup(); nativeDispose(this.handle); this.handle = 0; } From aa96c969500cb4e349418529b7c0f0fc756101b8 Mon Sep 17 00:00:00 2001 From: Jacob Perron Date: Mon, 9 Nov 2020 14:30:33 -0800 Subject: [PATCH 5/6] Compile generated action-related services (#140) * Remove redundant code generation The request and response messages are already generated as part of the srv template. Signed-off-by: Jacob Perron * Strip action service suffixes from C include prefix The generated C headers for actions are included in a single header named after the action. Signed-off-by: Jacob Perron * Generate Java code for SendGoal and GetResult service definitions Though not strictly necessary, it is nice to have definitions for these action-specific services for the purpose of writing unit tests. Signed-off-by: Jacob Perron * Compile generated service definitions for actions Previously, though we were generated service definitions for actions we were not compiling them. Signed-off-by: Jacob Perron --- ...dl_generator_java_generate_interfaces.cmake | 12 ++++++++++++ rosidl_generator_java/resource/action.cpp.em | 17 ----------------- rosidl_generator_java/resource/action.java.em | 18 ++++++++++++++++++ rosidl_generator_java/resource/msg.cpp.em | 10 ++++++++++ rosidl_generator_java/resource/srv.cpp.em | 15 ++++++++++++++- 5 files changed, 54 insertions(+), 18 deletions(-) diff --git a/rosidl_generator_java/cmake/rosidl_generator_java_generate_interfaces.cmake b/rosidl_generator_java/cmake/rosidl_generator_java_generate_interfaces.cmake index b6779281..e8c9e433 100644 --- a/rosidl_generator_java/cmake/rosidl_generator_java_generate_interfaces.cmake +++ b/rosidl_generator_java/cmake/rosidl_generator_java_generate_interfaces.cmake @@ -81,11 +81,23 @@ foreach(_abs_idl_file ${rosidl_generate_interfaces_ABS_IDL_FILES}) "${_output_path}/${_parent_folder}/${_idl_name}_Goal.java" "${_output_path}/${_parent_folder}/${_idl_name}_Result.java" "${_output_path}/${_parent_folder}/${_idl_name}_Feedback.java" + "${_output_path}/${_parent_folder}/${_idl_name}_SendGoal.java" + "${_output_path}/${_parent_folder}/${_idl_name}_SendGoal_Request.java" + "${_output_path}/${_parent_folder}/${_idl_name}_SendGoal_Response.java" + "${_output_path}/${_parent_folder}/${_idl_name}_GetResult.java" + "${_output_path}/${_parent_folder}/${_idl_name}_GetResult_Request.java" + "${_output_path}/${_parent_folder}/${_idl_name}_GetResult_Response.java" ) foreach(_typesupport_impl ${_typesupport_impls}) list(APPEND _generated_extension_${_typesupport_impl}_files "${_output_path}/${_parent_folder}/${_idl_name}_Goal.ep.${_typesupport_impl}.cpp") list(APPEND _generated_extension_${_typesupport_impl}_files "${_output_path}/${_parent_folder}/${_idl_name}_Result.ep.${_typesupport_impl}.cpp") list(APPEND _generated_extension_${_typesupport_impl}_files "${_output_path}/${_parent_folder}/${_idl_name}_Feedback.ep.${_typesupport_impl}.cpp") + list(APPEND _generated_extension_${_typesupport_impl}_files "${_output_path}/${_parent_folder}/${_idl_name}_SendGoal.ep.${_typesupport_impl}.cpp") + list(APPEND _generated_extension_${_typesupport_impl}_files "${_output_path}/${_parent_folder}/${_idl_name}_SendGoal_Request.ep.${_typesupport_impl}.cpp") + list(APPEND _generated_extension_${_typesupport_impl}_files "${_output_path}/${_parent_folder}/${_idl_name}_SendGoal_Response.ep.${_typesupport_impl}.cpp") + list(APPEND _generated_extension_${_typesupport_impl}_files "${_output_path}/${_parent_folder}/${_idl_name}_GetResult.ep.${_typesupport_impl}.cpp") + list(APPEND _generated_extension_${_typesupport_impl}_files "${_output_path}/${_parent_folder}/${_idl_name}_GetResult_Request.ep.${_typesupport_impl}.cpp") + list(APPEND _generated_extension_${_typesupport_impl}_files "${_output_path}/${_parent_folder}/${_idl_name}_GetResult_Response.ep.${_typesupport_impl}.cpp") endforeach() endif() diff --git a/rosidl_generator_java/resource/action.cpp.em b/rosidl_generator_java/resource/action.cpp.em index 266922e9..0d3492e4 100644 --- a/rosidl_generator_java/resource/action.cpp.em +++ b/rosidl_generator_java/resource/action.cpp.em @@ -58,25 +58,8 @@ expand_template( data, output_file) -# Generate SendGoal message type -data.update({'msg': action.send_goal_service.request_message}) -output_file = os.path.join(output_dir, *namespaces[1:], '{0}.ep.{1}.cpp'.format(send_goal_type_name, typesupport_impl)) -expand_template( - 'msg.cpp.em', - data, - output_file) - -# Generate GetResult message type -data.update({'msg': action.get_result_service.request_message}) -output_file = os.path.join(output_dir, *namespaces[1:], '{0}.ep.{1}.cpp'.format(send_goal_type_name, typesupport_impl)) -expand_template( - 'msg.cpp.em', - data, - output_file) - data = { 'package_name': package_name, - 'interface_path': interface_path, 'output_dir': output_dir, 'template_basepath': template_basepath, 'typesupport_impl': typesupport_impl, diff --git a/rosidl_generator_java/resource/action.java.em b/rosidl_generator_java/resource/action.java.em index 070ddd61..5e7ebbe9 100644 --- a/rosidl_generator_java/resource/action.java.em +++ b/rosidl_generator_java/resource/action.java.em @@ -13,6 +13,8 @@ type_name = action.namespaced_type.name goal_type_name = action.goal.structure.namespaced_type.name result_type_name = action.result.structure.namespaced_type.name feedback_type_name = action.feedback.structure.namespaced_type.name +send_goal_type_name = action.send_goal_service.namespaced_type.name +get_result_type_name = action.get_result_service.namespaced_type.name data = { 'package_name': package_name, @@ -44,6 +46,22 @@ expand_template( output_file, template_basepath=template_basepath) +data.update({'service': action.send_goal_service}) +output_file = os.path.join(output_dir, *namespaces[1:], send_goal_type_name + '.java') +expand_template( + 'srv.java.em', + data, + output_file, + template_basepath=template_basepath) + +data.update({'service': action.get_result_service}) +output_file = os.path.join(output_dir, *namespaces[1:], get_result_type_name + '.java') +expand_template( + 'srv.java.em', + data, + output_file, + template_basepath=template_basepath) + action_imports = [ 'org.ros2.rcljava.common.JNIUtils', 'org.ros2.rcljava.interfaces.ActionDefinition', diff --git a/rosidl_generator_java/resource/msg.cpp.em b/rosidl_generator_java/resource/msg.cpp.em index 6810a67c..9458b285 100644 --- a/rosidl_generator_java/resource/msg.cpp.em +++ b/rosidl_generator_java/resource/msg.cpp.em @@ -62,6 +62,7 @@ for member in message.structure.members: namespaced_types.add(get_jni_type(type_)) include_prefix = idl_structure_type_to_c_include_prefix(type_) # TODO(jacobperron): Remove this logic after https://github.com/ros2/rosidl/pull/432 (Foxy) + # and https://github.com/ros2/rosidl/pull/538 # Strip off any service or action suffix # There are several types that actions and services are composed of, but they are included # a common header that is based on the action or service name @@ -76,10 +77,15 @@ for member in message.structure.members: include_prefix = include_prefix[:-8] elif include_prefix.endswith('__feedback'): include_prefix = include_prefix[:-10] + elif include_prefix.endswith('__send_goal'): + include_prefix = include_prefix[:-11] + elif include_prefix.endswith('__get_result'): + include_prefix = include_prefix[:-12] member_includes.add(include_prefix + '.h') }@ @{ # TODO(jacobperron): Remove this logic after https://github.com/ros2/rosidl/pull/432 (Foxy) +# and https://github.com/ros2/rosidl/pull/538 message_c_include_prefix = idl_structure_type_to_c_include_prefix(message.structure.namespaced_type) # Strip off any service or action suffix if message_c_include_prefix.endswith('__request'): @@ -92,6 +98,10 @@ elif message_c_include_prefix.endswith('__result'): message_c_include_prefix = message_c_include_prefix[:-8] elif message_c_include_prefix.endswith('__feedback'): message_c_include_prefix = message_c_include_prefix[:-10] +elif message_c_include_prefix.endswith('__send_goal'): + message_c_include_prefix = message_c_include_prefix[:-11] +elif message_c_include_prefix.endswith('__get_result'): + message_c_include_prefix = message_c_include_prefix[:-12] }@ #include diff --git a/rosidl_generator_java/resource/srv.cpp.em b/rosidl_generator_java/resource/srv.cpp.em index f22bf408..4c13f6b5 100644 --- a/rosidl_generator_java/resource/srv.cpp.em +++ b/rosidl_generator_java/resource/srv.cpp.em @@ -40,7 +40,20 @@ expand_template( #include "rosidl_runtime_c/service_type_support_struct.h" -#include "@(idl_structure_type_to_c_include_prefix(service.namespaced_type)).h" +@{ +include_prefix = idl_structure_type_to_c_include_prefix(service.namespaced_type) +# TODO(jacobperron): Remove this logic after https://github.com/ros2/rosidl/pull/538 +# Strip off any service suffix +# There are a couple service types that actions are composed of, but they are included +# a common header that is based on the action name +# ie. there are not separate headers for each type +if include_prefix.endswith('__send_goal'): + include_prefix = include_prefix[:-11] +elif include_prefix.endswith('__get_result'): + include_prefix = include_prefix[:-12] +}@ + +#include "@(include_prefix).h" // Ensure that a jlong is big enough to store raw pointers static_assert(sizeof(jlong) >= sizeof(std::intptr_t), "jlong must be able to store pointers"); From 244d898b91dba6f6685da973d896e4767d4219b5 Mon Sep 17 00:00:00 2001 From: Jacob Perron Date: Mon, 9 Nov 2020 18:34:19 -0800 Subject: [PATCH 6/6] Allow undeclared parameters in parameters client tests Signed-off-by: Jacob Perron --- .../ros2/rcljava/parameters/AsyncParametersClientTest.java | 5 ++++- .../ros2/rcljava/parameters/SyncParametersClientTest.java | 5 ++++- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/rcljava/src/test/java/org/ros2/rcljava/parameters/AsyncParametersClientTest.java b/rcljava/src/test/java/org/ros2/rcljava/parameters/AsyncParametersClientTest.java index a458c6a2..67154902 100644 --- a/rcljava/src/test/java/org/ros2/rcljava/parameters/AsyncParametersClientTest.java +++ b/rcljava/src/test/java/org/ros2/rcljava/parameters/AsyncParametersClientTest.java @@ -37,6 +37,7 @@ import org.ros2.rcljava.concurrent.RCLFuture; import org.ros2.rcljava.consumers.Consumer; import org.ros2.rcljava.node.Node; +import org.ros2.rcljava.node.NodeOptions; import org.ros2.rcljava.parameters.ParameterVariant; import org.ros2.rcljava.parameters.client.AsyncParametersClient; import org.ros2.rcljava.parameters.client.AsyncParametersClientImpl; @@ -74,7 +75,9 @@ public static void setupOnce() throws Exception { @Before public void setUp() throws Exception { - node = RCLJava.createNode("test_node"); + NodeOptions opts = new NodeOptions(); + opts.setAllowUndeclaredParameters(true); + node = RCLJava.createNode("test_node", "", opts); parameterService = new ParameterServiceImpl(node); parametersClient = new AsyncParametersClientImpl(node); } diff --git a/rcljava/src/test/java/org/ros2/rcljava/parameters/SyncParametersClientTest.java b/rcljava/src/test/java/org/ros2/rcljava/parameters/SyncParametersClientTest.java index 8ec4266a..8248f1dd 100644 --- a/rcljava/src/test/java/org/ros2/rcljava/parameters/SyncParametersClientTest.java +++ b/rcljava/src/test/java/org/ros2/rcljava/parameters/SyncParametersClientTest.java @@ -37,6 +37,7 @@ import org.ros2.rcljava.concurrent.RCLFuture; import org.ros2.rcljava.consumers.Consumer; import org.ros2.rcljava.node.Node; +import org.ros2.rcljava.node.NodeOptions; import org.ros2.rcljava.parameters.ParameterVariant; import org.ros2.rcljava.parameters.client.SyncParametersClient; import org.ros2.rcljava.parameters.client.SyncParametersClientImpl; @@ -57,7 +58,9 @@ public static void setupOnce() throws Exception { @Before public void setUp() throws Exception { - node = RCLJava.createNode("test_node"); + NodeOptions opts = new NodeOptions(); + opts.setAllowUndeclaredParameters(true); + node = RCLJava.createNode("test_node", "", opts); parameterService = new ParameterServiceImpl(node); parametersClient = new SyncParametersClientImpl(node); }