1
$\begingroup$

Rosanswers logo

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?


Originally posted by Dimitar Simeonov on ROS Answers with karma: 535 on 2011-06-21

Post score: 6


Original comments

Comment by Dimitar Simeonov on 2011-06-21:
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.

Comment by JonW on 2011-06-21:
This may be off topic, but what method are you using for video capture?

Comment by Josch on 2013-03-13:
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?

$\endgroup$

4 Answers 4

1
$\begingroup$

Rosanswers logo

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.


Originally posted by hsu with karma: 5780 on 2011-06-21

This answer was ACCEPTED on the original site

Post score: 4


Original comments

Comment by hsu on 2011-07-08:
I believe if you set "Overlay Alpha" to 1 for your camera in rviz, then you should not see the superimposed image.

Comment by Dimitar Simeonov on 2011-07-08:
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.

Comment by hsu on 2011-06-26:
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.

Comment by Dimitar Simeonov on 2011-06-24:
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.

Comment by Dimitar Simeonov on 2011-06-22:
Your second approach seems better for my needs - thanks for the XML!

$\endgroup$
1
$\begingroup$

Rosanswers logo

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.


Originally posted by Josch with karma: 230 on 2013-03-13

This answer was NOT ACCEPTED on the original site

Post score: 3

$\endgroup$
1
$\begingroup$

Rosanswers logo

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 visual scene
  gazebo::rendering::ScenePtr scene = visual->GetScene();
  m_camera = scene->GetUserCamera(0);

  m_update_connection = gazebo::event::Events::ConnectPreRender(
    boost::bind(&CameraSimPlugin::onUpdate, this));
}

void CameraSimPlugin::onUpdate() {
  // publish pose
  ignition::math::Pose3d custom_pose = ignition::math::Pose3d(
    0, 0, 1, 0, 0, 0);

  // set pose
  m_camera->SetWorldPose(custom_pose);
}

Originally posted by LSD with karma: 98 on 2023-05-11

This answer was NOT ACCEPTED on the original site

Post score: 1

$\endgroup$
0
$\begingroup$

Rosanswers logo

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.


Originally posted by peci1 with karma: 1366 on 2017-03-04

This answer was NOT ACCEPTED on the original site

Post score: 3

$\endgroup$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.