Ask Your Question
1

Ros message types and Object Oriented Programming

asked 2015-06-26 13:47:28 -0600

dinosaur gravatar image

Has anyone found a good way to incorporate ROS message types into an object oriented approach?

It bothers me how messages represent things that should be seen as objects in an OOP mindset, yet the class associated with each message type is just a dumb data class, auto-generated by the ros build system.

Here's a toy example of what my fantasy ros msg would look like.

------------- Point.msg ----------------
float64 x
float64 y
float64 z

# indicates that Point.py defines methods for this ros msg type
@implementation 'point_package/Point.py' 

------------- Point.py ----------------
# omitting method bodies for conciseness
class Point(ROSMessage):
    ORIGIN = Point(0, 0, 0)
    def __init__(self, x, y, z):
    def __init__(self, point):
    def euclidean_distance(self, other_point):

------------- PointRecorder.py ----------------
# keeps a record of all the points sent to it and tracks which is closest to the origin
class PointRecorder(object):
    def __init__(self):
        self.points = []
        self.closest_point_to_origin = None
        self.closest_distance = float('inf')
        rospy.Service('point_recorder', RecordPoint, self.record_point)

    def record_point(self, request):
        new_point_closest = False
        self.points.append(request.point)
        distance_from_origin = request.point.euclidean_distance(Point.ORIGIN)
        if distance_from_origin < self.closest_distance:
           new_point_closest = True
           self.closest_distance = distance_from_origin
           self.closest_point_to_origin = request.point
        return RecordPointResponse(new_point_closest)

------------- RecordPoint.srv ----------------
point_package/Point point
---
bool new_point_is_closest

This code is just a toy example, but it illustrates a few things I'd like to be able to do with ros message classes.

  1. Have a special parent class for all ros message types class Point(ROSMessage):
  2. Define relevant methods on the message class, e.g. euclidean_distance
  3. Define named constant members of the message class, e.g. ORIGIN
  4. Define other kinds of constructors on the message class, e.g. def __init__(self, point):
  5. Unpack a ros service request or response and be able to call a method on one of its members, e.g. request.point.euclidean_distance(Point.ORIGIN)

I've considered extending the auto-generated msg classes. Ros will accept a message with a member that's a subclass of the intended class, but this makes me nervous. Inheritance is often the wrong solution, and I anticipate pitfalls. Furthermore, that wouldn't work for unpacking requests and responses, as in request.point.euclidean_distance(Point.ORIGIN).

The best solution I've come up with so far is to use composition and wrap a ros msg in a useful class. The class would have methods that operate on the msg, be constructed from a msg, and be able to return its underlying msg.

------------- EnhancedPoint.py ----------------
# omitting some method bodies for conciseness
class EnhancedPoint(object):
    ORIGIN = Point(0, 0, 0)
    def __init__(self, x, y, z):
        self.point = Point(x, y, z)
    def __init__(self, point):
        self.point = copy(point)
    def euclidean_distance(self, other_enhanced_point):
    def to_msg(self):
        return copy(self.point)

With this approach, calling a method on a member extraced from a ros srv request or response is possible, but clunky. EnhancedPoint(request.point).euclidean_distance(EnhancedPoint.ORIGIN) I'm not looking forward to constructing an EnhancedPoint every time I want to do something with a point.

Does anyone have a better way?

edit retag flag offensive close merge delete

1 Answer

Sort by ยป oldest newest most voted
2

answered 2015-06-26 15:38:21 -0600

ahendrix gravatar image

In C++, you can define your own classes, and have those classes serialize the same way as an equivalent ROS message: http://wiki.ros.org/roscpp/Overview/M...

You should be able to do the same thing in python, but I'm not aware of a document that describes how to do it.

edit flag offensive delete link more

Your Answer

Please start posting anonymously - your entry will be published after you log in or create a new account.

Add Answer

Question Tools

2 followers

Stats

Asked: 2015-06-26 13:47:28 -0600

Seen: 1,199 times

Last updated: Jun 26 '15