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

Programatically set the camera pose in gazebo or rviz.

asked 2011-06-21 03:36:12 -0500

updated 2011-06-21 05:13:57 -0500

Wim gravatar image

Hello, I am trying to automatically generate a bunch of videos of a robot manipulating objects. I figured out a way to record the screen from gazebo or rviz, but I can't find any tutorial about how to programatically move the camera around the robot.

Do you know if in either gazebo or rviz the viewpoint can be set programatically? Gazebo shows XYZ and RPY as you move with the mouse so it seems reasonable to think that one can set those. Maybe in rviz, I should set the fixed frame to be a frame offset of the head of the robot?

edit retag flag offensive close merge delete

Comments

1
This may be off topic, but what method are you using for video capture?
JonW gravatar image JonW  ( 2011-06-21 14:37:58 -0500 )edit
1
glc, look at http://www.ros.org/wiki/RecordingOpenGLAppsWithGLC The glc installation script appear to be broken for me but I hacked my way though it and now it works fine. Let me know if you encounter any troubles and I can send you my version of the install script.
Dimitar Simeonov gravatar image Dimitar Simeonov  ( 2011-06-21 15:09:42 -0500 )edit

Hi, I'm currently trying to record RViz via GLC. Since I'm doing this via a RViz plugin, the software should execute the Shift+F8 command for GLC programmatically. Do you have any idea how to do this? Did you only hack the install script or also the source code?

Josch gravatar image Josch  ( 2013-03-13 03:14:31 -0500 )edit

4 Answers

Sort by ยป oldest newest most voted
4

answered 2011-06-21 15:47:04 -0500

hsu gravatar image

If you're using glc-capture, one way to do this is to can write a plugin to move the cameras, for example, by putting this code in UpdateChild() of the plugin:

gazebo::OgreCamera *cam = gazebo::CameraManager::Instance()->GetCamera("UserCamera(0)");
gazebo::Pose3d pose = cam->GetCameraWorldPose();
pose.pos.z = pose.pos.z + 0.001;
cam->SetWorldPose(pose);

should make the gui view camera move upwards in z-direction 1mm on every udpate.

Alternatively, you can spawn a single urdf link with a camera sensor attached, e.g.

<?xml version="1.0" ?>
<robot name="camera" xmlns:body="http://playerstage.sourceforge.net/gazebo/xmlschema/#body" xmlns:controller="http://playerstage.sourceforge.net/gazebo/xmlschema/#controller" xmlns:geom="http://playerstage.sourceforge.net/gazebo/xmlschema/#geom"  xmlns:sensor="http://playerstage.sourceforge.net/gazebo/xmlschema/#sensor" xmlns:xacro="http://ros.org/wiki/xacro">
  <link name="camera_link">
    <inertial>
      <mass value="1"/>
      <origin xyz="0 0 0"/>
      <inertia ixx="0.1" ixy="0.0" ixz="0.0" iyy="0.1" iyz="0.0" izz="0.1"/>
    </inertial>
  </link>
  <gazebo reference="camera_link">
    <sensor:camera name="camera_sensor">
      <imageSize>640 480</imageSize>
      <imageFormat>BAYER_BGGR8</imageFormat>
      <hfov>90</hfov>
      <nearClip>0.1</nearClip>
      <farClip>100</farClip>
      <updateRate>25.0</updateRate>
      <controller:gazebo_ros_camera name="camera_controller" plugin="libgazebo_ros_camera.so">
        <alwaysOn>true</alwaysOn>
        <updateRate>25.0</updateRate>
        <cameraName>camera</cameraName>
        <imageTopicName>image_raw</imageTopicName>
        <cameraInfoTopicName>camera_info</cameraInfoTopicName>
        <frameName>camera_link</frameName>
        <CxPrime>320.5</CxPrime>
        <Cx>320.5</Cx>
        <Cy>240.5</Cy>
        <!-- image_width / (2*tan(hfov_radian /2)) -->
        <!-- 320 for wide and 772.55 for narrow stereo camera -->
        <focal_length>320</focal_length>
        <distortion_k1>0.0</distortion_k1>
        <distortion_k2>0.0</distortion_k2>
        <distortion_k3>0.0</distortion_k3>
        <distortion_t1>0.0</distortion_t1>
        <distortion_t2>0.0</distortion_t2>
      </controller:gazebo_ros_camera>
    </sensor:camera>
    <turnGravityOff>true</turnGravityOff>
    <material>Gazebo/Blue</material>
  </gazebo>
</robot>

and use ros service /gazebo/set_model_state to update the camera pose. Using ''rosbag record'' to capture a series of images.

edit flag offensive delete link more

Comments

Your second approach seems better for my needs - thanks for the XML!
Dimitar Simeonov gravatar image Dimitar Simeonov  ( 2011-06-22 00:45:24 -0500 )edit
hsu, this has been very helpful and I was able to create an artificial camera. Can you point me to the documentation format for sensor:camera I am seeing few images overlap in RVIZ when I look at the camera, and I'd like to try different camera options.
Dimitar Simeonov gravatar image Dimitar Simeonov  ( 2011-06-24 10:50:21 -0500 )edit
There isn't one but we are actively working on it right now. In the mean time you can see everything being read by gazebo's camera sensor in https://kforge.ros.org/gazebo/hg/file/0d8f8ab482ed/server/rendering/OgreCamera.cc. We'll make an announcement as soon as we are done updating xml/docs.
hsu gravatar image hsu  ( 2011-06-26 07:49:16 -0500 )edit
thanks a lot! Do you know how frameName is used - I couldn't find it referenced in the code that you linked to. When I look at the camera in rviz it shows me two superimposed images- the correct one and the one from the origin of frameName as seen in rviz - I'd like to turn this second image off.
Dimitar Simeonov gravatar image Dimitar Simeonov  ( 2011-07-08 09:55:24 -0500 )edit
I believe if you set "Overlay Alpha" to 1 for your camera in rviz, then you should not see the superimposed image.
hsu gravatar image hsu  ( 2011-07-08 10:14:05 -0500 )edit
3

answered 2013-03-13 03:18:33 -0500

Josch gravatar image

For all the googlers that are coming to this thread: There is a way to programmatically set the camera perspectives completely custom in RViz: You have to create a RViz plugin and override the onInitialize() method. This will allow you to access the RViz VisualizationManager, which contains a ViewController instance. That's all you need. You can have a look at the answers to my question when you need further information.

edit flag offensive delete link more
3

answered 2017-03-04 06:05:59 -0500

peci1 gravatar image

CameraManager is no longer a part of Gazebo, but if you want, you can create a Gazebo plugin that publishes to gazebo topic ~/user_camera/joy_pose. Don't care about the name, it's just a function that sets the default (gzclient) camera pose. Interestingly, you can also set camera twist (aka velocity) in a similar way.

Also, since Gazebo 8, video recording is integrated right into gzclient.

edit flag offensive delete link more
1

answered 2023-05-11 01:14:22 -0500

I tried approaching this issue in two ways: using the gazebo topics and a custom visual model plugin to move the camera pose programmatically.

1. Publishing to a Gazebo Camera Topic


These are the topics you need to publish for the former way to control position or velocity:

  • /gazebo/default/user_camera/joy_pose
  • /gazebo/default/user_camera/joy_twist

I have attached a demo script with which you can test out the functionality of joy_pose and joy_twist:

gz_camera_pub.cpp

#include <ros/ros.h>
#include <tf2_geometry_msgs/tf2_geometry_msgs.h>

#include <random>

#include <gazebo/msgs/msgs.hh>
#include <gazebo/transport/transport.hh>
#include <gazebo/gazebo_client.hh>


/**
* GZCameraPub Class
*/
class GZCameraPub {
private:
  float update_rate = 50.0;
  float time_period = 1. / update_rate;

  ros::Timer timer_;

  gazebo::transport::PublisherPtr gz_pose_pub_;
  gazebo::transport::PublisherPtr gz_twist_pub_;

public:
  /**
    * Constructor
    */
  GZCameraPub(ros::NodeHandle *nh, gazebo::transport::NodePtr gz_nh) {
    // define publishers
    gz_pose_pub_ = gz_nh->Advertise<gazebo::msgs::Pose>(
        "/gazebo/default/user_camera/joy_pose", 10);
    gz_twist_pub_ = gz_nh->Advertise<gazebo::msgs::Joystick>(
        "/gazebo/default/user_camera/joy_twist", 10);

    gz_pose_pub_->WaitForConnection();
    gz_twist_pub_->WaitForConnection();

    // Timers
    timer_ = nh->createTimer(
        ros::Duration(time_period), &GZCameraPub::timer_update, this);
  }

  void pubPose() {
    // Saved pose
    gazebo::msgs::Pose poseMsg;

    // use random
    std::random_device rd;
    std::mt19937 gen(rd());
    std::uniform_real_distribution<> dis(-5.0, 5.0);

    poseMsg.mutable_position()->set_x(dis(gen));
    poseMsg.mutable_position()->set_y(dis(gen));
    poseMsg.mutable_position()->set_z(dis(gen));

    tf2::Quaternion q;
    q.setRPY(0, 0, M_PI/2);
    poseMsg.mutable_orientation()->set_x(q.x());
    poseMsg.mutable_orientation()->set_y(q.y());
    poseMsg.mutable_orientation()->set_z(q.z());
    poseMsg.mutable_orientation()->set_w(q.w());
    gz_pose_pub_->Publish(poseMsg);
  }

  void pubVel() {
    gazebo::msgs::Joystick twistMsg;
    twistMsg.mutable_translation()->set_x(0);
    twistMsg.mutable_translation()->set_y(-0.8);
    twistMsg.mutable_translation()->set_z(0);

    twistMsg.mutable_rotation()->set_x(0);
    twistMsg.mutable_rotation()->set_y(0);
    twistMsg.mutable_rotation()->set_z(0);
    gz_twist_pub_->Publish(twistMsg);
  }

  /**
    * Function to test gazebo camera publishers
    */
  void timer_update(const ros::TimerEvent& event) {
    std::string mode = "pose";

    if (mode == "pose") {
      pubPose();
      ros::Duration(1.0).sleep();
    } else if (mode == "velocity") {
      pubVel();
    } else {
      ROS_ERROR("Invalid mode");
    }
  }
};

/**
* Main Function
*/
int main(int argc, char **argv) {
    // Initialize Gazebo client
    gazebo::client::setup(argc, argv);
    gazebo::transport::init();
    gazebo::transport::run();
    gazebo::transport::NodePtr gz_nh(new gazebo::transport::Node());
    gz_nh->Init("default");

    ros::init(argc, argv, "gz_camera_pub_node");
    ros::NodeHandle nh;

    GZCameraPub obj = GZCameraPub(&nh, gz_nh);
    ros::spin();

    gazebo::transport::fini();
    gazebo::client::shutdown();

    return 0;
}

CMakeLists.txt

cmake_minimum_required(VERSION 2.8.3)
project(flappy_bird_gazebo)

find_package(catkin REQUIRED COMPONENTS
  roscpp
  gazebo_msgs
)

find_package(gazebo REQUIRED)

catkin_package(
  CATKIN_DEPENDS roscpp gazebo_msgs
)

include_directories(
  ${catkin_INCLUDE_DIRS}
  ${GAZEBO_INCLUDE_DIRS}
)

link_directories(${GAZEBO_LIBRARY_DIRS})

add_executable(gz_camera_pub_node src/gz_camera_pub.cpp)
target_link_libraries(gz_camera_pub_node ${catkin_LIBRARIES} ${GAZEBO_LIBRARIES})

However, publishing to these topics over an extended field of time causes gazebo to lose all of its visuals. I did not know how to get around this, so I followed the second method.

2. Developing a Custom Visual Plugin.

This was relatively easier to implement, and the visual disappearing issue and the occasional gazebo freeze had disappeared.

custom.world

<model name="set_camera_pose_model">
  <link name="link">
    <visual name="visual">
      <geometry>
        <empty/>
      </geometry>
      <plugin name="CameraSim" filename="libCameraSimPlugin.so"/>
    </visual>
  </link>
</model>

Code snippet of the CameraSimPlugin class:

void CameraSimPlugin::Load(
  gazebo::rendering::VisualPtr visual, sdf::ElementPtr sdf) {
  // get ...
(more)
edit flag offensive delete link more

Question Tools

5 followers

Stats

Asked: 2011-06-21 03:36:12 -0500

Seen: 5,932 times

Last updated: May 11 '23