Skip to content

ROS 2 Migration: Camera

chapulina edited this page Aug 26, 2019 · 17 revisions

Overview

This pages describes the changes for the camera plugins in gazebo_plugins for ROS2, including a guide to migrate.

Table of Contents

  1. Deprecation of gazebo_ros_camera_utils
  2. Shared Migration Steps
    1. SDF Parameters
  3. Additional steps for gazebo_ros_camera
  4. Additional steps for gazebo_ros_triggered_camera
  5. Additional steps for gazebo_ros_multicamera
  6. Additional steps for gazebo_ros_triggered_multicamera
  7. Additional steps for gazebo_ros_depth_camera
  8. Additional steps for gazebo_ros_openni_kinect
  9. gazebo_ros_prosilica

gazebo_ros_camera_utils

On ROS 1, this file provided the class GazeboRosCameraUtils, which served as a base class for several plugins. On ROS 2, the functionality which used to be provided by this class is now provided directly by gazebo_ros_camera, which can be configured via SDF to behave like the plugins which used to depend on camera utils.

Some of the problems with the ROS 1 approach were:

  1. Plugins had multiple inheritance, from GazeboRosCameraUtils and CameraPlugin, and had to copy inherited variables like parentSensor between these classes.

  2. GazeboRosCameraUtils, instead of being a thin base class which only provided functionality which is common among plugins, would also provide features that some inherited classes wouldn't use, like triggering. So we might as well expose this functionality in a single plugin and reduce code duplication.

Shared

  • Topic names: they should be given by remapping arguments inside <ros>, so <imageTopicName> and <cameraInfoTopicName> are deprecated.

  • Distortion: On ROS1, distortion had to either be:

    • duplicated between the camera sensor and the plugin
    • or the <auto_distortion> flag had to be set to true so the plugin would use the distortion from the sensor

    On ROS2, all these flags are deprecated, and the distortion from the camera is always used.

  • Update rate: set the rate on the sensor.

  • TF Frame ID: The use of tf prefixes has been deprecated entirely. The TF frame will by default be the name of the link the sensor is attached to, but may be overridden by setting the <frame_name> tag.

  • Namespaces: ROS 1 used a combination of 2 tags to set the node's namespace: <robotNamespace>/<cameraName>. On ROS 2, the namespace is given by <ros><namespace>my_namespace</namespace></ros> and <camera_name> is prepended to all the advertized topics, but is not part of the namespace.

SDF parameters

ROS 1 ROS 2
imageTopicName <ros><argument>image_raw:=custom_image_raw</argument></ros>
cameraInfoTopicName <ros><argument>camera_info:=custom_camera_info</argument></ros>
robotNamespace <ros><namespace>my_namespace</namespace></ros>
cameraName camera_name
frameName frame_name
hackBaseline hack_baseline
autoDistortion :x:
distortionK1 :x:
distortionK2 :x:
distortionK3 :x:
distortionT1 :x:
distortionT2 :x:
updateRate :x:

gazebo_ros_camera

No additional changes.

Example Migration

ROS1

  <link name="link_name">
    ...
    <sensor type="camera" name="sensor_name">
      ...
      <always_on>0</always_on>
      <update_rate>1</update_rate>

      <camera name="camera_name">
        ...
        <distortion>
          <k1>0.1</k1>
          <k2>0.2</k2>
          <k3>0.3</k3>
          <p1>0.4</p1>
          <p2>0.5</p2>
          <center>0.5 0.5</center>
        </distortion>
      </camera>

      <plugin name="plugin_name" filename="libgazebo_ros_camera.so">
        <alwaysOn>true</alwaysOn>
        <updateRate>0.0</updateRate>
        <robotNamespace>custom_ns</robot_namespace>
        <cameraName>custom_camera</cameraName>
        <imageTopicName>custom_image</imageTopicName>
        <cameraInfoTopicName>custom_info</cameraInfoTopicName>
        <frameName>custom_frame</frameName>
        <hackBaseline>0.07</hackBaseline>
        <distortionK1>0.1</distortionK1>
        <distortionK2>0.2</distortionK2>
        <distortionK3>0.3</distortionK3>
        <distortionT1>0.5</distortionT1>
        <distortionT2>0.5</distortionT2>
      </plugin>
    </sensor>
  </link>

ROS2

      <link name="link_name">
        ...
        <sensor type="camera" name="sensor_name">
          ...

          <!-- Set always_on only sensor, not on plugin -->
          <always_on>0</always_on>

          <!-- Set update_rate only sensor, not on plugin -->
          <update_rate>1</update_rate>

          <camera name="camera_name">
            ...
            <distortion>
              <k1>0.1</k1>
              <k2>0.2</k2>
              <k3>0.3</k3>
              <p1>0.4</p1>
              <p2>0.5</p2>
              <center>0.5 0.5</center>
            </distortion>
          </camera>

          <!-- Use camera, not camera_triggered -->
          <plugin name="plugin_name" filename="libgazebo_ros_camera.so">
            <!-- Change namespace, camera name and topics so:
                 * Images are published to: /custom_ns/custom_camera/custom_image
                 * Camera info is published to: /custom_ns/custom_camera/custom_info 
            -->
            <ros>
              <namespace>custom_ns</namespace>
              <argument>image_raw:=custom_img</argument>
              <argument>camera_info:=custom_info</argument>
            </ros>

            <!-- Set camera name. If empty, defaults to sensor name (i.e. "sensor_name") -->
            <camera_name>custom_camera</camera_name>

            <!-- Set TF frame name. If empty, defaults to link name (i.e. "link_name") -->
            <frame_name>custom_frame</frame_name>

            <hack_baseline>0.07</hack_baseline>

            <!-- No need to repeat distortion parameters or to set autoDistortion -->
          </plugin>
        </sensor>

gazebo_ros_triggered_camera

Additional changes:

  • Instead of using a different plugin, use gazebo_ros_camera and pass the <triggered>true</triggered> flag.
  • The trigger topic can be changed by remapping: <ros><argument>image_trigger:=image_trigger_test</argument></ros>

Example Migration

ROS1

  <link name="link_name">
    ...
    <sensor type="camera" name="sensor_name">
      ...
      <always_on>0</always_on>
      <update_rate>1</update_rate>

      <camera name="camera_name">
        ...
        <distortion>
          <k1>0.1</k1>
          <k2>0.2</k2>
          <k3>0.3</k3>
          <p1>0.4</p1>
          <p2>0.5</p2>
          <center>0.5 0.5</center>
        </distortion>
      </camera>

      <plugin name="plugin_name" filename="libgazebo_ros_triggered_camera.so">
        <alwaysOn>true</alwaysOn>
        <updateRate>0.0</updateRate>
        <robotNamespace>custom_ns</robot_namespace>
        <triggerTopicName>custom_trigger</triggerTopicName>
        <cameraName>custom_camera</cameraName>
        <imageTopicName>custom_image</imageTopicName>
        <cameraInfoTopicName>custom_info</cameraInfoTopicName>
        <frameName>custom_frame</frameName>
        <hackBaseline>0.07</hackBaseline>
        <distortionK1>0.1</distortionK1>
        <distortionK2>0.2</distortionK2>
        <distortionK3>0.3</distortionK3>
        <distortionT1>0.5</distortionT1>
        <distortionT2>0.5</distortionT2>
      </plugin>
    </sensor>
  </link>

ROS2

      <link name="link_name">
        ...
        <sensor type="camera" name="sensor_name">
          ...

          <!-- Set always_on only sensor, not on plugin -->
          <always_on>0</always_on>

          <!-- Set update_rate only sensor, not on plugin -->
          <update_rate>1</update_rate>

          <camera name="camera_name">
            ...
            <distortion>
              <k1>0.1</k1>
              <k2>0.2</k2>
              <k3>0.3</k3>
              <p1>0.4</p1>
              <p2>0.5</p2>
              <center>0.5 0.5</center>
            </distortion>
          </camera>

          <!-- Use camera, not camera_triggered -->
          <plugin name="plugin_name" filename="libgazebo_ros_camera.so">
            <!-- Change namespace, camera name and topics so:
                 * Images are published to: /custom_ns/custom_camera/custom_image
                 * Camera info is published to: /custom_ns/custom_camera/custom_info 
                 * Trigger is received on: /custom_ns/custom_camera/custom_trigger 
            -->
            <ros>
              <namespace>custom_ns</namespace>
              <argument>image_raw:=custom_img</argument>
              <argument>camera_info:=custom_info</argument>
              <argument>image_trigger:=custom_trigger</argument>
            </ros>

            <!-- Set camera name. If empty, defaults to sensor name (i.e. "sensor_name") -->
            <camera_name>custom_camera</camera_name>

            <!-- Set TF frame name. If empty, defaults to link name (i.e. "link_name") -->
            <frame_name>custom_frame</frame_name>

            <!-- Set to true to turn on triggering -->
            <triggered>true</triggered>

            <hack_baseline>0.07</hack_baseline>

            <!-- No need to repeat distortion parameters or to set autoDistortion -->
          </plugin>
        </sensor>

gazebo_ros_multicamera

Additional changes:

  • Instead of using a different plugin, use gazebo_ros_camera.
  • Multi camera is no longer limited to 2 cameras as in ROS1.
  • Topic names: they should be given by remapping arguments inside <ros>.
  • The image topic name by default is as follows: /namespace/camera_name(common)/camera(individual)/image_raw
  • The camera info topic name by default is as follows: /namespace/camera_name(common)/camera(individual)/camera_info

SDF parameters

ROS 1 ROS 2
imageTopicName <ros><argument>custom_cam/cam_name/image_raw:=custom_image_raw</argument></ros>
cameraInfoTopicName <ros><argument>custom_cam/cam_name/camera_info_:=custom_camera_info</argument></ros>

Example Migration

ROS1

  <link name="link_name">
    ...
    <sensor type="multicamera" name="stereo_camera">
      <update_rate>30.0</update_rate>
      <camera name="left">
        ...
      </camera>
      <camera name="right">
        ...
      </camera>
      <plugin name="stereo_camera_controller" filename="libgazebo_ros_multicamera.so">
        <alwaysOn>true</alwaysOn>
        <updateRate>0.0</updateRate>
        <cameraName>multisense_sl/camera</cameraName>
        <imageTopicName>image_raw</imageTopicName>
        <cameraInfoTopicName>camera_info</cameraInfoTopicName>
        <frameName>left_camera_optical_frame</frameName>
      </plugin>
    </sensor>
  </link>

ROS2

      <link name="link_name">

        <sensor type="multicamera" name="sensor_name">
          <camera name="left">
            ...
          </camera>
          <camera name="right">
            ...
          </camera>

          <!-- Set update_rate only sensor, not on plugin -->
          <update_rate>1</update_rate>

          <plugin name="plugin_name" filename="libgazebo_ros_camera.so">
            <!-- Change namespace, camera name and topics so:
                 * Left images are published to: /custom_ns/custom_camera/left/custom_image
                 * Right images are published to: /custom_ns/custom_camera/right/custom_image
                 * Left camera info is published to: /custom_ns/custom_camera/left/custom_camera_info
                 * Right camera info is published to: /custom_ns/custom_camera/right/custom_camera_info
            -->
            <ros>
              <namespace>custom_ns</namespace>
              <!-- topics need to be prefixed with camera_name for remapping -->
              <argument>custom_camera/left/image_raw:=custom_camera/left/custom_image</argument>
              <argument>custom_camera/right/image_raw:=custom_camera/right/custom_image</argument>
              <argument>custom_camera/left/camera_info:=custom_camera/left/custom_camera_info</argument>
              <argument>custom_camera/right/camera_info:=custom_camera/right/custom_camera_info</argument>
            </ros>

            <camera_name>custom_camera</camera_name>

            <frame_name>left_camera_optical_frame</frameName>
          </plugin>
        </sensor>

gazebo_ros_triggered_multicamera

Additional changes:

  • Instead of using a different plugin, use gazebo_ros_camera as gazebo_ros_multicamera and pass <triggered>true</triggered> flag.
  • The trigger topic can be changed by remapping: <ros><argument>image_trigger:=image_trigger_test</argument></ros>

gazebo_ros_depth_camera

Additional changes:

  • Instead of using a different plugin, use gazebo_ros_camera.
  • Topic names: they should be given by remapping arguments inside <ros>, so <depthImageTopicName>, <depthImageCameraInfoTopicName and <pointCloudTopicName> are deprecated.

SDF parameters

ROS 1 ROS 2
depthImageTopicName <ros><argument>custom_cam/image_depth:=custom_depth_raw</argument></ros>
depthImageCameraInfoTopicName <ros><argument>custom_cam/camera_info_depth:=custom_camera_info</argument></ros>
pointCloudTopicName <ros><argument>custom_cam/points:=custom_points</argument></ros>
pointCloudCutoff min_depth

Example Migration

ROS1

  <link name="link_name">
    ...
    <sensor type="depth" name="sensor_name">
      ...
      <always_on>0</always_on>
      <update_rate>1</update_rate>

      <camera name="camera_name">
        ...
        <distortion>
          <k1>0.1</k1>
          <k2>0.2</k2>
          <k3>0.3</k3>
          <p1>0.4</p1>
          <p2>0.5</p2>
          <center>0.5 0.5</center>
        </distortion>
      </camera>

      <plugin name="camera_controller" filename="libgazebo_ros_depth_camera.so">
        <alwaysOn>true</alwaysOn>
        <!-- Keep this zero, update_rate will control the frame rate -->
        <updateRate>0.0</updateRate>
        <cameraName>camera1</cameraName>
        <imageTopicName>custom_image</imageTopicName>
        <cameraInfoTopicName>custom_info_raw</cameraInfoTopicName>
        <depthImageTopicName>custom_image_depth</depthImageTopicName>
        <depthImageCameraInfoTopicName>custom_info_depth</depthImageCameraInfoTopicName>
        <pointCloudTopicName>custom_points</pointCloudTopicName>
        <frameName>camera_link</frameName>

        <pointCloudCutoff>0.001</pointCloudCutoff>
        <hackBaseline>0.07</hackBaseline>
        <distortionK1>0.0</distortionK1>
        <distortionK2>0.0</distortionK2>
        <distortionK3>0.0</distortionK3>
        <distortionT1>0.0</distortionT1>
        <distortionT2>0.0</distortionT2>
      </plugin>
    </sensor>
  </link>

ROS2

      <link name="link_name">
        ...
        <sensor type="depth" name="sensor_name">
          ...

          <!-- Set always_on only sensor, not on plugin -->
          <always_on>0</always_on>

          <!-- Set update_rate only sensor, not on plugin -->
          <update_rate>1</update_rate>

          <camera name="camera_name">
            ...
            <distortion>
              <k1>0.1</k1>
              <k2>0.2</k2>
              <k3>0.3</k3>
              <p1>0.4</p1>
              <p2>0.5</p2>
              <center>0.5 0.5</center>
            </distortion>
          </camera>

          <plugin name="plugin_name" filename="libgazebo_ros_camera.so">
            <!-- Change namespace, camera name and topics so:
                 * Raw images are published to: /custom_ns/custom_camera/custom_image
                 * Depth images are published to: /custom_ns/custom_camera/custom_image_depth
                 * Raw image camera info is published to: /custom_ns/custom_camera/custom_info_raw
                 * Depth image camera info is published to: /custom_ns/custom_camera/custom_info_depth
                 * Point cloud is published to: /custom_ns/custom_camera/custom_points 
            -->
            <ros>
              <namespace>custom_ns</namespace>
              <argument>custom_camera/image_raw:=custom_camera/custom_image</argument>
              <argument>custom_camera/image_depth:=custom_camera/custom_image_depth</argument>
              <argument>custom_camera/camera_info:=custom_camera/custom_info_raw</argument>
              <argument>custom_camera/camera_info_depth:=custom_camera/custom_info_depth</argument>
              <argument>custom_camera/points:=custom_camera/custom_points</argument>
            </ros>

            <!-- Set camera name. If empty, defaults to sensor name (i.e. "sensor_name") -->
            <camera_name>custom_camera</camera_name>

            <!-- Set TF frame name. If empty, defaults to link name (i.e. "link_name") -->
            <frame_name>custom_frame</frame_name>

            <hack_baseline>0.07</hack_baseline>

            <!-- No need to repeat distortion parameters or to set autoDistortion -->

             <min_depth>0.001</min_depth>
          </plugin>
        </sensor>

gazebo_ros_openni_kinect

Additional changes:

  • Instead of using a different plugin, use gazebo_ros_camera.

SDF parameters

ROS 1 ROS 2
pointCloudCutoffMax max_depth

Example Migration

ROS1

  <link name="link_name">
    ...
    <sensor type="depth" name="sensor_name">
      ...
      <always_on>0</always_on>
      <update_rate>1</update_rate>

      <camera name="camera_name">
        ...
        <distortion>
          <k1>0.1</k1>
          <k2>0.2</k2>
          <k3>0.3</k3>
          <p1>0.4</p1>
          <p2>0.5</p2>
          <center>0.5 0.5</center>
        </distortion>
      </camera>

      <plugin name="camera_controller" filename="libgazebo_ros_openni_kinect.so">
        <alwaysOn>true</alwaysOn>
        <!-- Keep this zero, update_rate will control the frame rate -->
        <updateRate>0.0</updateRate>
        <cameraName>camera1</cameraName>
        <imageTopicName>custom_image</imageTopicName>
        <cameraInfoTopicName>custom_info_raw</cameraInfoTopicName>
        <depthImageTopicName>custom_image_depth</depthImageTopicName>
        <depthImageCameraInfoTopicName>custom_info_depth</depthImageCameraInfoTopicName>
        <pointCloudTopicName>custom_points</pointCloudTopicName>
        <frameName>camera_link</frameName>

        <pointCloudCutoff>0.001</pointCloudCutoff>
        <pointCloudCutoffMax>300.0</pointCloudCutoffMax>
        <hackBaseline>0.07</hackBaseline>
        <distortionK1>0.0</distortionK1>
        <distortionK2>0.0</distortionK2>
        <distortionK3>0.0</distortionK3>
        <distortionT1>0.0</distortionT1>
        <distortionT2>0.0</distortionT2>
      </plugin>
    </sensor>
  </link>

ROS2

      <link name="link_name">
        ...
        <sensor type="depth" name="sensor_name">
          ...

          <!-- Set always_on only sensor, not on plugin -->
          <always_on>0</always_on>

          <!-- Set update_rate only sensor, not on plugin -->
          <update_rate>1</update_rate>

          <camera name="camera_name">
            ...
            <distortion>
              <k1>0.1</k1>
              <k2>0.2</k2>
              <k3>0.3</k3>
              <p1>0.4</p1>
              <p2>0.5</p2>
              <center>0.5 0.5</center>
            </distortion>
          </camera>

          <plugin name="plugin_name" filename="libgazebo_ros_camera.so">
            <!-- Change namespace, camera name and topics so:
                 * Raw images are published to: /custom_ns/custom_camera/custom_image
                 * Depth images are published to: /custom_ns/custom_camera/custom_image_depth
                 * Raw image camera info is published to: /custom_ns/custom_camera/custom_info_raw
                 * Depth image camera info is published to: /custom_ns/custom_camera/custom_info_depth
                 * Point cloud is published to: /custom_ns/custom_camera/custom_points 
            -->
            <ros>
              <namespace>custom_ns</namespace>
              <argument>custom_camera/image_raw:=custom_camera/custom_image</argument>
              <argument>custom_camera/image_depth:=custom_camera/custom_image_depth</argument>
              <argument>custom_camera/camera_info:=custom_camera/custom_info_raw</argument>
              <argument>custom_camera/camera_info_depth:=custom_camera/custom_info_depth</argument>
              <argument>custom_camera/points:=custom_camera/custom_points</argument>
            </ros>

            <!-- Set camera name. If empty, defaults to sensor name (i.e. "sensor_name") -->
            <camera_name>custom_camera</camera_name>

            <!-- Set TF frame name. If empty, defaults to link name (i.e. "link_name") -->
            <frame_name>custom_frame</frame_name>

            <hack_baseline>0.07</hack_baseline>

            <!-- No need to repeat distortion parameters or to set autoDistortion -->

             <min_depth>0.001</min_depth>
             <max_depth>300.0</max_depth>
          </plugin>
        </sensor>

gazebo_ros_prosilica

:warning: deprecated

You can’t perform that action at this time.