Skip to content

Instantly share code, notes, and snippets.

@chadrockey
Created February 7, 2013 20:13
Show Gist options
  • Save chadrockey/4733787 to your computer and use it in GitHub Desktop.
Save chadrockey/4733787 to your computer and use it in GitHub Desktop.
Namespaces in the ROS camera API
Patrick Mihelich
On Sun, Sep 18, 2011 at 10:17 AM, Jack O'Quin <[email protected]> wrote:
On Sat, Sep 17, 2011 at 7:16 PM, Ken Tossell <[email protected]> wrote:
>> cameras
>
> The ROS camera API is pretty consistent in its topic naming, but (last
> I looked) there was no standard topic layout for stereo cameras or
> other camera arrays. Also many of the drivers push their topics under
> a new namespace ("camera"); this seems strange when many other drivers
> publish their topics directly under the namespace the user provides.
The "camera" sub-namespace is helpful for grouping image and
camera_info topics for the image pipeline and other consumers.
The standard names for stereo cameras are "left" and "right" in place
of "camera". For more numerous arrays there are no standard names that
I know about. Perhaps an informational REP would be helpful.
I think this issue is mostly within the scope of the Perception Pipelines SIG.
Well, currently image_pipeline and camera_drivers disagree on how to handle the "camera" namespace, so this is open for discussion :).
The "camera" sub-namespace is indeed useful for grouping, but I think the way we currently implement it in drivers is wrong. We implement it in the driver itself, as a namespace remapping: ros::NodeHandle nh("camera"). It's better to do it externally as a push-down, launching the node in the "camera" namespace. That's what image_pipeline does. For example, image_proc subscribes directly to "image_raw" and "camera_info", and to run it in the "camera" namespace you do: rosrun image_proc image_proc __ns:=camera.
While working on the nodelet-ized OpenNI driver, I actually experimented with having some of the image_pipeline nodelets remap "camera" for consistency with the drivers. It was a failure, and I reverted back. I suddenly had a very difficult time writing, for example, a launch-file-with-nodelets version of stereo_image_proc. The basic problem is that you can't compose remappings in any reasonable way.
I can't easily explain this without an example, so here's a before-and-after example of how you might write image_proc as a nodelet launch file: http://www.ros.org/wiki/image_pipeline/nodelet_launch
Note that this is a minimal example. Things get rapidly worse as you try to more. If you repeat the exercise for stereo_image_proc, you basically have two instances of image_proc in "camera/left" and "camera/right". So you end up doing bizarre things like <remap from="camera" to="$(arg camera)/left" />. And then who knows what happens when you need to remap specific topics for the rectify_color nodelets. I'd have to think about how to do it, and would probably get it wrong the first couple times.
Push-downs, meanwhile, stack nicely. They also make it much easier to decompose complicated launch files into smaller, modular, reusable ones. See the openni_launch package for a complete example of a driver + processing pipeline implemented in nodelets with modular launch files.
The OpenNI driver itself is another example. The Kinect publishes various image streams (depth, RGB, IR), which in ROS go into sub-namespaces "depth", "rgb", "ir". Originally I had the driver push these into the top-level remappable "camera" namespace, but abandoned that for similar reasons. Instead the openni.launch launch file has a "camera" argument and pushes the driver nodelet down into that namespace.
The rule of thumb I learned is: if every topic in my_node's ROS API is in namespace foo, implement foo as a push-down, not a remapping. In retrospect that seems kind of obvious, but I had to write some very ugly launch files to understand why.
Anyway, this turned into a long email :). In the end, I want to strip the "camera" remapping out of camera driver node(let)s and have them publish under the user-provided namespace. Camera launch files can have a "camera" argument instead. That's obviously a breaking change, but with a little cleverness we can provide backwards compatibility in Fuerte to conform to tick-tock.
Did all that make sense? Thoughts?
Cheers,
Patrick
-------
Jack O'Quin
On Thu, Sep 22, 2011 at 7:47 PM, Patrick Mihelich
<[email protected]> wrote:
> Well, currently image_pipeline and camera_drivers disagree on how to handle
> the "camera" namespace, so this is open for discussion :).
>
> The "camera" sub-namespace is indeed useful for grouping, but I think the
> way we currently implement it in drivers is wrong. We implement it in the
> driver itself, as a namespace remapping: ros::NodeHandle nh("camera"). It's
> better to do it externally as a push-down, launching the node in the
> "camera" namespace. That's what image_pipeline does. For example, image_proc
> subscribes directly to "image_raw" and "camera_info", and to run it in the
> "camera" namespace you do: rosrun image_proc image_proc __ns:=camera.
>
> While working on the nodelet-ized OpenNI driver, I actually experimented
> with having some of the image_pipeline nodelets remap "camera" for
> consistency with the drivers. It was a failure, and I reverted back. I
> suddenly had a very difficult time writing, for example, a
> launch-file-with-nodelets version of stereo_image_proc. The basic problem is
> that you can't compose remappings in any reasonable way.
>
> I can't easily explain this without an example, so here's a before-and-after
> example of how you might write image_proc as a nodelet launch file:
> http://www.ros.org/wiki/image_pipeline/nodelet_launch
I tried to understand both the "bad" and "good" examples as best I
could. To me, both seem about equally ugly.
> Note that this is a minimal example. Things get rapidly worse as you try to
> more. If you repeat the exercise for stereo_image_proc, you basically have
> two instances of image_proc in "camera/left" and "camera/right". So you end
> up doing bizarre things like <remap from="camera" to="$(arg camera)/left"
> />. And then who knows what happens when you need to remap specific topics
> for the rectify_color nodelets. I'd have to think about how to do it, and
> would probably get it wrong the first couple times.
I thought the stereo convention was "left" and "right" instead of
"camera", not in addition to it.
And, don't forget the WGE100 driver, which also publishes images to
"camera_alternate".
http://www.ros.org/wiki/wge100_camera#ROS_API
> Anyway, this turned into a long email :). In the end, I want to strip the
> "camera" remapping out of camera driver node(let)s and have them publish
> under the user-provided namespace. Camera launch files can have a "camera"
> argument instead. That's obviously a breaking change, but with a little
> cleverness we can provide backwards compatibility in Fuerte to conform to
> tick-tock.
>
> Did all that make sense? Thoughts?
It is not clear to me that the gain from this is worth the pain of
migrating to a different API.
What Fuerte tricks do you suggest for maintaining backwards
compatibility? Parsing the last part of the namespace to see if it
matches "camera"?
---
Chad Rockey
I recently worked with nodelets and namepsaces, and noticed this issue as well.
With multiple drivers running in the same nodelet manager, it is more convenient if the driver itself doesn't control the namespace.
While I did not use args like in Patricks example, I often lost track of the different namespaces when the 1394 driver added /camera to the front of its topics. I had already put the manager in a namespace and easily ended up with /camera/camera/image_raw, oops. :) I eventually just manually remapped all of my nodelets topics since it was a simple, non-production test I was running.
I support changing the camera drivers to publish in the user provided namespace. It's ultimately more flexible and will allow less work to provide image_proc nodelets for each driver.
I am also not clear on the backwards-compatibility tricks, though. That needs more explanation.
---
Jack O'Quin
On Sat, Sep 24, 2011 at 11:30 PM, Chad Rockey <[email protected]> wrote:
> I recently worked with nodelets and namepsaces, and noticed this issue as
> well.
> With multiple drivers running in the same nodelet manager, it is more
> convenient if the driver itself doesn't control the namespace.
> While I did not use args like in Patricks example, I often lost track of the
> different namespaces when the 1394 driver added /camera to the front of its
> topics. I had already put the manager in a namespace and easily ended up
> with /camera/camera/image_raw, oops. :) I eventually just manually
> remapped all of my nodelets topics since it was a simple, non-production
> test I was running.
> I support changing the camera drivers to publish in the user provided
> namespace. It's ultimately more flexible and will allow less work to
> provide image_proc nodelets for each driver.
I have no strong objection to this change. It's easy to do in
camera1394, and Patrick can change the Prosilica and WGE100 drivers.
If we do this, I think it needs a REP to explain the interface and how
it's all supposed to work. There are lots of other camera drivers
around. I am sure they would appreciate some guidance.
> I am also not clear on the backwards-compatibility tricks, though. That
> needs more explanation.
I believe we can invent some way to make that work.
The first idea that comes to mind is to check if the node's containing
namespace ends in "/camera". If so, do not add an extra one; otherwise
add the "camera" sub-namespace as before. That might break Chad's
workaround (above), but would have done the "right thing" had it
already been implemented before he stumbled over it.
But, what about parameters? They don't go in the "camera"
sub-namespace. It's going to be somewhat confusing no matter what.
Maybe we should just start with the REP and take it wherever that leads us.
---
Patrick Mihelich
On Wed, Sep 28, 2011 at 9:44 AM, Jack O'Quin <[email protected]> wrote:
On Sat, Sep 24, 2011 at 11:30 PM, Chad Rockey <[email protected]> wrote:
> I support changing the camera drivers to publish in the user provided
> namespace. It's ultimately more flexible and will allow less work to
> provide image_proc nodelets for each driver.
I have no strong objection to this change. It's easy to do in
camera1394, and Patrick can change the Prosilica and WGE100 drivers.
Great. It's also easy for Prosilica, and whatever USB cam driver we come up with.
The WGE100 driver I probably would not change, because (as Jack brought up) it publishes in two different camera namespaces "camera" and "camera_alternate". A push-down doesn't work, since not every topic is in the same namespace. Similarly, videre_stereo_camera publishes in (remappable) "left" and "right" namespaces, and openni_camera publishes in 4 ("rgb", "depth", "depth_registered", "ir").
The idea is to use push-downs wherever possible, to simplify writing launch files. Remapping is appropriate for complex drivers which publish multiple, distinct image streams. Either way, the driver is not responsible for its full namespace, which is the main issue with the current convention.
If we do this, I think it needs a REP to explain the interface and how
it's all supposed to work. There are lots of other camera drivers
around. I am sure they would appreciate some guidance.
OK. I suppose I've volunteered myself for this :)
> I am also not clear on the backwards-compatibility tricks, though. That
> needs more explanation.
I believe we can invent some way to make that work.
The first idea that comes to mind is to check if the node's containing
namespace ends in "/camera". If so, do not add an extra one; otherwise
add the "camera" sub-namespace as before. That might break Chad's
workaround (above), but would have done the "right thing" had it
already been implemented before he stumbled over it.
But, what about parameters? They don't go in the "camera"
sub-namespace. It's going to be somewhat confusing no matter what.
My idea was to check if the user has remapped "camera", and if so use that namespace with a warning. I actually do a similar sanity check in the image_pipeline nodes, as (at least early on) a common user error was to try something like "rosrun image_proc image_proc camera:=prosilica". For Fuerte we might also warn if the driver is started in the global namespace, as that could be due to the behavior change.
In code, something like:
ros::NodeHandle nh; // camera namespace is simply the node namespace
// Permit remapping "camera" for backwards compatibility
if (ros::names::remap("camera") != "camera")
{
nh = ros::NodeHandle("camera");
ROS_WARN("Remapping 'camera' is deprecated. Launch the driver in the "
"camera namespace instead. Example command-line usage:\n"
"\t$ ROS_NAMESPACE=%s rosrun prosilica_camera prosilica_node",
nh.getNamespace().c_str());
}
// May still break if user expects the old default "camera" namespace
if (ros::this_node::getNamespace() == "/")
{
ROS_WARN("Driver started in the global namespace! This may be wrong. "
"If you expect topics in namespace '/camera', explicitly "
"launch the driver in that namespace instead. Example "
"command-line usage:\n"
"\t$ ROS_NAMESPACE=camera rosrun prosilica_camera prosilica_node");
}
Parameters still go into the node private namespace, so nothing should change there.
Cheers,
Patrick
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment