Program Listing for File parameters.hpp
↰ Return to documentation for file (/tmp/ws/src/v4l2_camera/include/v4l2_camera/parameters.hpp
)
// Copyright 2022 Bold Hearts
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#ifndef V4L2_CAMERA__PARAMETERS_HPP_
#define V4L2_CAMERA__PARAMETERS_HPP_
#include <memory>
#include <string>
#include <unordered_map>
#include <utility>
#include <vector>
#include <rclcpp/parameter_client.hpp>
#include <rclcpp/node_interfaces/node_logging_interface.hpp>
#include <rclcpp/node_interfaces/node_parameters_interface.hpp>
#include <rclcpp/node_interfaces/node_topics_interface.hpp>
#include <v4l2_camera/v4l2_camera_device.hpp>
namespace rclcpp {namespace node_interfaces {struct PostSetParametersCallbackHandle;}}
namespace v4l2_camera
{
class Parameters
{
public:
Parameters(
rclcpp::node_interfaces::NodeParametersInterface::SharedPtr parameters_interface,
rclcpp::node_interfaces::NodeTopicsInterface::SharedPtr topics_interface,
rclcpp::node_interfaces::NodeLoggingInterface::SharedPtr logging_interface);
void declareStaticParameters();
void declareOutputParameters();
void declareDeviceParameters(V4l2CameraDevice const & device);
void setParameterChangedCallback(std::function<void(rclcpp::Parameter)> callback);
rclcpp::Parameter getParameter(std::string const & name) const
{
return parameters_interface_->get_parameter(name);
}
const rclcpp::ParameterValue & getParameterValue(std::string const & name) const
{
return parameters_interface_->get_parameter(name).get_parameter_value();
}
template<typename T>
decltype(auto) getValue(std::string const & name) const
{
return parameters_interface_->get_parameter(name).get_value<T>();
}
std::string getVideoDevice() const {return getValue<std::string>("video_device");}
std::string getCameraInfoUrl() const {return getValue<std::string>("camera_info_url");}
std::string getCameraFrameId() const {return getValue<std::string>("camera_frame_id");}
std::string getOutputEncoding() const {return getValue<std::string>("output_encoding");}
std::string getPixelFormat() const {return getValue<std::string>("pixel_format");}
std::vector<int64_t> getImageSize() const {return getValue<std::vector<int64_t>>("image_size");}
std::vector<rclcpp::Parameter> getControlParameters() const
{
auto names = std::vector<std::string>{};
std::transform(
control_name_to_id_.begin(), control_name_to_id_.end(),
std::back_inserter(names),
[](auto kv) {return kv.first;});
return parameters_interface_->get_parameters(names);
}
bool isControlParameter(rclcpp::Parameter const & parameter) const
{
return control_name_to_id_.find(parameter.get_name()) != control_name_to_id_.end();
}
int32_t getControlId(std::string const & name) const {return control_name_to_id_.at(name);}
int32_t getControlId(rclcpp::Parameter const & param) const
{
return getControlId(param.get_name());
}
private:
using NodeLoggingInterface = rclcpp::node_interfaces::NodeLoggingInterface;
using NodeParametersInterface = rclcpp::node_interfaces::NodeParametersInterface;
using NodeTopicsInterface = rclcpp::node_interfaces::NodeTopicsInterface;
NodeLoggingInterface::SharedPtr logging_interface_;
NodeParametersInterface::SharedPtr parameters_interface_;
NodeTopicsInterface::SharedPtr topics_interface_;
std::shared_ptr<rclcpp::node_interfaces::OnSetParametersCallbackHandle>
on_set_parameter_callback_handle_;
std::shared_ptr<rclcpp::node_interfaces::PostSetParametersCallbackHandle>
post_set_parameter_callback_handle_;
rclcpp::Subscription<rcl_interfaces::msg::ParameterEvent>::SharedPtr parameter_event_sub_;
std::function<void(rclcpp::Parameter)> parameter_changed_callback_;
std::unordered_map<std::string, int32_t> control_name_to_id_;
void declareFormatParameters(V4l2CameraDevice const & device);
void declareControlParameters(V4l2CameraDevice const & device);
inline rcl_interfaces::msg::ParameterDescriptor make_descriptor(
std::string description,
std::string additional_constraints, bool read_only)
{
auto parameter_descriptor = rcl_interfaces::msg::ParameterDescriptor{};
parameter_descriptor.description = std::move(description);
parameter_descriptor.additional_constraints = std::move(additional_constraints);
parameter_descriptor.read_only = read_only;
return parameter_descriptor;
}
template<typename T>
void declareParameter(
std::string const & name, T value,
rcl_interfaces::msg::ParameterDescriptor const & parameter_descriptor)
{
auto parameter_value = rclcpp::ParameterValue{value};
parameters_interface_->declare_parameter(name, parameter_value, parameter_descriptor);
}
template<typename T>
void declareParameter(
std::string const & name, T value, std::string const & description,
std::string const & additional_constraints,
bool read_only = false)
{
auto parameter_descriptor = make_descriptor(description, additional_constraints, read_only);
declareParameter(name, value, parameter_descriptor);
}
template<typename T>
void declareParameter(
std::string const & name, T value, std::string const & description,
bool read_only = false)
{
declareParameter(name, value, description, "", read_only);
}
template<typename T>
struct hasAddPostSetParametersCallback
{
template<typename A>
static std::true_type test(decltype(&A::add_post_set_parameters_callback));
template<typename A>
static std::false_type test(...);
static const bool value = decltype(test<T>(nullptr))::value;
};
// Humble variant using AsyncParametersClient::on_parameter_event
template<typename T>
std::enable_if_t<!hasAddPostSetParametersCallback<T>::value> setParameterChangedCallbackImpl(
std::shared_ptr<T>/*parameters_interface*/,
rclcpp::node_interfaces::NodeTopicsInterface::SharedPtr topics_interface,
std::function<void(rclcpp::Parameter)> callback)
{
parameter_event_sub_ = rclcpp::AsyncParametersClient::on_parameter_event(
topics_interface,
[this, callback = std::move(callback)](
rcl_interfaces::msg::ParameterEvent::ConstSharedPtr event) {
if (event->node !=
topics_interface_->get_node_base_interface()->get_fully_qualified_name())
{
return;
}
for (auto const & parameter : event->changed_parameters) {
callback(parameters_interface_->get_parameter(parameter.name));
}
});
}
// Post-Humble variant using add_post_set_parameters_callback
template<typename T>
std::enable_if_t<hasAddPostSetParametersCallback<T>::value> setParameterChangedCallbackImpl(
std::shared_ptr<T> parameters_interface,
rclcpp::node_interfaces::NodeTopicsInterface::SharedPtr /*topics_interface*/,
std::function<void(rclcpp::Parameter)> callback)
{
post_set_parameter_callback_handle_ = parameters_interface->add_post_set_parameters_callback(
[this, callback = std::move(callback)](
std::vector<rclcpp::Parameter> const & parameters) {
for (auto const & parameter : parameters) {
callback(parameter);
}
});
}
};
} // namespace v4l2_camera
#endif // V4L2_CAMERA__PARAMETERS_HPP_