Skip to content

Commit 5b8ef22

Browse files
authored
[RSDK-11703, RSDK-11602] Update C++ GetImages signature (viamrobotics#481)
1 parent 177911c commit 5b8ef22

File tree

8 files changed

+114
-15
lines changed

8 files changed

+114
-15
lines changed

BUILDING.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -441,7 +441,7 @@ that they are pre-populated.
441441
cmake -DVIAMCPPSDK_USE_DYNAMIC_PROTOS=ON ...
442442
ninja all # FAILS!
443443
ninja generate-dynamic-protos
444-
nina all # OK!
444+
ninja all # OK!
445445
```
446446

447447
### Build Issue: Proto Mismatch

src/viam/sdk/components/camera.hpp

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -160,7 +160,27 @@ class Camera : public Component {
160160
/// @brief Get the next images from the camera as a vector of raw images with names and
161161
/// metadata.
162162
/// @return a vector of raw_images and associated response metadata.
163-
virtual image_collection get_images() = 0;
163+
inline image_collection get_images() {
164+
return get_images({}, {});
165+
}
166+
167+
/// @brief Get the next images from specific sources as a vector of raw images with names and
168+
/// metadata.
169+
/// @param filter_source_names the names of sources to receive images from. If empty, all
170+
/// sources are returned.
171+
/// @return a vector of raw_images and associated response metadata.
172+
inline image_collection get_images(std::vector<std::string> filter_source_names) {
173+
return get_images(std::move(filter_source_names), {});
174+
}
175+
176+
/// @brief Get the next images from the camera as a vector of raw images with names and
177+
/// metadata.
178+
/// @param filter_source_names the names of sources to receive images from. If empty, all
179+
/// sources are returned.
180+
/// @param extra any additional arguments to the method.
181+
/// @return a vector of raw_images and associated response metadata.
182+
virtual image_collection get_images(std::vector<std::string> filter_source_names,
183+
const ProtoStruct& extra) = 0;
164184

165185
/// @brief Get the next `point_cloud` from the camera.
166186
/// @param mime_type the desired mime_type of the point_cloud (does not guarantee output type).

src/viam/sdk/components/private/camera_client.cpp

Lines changed: 22 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,13 @@ Camera::image_collection from_proto(const viam::component::camera::v1::GetImages
5454
std::string img_string = img.image();
5555
const std::vector<unsigned char> bytes(img_string.begin(), img_string.end());
5656
raw_image.bytes = bytes;
57-
raw_image.mime_type = format_to_MIME_string(img.format());
57+
// TODO(RSDK-11733): This is a temporary fix to support handling both the format and mime
58+
// type. We will remove this once we remove the format field from the proto.
59+
if (!img.mime_type().empty()) {
60+
raw_image.mime_type = img.mime_type();
61+
} else {
62+
raw_image.mime_type = format_to_MIME_string(img.format());
63+
}
5864
raw_image.source_name = img.source_name();
5965
images.push_back(raw_image);
6066
}
@@ -122,10 +128,21 @@ Camera::raw_image CameraClient::get_image(std::string mime_type, const ProtoStru
122128
.invoke([](auto& response) { return from_proto(response); });
123129
};
124130

125-
Camera::image_collection CameraClient::get_images() {
126-
return make_client_helper(this, *stub_, &StubType::GetImages).invoke([](auto& response) {
127-
return from_proto(response);
128-
});
131+
Camera::image_collection CameraClient::get_images(std::vector<std::string> filter_source_names,
132+
const ProtoStruct& extra) {
133+
return make_client_helper(this, *stub_, &StubType::GetImages)
134+
.with(extra,
135+
[&](auto& request) {
136+
if (!filter_source_names.empty()) {
137+
// in newer gRPC versions we would be able to call `Add` or `Assign` on an
138+
// iterator range rather than element-wise copy
139+
request.mutable_filter_source_names()->Reserve(filter_source_names.size());
140+
for (auto& source_name : filter_source_names) {
141+
request.add_filter_source_names(std::move(source_name));
142+
}
143+
}
144+
})
145+
.invoke([](auto& response) { return from_proto(response); });
129146
};
130147

131148
Camera::point_cloud CameraClient::get_point_cloud(std::string mime_type, const ProtoStruct& extra) {

src/viam/sdk/components/private/camera_client.hpp

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,8 @@ class CameraClient : public Camera {
2626
CameraClient(std::string name, std::shared_ptr<grpc::Channel> channel);
2727
ProtoStruct do_command(const ProtoStruct& command) override;
2828
raw_image get_image(std::string mime_type, const ProtoStruct& extra) override;
29-
image_collection get_images() override;
29+
image_collection get_images(std::vector<std::string> filter_source_names,
30+
const ProtoStruct& extra) override;
3031
point_cloud get_point_cloud(std::string mime_type, const ProtoStruct& extra) override;
3132
properties get_properties() override;
3233
std::vector<GeometryConfig> get_geometries(const ProtoStruct& extra) override;
@@ -42,6 +43,7 @@ class CameraClient : public Camera {
4243
// we need to include these `using` lines.
4344
using Camera::get_geometries;
4445
using Camera::get_image;
46+
using Camera::get_images;
4547
using Camera::get_point_cloud;
4648

4749
protected:

src/viam/sdk/components/private/camera_server.cpp

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -83,12 +83,15 @@ ::grpc::Status CameraServer::GetImages(
8383
const ::viam::component::camera::v1::GetImagesRequest* request,
8484
::viam::component::camera::v1::GetImagesResponse* response) noexcept {
8585
return make_service_helper<Camera>(
86-
"CameraServer::GetImages", this, request)([&](auto&, auto& camera) {
87-
const Camera::image_collection image_coll = camera->get_images();
86+
"CameraServer::GetImages", this, request)([&](auto& helper, auto& camera) {
87+
const Camera::image_collection image_coll = camera->get_images(
88+
{request->filter_source_names().begin(), request->filter_source_names().end()},
89+
helper.getExtra());
8890
for (const auto& img : image_coll.images) {
8991
::viam::component::camera::v1::Image proto_image;
9092
const std::string img_string = bytes_to_string(img.bytes);
9193
proto_image.set_source_name(img.source_name);
94+
proto_image.set_mime_type(img.mime_type);
9295
proto_image.set_format(
9396
MIME_string_to_format(Camera::normalize_mime_type(img.mime_type)));
9497
proto_image.set_image(img_string);

src/viam/sdk/tests/mocks/camera_mocks.cpp

Lines changed: 20 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
#include <algorithm>
12
#include <viam/sdk/tests/mocks/camera_mocks.hpp>
23

34
#include <viam/sdk/common/proto_value.hpp>
@@ -16,8 +17,23 @@ ProtoStruct MockCamera::do_command(const ProtoStruct&) {
1617
Camera::raw_image MockCamera::get_image(std::string, const ProtoStruct&) {
1718
return image_;
1819
}
19-
Camera::image_collection MockCamera::get_images() {
20-
return images_;
20+
Camera::image_collection MockCamera::get_images(std::vector<std::string> filter_source_names,
21+
const ProtoStruct& extra) {
22+
last_filter_source_names_ = std::move(filter_source_names);
23+
last_extra_ = extra;
24+
if (last_filter_source_names_.empty()) {
25+
return images_;
26+
}
27+
Camera::image_collection filtered = images_;
28+
filtered.images.clear();
29+
for (const auto& img : images_.images) {
30+
if (std::find(last_filter_source_names_.begin(),
31+
last_filter_source_names_.end(),
32+
img.source_name) != last_filter_source_names_.end()) {
33+
filtered.images.push_back(img);
34+
}
35+
}
36+
return filtered;
2137
}
2238
Camera::point_cloud MockCamera::get_point_cloud(std::string, const ProtoStruct&) {
2339
return pc_;
@@ -43,13 +59,13 @@ Camera::image_collection fake_raw_images() {
4359
std::vector<Camera::raw_image> images;
4460
Camera::raw_image image1;
4561
image1.mime_type = "image/jpeg";
46-
image1.source_name = "color_sensor";
62+
image1.source_name = "color";
4763
std::vector<unsigned char> bytes1 = {'a', 'b', 'c'};
4864
image1.bytes = bytes1;
4965
images.push_back(image1);
5066
Camera::raw_image image2;
5167
image2.mime_type = "image/vnd.viam.dep";
52-
image2.source_name = "depth_sensor";
68+
image2.source_name = "depth";
5369
std::vector<unsigned char> bytes2 = {'d', 'e', 'f'};
5470
image2.bytes = bytes2;
5571
images.push_back(image2);

src/viam/sdk/tests/mocks/camera_mocks.hpp

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,13 +12,21 @@ class MockCamera : public Camera {
1212
public:
1313
ProtoStruct do_command(const ProtoStruct& command) override;
1414
raw_image get_image(std::string mime_type, const sdk::ProtoStruct& extra) override;
15-
image_collection get_images() override;
15+
image_collection get_images(std::vector<std::string> filter_source_names,
16+
const sdk::ProtoStruct& extra) override;
1617
point_cloud get_point_cloud(std::string mime_type, const sdk::ProtoStruct& extra) override;
1718
std::vector<GeometryConfig> get_geometries(const sdk::ProtoStruct& extra) override;
1819
properties get_properties() override;
1920
static std::shared_ptr<MockCamera> get_mock_camera();
2021
MockCamera(std::string name) : Camera(std::move(name)) {}
2122

23+
const std::vector<std::string>& last_filter_source_names() const {
24+
return last_filter_source_names_;
25+
}
26+
const ProtoStruct& last_extra() const {
27+
return last_extra_;
28+
}
29+
2230
private:
2331
Camera::intrinsic_parameters intrinsic_parameters_;
2432
Camera::distortion_parameters distortion_parameters_;
@@ -28,6 +36,8 @@ class MockCamera : public Camera {
2836
Camera::point_cloud pc_;
2937
ProtoStruct map_;
3038
std::vector<GeometryConfig> geometries_;
39+
std::vector<std::string> last_filter_source_names_;
40+
ProtoStruct last_extra_;
3141
};
3242

3343
Camera::raw_image fake_raw_image();

src/viam/sdk/tests/test_camera.cpp

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,37 @@ BOOST_AUTO_TEST_CASE(test_get_images) {
5151
});
5252
}
5353

54+
BOOST_AUTO_TEST_CASE(test_get_images_filtering) {
55+
std::shared_ptr<MockCamera> mock = MockCamera::get_mock_camera();
56+
client_to_mock_pipeline<Camera>(mock, [&](Camera& client) {
57+
// request only color
58+
Camera::image_collection images = client.get_images({"color"});
59+
BOOST_CHECK_EQUAL(images.images.size(), 1);
60+
BOOST_CHECK_EQUAL(images.images[0].source_name, "color");
61+
62+
// empty filter returns all
63+
Camera::image_collection all_images = client.get_images({});
64+
BOOST_CHECK_EQUAL(all_images.images.size(), 2);
65+
66+
// verify filter propagated to mock
67+
auto last_filter = mock->last_filter_source_names();
68+
BOOST_CHECK_EQUAL(last_filter.size(), 0);
69+
});
70+
}
71+
72+
BOOST_AUTO_TEST_CASE(test_get_images_with_extra) {
73+
std::shared_ptr<MockCamera> mock = MockCamera::get_mock_camera();
74+
client_to_mock_pipeline<Camera>(mock, [&](Camera& client) {
75+
ProtoStruct extra;
76+
extra["foo"] = ProtoValue("bar");
77+
auto images = client.get_images({}, extra);
78+
(void)images; // unused variable in test body
79+
const auto& last_extra = mock->last_extra();
80+
BOOST_CHECK(last_extra.at("foo").is_a<std::string>());
81+
BOOST_CHECK_EQUAL(last_extra.at("foo").get_unchecked<std::string>(), "bar");
82+
});
83+
}
84+
5485
BOOST_AUTO_TEST_CASE(test_get_point_cloud) {
5586
std::shared_ptr<MockCamera> mock = MockCamera::get_mock_camera();
5687
client_to_mock_pipeline<Camera>(mock, [](Camera& client) {

0 commit comments

Comments
 (0)