Skip to content

Commit

Permalink
implement support for new control types
Browse files Browse the repository at this point in the history
  • Loading branch information
christianrauch committed Dec 31, 2024
1 parent ee98bdf commit 2e974e0
Show file tree
Hide file tree
Showing 7 changed files with 179 additions and 39 deletions.
25 changes: 13 additions & 12 deletions src/CameraNode.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,12 @@ namespace rclcpp
class NodeOptions;
}

#define CASE_RANGE(T, R) \
case libcamera::ControlType##T: \
R.from_value = max<libcamera::ControlType##T>(info.min()); \
R.to_value = min<libcamera::ControlType##T>(info.max()); \
break;


namespace camera
{
Expand Down Expand Up @@ -528,18 +534,13 @@ CameraNode::declareParameters()
rcl_interfaces::msg::FloatingPointRange range_float;

switch (id->type()) {
case libcamera::ControlTypeInteger32:
range_int.from_value = max<libcamera::ControlTypeInteger32>(info.min());
range_int.to_value = min<libcamera::ControlTypeInteger32>(info.max());
break;
case libcamera::ControlTypeInteger64:
range_int.from_value = max<libcamera::ControlTypeInteger64>(info.min());
range_int.to_value = min<libcamera::ControlTypeInteger64>(info.max());
break;
case libcamera::ControlTypeFloat:
range_float.from_value = max<libcamera::ControlTypeFloat>(info.min());
range_float.to_value = min<libcamera::ControlTypeFloat>(info.max());
break;
CASE_RANGE(Integer32, range_int)
CASE_RANGE(Integer64, range_int)
CASE_RANGE(Float, range_float)
#if LIBCAMERA_VER_GE(0, 4, 0)
CASE_RANGE(Unsigned16, range_int)
CASE_RANGE(Unsigned32, range_int)
#endif
default:
break;
}
Expand Down
55 changes: 55 additions & 0 deletions src/clamp.cpp
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
#include "libcamera_version_utils.hpp"
#include "types.hpp"
#include <algorithm>
#include <cassert>
Expand Down Expand Up @@ -66,6 +67,12 @@ MIN(Float)
MAX(Integer32)
MAX(Integer64)
MAX(Float)
#if LIBCAMERA_VER_GE(0, 4, 0)
MIN(Unsigned16)
MIN(Unsigned32)
MAX(Unsigned16)
MAX(Unsigned32)
#endif

namespace std
{
Expand All @@ -79,6 +86,17 @@ clamp(const CTRectangle &val, const CTRectangle &lo, const CTRectangle &hi)

return CTRectangle {x, y, width, height};
}

#if LIBCAMERA_VER_GE(0, 4, 0)
CTPoint
clamp(const CTPoint &val, const CTPoint &lo, const CTPoint &hi)
{
const int x = std::clamp(val.x, lo.x, hi.x);
const int y = std::clamp(val.y, lo.y, hi.y);

return CTPoint {x, y};
}
#endif
} // namespace std


Expand Down Expand Up @@ -135,6 +153,11 @@ clamp(const libcamera::ControlValue &value, const libcamera::ControlValue &min,
CASE_CLAMP(String)
CASE_CLAMP(Rectangle)
CASE_CLAMP(Size)
#if LIBCAMERA_VER_GE(0, 4, 0)
CASE_CLAMP(Unsigned16)
CASE_CLAMP(Unsigned32)
CASE_CLAMP(Point)
#endif
}

return {};
Expand All @@ -157,6 +180,28 @@ operator>(const libcamera::Rectangle &lhs, const libcamera::Rectangle &rhs)
(lhs.y + lhs.height) > (rhs.y + rhs.height);
}

#if LIBCAMERA_VER_GE(0, 4, 0)
int
squared_sum(const libcamera::Point &p)
{
return p.x * p.x + p.y * p.y;
}

bool
operator<(const libcamera::Point &lhs, const libcamera::Point &rhs)
{
// check if lhs point is closer to origin than rhs point
return squared_sum(lhs) < squared_sum(rhs);
}

bool
operator>(const libcamera::Point &lhs, const libcamera::Point &rhs)
{
// check if lhs point is further away from origin than rhs point
return squared_sum(lhs) > squared_sum(rhs);
}
#endif

template<typename T>
bool
less(const libcamera::ControlValue &lhs, const libcamera::ControlValue &rhs)
Expand Down Expand Up @@ -261,6 +306,11 @@ operator<(const libcamera::ControlValue &lhs, const libcamera::ControlValue &rhs
CASE_LESS(String)
CASE_LESS(Rectangle)
CASE_LESS(Size)
#if LIBCAMERA_VER_GE(0, 4, 0)
CASE_LESS(Unsigned16)
CASE_LESS(Unsigned32)
CASE_LESS(Point)
#endif
}

throw std::runtime_error("unhandled control type " + std::to_string(lhs.type()));
Expand All @@ -282,6 +332,11 @@ operator>(const libcamera::ControlValue &lhs, const libcamera::ControlValue &rhs
CASE_GREATER(String)
CASE_GREATER(Rectangle)
CASE_GREATER(Size)
#if LIBCAMERA_VER_GE(0, 4, 0)
CASE_GREATER(Unsigned16)
CASE_GREATER(Unsigned32)
CASE_GREATER(Point)
#endif
}

throw std::runtime_error("unhandled control type " + std::to_string(lhs.type()));
Expand Down
30 changes: 30 additions & 0 deletions src/cv_to_pv.cpp
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
#include "cv_to_pv.hpp"
#include "libcamera_version_utils.hpp"
#include "type_extent.hpp"
#include "types.hpp"
#include <cstdint>
Expand Down Expand Up @@ -85,6 +86,14 @@ cv_to_pv_scalar(const libcamera::Size &size)
return rclcpp::ParameterValue(std::vector<int64_t> {size.width, size.height});
}

#if LIBCAMERA_VER_GE(0, 4, 0)
rclcpp::ParameterValue
cv_to_pv_scalar(const libcamera::Point &point)
{
return rclcpp::ParameterValue(std::vector<int64_t> {point.x, point.y});
}
#endif

template<typename T>
rclcpp::ParameterValue
cv_to_pv(const std::vector<T> &values)
Expand Down Expand Up @@ -115,6 +124,11 @@ cv_to_pv(const libcamera::ControlValue &value)
CASE_CONVERT(String)
CASE_CONVERT(Rectangle)
CASE_CONVERT(Size)
#if LIBCAMERA_VER_GE(0, 4, 0)
CASE_CONVERT(Unsigned16)
CASE_CONVERT(Unsigned32)
CASE_CONVERT(Point)
#endif
}

return {};
Expand All @@ -130,6 +144,10 @@ cv_to_pv_type(const libcamera::ControlId *const id)
case libcamera::ControlType::ControlTypeBool:
return rclcpp::ParameterType::PARAMETER_BOOL;
case libcamera::ControlType::ControlTypeByte:
#if LIBCAMERA_VER_GE(0, 4, 0)
case libcamera::ControlType::ControlTypeUnsigned16:
case libcamera::ControlType::ControlTypeUnsigned32:
#endif
case libcamera::ControlType::ControlTypeInteger32:
case libcamera::ControlType::ControlTypeInteger64:
return rclcpp::ParameterType::PARAMETER_INTEGER;
Expand All @@ -141,6 +159,10 @@ cv_to_pv_type(const libcamera::ControlId *const id)
return rclcpp::ParameterType::PARAMETER_INTEGER_ARRAY;
case libcamera::ControlType::ControlTypeSize:
return rclcpp::ParameterType::PARAMETER_INTEGER_ARRAY;
#if LIBCAMERA_VER_GE(0, 4, 0)
case libcamera::ControlType::ControlTypePoint:
return rclcpp::ParameterType::PARAMETER_INTEGER_ARRAY;
#endif
}
}
else {
Expand All @@ -150,6 +172,10 @@ cv_to_pv_type(const libcamera::ControlId *const id)
case libcamera::ControlType::ControlTypeBool:
return rclcpp::ParameterType::PARAMETER_BOOL_ARRAY;
case libcamera::ControlType::ControlTypeByte:
#if LIBCAMERA_VER_GE(0, 4, 0)
case libcamera::ControlType::ControlTypeUnsigned16:
case libcamera::ControlType::ControlTypeUnsigned32:
#endif
case libcamera::ControlType::ControlTypeInteger32:
case libcamera::ControlType::ControlTypeInteger64:
return rclcpp::ParameterType::PARAMETER_INTEGER_ARRAY;
Expand All @@ -161,6 +187,10 @@ cv_to_pv_type(const libcamera::ControlId *const id)
return rclcpp::ParameterType::PARAMETER_NOT_SET;
case libcamera::ControlType::ControlTypeSize:
return rclcpp::ParameterType::PARAMETER_NOT_SET;
#if LIBCAMERA_VER_GE(0, 4, 0)
case libcamera::ControlType::ControlTypePoint:
return rclcpp::ParameterType::PARAMETER_NOT_SET;
#endif
}
}

Expand Down
6 changes: 6 additions & 0 deletions src/exceptions.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -7,3 +7,9 @@ class invalid_conversion : public std::runtime_error
public:
explicit invalid_conversion(const std::string &msg) : std::runtime_error(msg) {}
};

class should_not_reach : public std::runtime_error
{
public:
explicit should_not_reach() : std::runtime_error("should not reach here") {}
};
91 changes: 64 additions & 27 deletions src/pv_to_cv.cpp
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
#include "pv_to_cv.hpp"
#include "exceptions.hpp"
#include "libcamera_version_utils.hpp"
#include "types.hpp"
#include <cstdint>
#include <libcamera/base/span.h>
Expand All @@ -9,23 +11,50 @@
#include <vector>


#define CASE_CONVERT_INT(T) \
case libcamera::ControlType##T: \
return ControlTypeMap<libcamera::ControlType##T>::type(parameter.as_int());

#define CASE_CONVERT_INT_ARRAY(T) \
case libcamera::ControlType##T: \
return libcamera::Span<const ControlTypeMap<libcamera::ControlType##T>::type>(std::vector<ControlTypeMap<libcamera::ControlType##T>::type>(values.begin(), values.end()));

#define CASE_NONE(T) \
case libcamera::ControlType##T: \
return {};

#define CASE_INVALID(T) \
case libcamera::ControlType##T: \
throw invalid_conversion("cannot convert integer array to ##T");


libcamera::ControlValue
pv_to_cv_int_array(const std::vector<int64_t> &values, const libcamera::ControlType &type)
{
// convert to Span (Integer32, Integer64) or geometric type Rectangle, Size
// convert to integer Span, geometric type Rectangle, Size, Point, or throw exception
switch (type) {
case libcamera::ControlTypeInteger32:
return {
libcamera::Span<const CTInteger32>(std::vector<CTInteger32>(values.begin(), values.end()))};
CASE_NONE(None)
CASE_INVALID(Bool)
CASE_INVALID(Byte)
CASE_CONVERT_INT_ARRAY(Integer32)
case libcamera::ControlTypeInteger64:
return {libcamera::Span<const CTInteger64>(values)};
return libcamera::Span<const CTInteger64>(values);
#if LIBCAMERA_VER_GE(0, 4, 0)
CASE_CONVERT_INT_ARRAY(Unsigned16)
CASE_CONVERT_INT_ARRAY(Unsigned32)
#endif
CASE_CONVERT_INT_ARRAY(Float)
CASE_INVALID(String)
case libcamera::ControlTypeRectangle:
return {libcamera::Rectangle(values[0], values[1], values[2], values[3])};
return libcamera::Rectangle(values[0], values[1], values[2], values[3]);
case libcamera::ControlTypeSize:
return {libcamera::Size(values[0], values[1])};
default:
return {};
return libcamera::Size(values[0], values[1]);
#if LIBCAMERA_VER_GE(0, 4, 0)
case libcamera::ControlTypePoint:
return libcamera::Point(values[0], values[1]);
#endif
}
throw should_not_reach();
}

libcamera::ControlValue
Expand All @@ -35,33 +64,41 @@ pv_to_cv(const rclcpp::Parameter &parameter, const libcamera::ControlType &type)
case rclcpp::ParameterType::PARAMETER_NOT_SET:
return {};
case rclcpp::ParameterType::PARAMETER_BOOL:
return {parameter.as_bool()};
return parameter.as_bool();
case rclcpp::ParameterType::PARAMETER_INTEGER:
if (type == libcamera::ControlTypeInteger32)
return {CTInteger32(parameter.as_int())};
else if (type == libcamera::ControlTypeInteger64)
return {CTInteger64(parameter.as_int())};
else
return {};
switch (type) {
CASE_NONE(None)
CASE_CONVERT_INT(Bool)
CASE_CONVERT_INT(Byte)
CASE_CONVERT_INT(Integer32)
CASE_CONVERT_INT(Integer64)
CASE_CONVERT_INT(Float)
CASE_NONE(String)
CASE_NONE(Rectangle)
CASE_NONE(Size)
#if LIBCAMERA_VER_GE(0, 4, 0)
CASE_CONVERT_INT(Unsigned16)
CASE_CONVERT_INT(Unsigned32)
CASE_NONE(Point)
#endif
}
throw should_not_reach();
case rclcpp::ParameterType::PARAMETER_DOUBLE:
return {CTFloat(parameter.as_double())};
return CTFloat(parameter.as_double());
case rclcpp::ParameterType::PARAMETER_STRING:
return {parameter.as_string()};
return CTString(parameter.as_string());
case rclcpp::ParameterType::PARAMETER_BYTE_ARRAY:
return {libcamera::Span<const CTByte>(parameter.as_byte_array())};
return libcamera::Span<const CTByte>(parameter.as_byte_array());
case rclcpp::ParameterType::PARAMETER_BOOL_ARRAY:
return {};
throw invalid_conversion("cannot convert bool array to control value");
case rclcpp::ParameterType::PARAMETER_INTEGER_ARRAY:
return pv_to_cv_int_array(parameter.as_integer_array(), type);
case rclcpp::ParameterType::PARAMETER_DOUBLE_ARRAY:
{
// convert to float vector
return {libcamera::Span<const CTFloat>(
std::vector<CTFloat>(parameter.as_double_array().begin(), parameter.as_double_array().end()))};
}
return libcamera::Span<const CTFloat>(
std::vector<CTFloat>(parameter.as_double_array().begin(), parameter.as_double_array().end()));
case rclcpp::ParameterType::PARAMETER_STRING_ARRAY:
return {libcamera::Span<const CTString>(parameter.as_string_array())};
default:
return {};
return libcamera::Span<const CTString>(parameter.as_string_array());
}
throw should_not_reach();
}
5 changes: 5 additions & 0 deletions src/types.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,11 @@ std::to_string(const libcamera::ControlType id)
CASE_TYPE(String)
CASE_TYPE(Rectangle)
CASE_TYPE(Size)
#if LIBCAMERA_VER_GE(0, 4, 0)
CASE_TYPE(Unsigned16)
CASE_TYPE(Unsigned32)
CASE_TYPE(Point)
#endif
}

return {};
Expand Down
6 changes: 6 additions & 0 deletions src/types.hpp
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
#pragma once
#include "libcamera_version_utils.hpp"
#include <cstdint>
#include <libcamera/controls.h>
#include <libcamera/geometry.h>
Expand Down Expand Up @@ -34,3 +35,8 @@ MAP(float, Float)
MAP(std::string, String)
MAP(libcamera::Rectangle, Rectangle)
MAP(libcamera::Size, Size)
#if LIBCAMERA_VER_GE(0, 4, 0)
MAP(uint16_t, Unsigned16)
MAP(uint32_t, Unsigned32)
MAP(libcamera::Point, Point)
#endif

0 comments on commit 2e974e0

Please sign in to comment.