Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
55 changes: 38 additions & 17 deletions rcljava/src/main/java/org/ros2/rcljava/RCLJava.java
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@
import org.ros2.rcljava.timer.Timer;

/**
* Entry point for the ROS2 Java API, similar to the rclcpp API.
* Entry point for the ROS 2 Java API, similar to the rclcpp API.
*/
public final class RCLJava {
private static final Logger logger = LoggerFactory.getLogger(RCLJava.class);
Expand Down Expand Up @@ -149,7 +149,7 @@ public static boolean isInitialized() {

/**
* Initialize the RCLJava API. If successful, a valid RMW implementation will
* be loaded and accessible, enabling the creating of ROS2 entities
* be loaded and accessible, enabling the creating of ROS 2 entities
* (@{link Node}s, @{link Publisher}s and @{link Subscription}s.
* This also initializes the default context.
*/
Expand Down Expand Up @@ -180,18 +180,18 @@ public static synchronized void rclJavaInit(String args[]) {
private static native long nativeCreateContextHandle();

/**
* Create a ROS2 node (rcl_node_t) and return a pointer to it as an integer.
* Create a ROS 2 node (rcl_node_t) and return a pointer to it as an integer.
*
* @param nodeName The name that will identify this node in a ROS2 graph.
* @param nodeName The name that will identify this node in a ROS 2 graph.
* @param namespace The namespace of the node.
* @param contextHandle Pointer to a context (rcl_context_t) with which to associated the node.
* @return A pointer to the underlying ROS2 node structure.
* @return A pointer to the underlying ROS 2 node structure.
*/
private static native long nativeCreateNodeHandle(String nodeName, String namespace, long contextHandle, ArrayList<String> arguments, boolean useGlobalArguments, boolean enableRosout);

/**
* @return The identifier of the currently active RMW implementation via the
* native ROS2 API.
* native ROS 2 API.
*/
private static native String nativeGetRMWIdentifier();

Expand All @@ -203,7 +203,7 @@ public static String getRMWIdentifier() {
}

/**
* Call the underlying ROS2 rcl mechanism to check if ROS2 has been shut
* Call the underlying ROS 2 rcl mechanism to check if ROS 2 has been shut
* down.
*
* @return true if RCLJava hasn't been shut down, false otherwise.
Expand Down Expand Up @@ -239,29 +239,50 @@ public static Context createContext() {
/**
* Create a @{link Node}.
*
* @param nodeName The name that will identify this node in a ROS2 graph.
* @return A @{link Node} that represents the underlying ROS2 node
* structure.
* @param nodeName The name that will identify this node in a ROS 2 graph.
* @return A @{link Node} that represents the underlying ROS 2 node structure.
*/
public static Node createNode(final String nodeName) {
return createNode(nodeName, "", RCLJava.getDefaultContext(), new NodeOptions());
return createNode(nodeName, "", new NodeOptions());
}

/**
* Create a @{link Node}.
*
* @param nodeName The name that will identify this node in a ROS2 graph.
* @param nodeName The name that will identify this node in a ROS 2 graph.
* @param namespace The namespace of the node.
* @return A @{link Node} that represents the underlying ROS2 node
* structure.
* @return A @{link Node} that represents the underlying ROS 2 node structure.
*/
public static Node createNode(final String nodeName, final String namespace) {
return createNode(nodeName, namespace, new NodeOptions());
}

/**
* Create a @{link Node}.
*
* @deprecated Use `RCLJava.createNode(nodeName, namespace, new NodeOptions.setContext(context))` instead.
* @param nodeName The name that will identify this node in a ROS 2 graph.
* @param namespace The namespace of the node.
* @param context Context used for creating the node, @link{RCLJava.getDefaultContext()} will be used if `null`.
* @return A @{link Node} that represents the underlying ROS 2 node structure.
*/
@Deprecated
public static Node createNode(final String nodeName, final String namespace, final Context context) {
return createNode(nodeName, namespace, context, new NodeOptions());
return createNode(nodeName, namespace, new NodeOptions().setContext(context));
}

public static Node createNode(final String nodeName, final String namespace, final Context context, final NodeOptions options) {
/**
* Create a @{link Node}.
*
* @param nodeName The name that will identify this node in a ROS 2 graph.
* @param namespace The namespace of the node.
* @param options Additional options to customize the Node creation. See @link{org.ros2.rcljava.node.NodeOptions}.
* @return A @{link Node} that represents the underlying ROS 2 node structure.
*/
public static Node createNode(final String nodeName, final String namespace, final NodeOptions options) {
Context context = options.getContext() == null ? RCLJava.getDefaultContext() : options.getContext();
long nodeHandle = nativeCreateNodeHandle(nodeName, namespace, context.getHandle(), options.getCliArgs(), options.getUseGlobalArguments(), options.getEnableRosout());
Node node = new NodeImpl(nodeHandle, context, options.getAllowUndeclaredParameters());
Node node = new NodeImpl(nodeHandle, options);
nodes.add(node);
return node;
}
Expand Down
24 changes: 21 additions & 3 deletions rcljava/src/main/java/org/ros2/rcljava/node/NodeImpl.java
Original file line number Diff line number Diff line change
Expand Up @@ -28,13 +28,16 @@
import org.ros2.rcljava.graph.NameAndTypes;
import org.ros2.rcljava.interfaces.MessageDefinition;
import org.ros2.rcljava.interfaces.ServiceDefinition;
import org.ros2.rcljava.node.NodeOptions;
import org.ros2.rcljava.parameters.InvalidParametersException;
import org.ros2.rcljava.parameters.InvalidParameterValueException;
import org.ros2.rcljava.parameters.ParameterAlreadyDeclaredException;
import org.ros2.rcljava.parameters.ParameterCallback;
import org.ros2.rcljava.parameters.ParameterNotDeclaredException;
import org.ros2.rcljava.parameters.ParameterType;
import org.ros2.rcljava.parameters.ParameterVariant;
import org.ros2.rcljava.parameters.service.ParameterService;
import org.ros2.rcljava.parameters.service.ParameterServiceImpl;
import org.ros2.rcljava.publisher.Publisher;
import org.ros2.rcljava.publisher.PublisherImpl;
import org.ros2.rcljava.qos.QoSProfile;
Expand Down Expand Up @@ -146,29 +149,44 @@ class ParameterAndDescriptor {
private Object parameterCallbacksMutex;
private List<ParameterCallback> parameterCallbacks;

private final ParameterService parameterService;

/**
* Constructor.
*
* @param handle A pointer to the underlying ROS2 node structure. Must not
* be zero.
*/
public NodeImpl(final long handle, final Context context, final boolean allowUndeclaredParameters) {
public NodeImpl(final long handle, final NodeOptions nodeOptions) {
this.handle = handle;
this.context = context;
this.context = nodeOptions.getContext() == null ?
RCLJava.getDefaultContext() : nodeOptions.getContext();
this.publishers = new LinkedBlockingQueue<Publisher>();
this.subscriptions = new LinkedBlockingQueue<Subscription>();
this.services = new LinkedBlockingQueue<Service>();
this.clients = new LinkedBlockingQueue<Client>();
this.timers = new LinkedBlockingQueue<Timer>();
this.parametersMutex = new Object();
this.parameters = new ConcurrentHashMap<String, ParameterAndDescriptor>();
this.allowUndeclaredParameters = allowUndeclaredParameters;
this.allowUndeclaredParameters = nodeOptions.getAllowUndeclaredParameters();
this.parameterCallbacksMutex = new Object();
this.parameterCallbacks = new ArrayList<ParameterCallback>();
this.clock = new Clock(ClockType.ROS_TIME);
this.wall_clock = new Clock(ClockType.STEADY_TIME);
this.timeSource = new TimeSource(this);
this.timeSource.attachClock(this.clock);
try {
this.parameterService = nodeOptions.getStartParameterServices() ?
new ParameterServiceImpl(this) : null;
// TODO(ivanpauno): Modify createService, createClient so they don't declare
// NoSuchFieldException and IllegalAccessException checked exceptions.
// That only happens if the user passed the wrong Class object, and the exception should
// be rethrown as an unchecked IllegalArgumentException.
} catch (NoSuchFieldException ex) {
throw new IllegalArgumentException(ex.getMessage());
} catch (IllegalAccessException ex) {
throw new IllegalArgumentException(ex.getMessage());
}
}

/**
Expand Down
37 changes: 26 additions & 11 deletions rcljava/src/main/java/org/ros2/rcljava/node/NodeOptions.java
Original file line number Diff line number Diff line change
Expand Up @@ -17,18 +17,15 @@

import java.util.ArrayList;

import org.ros2.rcljava.contexts.Context;

public class NodeOptions {
private boolean useGlobalArguments;
private boolean enableRosout;
private boolean allowUndeclaredParameters;
private ArrayList<String> cliArgs;

public NodeOptions() {
this.useGlobalArguments = true;
this.enableRosout = true;
this.allowUndeclaredParameters = false;
this.cliArgs = new ArrayList<String>();
}
private boolean useGlobalArguments = true;
private boolean enableRosout = true;
private boolean allowUndeclaredParameters = false;
private boolean startParameterServices = true;
private Context context = null;
private ArrayList<String> cliArgs = new ArrayList<String>();

public final boolean getUseGlobalArguments() {
return this.useGlobalArguments;
Expand Down Expand Up @@ -57,6 +54,24 @@ public NodeOptions setAllowUndeclaredParameters(boolean allow) {
return this;
}

public final boolean getStartParameterServices() {
return this.startParameterServices;
}

public NodeOptions setStartParameterServices(boolean startParameterServices) {
this.startParameterServices = startParameterServices;
return this;
}

public final Context getContext() {
return this.context;
}

public NodeOptions setContext(Context context) {
this.context = context;
return this;
}

public final ArrayList<String> getCliArgs() {
return this.cliArgs;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,4 +15,4 @@

package org.ros2.rcljava.parameters.service;

public interface ParameterService {}
public interface ParameterService {}
Original file line number Diff line number Diff line change
Expand Up @@ -149,4 +149,4 @@ public void accept(RMWRequestId rmwRequestId,
public ParameterServiceImpl(final Node node) throws NoSuchFieldException, IllegalAccessException {
this(node, QoSProfile.PARAMETERS);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ public static void tearDownOnce() {
public final void testCreateNodeWithArgs() {
NodeOptions options = new NodeOptions();
options.setCliArgs(new ArrayList<String>(Arrays.asList("--ros-args", "-r", "__ns:=/foo")));
Node node = RCLJava.createNode("test_node", "", RCLJava.getDefaultContext(), options);
Node node = RCLJava.createNode("test_node", "", options);
assertEquals("test_node", node.getName());
assertEquals("/foo", node.getNamespace());

Expand Down
12 changes: 9 additions & 3 deletions rcljava/src/test/java/org/ros2/rcljava/node/NodeTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@
import org.ros2.rcljava.graph.NameAndTypes;
import org.ros2.rcljava.graph.NodeNameInfo;
import org.ros2.rcljava.node.Node;
import org.ros2.rcljava.node.NodeOptions;
import org.ros2.rcljava.publisher.Publisher;
import org.ros2.rcljava.qos.policies.Reliability;
import org.ros2.rcljava.qos.QoSProfile;
Expand Down Expand Up @@ -124,7 +125,8 @@ public final void accept(final T msg) {

@Before
public void setUp() {
node = RCLJava.createNode("test_node");
node = RCLJava.createNode(
"test_node", "/", new NodeOptions().setStartParameterServices(false));

primitives1 = new rcljava.msg.Primitives();
primitives2 = new rcljava.msg.Primitives();
Expand Down Expand Up @@ -1357,7 +1359,9 @@ public void accept(final Collection<NameAndTypes> local, Collection<NameAndTypes

@Test
public final void testGetServiceNamesAndTypesByNode() throws Exception {
final Node remoteNode = RCLJava.createNode("test_get_service_names_and_types_remote_node");
final Node remoteNode = RCLJava.createNode(
"test_get_service_names_and_types_remote_node", "/",
new NodeOptions().setStartParameterServices(false));
Service<rcljava.srv.AddTwoInts> service1 = node.<rcljava.srv.AddTwoInts>createService(
rcljava.srv.AddTwoInts.class, "test_get_service_names_and_types_one",
new TriConsumer<
Expand Down Expand Up @@ -1475,7 +1479,9 @@ public void accept(final Collection<NameAndTypes> local, Collection<NameAndTypes

@Test
public final void testGetClientNamesAndTypesByNode() throws Exception {
final Node remoteNode = RCLJava.createNode("test_get_client_names_and_types_remote_node");
final Node remoteNode = RCLJava.createNode(
"test_get_client_names_and_types_remote_node", "/",
new NodeOptions().setStartParameterServices(false));
Client<rcljava.srv.AddTwoInts> client1 = node.<rcljava.srv.AddTwoInts>createClient(
rcljava.srv.AddTwoInts.class, "test_get_client_names_and_types_one");
Client<rcljava.srv.AddTwoInts> client2 = node.<rcljava.srv.AddTwoInts>createClient(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ public static void tearDownOnce() {
public void setUp() {
NodeOptions options = new NodeOptions();
options.setAllowUndeclaredParameters(true);
node = RCLJava.createNode("test_node", "", RCLJava.getDefaultContext(), options);
node = RCLJava.createNode("test_node", "", options);
}

@After
Expand Down