Skip to content

Commit fd2dd7b

Browse files
committed
Update qos profile -- take 2 (osrf#25)
* Improve QoSProfile constructors * Add documentation to QoSProfile class * Add fromRCL method to QoSProfile * Use fromRCL to create the built-in qos profiles. Signed-off-by: Ivan Santiago Paunovic <ivanpauno@ekumenlabs.com>
1 parent 13d4b11 commit fd2dd7b

File tree

8 files changed

+484
-37
lines changed

8 files changed

+484
-37
lines changed

rcljava/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,7 @@ set(${PROJECT_NAME}_jni_sources
6666
"src/main/cpp/org_ros2_rcljava_publisher_statuses_OfferedQosIncompatible.cpp"
6767
"src/main/cpp/org_ros2_rcljava_node_NodeImpl.cpp"
6868
"src/main/cpp/org_ros2_rcljava_publisher_PublisherImpl.cpp"
69+
"src/main/cpp/org_ros2_rcljava_qos_QoSProfile.cpp"
6970
"src/main/cpp/org_ros2_rcljava_service_ServiceImpl.cpp"
7071
"src/main/cpp/org_ros2_rcljava_subscription_SubscriptionImpl.cpp"
7172
"src/main/cpp/org_ros2_rcljava_subscription_statuses_LivelinessChanged.cpp"
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
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_qos_QoSProfile */
17+
18+
#ifndef ORG_ROS2_RCLJAVA_QOS_QOSPROFILE_H_
19+
#define ORG_ROS2_RCLJAVA_QOS_QOSPROFILE_H_
20+
#ifdef __cplusplus
21+
extern "C" {
22+
#endif
23+
/*
24+
* Class: org_ros2_rcljava_qos_QoSProfile
25+
* Method: nativeFromRCL
26+
* Signature: (J)V
27+
*/
28+
JNIEXPORT void
29+
JNICALL Java_org_ros2_rcljava_qos_QoSProfile_nativeFromRCL(JNIEnv *, jobject, jlong);
30+
31+
/*
32+
* Class: org_ros2_rcljava_qos_QoSProfile
33+
* Method: nativeGetHandleFromName
34+
* Signature: (Ljava/lang/String;)J
35+
*/
36+
JNIEXPORT jlong
37+
JNICALL Java_org_ros2_rcljava_qos_QoSProfile_nativeGetHandleFromName(JNIEnv *, jclass, jstring);
38+
#ifdef __cplusplus
39+
}
40+
#endif
41+
#endif // ORG_ROS2_RCLJAVA_QOS_QOSPROFILE_H_
Lines changed: 250 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,250 @@
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_qos_QoSProfile.h"
16+
17+
#include <jni.h>
18+
#include <limits>
19+
20+
#include "rcljava_common/exceptions.hpp"
21+
#include "rmw/qos_profiles.h"
22+
#include "rmw/types.h"
23+
24+
using rcljava_common::exceptions::rcljava_throw_exception;
25+
26+
static void
27+
qos_set_duration(JNIEnv * env, uint64_t seconds, uint64_t nanos, jobject jqos, jfieldID fid)
28+
{
29+
if (static_cast<uint64_t>(std::numeric_limits<jlong>::max()) < seconds) {
30+
// Throwing an exception here would be weird, as we cannot control the durability that was set
31+
// on all other endpoints in the network. Set jqos seconds to jlong max.
32+
seconds = static_cast<uint64_t>(std::numeric_limits<jlong>::max());
33+
}
34+
if (static_cast<uint64_t>(std::numeric_limits<jlong>::max()) < nanos) {
35+
// This should never happen, as nanoseconds within a second can perfectly be represented
36+
// in a jlong.
37+
nanos = static_cast<uint64_t>(std::numeric_limits<jlong>::max());
38+
}
39+
jclass duration_clazz = env->FindClass("java/time/Duration");
40+
RCLJAVA_COMMON_CHECK_FOR_EXCEPTION(env);
41+
jmethodID factory_mid = env->GetStaticMethodID(
42+
duration_clazz, "ofSeconds", "(JJ)Ljava/time/Duration;");
43+
RCLJAVA_COMMON_CHECK_FOR_EXCEPTION(env);
44+
jobject jduration = env->CallStaticObjectMethod(
45+
duration_clazz, factory_mid, static_cast<jlong>(seconds), static_cast<jlong>(nanos));
46+
RCLJAVA_COMMON_CHECK_FOR_EXCEPTION(env);
47+
env->SetObjectField(jqos, fid, jduration);
48+
}
49+
50+
static void
51+
qos_from_rcl(JNIEnv * env, const rmw_qos_profile_t & qos, jobject jqos)
52+
{
53+
// TODO(ivanpauno): class and field lookup could be done at startup time
54+
jclass clazz = env->GetObjectClass(jqos);
55+
const char * history_class_path = "Lorg/ros2/rcljava/qos/policies/History;";
56+
jfieldID history_fid = env->GetFieldID(clazz, "history", history_class_path);
57+
RCLJAVA_COMMON_CHECK_FOR_EXCEPTION(env);
58+
jfieldID depth_fid = env->GetFieldID(clazz, "depth", "I");
59+
RCLJAVA_COMMON_CHECK_FOR_EXCEPTION(env);
60+
const char * reliability_class_path = "Lorg/ros2/rcljava/qos/policies/Reliability;";
61+
jfieldID reliability_fid = env->GetFieldID(clazz, "reliability", reliability_class_path);
62+
RCLJAVA_COMMON_CHECK_FOR_EXCEPTION(env);
63+
const char * durability_class_path = "Lorg/ros2/rcljava/qos/policies/Durability;";
64+
jfieldID durability_fid = env->GetFieldID(clazz, "durability", durability_class_path);
65+
RCLJAVA_COMMON_CHECK_FOR_EXCEPTION(env);
66+
jfieldID deadline_fid = env->GetFieldID(clazz, "deadline", "Ljava/time/Duration;");
67+
RCLJAVA_COMMON_CHECK_FOR_EXCEPTION(env);
68+
jfieldID lifespan_fid = env->GetFieldID(clazz, "lifespan", "Ljava/time/Duration;");
69+
RCLJAVA_COMMON_CHECK_FOR_EXCEPTION(env);
70+
const char * liveliness_class_path = "Lorg/ros2/rcljava/qos/policies/Liveliness;";
71+
jfieldID liveliness_fid = env->GetFieldID(clazz, "liveliness", liveliness_class_path);
72+
RCLJAVA_COMMON_CHECK_FOR_EXCEPTION(env);
73+
jfieldID liveliness_lease_fid = env->GetFieldID(
74+
clazz, "livelinessLeaseDuration", "Ljava/time/Duration;");
75+
RCLJAVA_COMMON_CHECK_FOR_EXCEPTION(env);
76+
jfieldID avoid_ros_conventions_fid = env->GetFieldID(
77+
clazz, "avoidROSNamespaceConventions", "Z");
78+
RCLJAVA_COMMON_CHECK_FOR_EXCEPTION(env);
79+
80+
jclass history_clazz = env->FindClass("org/ros2/rcljava/qos/policies/History");
81+
jfieldID history_value_fid;
82+
switch (qos.history) {
83+
case RMW_QOS_POLICY_HISTORY_SYSTEM_DEFAULT:
84+
history_value_fid = env->GetStaticFieldID(
85+
history_clazz, "SYSTEM_DEFAULT", history_class_path);
86+
break;
87+
case RMW_QOS_POLICY_HISTORY_KEEP_LAST:
88+
history_value_fid = env->GetStaticFieldID(
89+
history_clazz, "KEEP_LAST", history_class_path);
90+
break;
91+
case RMW_QOS_POLICY_HISTORY_KEEP_ALL:
92+
history_value_fid = env->GetStaticFieldID(
93+
history_clazz, "KEEP_ALL", history_class_path);
94+
break;
95+
case RMW_QOS_POLICY_HISTORY_UNKNOWN:
96+
history_value_fid = env->GetStaticFieldID(
97+
history_clazz, "UNKNOWN", history_class_path);
98+
break;
99+
default:
100+
rcljava_throw_exception(
101+
env, "java/lang/IllegalStateException", "unknown history policy value");
102+
break;
103+
}
104+
RCLJAVA_COMMON_CHECK_FOR_EXCEPTION(env);
105+
jobject history_value = env->GetStaticObjectField(history_clazz, history_value_fid);
106+
env->SetObjectField(jqos, history_fid, history_value);
107+
108+
env->SetIntField(jqos, depth_fid, qos.depth);
109+
110+
jclass reliability_clazz = env->FindClass("org/ros2/rcljava/qos/policies/Reliability");
111+
jfieldID reliability_value_fid;
112+
switch (qos.reliability) {
113+
case RMW_QOS_POLICY_RELIABILITY_SYSTEM_DEFAULT:
114+
reliability_value_fid = env->GetStaticFieldID(
115+
reliability_clazz, "SYSTEM_DEFAULT", reliability_class_path);
116+
break;
117+
case RMW_QOS_POLICY_RELIABILITY_RELIABLE:
118+
reliability_value_fid = env->GetStaticFieldID(
119+
reliability_clazz, "RELIABLE", reliability_class_path);
120+
break;
121+
case RMW_QOS_POLICY_RELIABILITY_BEST_EFFORT:
122+
reliability_value_fid = env->GetStaticFieldID(
123+
reliability_clazz, "BEST_EFFORT", reliability_class_path);
124+
break;
125+
case RMW_QOS_POLICY_RELIABILITY_UNKNOWN:
126+
reliability_value_fid = env->GetStaticFieldID(
127+
reliability_clazz, "UNKNOWN", reliability_class_path);
128+
break;
129+
default:
130+
rcljava_throw_exception(
131+
env, "java/lang/IllegalStateException", "unknown reliability policy value");
132+
break;
133+
}
134+
RCLJAVA_COMMON_CHECK_FOR_EXCEPTION(env);
135+
jobject reliability_value = env->GetStaticObjectField(reliability_clazz, reliability_value_fid);
136+
env->SetObjectField(jqos, reliability_fid, reliability_value);
137+
138+
jclass durability_clazz = env->FindClass("org/ros2/rcljava/qos/policies/Durability");
139+
jfieldID durability_value_fid;
140+
switch (qos.durability) {
141+
case RMW_QOS_POLICY_DURABILITY_SYSTEM_DEFAULT:
142+
durability_value_fid = env->GetStaticFieldID(
143+
durability_clazz, "SYSTEM_DEFAULT", durability_class_path);
144+
break;
145+
case RMW_QOS_POLICY_DURABILITY_TRANSIENT_LOCAL:
146+
durability_value_fid = env->GetStaticFieldID(
147+
durability_clazz, "TRANSIENT_LOCAL", durability_class_path);
148+
break;
149+
case RMW_QOS_POLICY_DURABILITY_VOLATILE:
150+
durability_value_fid = env->GetStaticFieldID(
151+
durability_clazz, "VOLATILE", durability_class_path);
152+
break;
153+
case RMW_QOS_POLICY_DURABILITY_UNKNOWN:
154+
durability_value_fid = env->GetStaticFieldID(
155+
durability_clazz, "UNKNOWN", durability_class_path);
156+
break;
157+
default:
158+
rcljava_throw_exception(
159+
env, "java/lang/IllegalStateException", "unknown durability policy value");
160+
break;
161+
}
162+
RCLJAVA_COMMON_CHECK_FOR_EXCEPTION(env);
163+
jobject durability_value = env->GetStaticObjectField(durability_clazz, durability_value_fid);
164+
env->SetObjectField(jqos, durability_fid, durability_value);
165+
166+
qos_set_duration(env, qos.deadline.sec, qos.deadline.nsec, jqos, deadline_fid);
167+
RCLJAVA_COMMON_CHECK_FOR_EXCEPTION(env);
168+
qos_set_duration(env, qos.lifespan.sec, qos.lifespan.nsec, jqos, lifespan_fid);
169+
RCLJAVA_COMMON_CHECK_FOR_EXCEPTION(env);
170+
qos_set_duration(
171+
env, qos.liveliness_lease_duration.sec,
172+
qos.liveliness_lease_duration.nsec, jqos, liveliness_lease_fid);
173+
RCLJAVA_COMMON_CHECK_FOR_EXCEPTION(env);
174+
175+
jclass liveliness_clazz = env->FindClass("org/ros2/rcljava/qos/policies/Liveliness");
176+
jfieldID liveliness_value_fid;
177+
switch (qos.liveliness) {
178+
case RMW_QOS_POLICY_LIVELINESS_SYSTEM_DEFAULT:
179+
liveliness_value_fid = env->GetStaticFieldID(
180+
liveliness_clazz, "SYSTEM_DEFAULT", liveliness_class_path);
181+
break;
182+
case RMW_QOS_POLICY_LIVELINESS_AUTOMATIC:
183+
liveliness_value_fid = env->GetStaticFieldID(
184+
liveliness_clazz, "AUTOMATIC", liveliness_class_path);
185+
break;
186+
case RMW_QOS_POLICY_LIVELINESS_MANUAL_BY_TOPIC:
187+
liveliness_value_fid = env->GetStaticFieldID(
188+
liveliness_clazz, "MANUAL_BY_TOPIC", liveliness_class_path);
189+
break;
190+
case RMW_QOS_POLICY_LIVELINESS_UNKNOWN:
191+
liveliness_value_fid = env->GetStaticFieldID(
192+
liveliness_clazz, "UNKNOWN", liveliness_class_path);
193+
break;
194+
default:
195+
rcljava_throw_exception(
196+
env, "java/lang/IllegalStateException", "unknown liveliness policy value");
197+
break;
198+
}
199+
RCLJAVA_COMMON_CHECK_FOR_EXCEPTION(env);
200+
jobject liveliness_value = env->GetStaticObjectField(liveliness_clazz, liveliness_value_fid);
201+
env->SetObjectField(jqos, liveliness_fid, liveliness_value);
202+
203+
env->SetBooleanField(jqos, avoid_ros_conventions_fid, qos.avoid_ros_namespace_conventions);
204+
}
205+
206+
JNIEXPORT void JNICALL
207+
Java_org_ros2_rcljava_qos_QoSProfile_nativeFromRCL(JNIEnv * env, jobject jqos, jlong handle)
208+
{
209+
auto * qos_profile = reinterpret_cast<rmw_qos_profile_t *>(handle);
210+
if (!handle) {
211+
rcljava_throw_exception(
212+
env, "java/lang/IllegalArgumentException", "rmw qos profile handle is NULL");
213+
return;
214+
}
215+
qos_from_rcl(env, *qos_profile, jqos);
216+
}
217+
218+
JNIEXPORT jlong JNICALL
219+
Java_org_ros2_rcljava_qos_QoSProfile_nativeGetHandleFromName(
220+
JNIEnv * env, jclass, jstring jprofile_name)
221+
{
222+
const rmw_qos_profile_t * qos = NULL;
223+
const char * profile_name = env->GetStringUTFChars(jprofile_name, NULL);
224+
if (strcmp(profile_name, "default") == 0) {
225+
qos = &rmw_qos_profile_default;
226+
}
227+
if (strcmp(profile_name, "system_default") == 0) {
228+
qos = &rmw_qos_profile_system_default;
229+
}
230+
if (strcmp(profile_name, "sensor_data") == 0) {
231+
qos = &rmw_qos_profile_sensor_data;
232+
}
233+
if (strcmp(profile_name, "parameters") == 0) {
234+
qos = &rmw_qos_profile_parameters;
235+
}
236+
if (strcmp(profile_name, "services") == 0) {
237+
qos = &rmw_qos_profile_services_default;
238+
}
239+
if (strcmp(profile_name, "parameter_events") == 0) {
240+
qos = &rmw_qos_profile_parameter_events;
241+
}
242+
243+
env->ReleaseStringUTFChars(jprofile_name, profile_name);
244+
if (qos) {
245+
return reinterpret_cast<jlong>(qos);
246+
}
247+
rcljava_throw_exception(
248+
env, "java/lang/IllegalArgumentException", "unexpected profile identifier");
249+
return 0;
250+
}

0 commit comments

Comments
 (0)