Program Listing for File as2_usb_camera_interface.cpp
↰ Return to documentation for file (/tmp/ws/src/aerostack2/as2_hardware_drivers/as2_usb_camera_interface/src/as2_usb_camera_interface.cpp
)
/*!*******************************************************************************************
* \file usb_camera_interface.cpp
* \brief usb camera interface implementation file.
* \authors David Perez Saura
* Miguel Fernandez Cortizas
* \copyright Copyright (c) 2022 Universidad Politécnica de Madrid
* All Rights Reserved
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* 3. Neither the name of the copyright holder nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
* OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
********************************************************************************/
#include "as2_usb_camera_interface.hpp"
UsbCameraInterface::UsbCameraInterface() : as2::Node("usb_camera_interface") {
loadParameters();
camera_ = std::make_shared<as2::sensors::Camera>(camera_name_ + "/image", this);
setCameraParameters(camera_matrix_, dist_coeffs_);
setupCamera();
// create timer for image capture
static auto image_capture_timer_ = this->create_timer(
std::chrono::milliseconds(10), std::bind(&UsbCameraInterface::captureImage, this));
};
void UsbCameraInterface::loadParameters() {
// parameters
this->declare_parameter<std::string>("video_device");
this->declare_parameter<double>("framerate");
this->declare_parameter<std::string>("camera_model");
// camera info
this->declare_parameter<std::string>("camera_name");
this->declare_parameter<int>("image_width");
this->declare_parameter<int>("image_height");
this->declare_parameter<std::string>("distortion_model");
this->declare_parameter<std::vector<double>>("camera_matrix.data");
this->declare_parameter<std::vector<double>>("distortion_coefficients.data");
// tf
this->declare_parameter<std::string>("reference_frame");
this->declare_parameter<double>("x");
this->declare_parameter<double>("y");
this->declare_parameter<double>("z");
this->declare_parameter<double>("roll");
this->declare_parameter<double>("pitch");
this->declare_parameter<double>("yaw");
this->get_parameter("video_device", device_port_);
this->get_parameter("framerate", framerate_);
this->get_parameter("camera_model", camera_model_);
this->get_parameter("camera_name", camera_name_);
this->get_parameter("image_width", image_width_);
this->get_parameter("image_height", image_height_);
this->get_parameter("distortion_model", distortion_model_);
rclcpp::Parameter cm_param = this->get_parameter("camera_matrix.data");
rclcpp::Parameter dc_param = this->get_parameter("distortion_coefficients.data");
std::vector<double> cm_param_vec = cm_param.as_double_array();
std::vector<double> dc_param_vec = dc_param.as_double_array();
camera_matrix_ = cv::Mat(3, 3, CV_64F, cm_param_vec.data()).clone();
dist_coeffs_ = cv::Mat(1, dc_param_vec.size(), CV_64F, dc_param_vec.data()).clone();
RCLCPP_INFO(this->get_logger(), "Video device: %s", device_port_.c_str());
RCLCPP_INFO(this->get_logger(), "Framerate: %.2f", framerate_);
RCLCPP_INFO(this->get_logger(), "Camera model: %s", camera_model_.c_str());
RCLCPP_INFO(this->get_logger(), "Camera name: %s", camera_name_.c_str());
RCLCPP_INFO(this->get_logger(), "Image width: %d", image_width_);
RCLCPP_INFO(this->get_logger(), "Image height: %d", image_height_);
RCLCPP_INFO(this->get_logger(), "Distortion model: %s", distortion_model_.c_str());
encoding_ = sensor_msgs::image_encodings::BGR8;
}
void UsbCameraInterface::setCameraParameters(const cv::Mat &_camera_matrix,
const cv::Mat &_dist_coeffs) {
RCLCPP_INFO(get_logger(), "Setting camera parameters");
sensor_msgs::msg::CameraInfo camera_info;
camera_info.width = image_width_;
camera_info.height = image_height_;
camera_info.k[0] = _camera_matrix.at<double>(0, 0);
camera_info.k[1] = _camera_matrix.at<double>(0, 1);
camera_info.k[2] = _camera_matrix.at<double>(0, 2);
camera_info.k[3] = _camera_matrix.at<double>(1, 0);
camera_info.k[4] = _camera_matrix.at<double>(1, 1);
camera_info.k[5] = _camera_matrix.at<double>(1, 2);
camera_info.k[6] = _camera_matrix.at<double>(2, 0);
camera_info.k[7] = _camera_matrix.at<double>(2, 1);
camera_info.k[8] = _camera_matrix.at<double>(2, 2);
for (int i = 0; i < _dist_coeffs.cols; i++) {
camera_info.d.emplace_back(_dist_coeffs.at<double>(0, i));
}
camera_->setParameters(camera_info, encoding_, camera_model_);
RCLCPP_INFO(get_logger(), "Camera parameters set");
}
void UsbCameraInterface::setupCamera() {
cap_.open(device_port_);
if (!cap_.isOpened()) {
RCLCPP_ERROR(get_logger(), "Cannot open device");
return;
}
cap_.set(cv::CAP_PROP_FRAME_WIDTH, image_width_);
cap_.set(cv::CAP_PROP_FRAME_HEIGHT, image_height_);
cap_.set(cv::CAP_PROP_FPS, framerate_);
RCLCPP_INFO(get_logger(), "Camera capture setup complete");
setCameraTransform();
}
void UsbCameraInterface::setCameraTransform() {
std::string ns = this->get_namespace();
std::string reference_frame = this->get_parameter("reference_frame").as_string();
reference_frame = as2::tf::generateTfName(ns, reference_frame);
camera_frame_ = as2::tf::generateTfName(get_namespace(), camera_name_) + "/camera_link";
float x = this->get_parameter("x").as_double();
float y = this->get_parameter("y").as_double();
float z = this->get_parameter("z").as_double();
float roll = this->get_parameter("roll").as_double();
float pitch = this->get_parameter("pitch").as_double();
float yaw = this->get_parameter("yaw").as_double();
// Camera position in FLU
std::string sensor_flu_frame = as2::tf::generateTfName(ns, camera_name_);
camera_->setStaticTransform(sensor_flu_frame, reference_frame, x, y, z, roll, pitch, yaw);
}
void UsbCameraInterface::setCameraModelTransform(const std::string &_camera_rdf,
const std::string &_camera_flu) {
float roll = 0;
float pitch = -1.57079632679;
float yaw = -1.57079632679;
camera_->setStaticTransform(_camera_rdf, _camera_flu, 0, 0, 0, roll, pitch, yaw);
}
void UsbCameraInterface::captureImage() {
// Capture image in device with opencv2
cv::Mat frame;
if (!cap_.read(frame)) {
RCLCPP_ERROR(get_logger(), "Cannot read image");
return;
}
camera_->updateData(frame);
}