ROS Resources: Documentation | Support | Discussion Forum | Index | Service Status | ros @ Robotics Stack Exchange
Ask Your Question
2

Creating composite rosjava messages without a Node

asked 2012-08-14 01:22:06 -0500

tamias gravatar image

I saw that rosjava changed some months ago to define Messages as interfaces rather than instantiable classes (http://answers.ros.org/question/31399/how-do-you-construct-composite-messages-in-rosjava/). I also saw that a Node instance is now required to provide a MessageFactory so that Messages can be created (http://answers.ros.org/question/36044/declare-a-message-outside-of-a-node-scope-problems/).

I'm currently writing material for a university course in which rosjava is used. Last year the students' code to create composite messages was fairly simple, as I supplied them with an Abstract helper class and they only needed to implement methods such as:

public Twist turnLeft() {
  Twist left = new Twist();
  left.angular.z = 0.5;
  return left;
}

However, with the recent changes they now have the triple confusion of a) having to pre-define and populate a Vector3 message to be inserted into the Twist, b) create the Vector3 and a Twist message using a MessageFactory, and c) instantiate a temporary DefaultNode to get access to a MessageFactory. So the code looks like this:

public Twist turnLeft() {
  DefaultNode node = new DefaultNode(null, null, null);
  Twist left = node.getTopicMessageFactory().newFromType(Twist._TYPE);
  Vector3 move = node.getTopicMessageFactory().newFromType(Vector3._TYPE);
  move.setZ(0.5);
  left.setAngular(move);
  return left;
}

Is all the above really necessary, or have I misunderstood the way in which the MessageFactory and composite messages should work? Is there an easier / less verbose way of creating composite messages, particularly when no Node object is already present within the class?

edit retag flag offensive close merge delete

Comments

Actually the situation is even worse than in my example code; a DefaultNode can't be instantiated directly, but rather a DefaultNodeFactory needs to be created first, then a DefaultNode created, then its own MessageFactory used to create Twist and Vector3 messages!

tamias gravatar image tamias  ( 2012-08-14 04:05:24 -0500 )edit

2 Answers

Sort by ยป oldest newest most voted
7

answered 2012-08-15 21:52:40 -0500

damonkohler gravatar image

updated 2012-08-15 23:37:59 -0500

The easiest way to do what you're asking is:

NodeConfiguration nodeConfiguration = NodeConfiguration.newPrivate()
MessageFactory messageFactory = nodeConfiguration.getTopicMessageFactory();
Twist twist = messageFactory.newFromType(Twist._TYPE);
twist.getAngular().setZ(0.5);

Note that nested messages are created automatically. You can use the getter to access them and then modify them. In the future, when messages become immutable, this will be slightly different and use a builder pattern.

The need for a message factory is unlikely to change as it is necessary to decouple messaging infrastructure from the rest of the system (i.e. to support other message types like protobuff). I'm primarily focused on the case where messages are created by publishers or service clients (the most common cases).

I think it's reasonable, however, to create a helper class that constructs a message factory for your use case. See the NodeConfiguration class for an example of how to construct one from scratch.

edit flag offensive delete link more

Comments

I think I'm facing a similar situation, however I'm not sure of that. Do you happen to know somewhere I could examine some examples? I had some trouble finding a complete reference (mostly because of similar names from ROS and documentation from previous versions of rosjava clogging up my searches).

Pickman gravatar image Pickman  ( 2016-08-06 10:17:30 -0500 )edit
2

answered 2012-08-14 03:40:25 -0500

jbohren gravatar image

As far as I understand, there is no simpler way to do what you're trying to do, but I think the design patterns in the current manifestation of rosjava are very different than those used in roscpp or rospy (or even earlier versions of rosjava). I think the design decisions have made it harder to decouple message construction from a node in the way that you seem to be trying to do.

I'd suggest creating a ticket here: http://code.google.com/p/rosjava/issues/list to see if Damon can help you figure out a way to satisfy your needs for the class with the current API.

edit flag offensive delete link more

Question Tools

1 follower

Stats

Asked: 2012-08-14 01:22:06 -0500

Seen: 1,525 times

Last updated: Aug 15 '12