diff --git a/gazebo_plugins/CMakeLists.txt b/gazebo_plugins/CMakeLists.txt index d2c31c26d..b3fefc62c 100644 --- a/gazebo_plugins/CMakeLists.txt +++ b/gazebo_plugins/CMakeLists.txt @@ -1,6 +1,8 @@ cmake_minimum_required(VERSION 2.8.3) project(gazebo_plugins) +option(ENABLE_DISPLAY_TESTS "Enable the building of tests that requires a display" OFF) + find_package(catkin REQUIRED COMPONENTS message_generation gazebo_msgs @@ -357,6 +359,8 @@ install(DIRECTORY test ) # Tests +# These need to be run with -j1 flag because gazebo can't be run +# in parallel. if (CATKIN_ENABLE_TESTING) find_package(rostest REQUIRED) add_rostest_gtest(set_model_state-test @@ -364,4 +368,19 @@ if (CATKIN_ENABLE_TESTING) test/set_model_state_test/set_model_state_test.cpp) add_rostest(test/range/range_plugin.test) target_link_libraries(set_model_state-test ${catkin_LIBRARIES}) + + if (ENABLE_DISPLAY_TESTS) + add_rostest_gtest(depth_camera-test + test/camera/depth_camera.test + test/camera/depth_camera.cpp) + target_link_libraries(depth_camera-test ${catkin_LIBRARIES}) + add_rostest_gtest(multicamera-test + test/camera/multicamera.test + test/camera/multicamera.cpp) + target_link_libraries(multicamera-test ${catkin_LIBRARIES}) + add_rostest_gtest(camera-test + test/camera/camera.test + test/camera/camera.cpp) + target_link_libraries(camera-test ${catkin_LIBRARIES}) + endif() endif() diff --git a/gazebo_plugins/include/gazebo_plugins/gazebo_ros_multicamera.h b/gazebo_plugins/include/gazebo_plugins/gazebo_ros_multicamera.h index 233194551..aa9970541 100644 --- a/gazebo_plugins/include/gazebo_plugins/gazebo_ros_multicamera.h +++ b/gazebo_plugins/include/gazebo_plugins/gazebo_ros_multicamera.h @@ -42,6 +42,8 @@ namespace gazebo std::vector utils; + protected: void OnNewFrame(const unsigned char *_image, + GazeboRosCameraUtils* util); /// \brief Update the controller /// FIXME: switch to function vectors protected: virtual void OnNewFrameLeft(const unsigned char *_image, diff --git a/gazebo_plugins/src/gazebo_ros_camera.cpp b/gazebo_plugins/src/gazebo_ros_camera.cpp index 10f6d0c00..9c71c69fa 100644 --- a/gazebo_plugins/src/gazebo_ros_camera.cpp +++ b/gazebo_plugins/src/gazebo_ros_camera.cpp @@ -77,9 +77,9 @@ void GazeboRosCamera::OnNewFrame(const unsigned char *_image, const std::string &_format) { # if GAZEBO_MAJOR_VERSION >= 7 - this->sensor_update_time_ = this->parentSensor_->LastUpdateTime(); + common::Time sensor_update_time = this->parentSensor_->LastMeasurementTime(); # else - this->sensor_update_time_ = this->parentSensor_->GetLastUpdateTime(); + common::Time sensor_update_time = this->parentSensor_->GetLastMeasurementTime(); # endif if (!this->parentSensor->IsActive()) @@ -92,12 +92,18 @@ void GazeboRosCamera::OnNewFrame(const unsigned char *_image, { if ((*this->image_connect_count_) > 0) { - common::Time cur_time = this->world_->GetSimTime(); - if (cur_time - this->last_update_time_ >= this->update_period_) + // OnNewFrame is triggered at the gazebo sensor + // while there is also a plugin that can throttle the + // rate down further (but then why not reduce the sensor rate? + // what is the use case?). + // Setting the to zero will make this plugin + // update at the gazebo sensor , update_period_ will be + // zero and the conditional always will be true. + if (sensor_update_time - this->last_update_time_ >= this->update_period_) { - this->PutCameraData(_image); - this->PublishCameraInfo(); - this->last_update_time_ = cur_time; + this->PutCameraData(_image, sensor_update_time); + this->PublishCameraInfo(sensor_update_time); + this->last_update_time_ = sensor_update_time; } } } diff --git a/gazebo_plugins/src/gazebo_ros_camera_utils.cpp b/gazebo_plugins/src/gazebo_ros_camera_utils.cpp index 4776cae45..7d34042bd 100644 --- a/gazebo_plugins/src/gazebo_ros_camera_utils.cpp +++ b/gazebo_plugins/src/gazebo_ros_camera_utils.cpp @@ -626,15 +626,14 @@ void GazeboRosCameraUtils::PublishCameraInfo() if (this->camera_info_pub_.getNumSubscribers() > 0) { # if GAZEBO_MAJOR_VERSION >= 7 - this->sensor_update_time_ = this->parentSensor_->LastUpdateTime(); + this->sensor_update_time_ = this->parentSensor_->LastMeasurementTime(); # else - this->sensor_update_time_ = this->parentSensor_->GetLastUpdateTime(); + this->sensor_update_time_ = this->parentSensor_->GetLastMeasurementTime(); # endif - common::Time cur_time = this->world_->GetSimTime(); - if (cur_time - this->last_info_update_time_ >= this->update_period_) + if (this->sensor_update_time_ - this->last_info_update_time_ >= this->update_period_) { this->PublishCameraInfo(this->camera_info_pub_); - this->last_info_update_time_ = cur_time; + this->last_info_update_time_ = this->sensor_update_time_; } } } diff --git a/gazebo_plugins/src/gazebo_ros_depth_camera.cpp b/gazebo_plugins/src/gazebo_ros_depth_camera.cpp index b1438c38a..a9f027eed 100644 --- a/gazebo_plugins/src/gazebo_ros_depth_camera.cpp +++ b/gazebo_plugins/src/gazebo_ros_depth_camera.cpp @@ -192,9 +192,9 @@ void GazeboRosDepthCamera::OnNewDepthFrame(const float *_image, return; # if GAZEBO_MAJOR_VERSION >= 7 - this->depth_sensor_update_time_ = this->parentSensor->LastUpdateTime(); + this->depth_sensor_update_time_ = this->parentSensor->LastMeasurementTime(); # else - this->depth_sensor_update_time_ = this->parentSensor->GetLastUpdateTime(); + this->depth_sensor_update_time_ = this->parentSensor->GetLastMeasurementTime(); # endif if (this->parentSensor->IsActive()) { @@ -232,9 +232,9 @@ void GazeboRosDepthCamera::OnNewRGBPointCloud(const float *_pcd, return; # if GAZEBO_MAJOR_VERSION >= 7 - this->depth_sensor_update_time_ = this->parentSensor->LastUpdateTime(); + this->depth_sensor_update_time_ = this->parentSensor->LastMeasurementTime(); # else - this->depth_sensor_update_time_ = this->parentSensor->GetLastUpdateTime(); + this->depth_sensor_update_time_ = this->parentSensor->GetLastMeasurementTime(); # endif if (!this->parentSensor->IsActive()) { @@ -302,9 +302,9 @@ void GazeboRosDepthCamera::OnNewImageFrame(const unsigned char *_image, //ROS_ERROR("camera_ new frame %s %s",this->parentSensor_->GetName().c_str(),this->frame_name_.c_str()); # if GAZEBO_MAJOR_VERSION >= 7 - this->sensor_update_time_ = this->parentSensor->LastUpdateTime(); + this->sensor_update_time_ = this->parentSensor->LastMeasurementTime(); # else - this->sensor_update_time_ = this->parentSensor->GetLastUpdateTime(); + this->sensor_update_time_ = this->parentSensor->GetLastMeasurementTime(); # endif if (!this->parentSensor->IsActive()) @@ -316,7 +316,11 @@ void GazeboRosDepthCamera::OnNewImageFrame(const unsigned char *_image, else { if ((*this->image_connect_count_) > 0) + { this->PutCameraData(_image); + // TODO(lucasw) publish camera info with depth image + // this->PublishCameraInfo(sensor_update_time); + } } } @@ -502,15 +506,15 @@ void GazeboRosDepthCamera::PublishCameraInfo() if (this->depth_info_connect_count_ > 0) { # if GAZEBO_MAJOR_VERSION >= 7 - this->sensor_update_time_ = this->parentSensor_->LastUpdateTime(); + common::Time sensor_update_time = this->parentSensor_->LastMeasurementTime(); # else - this->sensor_update_time_ = this->parentSensor_->GetLastUpdateTime(); + common::Time sensor_update_time = this->parentSensor_->GetLastMeasurementTime(); # endif - common::Time cur_time = this->world_->GetSimTime(); - if (cur_time - this->last_depth_image_camera_info_update_time_ >= this->update_period_) + this->sensor_update_time_ = sensor_update_time; + if (sensor_update_time - this->last_depth_image_camera_info_update_time_ >= this->update_period_) { - this->PublishCameraInfo(this->depth_image_camera_info_pub_); - this->last_depth_image_camera_info_update_time_ = cur_time; + this->PublishCameraInfo(this->depth_image_camera_info_pub_); // , sensor_update_time); + this->last_depth_image_camera_info_update_time_ = sensor_update_time; } } } diff --git a/gazebo_plugins/src/gazebo_ros_multicamera.cpp b/gazebo_plugins/src/gazebo_ros_multicamera.cpp index 6a9a1f941..e46649c9c 100644 --- a/gazebo_plugins/src/gazebo_ros_multicamera.cpp +++ b/gazebo_plugins/src/gazebo_ros_multicamera.cpp @@ -102,52 +102,41 @@ void GazeboRosMultiCamera::Load(sensors::SensorPtr _parent, } //////////////////////////////////////////////////////////////////////////////// -// Update the controller -void GazeboRosMultiCamera::OnNewFrameLeft(const unsigned char *_image, - unsigned int _width, unsigned int _height, unsigned int _depth, - const std::string &_format) + +void GazeboRosMultiCamera::OnNewFrame(const unsigned char *_image, + GazeboRosCameraUtils* util) { - GazeboRosCameraUtils* util = this->utils[0]; # if GAZEBO_MAJOR_VERSION >= 7 - util->sensor_update_time_ = util->parentSensor_->LastUpdateTime(); + common::Time sensor_update_time = util->parentSensor_->LastMeasurementTime(); # else - util->sensor_update_time_ = util->parentSensor_->GetLastUpdateTime(); + common::Time sensor_update_time = util->parentSensor_->GetLastMeasurementTime(); # endif if (util->parentSensor_->IsActive()) { - common::Time cur_time = util->world_->GetSimTime(); - if (cur_time - util->last_update_time_ >= util->update_period_) + if (sensor_update_time - util->last_update_time_ >= util->update_period_) { - util->PutCameraData(_image); - util->PublishCameraInfo(); - util->last_update_time_ = cur_time; + util->PutCameraData(_image, sensor_update_time); + util->PublishCameraInfo(sensor_update_time); + util->last_update_time_ = sensor_update_time; } } } +// Update the controller +void GazeboRosMultiCamera::OnNewFrameLeft(const unsigned char *_image, + unsigned int _width, unsigned int _height, unsigned int _depth, + const std::string &_format) +{ + OnNewFrame(_image, this->utils[0]); +} + //////////////////////////////////////////////////////////////////////////////// // Update the controller void GazeboRosMultiCamera::OnNewFrameRight(const unsigned char *_image, unsigned int _width, unsigned int _height, unsigned int _depth, const std::string &_format) { - GazeboRosCameraUtils* util = this->utils[1]; -# if GAZEBO_MAJOR_VERSION >= 7 - util->sensor_update_time_ = util->parentSensor_->LastUpdateTime(); -# else - util->sensor_update_time_ = util->parentSensor_->GetLastUpdateTime(); -# endif - - if (util->parentSensor_->IsActive()) - { - common::Time cur_time = util->world_->GetSimTime(); - if (cur_time - util->last_update_time_ >= util->update_period_) - { - util->PutCameraData(_image); - util->PublishCameraInfo(); - util->last_update_time_ = cur_time; - } - } + OnNewFrame(_image, this->utils[1]); } } diff --git a/gazebo_plugins/src/gazebo_ros_openni_kinect.cpp b/gazebo_plugins/src/gazebo_ros_openni_kinect.cpp index c852f6f94..869c3fa64 100644 --- a/gazebo_plugins/src/gazebo_ros_openni_kinect.cpp +++ b/gazebo_plugins/src/gazebo_ros_openni_kinect.cpp @@ -189,9 +189,9 @@ void GazeboRosOpenniKinect::OnNewDepthFrame(const float *_image, return; # if GAZEBO_MAJOR_VERSION >= 7 - this->depth_sensor_update_time_ = this->parentSensor->LastUpdateTime(); + this->depth_sensor_update_time_ = this->parentSensor->LastMeasurementTime(); # else - this->depth_sensor_update_time_ = this->parentSensor->GetLastUpdateTime(); + this->depth_sensor_update_time_ = this->parentSensor->GetLastMeasurementTime(); # endif if (this->parentSensor->IsActive()) { @@ -231,9 +231,9 @@ void GazeboRosOpenniKinect::OnNewImageFrame(const unsigned char *_image, //ROS_ERROR("camera_ new frame %s %s",this->parentSensor_->GetName().c_str(),this->frame_name_.c_str()); # if GAZEBO_MAJOR_VERSION >= 7 - this->sensor_update_time_ = this->parentSensor_->LastUpdateTime(); + this->sensor_update_time_ = this->parentSensor_->LastMeasurementTime(); # else - this->sensor_update_time_ = this->parentSensor_->GetLastUpdateTime(); + this->sensor_update_time_ = this->parentSensor_->GetLastMeasurementTime(); # endif if (this->parentSensor->IsActive()) @@ -447,15 +447,14 @@ void GazeboRosOpenniKinect::PublishCameraInfo() if (this->depth_info_connect_count_ > 0) { # if GAZEBO_MAJOR_VERSION >= 7 - this->sensor_update_time_ = this->parentSensor_->LastUpdateTime(); + this->sensor_update_time_ = this->parentSensor_->LastMeasurementTime(); # else - this->sensor_update_time_ = this->parentSensor_->GetLastUpdateTime(); + this->sensor_update_time_ = this->parentSensor_->GetLastMeasurementTime(); # endif - common::Time cur_time = this->world_->GetSimTime(); - if (cur_time - this->last_depth_image_camera_info_update_time_ >= this->update_period_) + if (this->sensor_update_time_ - this->last_depth_image_camera_info_update_time_ >= this->update_period_) { this->PublishCameraInfo(this->depth_image_camera_info_pub_); - this->last_depth_image_camera_info_update_time_ = cur_time; + this->last_depth_image_camera_info_update_time_ = this->sensor_update_time_; } } } diff --git a/gazebo_plugins/src/gazebo_ros_prosilica.cpp b/gazebo_plugins/src/gazebo_ros_prosilica.cpp index dd0203290..2e529ca9b 100644 --- a/gazebo_plugins/src/gazebo_ros_prosilica.cpp +++ b/gazebo_plugins/src/gazebo_ros_prosilica.cpp @@ -132,9 +132,9 @@ void GazeboRosProsilica::OnNewImageFrame(const unsigned char *_image, // should do nothing except turning camera on/off, as we are using service. /// @todo: consider adding thumbnailing feature here if subscribed. # if GAZEBO_MAJOR_VERSION >= 7 - common::Time sensor_update_time = this->parentSensor_->LastUpdateTime(); + common::Time sensor_update_time = this->parentSensor_->LastMeasurementTime(); # else - common::Time sensor_update_time = this->parentSensor_->GetLastUpdateTime(); + common::Time sensor_update_time = this->parentSensor_->GetLastMeasurementTime(); # endif // as long as ros is connected, parent is active @@ -153,12 +153,11 @@ void GazeboRosProsilica::OnNewImageFrame(const unsigned char *_image, { if ((*this->image_connect_count_) > 0) { - common::Time cur_time = this->world_->GetSimTime(); - if (cur_time - this->last_update_time_ >= this->update_period_) + if (sensor_update_time - this->last_update_time_ >= this->update_period_) { this->PutCameraData(_image, sensor_update_time); this->PublishCameraInfo(sensor_update_time); - this->last_update_time_ = cur_time; + this->last_update_time_ = sensor_update_time; } } } @@ -227,9 +226,9 @@ void GazeboRosProsilica::pollCallback(polled_camera::GetPolledImage::Request& re this->roiCameraInfoMsg->header.frame_id = this->frame_name_; # if GAZEBO_MAJOR_VERSION >= 7 - common::Time roiLastRenderTime = this->parentSensor_->LastUpdateTime(); + common::Time roiLastRenderTime = this->parentSensor_->LastMeasurementTime(); # else - common::Time roiLastRenderTime = this->parentSensor_->GetLastUpdateTime(); + common::Time roiLastRenderTime = this->parentSensor_->GetLastMeasurementTime(); # endif this->roiCameraInfoMsg->header.stamp.sec = roiLastRenderTime.sec; this->roiCameraInfoMsg->header.stamp.nsec = roiLastRenderTime.nsec; @@ -285,9 +284,9 @@ void GazeboRosProsilica::pollCallback(polled_camera::GetPolledImage::Request& re this->image_msg_.header.frame_id = this->frame_name_; # if GAZEBO_MAJOR_VERSION >= 7 - common::Time lastRenderTime = this->parentSensor_->LastUpdateTime(); + common::Time lastRenderTime = this->parentSensor_->LastMeasurementTime(); # else - common::Time lastRenderTime = this->parentSensor_->GetLastUpdateTime(); + common::Time lastRenderTime = this->parentSensor_->GetLastMeasurementTime(); # endif this->image_msg_.header.stamp.sec = lastRenderTime.sec; this->image_msg_.header.stamp.nsec = lastRenderTime.nsec; @@ -313,9 +312,9 @@ void GazeboRosProsilica::pollCallback(polled_camera::GetPolledImage::Request& re this->roiImageMsg = ℑ this->roiImageMsg->header.frame_id = this->frame_name_; # if GAZEBO_MAJOR_VERSION >= 7 - common::Time roiLastRenderTime = this->parentSensor_->LastUpdateTime(); + common::Time roiLastRenderTime = this->parentSensor_->LastMeasurementTime(); # else - common::Time roiLastRenderTime = this->parentSensor_->GetLastUpdateTime(); + common::Time roiLastRenderTime = this->parentSensor_->GetLastMeasurementTime(); # endif this->roiImageMsg->header.stamp.sec = roiLastRenderTime.sec; this->roiImageMsg->header.stamp.nsec = roiLastRenderTime.nsec; diff --git a/gazebo_plugins/test/camera/camera.cpp b/gazebo_plugins/test/camera/camera.cpp new file mode 100644 index 000000000..b7805bbae --- /dev/null +++ b/gazebo_plugins/test/camera/camera.cpp @@ -0,0 +1,72 @@ +#include +#include +#include + +class CameraTest : public testing::Test +{ +protected: + virtual void SetUp() + { + has_new_image_ = false; + } + + ros::NodeHandle nh_; + image_transport::Subscriber cam_sub_; + bool has_new_image_; + ros::Time image_stamp_; +public: + void imageCallback(const sensor_msgs::ImageConstPtr& msg) + { + image_stamp_ = msg->header.stamp; + has_new_image_ = true; + } +}; + +// Test if the camera image is published at all, and that the timestamp +// is not too long in the past. +TEST_F(CameraTest, cameraSubscribeTest) +{ + image_transport::ImageTransport it(nh_); + cam_sub_ = it.subscribe("camera1/image_raw", 1, + &CameraTest::imageCallback, + dynamic_cast(this)); + +#if 0 + // wait for gazebo to start publishing + // TODO(lucasw) this isn't really necessary since this test + // is purely passive + bool wait_for_topic = true; + while (wait_for_topic) + { + // @todo this fails without the additional 0.5 second sleep after the + // publisher comes online, which means on a slower or more heavily + // loaded system it may take longer than 0.5 seconds, and the test + // would hang until the timeout is reached and fail. + if (cam_sub_.getNumPublishers() > 0) + wait_for_topic = false; + ros::Duration(0.5).sleep(); + } +#endif + + while (!has_new_image_) + { + ros::spinOnce(); + ros::Duration(0.1).sleep(); + } + + // This check depends on the update period being much longer + // than the expected difference between now and the received image time + // TODO(lucasw) + // this likely isn't that robust - what if the testing system is really slow? + double time_diff = (ros::Time::now() - image_stamp_).toSec(); + ROS_INFO_STREAM(time_diff); + EXPECT_LT(time_diff, 1.0); + cam_sub_.shutdown(); +} + +int main(int argc, char** argv) +{ + ros::init(argc, argv, "gazebo_camera_test"); + testing::InitGoogleTest(&argc, argv); + return RUN_ALL_TESTS(); +} diff --git a/gazebo_plugins/test/camera/camera.test b/gazebo_plugins/test/camera/camera.test new file mode 100644 index 000000000..3a91b824b --- /dev/null +++ b/gazebo_plugins/test/camera/camera.test @@ -0,0 +1,17 @@ + + + + + + + + + + + + + + diff --git a/gazebo_plugins/test/camera/camera.world b/gazebo_plugins/test/camera/camera.world new file mode 100644 index 000000000..3154be354 --- /dev/null +++ b/gazebo_plugins/test/camera/camera.world @@ -0,0 +1,138 @@ + + + + + + model://ground_plane + + + + + model://sun + + + + + + 4.927360 -4.376610 3.740080 0.000000 0.275643 2.356190 + orbit + + + + + false + 2.0 0.0 4.0 0.0 0.0 0.0 + + 0.0 0.0 0.0 0.0 0.0 0.0 + + 0.0 0.0 0.0 0.0 0.0 0.0 + + 1.0 + 0.0 + 0.0 + 1.0 + 0.0 + 1.0 + + 10.0 + + + 0.0 0.0 0.0 0.0 0.0 0.0 + + + 0.5 + + + + 0.03 0.5 0.5 1.0 + + + true + 100.0 + + + 0.0 0.0 0.0 0.0 0.0 0.0 + 250 + + + 0.5 + + + + + + 0.5 + 0.2 + 1.0 0 0 + 0 + 0 + + + + 0 + 1000000.0 + + + + 0 + 0.2 + 1e15 + 1e13 + 100.0 + 0.0001 + + + + 100.0 + + + + + + true + 0.0 0.0 0.5 0.0 0.0 0.0 + + 0.0 0.0 0.0 0.0 0.0 0.0 + + 0.5 + + 1.3962634 + + 640 + 480 + R8G8B8 + + + 0.02 + 300 + + + gaussian + + 0.0 + 0.007 + + + + true + + 0.0 + camera1 + image_raw + camera_info + camera_link + 0.07 + 0.0 + 0.0 + 0.0 + 0.0 + 0.0 + + + + + + + diff --git a/gazebo_plugins/test/camera/depth_camera.cpp b/gazebo_plugins/test/camera/depth_camera.cpp new file mode 100644 index 000000000..596e6d50f --- /dev/null +++ b/gazebo_plugins/test/camera/depth_camera.cpp @@ -0,0 +1,113 @@ +#include +#include +#include +#include + +class DepthCameraTest : public testing::Test +{ +protected: + virtual void SetUp() + { + has_new_image_ = false; + has_new_depth_ = false; + has_new_points_ = false; + } + + ros::NodeHandle nh_; + image_transport::Subscriber cam_sub_; + image_transport::Subscriber depth_sub_; + ros::Subscriber points_sub_; + bool has_new_image_; + ros::Time image_stamp_; + bool has_new_depth_; + ros::Time depth_stamp_; + bool has_new_points_; + ros::Time points_stamp_; +public: + void imageCallback(const sensor_msgs::ImageConstPtr& msg) + { + image_stamp_ = msg->header.stamp; + has_new_image_ = true; + } + void depthCallback(const sensor_msgs::ImageConstPtr& msg) + { + depth_stamp_ = msg->header.stamp; + has_new_depth_ = true; + } + void pointsCallback(const sensor_msgs::PointCloud2ConstPtr& msg) + { + points_stamp_ = msg->header.stamp; + has_new_points_ = true; + } +}; + +// Test if the camera image is published at all, and that the timestamp +// is not too long in the past. +TEST_F(DepthCameraTest, cameraSubscribeTest) +{ + image_transport::ImageTransport it(nh_); + cam_sub_ = it.subscribe("camera1/image_raw", 1, + &DepthCameraTest::imageCallback, + dynamic_cast(this)); + depth_sub_ = it.subscribe("camera1/depth/image_raw", 1, + &DepthCameraTest::depthCallback, + dynamic_cast(this)); + points_sub_ = nh_.subscribe("camera1/points", 1, + &DepthCameraTest::pointsCallback, + dynamic_cast(this)); +#if 0 + // wait for gazebo to start publishing + // TODO(lucasw) this isn't really necessary since this test + // is purely passive + bool wait_for_topic = true; + while (wait_for_topic) + { + // @todo this fails without the additional 0.5 second sleep after the + // publisher comes online, which means on a slower or more heavily + // loaded system it may take longer than 0.5 seconds, and the test + // would hang until the timeout is reached and fail. + if (cam_sub_.getNumPublishers() > 0) + wait_for_topic = false; + ros::Duration(0.5).sleep(); + } +#endif + + while (!has_new_image_ || !has_new_depth_ || !has_new_points_) + { + ros::spinOnce(); + ros::Duration(0.1).sleep(); + } + + EXPECT_EQ(depth_stamp_.toSec(), image_stamp_.toSec()); + EXPECT_EQ(depth_stamp_.toSec(), points_stamp_.toSec()); + // This check depends on the update period (currently 1.0/update_rate = 2.0 seconds) + // being much longer than the expected difference between now and the + // received image time. + const double max_time = 1.0; + const ros::Time current_time = ros::Time::now(); + // TODO(lucasw) + // this likely isn't that robust - what if the testing system is really slow? + double time_diff; + time_diff = (current_time - image_stamp_).toSec(); + ROS_INFO_STREAM(time_diff); + EXPECT_LT(time_diff, max_time); + + time_diff = (current_time - depth_stamp_).toSec(); + ROS_INFO_STREAM(time_diff); + EXPECT_LT(time_diff, max_time); + + time_diff = (current_time - points_stamp_).toSec(); + ROS_INFO_STREAM(time_diff); + EXPECT_LT(time_diff, max_time); + + cam_sub_.shutdown(); + depth_sub_.shutdown(); + points_sub_.shutdown(); +} + +int main(int argc, char** argv) +{ + ros::init(argc, argv, "gazebo_depth_camera_test"); + testing::InitGoogleTest(&argc, argv); + return RUN_ALL_TESTS(); +} diff --git a/gazebo_plugins/test/camera/depth_camera.test b/gazebo_plugins/test/camera/depth_camera.test new file mode 100644 index 000000000..3f4dd72bc --- /dev/null +++ b/gazebo_plugins/test/camera/depth_camera.test @@ -0,0 +1,17 @@ + + + + + + + + + + + + + + diff --git a/gazebo_plugins/test/camera/depth_camera.world b/gazebo_plugins/test/camera/depth_camera.world new file mode 100644 index 000000000..73132f908 --- /dev/null +++ b/gazebo_plugins/test/camera/depth_camera.world @@ -0,0 +1,144 @@ + + + + + + model://ground_plane + + + + + model://sun + + + + + + 4.927360 -4.376610 3.740080 0.000000 0.275643 2.356190 + orbit + + + + + false + 2.0 0.0 4.0 0.0 0.0 0.0 + + 0.0 0.0 0.0 0.0 0.0 0.0 + + 0.0 0.0 0.0 0.0 0.0 0.0 + + 1.0 + 0.0 + 0.0 + 1.0 + 0.0 + 1.0 + + 10.0 + + + 0.0 0.0 0.0 0.0 0.0 0.0 + + + 0.5 + + + + 0.03 0.5 0.5 1.0 + + + true + 100.0 + + + 0.0 0.0 0.0 0.0 0.0 0.0 + 250 + + + 0.5 + + + + + + 0.5 + 0.2 + 1.0 0 0 + 0 + 0 + + + + 0 + 1000000.0 + + + + 0 + 0.2 + 1e15 + 1e13 + 100.0 + 0.0001 + + + + 100.0 + + + + + + true + 0.0 0.0 0.5 0.0 0.0 0.0 + + 0.0 0.0 0.0 0.0 0.0 0.0 + + 0.5 + + + 1.3962634 + + 640 + 480 + R8G8B8 + + + 0.02 + 300 + + + + true + + 0.0 + camera1 + image_raw + camera_info + depth/image_raw + + depth/camera_info + points + camera_link + + 0.07 + 0.001 + 0.0 + 0.0 + 0.0 + 0.0 + 0.0 + + + + + + + diff --git a/gazebo_plugins/test/camera/multicamera.cpp b/gazebo_plugins/test/camera/multicamera.cpp new file mode 100644 index 000000000..0823c53da --- /dev/null +++ b/gazebo_plugins/test/camera/multicamera.cpp @@ -0,0 +1,101 @@ +#include +// #include +// #include +// #include +#include +#include +#include +#include + +class MultiCameraTest : public testing::Test +{ +protected: + virtual void SetUp() + { + has_new_image_ = false; + } + + ros::NodeHandle nh_; + // image_transport::SubscriberFilter cam_left_sub_; + // image_transport::SubscriberFilter cam_right_sub_; + message_filters::Subscriber cam_left_sub_; + message_filters::Subscriber cam_right_sub_; + + bool has_new_image_; + ros::Time image_left_stamp_; + ros::Time image_right_stamp_; + + // typedef message_filters::sync_policies::ApproximateTime< + // sensor_msgs::Image, sensor_msgs::Image + // > MySyncPolicy; + // message_filters::Synchronizer< MySyncPolicy > sync_; + + +public: + void imageCallback( + const sensor_msgs::ImageConstPtr& left_msg, + const sensor_msgs::ImageConstPtr& right_msg) + { + image_left_stamp_ = left_msg->header.stamp; + image_right_stamp_ = right_msg->header.stamp; + has_new_image_ = true; + } +}; + +// Test if the camera image is published at all, and that the timestamp +// is not too long in the past. +TEST_F(MultiCameraTest, cameraSubscribeTest) +{ + // image_transport::ImageTransport it(nh_); + // cam_left_sub_.subscribe(it, "stereo/camera/left/image_raw", 1); + // cam_right_sub_.subscribe(it, "stereo/camera/right/image_raw", 1); + // sync_ = message_filters::Synchronizer( + // MySyncPolicy(4), cam_left_sub_, cam_right_sub_); + cam_left_sub_.subscribe(nh_, "stereo/camera/left/image_raw", 1); + cam_right_sub_.subscribe(nh_, "stereo/camera/right/image_raw", 1); + message_filters::TimeSynchronizer sync( + cam_left_sub_, cam_right_sub_, 4); + sync.registerCallback(boost::bind(&MultiCameraTest::imageCallback, + dynamic_cast(this), _1, _2)); +#if 0 + // wait for gazebo to start publishing + // TODO(lucasw) this isn't really necessary since this test + // is purely passive + bool wait_for_topic = true; + while (wait_for_topic) + { + // @todo this fails without the additional 0.5 second sleep after the + // publisher comes online, which means on a slower or more heavily + // loaded system it may take longer than 0.5 seconds, and the test + // would hang until the timeout is reached and fail. + if (cam_sub_.getNumPublishers() > 0) + wait_for_topic = false; + ros::Duration(0.5).sleep(); + } +#endif + + while (!has_new_image_) + { + ros::spinOnce(); + ros::Duration(0.1).sleep(); + } + + double sync_diff = (image_left_stamp_ - image_right_stamp_).toSec(); + EXPECT_EQ(sync_diff, 0.0); + + // This check depends on the update period being much longer + // than the expected difference between now and the received image time + // TODO(lucasw) + // this likely isn't that robust - what if the testing system is really slow? + double time_diff = (ros::Time::now() - image_left_stamp_).toSec(); + ROS_INFO_STREAM(time_diff); + EXPECT_LT(time_diff, 1.0); + // cam_sub_.shutdown(); +} + +int main(int argc, char** argv) +{ + ros::init(argc, argv, "gazebo_multicamera_test"); + testing::InitGoogleTest(&argc, argv); + return RUN_ALL_TESTS(); +} diff --git a/gazebo_plugins/test/camera/multicamera.test b/gazebo_plugins/test/camera/multicamera.test new file mode 100644 index 000000000..7a96b28ef --- /dev/null +++ b/gazebo_plugins/test/camera/multicamera.test @@ -0,0 +1,11 @@ + + + + + + + + diff --git a/gazebo_plugins/test/camera/multicamera.world b/gazebo_plugins/test/camera/multicamera.world new file mode 100644 index 000000000..4c0b176b4 --- /dev/null +++ b/gazebo_plugins/test/camera/multicamera.world @@ -0,0 +1,146 @@ + + + + + + model://ground_plane + + + + + model://sun + + + + + + 4.927360 -4.376610 3.740080 0.000000 0.275643 2.356190 + orbit + + + + + false + 0.0 2.0 2.0 0.0 0.0 0.0 + + 0.0 0.0 0.0 0.0 0.0 0.0 + + 0.0 0.0 0.0 0.0 0.0 0.0 + + 1.0 + 0.0 + 0.0 + 1.0 + 0.0 + 1.0 + + 10.0 + + + 0.0 0.0 0.0 0.0 0.0 0.0 + + + 0.5 + + + + 0.03 0.5 0.5 1.0 + + + true + 100.0 + + + 0.0 0.0 0.0 0.0 0.0 0.0 + 250 + + + 0.5 + + + + + + 0.5 + 0.2 + 1.0 0 0 + 0 + 0 + + + + 0 + 1000000.0 + + + + 0 + 0.2 + 1e15 + 1e13 + 100.0 + 0.0001 + + + + 100.0 + + + + 0.1 + + 1.3962634 + + 640 + 480 + R8G8B8 + + + 0.02 + 300 + + + gaussian + 0.0 + 0.007 + + + + 0 -0.07 0 0 0 0 + 1.3962634 + + 640 + 480 + R8G8B8 + + + 0.02 + 300 + + + gaussian + 0.0 + 0.007 + + + + true + 0.0 + stereo/camera + image_raw + camera_info + left_camera_optical_frame + + 0.07 + 0.0 + 0.0 + 0.0 + 0.0 + 0.0 + + + + + + +