-
Notifications
You must be signed in to change notification settings - Fork 728
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
image_rotate: clean up #862
Merged
Merged
Changes from all commits
Commits
Show all changes
6 commits
Select commit
Hold shift + click to select a range
ea1af6d
image_rotate: initialize target vectors
mikeferguson 478d8ea
implement lazy subscribers
mikeferguson 29b148a
add parameter for subscriber transport
mikeferguson 652e5b2
remove dead code, make topic check actually work
mikeferguson ab8409f
linting
mikeferguson 6755ce5
use TransportHints
mikeferguson File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -72,31 +72,9 @@ namespace image_rotate | |
ImageRotateNode::ImageRotateNode(const rclcpp::NodeOptions & options) | ||
: rclcpp::Node("ImageRotateNode", options) | ||
{ | ||
config_.target_frame_id = this->declare_parameter("target_frame_id", std::string("")); | ||
config_.target_x = this->declare_parameter("target_x", 0.0); | ||
config_.target_y = this->declare_parameter("target_y", 0.0); | ||
config_.target_z = this->declare_parameter("target_z", 1.0); | ||
|
||
config_.source_frame_id = this->declare_parameter("source_frame_id", std::string("")); | ||
config_.source_x = this->declare_parameter("source_x", 0.0); | ||
config_.source_y = this->declare_parameter("source_y", -1.0); | ||
config_.source_z = this->declare_parameter("source_z", 0.0); | ||
|
||
config_.output_frame_id = this->declare_parameter("output_frame_id", std::string("")); | ||
config_.input_frame_id = this->declare_parameter("input_frame_id", std::string("")); | ||
config_.use_camera_info = this->declare_parameter("use_camera_info", true); | ||
config_.max_angular_rate = this->declare_parameter( | ||
"max_angular_rate", | ||
10.0); | ||
config_.output_image_size = this->declare_parameter( | ||
"output_image_size", | ||
2.0); | ||
|
||
auto reconfigureCallback = | ||
[this](std::vector<rclcpp::Parameter> parameters) -> rcl_interfaces::msg::SetParametersResult | ||
{ | ||
RCLCPP_INFO(get_logger(), "reconfigureCallback"); | ||
|
||
auto result = rcl_interfaces::msg::SetParametersResult(); | ||
result.successful = true; | ||
for (auto parameter : parameters) { | ||
|
@@ -128,13 +106,31 @@ ImageRotateNode::ImageRotateNode(const rclcpp::NodeOptions & options) | |
source_vector_.vector.x = config_.source_x; | ||
source_vector_.vector.y = config_.source_y; | ||
source_vector_.vector.z = config_.source_z; | ||
if (subscriber_count_) { // @todo: Could do this without an interruption at some point. | ||
unsubscribe(); | ||
subscribe(); | ||
} | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. this is unneeded - none of the parameters that are able to be updated would impact how the subscribers would actually be setup |
||
|
||
return result; | ||
}; | ||
on_set_parameters_callback_handle_ = this->add_on_set_parameters_callback(reconfigureCallback); | ||
|
||
// Set parameters AFTER add_on_set_parameters_callback | ||
config_.target_frame_id = this->declare_parameter("target_frame_id", std::string("")); | ||
config_.target_x = this->declare_parameter("target_x", 0.0); | ||
config_.target_y = this->declare_parameter("target_y", 0.0); | ||
config_.target_z = this->declare_parameter("target_z", 1.0); | ||
|
||
config_.source_frame_id = this->declare_parameter("source_frame_id", std::string("")); | ||
config_.source_x = this->declare_parameter("source_x", 0.0); | ||
config_.source_y = this->declare_parameter("source_y", -1.0); | ||
config_.source_z = this->declare_parameter("source_z", 0.0); | ||
|
||
config_.output_frame_id = this->declare_parameter("output_frame_id", std::string("")); | ||
config_.input_frame_id = this->declare_parameter("input_frame_id", std::string("")); | ||
config_.use_camera_info = this->declare_parameter("use_camera_info", true); | ||
config_.max_angular_rate = this->declare_parameter("max_angular_rate", 10.0); | ||
config_.output_image_size = this->declare_parameter("output_image_size", 2.0); | ||
|
||
// TransportHints does not actually declare the parameter | ||
this->declare_parameter<std::string>("image_transport", "raw"); | ||
|
||
onInit(); | ||
} | ||
|
||
|
@@ -187,13 +183,6 @@ void ImageRotateNode::do_work( | |
source_frame_id, input_frame_id, tf2_time, tf2_time - prev_stamp_); | ||
tf2::doTransform(source_vector_, source_vector_transformed, transform); | ||
|
||
// RCUTILS_LOG_INFO("target: %f %f %f", target_vector_.x, target_vector_.y, target_vector_.z); | ||
// RCUTILS_LOG_INFO("target_transformed: %f %f %f", target_vector_transformed.x, " | ||
// "target_vector_transformed.y, target_vector_transformed.z"); | ||
// RCUTILS_LOG_INFO("source: %f %f %f", source_vector_.x, source_vector_.y, source_vector_.z); | ||
// RCUTILS_LOG_INFO("source_transformed: %f %f %f", source_vector_transformed.x, " | ||
// "source_vector_transformed.y, source_vector_transformed.z"); | ||
|
||
// Calculate the angle of the rotation. | ||
double angle = angle_; | ||
if ((target_vector_transformed.vector.x != 0 || target_vector_transformed.vector.y != 0) && | ||
|
@@ -226,11 +215,9 @@ void ImageRotateNode::do_work( | |
} | ||
angle_ = fmod(angle_, 2.0 * M_PI); | ||
} catch (const tf2::TransformException & e) { | ||
RCUTILS_LOG_ERROR("Transform error: %s", e.what()); | ||
RCLCPP_ERROR(get_logger(), "Transform error: %s", e.what()); | ||
} | ||
|
||
// RCUTILS_LOG_INFO("angle: %f", 180 * angle_ / M_PI); | ||
|
||
// Publish the transform. | ||
geometry_msgs::msg::TransformStamped transform; | ||
transform.transform.translation.x = 0; | ||
|
@@ -262,7 +249,6 @@ void ImageRotateNode::do_work( | |
int step = config_.output_image_size; | ||
out_size = candidates[step] + (candidates[step + 1] - candidates[step]) * | ||
(config_.output_image_size - step); | ||
// RCUTILS_LOG_INFO("out_size: %d", out_size); | ||
|
||
// Compute the rotation matrix. | ||
cv::Mat rot_matrix = cv::getRotationMatrix2D( | ||
|
@@ -281,63 +267,15 @@ void ImageRotateNode::do_work( | |
out_img->header.frame_id = transform.child_frame_id; | ||
img_pub_.publish(out_img); | ||
} catch (const cv::Exception & e) { | ||
RCUTILS_LOG_ERROR( | ||
RCLCPP_ERROR( | ||
get_logger(), | ||
"Image processing error: %s %s %s %i", | ||
e.err.c_str(), e.func.c_str(), e.file.c_str(), e.line); | ||
} | ||
|
||
prev_stamp_ = tf2_ros::fromMsg(msg->header.stamp); | ||
} | ||
|
||
void ImageRotateNode::subscribe() | ||
{ | ||
RCUTILS_LOG_DEBUG("Subscribing to image topic."); | ||
if (config_.use_camera_info && config_.input_frame_id.empty()) { | ||
auto custom_qos = rmw_qos_profile_system_default; | ||
custom_qos.depth = 3; | ||
|
||
cam_sub_ = image_transport::create_camera_subscription( | ||
this, | ||
"image", | ||
std::bind( | ||
&ImageRotateNode::imageCallbackWithInfo, this, | ||
std::placeholders::_1, std::placeholders::_2), | ||
"raw", | ||
custom_qos); | ||
} else { | ||
auto custom_qos = rmw_qos_profile_system_default; | ||
custom_qos.depth = 3; | ||
img_sub_ = image_transport::create_subscription( | ||
this, | ||
"image", | ||
std::bind(&ImageRotateNode::imageCallback, this, std::placeholders::_1), | ||
"raw", | ||
custom_qos); | ||
} | ||
} | ||
|
||
void ImageRotateNode::unsubscribe() | ||
{ | ||
RCUTILS_LOG_DEBUG("Unsubscribing from image topic."); | ||
img_sub_.shutdown(); | ||
cam_sub_.shutdown(); | ||
} | ||
|
||
void ImageRotateNode::connectCb() | ||
{ | ||
if (subscriber_count_++ == 0) { | ||
subscribe(); | ||
} | ||
} | ||
|
||
void ImageRotateNode::disconnectCb() | ||
{ | ||
subscriber_count_--; | ||
if (subscriber_count_ == 0) { | ||
unsubscribe(); | ||
} | ||
} | ||
|
||
void ImageRotateNode::onInit() | ||
{ | ||
subscriber_count_ = 0; | ||
|
@@ -346,18 +284,62 @@ void ImageRotateNode::onInit() | |
rclcpp::Clock::SharedPtr clock = this->get_clock(); | ||
tf_buffer_ = std::make_shared<tf2_ros::Buffer>(clock); | ||
tf_sub_ = std::make_shared<tf2_ros::TransformListener>(*tf_buffer_); | ||
// TODO(yechun1): Implement when SubscriberStatusCallback is available | ||
// image_transport::SubscriberStatusCallback connect_cb = | ||
// boost::bind(&ImageRotateNode::connectCb, this, _1); | ||
// image_transport::SubscriberStatusCallback connect_cb = | ||
// std::bind(&CropForemostNode::connectCb, this); | ||
// image_transport::SubscriberStatusCallback disconnect_cb = | ||
// boost::bind(&ImageRotateNode::disconnectCb, this, _1); | ||
// img_pub_ = image_transport::ImageTransport(ros::NodeHandle(nh_, "rotated")).advertise( | ||
// "image", 1, connect_cb, disconnect_cb); | ||
connectCb(); | ||
img_pub_ = image_transport::create_publisher(this, "rotated/image"); | ||
tf_pub_ = std::make_shared<tf2_ros::TransformBroadcaster>(*this); | ||
|
||
// Create publisher with connect callback | ||
rclcpp::PublisherOptions pub_options; | ||
pub_options.event_callbacks.matched_callback = | ||
[this](rclcpp::MatchedInfo &) | ||
{ | ||
if (img_pub_.getNumSubscribers() == 0) { | ||
RCLCPP_DEBUG(get_logger(), "Unsubscribing from image topic."); | ||
img_sub_.shutdown(); | ||
cam_sub_.shutdown(); | ||
} else { | ||
// For compressed topics to remap appropriately, we need to pass a | ||
// fully expanded and remapped topic name to image_transport | ||
auto node_base = this->get_node_base_interface(); | ||
std::string topic_name = node_base->resolve_topic_or_service_name("image", false); | ||
RCLCPP_INFO(get_logger(), "Subscribing to %s topic.", topic_name.c_str()); | ||
|
||
// Check that remapping appears to be correct | ||
auto topics = this->get_topic_names_and_types(); | ||
if (topics.find(topic_name) == topics.end()) { | ||
RCLCPP_WARN( | ||
get_logger(), | ||
"Topic %s is not connected! Typical command-line usage:\n" | ||
"\t$ ros2 run image_rotate image_rotate --ros-args -r image:=<image topic>", | ||
topic_name.c_str()); | ||
} | ||
|
||
// This will check image_transport parameter to get proper transport | ||
image_transport::TransportHints transport_hint(this, "raw"); | ||
|
||
if (config_.use_camera_info && config_.input_frame_id.empty()) { | ||
auto custom_qos = rmw_qos_profile_system_default; | ||
custom_qos.depth = 3; | ||
cam_sub_ = image_transport::create_camera_subscription( | ||
this, | ||
topic_name, | ||
std::bind( | ||
&ImageRotateNode::imageCallbackWithInfo, this, | ||
std::placeholders::_1, std::placeholders::_2), | ||
transport_hint.getTransport(), | ||
custom_qos); | ||
} else { | ||
auto custom_qos = rmw_qos_profile_system_default; | ||
custom_qos.depth = 3; | ||
img_sub_ = image_transport::create_subscription( | ||
this, | ||
topic_name, | ||
std::bind(&ImageRotateNode::imageCallback, this, std::placeholders::_1), | ||
transport_hint.getTransport(), | ||
custom_qos); | ||
} | ||
} | ||
}; | ||
img_pub_ = image_transport::create_publisher( | ||
this, "rotated/image", rmw_qos_profile_default, pub_options); | ||
} | ||
} // namespace image_rotate | ||
|
||
|
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This debug message didn't work at all - made a more robust version by checking the overlap of our topic name with the actual topics that exist (as many of our depth_image_proc stuff does)