Skip to content

Commit 82fe376

Browse files
committed
merge main
2 parents f09e554 + 2c676a4 commit 82fe376

File tree

5 files changed

+374
-507
lines changed

5 files changed

+374
-507
lines changed

deep_tools/camera_sync/CMakeLists.txt

Lines changed: 1 addition & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -11,14 +11,13 @@
1111
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1212
# See the License for the specific language governing permissions and
1313
# limitations under the License.
14-
cmake_minimum_required(VERSION 3.8)
14+
cmake_minimum_required(VERSION 3.22)
1515
project(camera_sync)
1616

1717
if(CMAKE_COMPILER_IS_GNUCXX OR CMAKE_CXX_COMPILER_ID MATCHES "Clang")
1818
add_compile_options(-Wall -Wextra -Wpedantic)
1919
endif()
2020

21-
# find dependencies
2221
find_package(ament_cmake REQUIRED)
2322
find_package(rclcpp REQUIRED)
2423
find_package(rclcpp_lifecycle REQUIRED)
@@ -29,7 +28,6 @@ find_package(message_filters REQUIRED)
2928
find_package(image_transport REQUIRED)
3029
find_package(deep_msgs REQUIRED)
3130

32-
# Create include directory
3331
include_directories(include)
3432

3533
# Define lifecycle node support based on ROS distro
@@ -40,7 +38,6 @@ else()
4038
add_definitions(-DUSE_LIFECYCLE_NODE=0)
4139
endif()
4240

43-
# Add the multi-camera sync library for component
4441
add_library(multi_camera_sync_component SHARED src/multi_camera_sync_node.cpp)
4542
target_link_libraries(multi_camera_sync_component
4643
rclcpp::rclcpp
@@ -57,34 +54,25 @@ target_link_libraries(multi_camera_sync_component
5754
rclcpp_components_register_nodes(multi_camera_sync_component "camera_sync::MultiCameraSyncNode")
5855
set(node_plugins "${node_plugins}camera_sync::MultiCameraSyncNode;$<TARGET_FILE:multi_camera_sync_component>\n")
5956

60-
61-
62-
# Install executables and libraries
6357
install(TARGETS
6458
multi_camera_sync_component
6559
ARCHIVE DESTINATION lib
6660
LIBRARY DESTINATION lib
6761
RUNTIME DESTINATION bin
6862
)
6963

70-
71-
72-
# Install include directory
7364
install(DIRECTORY include/
7465
DESTINATION include
7566
)
7667

77-
# Install launch files if any
7868
install(DIRECTORY launch/
7969
DESTINATION share/${PROJECT_NAME}/launch
8070
FILES_MATCHING PATTERN "*.py" PATTERN "*.yaml" PATTERN "*.md"
8171
)
8272

83-
# Install config files
8473
install(DIRECTORY config/
8574
DESTINATION share/${PROJECT_NAME}/config
8675
FILES_MATCHING PATTERN "*.yaml"
8776
)
8877

89-
9078
ament_package()

deep_tools/camera_sync/config/multi_camera_sync_params.yaml

Lines changed: 27 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -24,21 +24,38 @@ multi_camera_sync:
2424
# Camera topics to synchronize
2525
# For raw images, use topics like: ["/camera1/image_raw", "/camera2/image_raw"]
2626
# For compressed images, use topics like: ["/camera1/image_raw/compressed", "/camera2/image_raw/compressed"]
27-
camera_topics: [
28-
"/CAM_FRONT/image_rect_compressed",
29-
"/CAM_FRONT_LEFT/image_rect_compressed",
30-
"/CAM_FRONT_RIGHT/image_rect_compressed",
31-
"/CAM_BACK/image_rect_compressed",
32-
"/CAM_BACK_LEFT/image_rect_compressed",
33-
"/CAM_BACK_RIGHT/image_rect_compressed"
34-
]
27+
camera_topics:
28+
- "/camera_lower_sw/image_rect"
29+
- "/camera_lower_ne/image_rect"
30+
- "/camera_lower_se/image_rect"
31+
- "/camera_lower_nw/image_rect"
32+
- "/camera_pano_ww/image_rect"
33+
- "/camera_pano_nn/image_rect"
34+
- "/camera_pano_ee/image_rect"
35+
- "/camera_pano_se/image_rect"
36+
- "/camera_pano_ne/image_rect"
37+
- "/camera_pano_nw/image_rect"
38+
- "/camera_pano_ss/image_rect"
39+
- "/camera_pano_sw/image_rect"
3540

3641
# Optional names for the cameras (if not provided, will auto-generate camera_1, camera_2, etc.)
37-
camera_names: ["front", "front_left", "front_right", "back", "back_left", "back_right"]
42+
camera_names:
43+
- "camera_lower_sw"
44+
- "camera_lower_ne"
45+
- "camera_lower_se"
46+
- "camera_lower_nw"
47+
- "camera_pano_ww"
48+
- "camera_pano_nn"
49+
- "camera_pano_ee"
50+
- "camera_pano_se"
51+
- "camera_pano_ne"
52+
- "camera_pano_nw"
53+
- "camera_pano_ss"
54+
- "camera_pano_sw"
3855

3956
# Whether to use compressed images (sensor_msgs/CompressedImage) instead of raw (sensor_msgs/Image)
4057
# Set to true if your camera topics publish compressed images
41-
use_compressed: true
58+
use_compressed: false
4259

4360
# Maximum time difference in milliseconds for message synchronization
4461
# Larger values allow more tolerance but may reduce temporal accuracy

deep_tools/camera_sync/include/camera_sync/multi_camera_sync_node.hpp

Lines changed: 37 additions & 113 deletions
Original file line numberDiff line numberDiff line change
@@ -15,16 +15,15 @@
1515
#ifndef CAMERA_SYNC__MULTI_CAMERA_SYNC_NODE_HPP_
1616
#define CAMERA_SYNC__MULTI_CAMERA_SYNC_NODE_HPP_
1717

18-
#include <message_filters/subscriber.h>
19-
#include <message_filters/sync_policies/approximate_time.h>
20-
#include <message_filters/synchronizer.h>
18+
#include <cv_bridge/cv_bridge.h>
2119

2220
#include <chrono>
21+
#include <map>
2322
#include <memory>
23+
#include <mutex>
2424
#include <string>
2525
#include <vector>
2626

27-
#include <image_transport/image_transport.hpp>
2827
#include <rclcpp/rclcpp.hpp>
2928
#include <sensor_msgs/msg/compressed_image.hpp>
3029
#include <sensor_msgs/msg/image.hpp>
@@ -47,11 +46,11 @@ namespace camera_sync
4746
{
4847

4948
/**
50-
* @brief Node that synchronizes N camera image messages using message filters
49+
* @brief Node that synchronizes N camera image messages using manual timestamp-based buffering
5150
*
5251
* This node can handle both raw images (sensor_msgs/Image) and compressed images
5352
* (sensor_msgs/CompressedImage) and synchronize them based on their timestamps.
54-
* Supports 2-6 cameras with a compact implementation.
53+
* Supports 2-12 cameras with a unified manual synchronization implementation.
5554
*/
5655
#if USE_LIFECYCLE_NODE
5756
class MultiCameraSyncNode : public rclcpp_lifecycle::LifecycleNode
@@ -87,38 +86,8 @@ class MultiCameraSyncNode : public rclcpp::Node
8786
using CompressedImageMsg = sensor_msgs::msg::CompressedImage;
8887

8988
// Subscriber types
90-
#if USE_LIFECYCLE_NODE
91-
using ImageSubscriber = message_filters::Subscriber<ImageMsg, rclcpp_lifecycle::LifecycleNode>;
92-
using CompressedImageSubscriber = message_filters::Subscriber<CompressedImageMsg, rclcpp_lifecycle::LifecycleNode>;
93-
#else
94-
using ImageSubscriber = message_filters::Subscriber<ImageMsg>;
95-
using CompressedImageSubscriber = message_filters::Subscriber<CompressedImageMsg>;
96-
#endif
97-
98-
// Sync policies for raw images
99-
using ImageSyncPolicy2 = message_filters::sync_policies::ApproximateTime<ImageMsg, ImageMsg>;
100-
using ImageSyncPolicy3 = message_filters::sync_policies::ApproximateTime<ImageMsg, ImageMsg, ImageMsg>;
101-
using ImageSyncPolicy4 = message_filters::sync_policies::ApproximateTime<ImageMsg, ImageMsg, ImageMsg, ImageMsg>;
102-
using ImageSyncPolicy5 =
103-
message_filters::sync_policies::ApproximateTime<ImageMsg, ImageMsg, ImageMsg, ImageMsg, ImageMsg>;
104-
using ImageSyncPolicy6 =
105-
message_filters::sync_policies::ApproximateTime<ImageMsg, ImageMsg, ImageMsg, ImageMsg, ImageMsg, ImageMsg>;
106-
107-
// Sync policies for compressed images
108-
using CompressedSyncPolicy2 = message_filters::sync_policies::ApproximateTime<CompressedImageMsg, CompressedImageMsg>;
109-
using CompressedSyncPolicy3 =
110-
message_filters::sync_policies::ApproximateTime<CompressedImageMsg, CompressedImageMsg, CompressedImageMsg>;
111-
using CompressedSyncPolicy4 = message_filters::sync_policies::
112-
ApproximateTime<CompressedImageMsg, CompressedImageMsg, CompressedImageMsg, CompressedImageMsg>;
113-
using CompressedSyncPolicy5 = message_filters::sync_policies::
114-
ApproximateTime<CompressedImageMsg, CompressedImageMsg, CompressedImageMsg, CompressedImageMsg, CompressedImageMsg>;
115-
using CompressedSyncPolicy6 = message_filters::sync_policies::ApproximateTime<
116-
CompressedImageMsg,
117-
CompressedImageMsg,
118-
CompressedImageMsg,
119-
CompressedImageMsg,
120-
CompressedImageMsg,
121-
CompressedImageMsg>;
89+
using ImageSubscriber = rclcpp::Subscription<ImageMsg>;
90+
using CompressedImageSubscriber = rclcpp::Subscription<CompressedImageMsg>;
12291

12392
/**
12493
* @brief Initialize the node parameters
@@ -140,61 +109,6 @@ class MultiCameraSyncNode : public rclcpp::Node
140109
*/
141110
void setupCompressedSync(size_t num_cameras);
142111

143-
/**
144-
* @brief Callback functions for synchronized raw images
145-
*/
146-
void syncCallback2Raw(const ImageMsg::ConstSharedPtr & img1, const ImageMsg::ConstSharedPtr & img2);
147-
void syncCallback3Raw(
148-
const ImageMsg::ConstSharedPtr & img1,
149-
const ImageMsg::ConstSharedPtr & img2,
150-
const ImageMsg::ConstSharedPtr & img3);
151-
void syncCallback4Raw(
152-
const ImageMsg::ConstSharedPtr & img1,
153-
const ImageMsg::ConstSharedPtr & img2,
154-
const ImageMsg::ConstSharedPtr & img3,
155-
const ImageMsg::ConstSharedPtr & img4);
156-
void syncCallback5Raw(
157-
const ImageMsg::ConstSharedPtr & img1,
158-
const ImageMsg::ConstSharedPtr & img2,
159-
const ImageMsg::ConstSharedPtr & img3,
160-
const ImageMsg::ConstSharedPtr & img4,
161-
const ImageMsg::ConstSharedPtr & img5);
162-
void syncCallback6Raw(
163-
const ImageMsg::ConstSharedPtr & img1,
164-
const ImageMsg::ConstSharedPtr & img2,
165-
const ImageMsg::ConstSharedPtr & img3,
166-
const ImageMsg::ConstSharedPtr & img4,
167-
const ImageMsg::ConstSharedPtr & img5,
168-
const ImageMsg::ConstSharedPtr & img6);
169-
170-
/**
171-
* @brief Callback functions for synchronized compressed images
172-
*/
173-
void syncCallback2Compressed(
174-
const CompressedImageMsg::ConstSharedPtr & img1, const CompressedImageMsg::ConstSharedPtr & img2);
175-
void syncCallback3Compressed(
176-
const CompressedImageMsg::ConstSharedPtr & img1,
177-
const CompressedImageMsg::ConstSharedPtr & img2,
178-
const CompressedImageMsg::ConstSharedPtr & img3);
179-
void syncCallback4Compressed(
180-
const CompressedImageMsg::ConstSharedPtr & img1,
181-
const CompressedImageMsg::ConstSharedPtr & img2,
182-
const CompressedImageMsg::ConstSharedPtr & img3,
183-
const CompressedImageMsg::ConstSharedPtr & img4);
184-
void syncCallback5Compressed(
185-
const CompressedImageMsg::ConstSharedPtr & img1,
186-
const CompressedImageMsg::ConstSharedPtr & img2,
187-
const CompressedImageMsg::ConstSharedPtr & img3,
188-
const CompressedImageMsg::ConstSharedPtr & img4,
189-
const CompressedImageMsg::ConstSharedPtr & img5);
190-
void syncCallback6Compressed(
191-
const CompressedImageMsg::ConstSharedPtr & img1,
192-
const CompressedImageMsg::ConstSharedPtr & img2,
193-
const CompressedImageMsg::ConstSharedPtr & img3,
194-
const CompressedImageMsg::ConstSharedPtr & img4,
195-
const CompressedImageMsg::ConstSharedPtr & img5,
196-
const CompressedImageMsg::ConstSharedPtr & img6);
197-
198112
/**
199113
* @brief Process synchronized images (statistics and custom logic)
200114
* @param timestamps Vector of synchronized timestamps from all cameras
@@ -204,31 +118,13 @@ class MultiCameraSyncNode : public rclcpp::Node
204118
// Parameters
205119
std::vector<std::string> camera_topics_;
206120
std::vector<std::string> camera_names_;
207-
std::vector<sensor_msgs::msg::Image::ConstSharedPtr> image_array;
208121
bool use_compressed_;
209122
double sync_tolerance_ms_;
210123
int queue_size_;
211-
bool publish_sync_info_;
212124

213125
// Subscribers
214-
std::vector<std::unique_ptr<ImageSubscriber>> image_subscribers_;
215-
std::vector<std::unique_ptr<CompressedImageSubscriber>> compressed_subscribers_;
216-
217-
// Synchronizers for raw images
218-
std::unique_ptr<message_filters::Synchronizer<ImageSyncPolicy2>> sync2_raw_;
219-
std::unique_ptr<message_filters::Synchronizer<ImageSyncPolicy3>> sync3_raw_;
220-
std::unique_ptr<message_filters::Synchronizer<ImageSyncPolicy4>> sync4_raw_;
221-
std::unique_ptr<message_filters::Synchronizer<ImageSyncPolicy5>> sync5_raw_;
222-
std::unique_ptr<message_filters::Synchronizer<ImageSyncPolicy6>> sync6_raw_;
223-
224-
// Synchronizers for compressed images
225-
std::unique_ptr<message_filters::Synchronizer<CompressedSyncPolicy2>> sync2_compressed_;
226-
std::unique_ptr<message_filters::Synchronizer<CompressedSyncPolicy3>> sync3_compressed_;
227-
std::unique_ptr<message_filters::Synchronizer<CompressedSyncPolicy4>> sync4_compressed_;
228-
std::unique_ptr<message_filters::Synchronizer<CompressedSyncPolicy5>> sync5_compressed_;
229-
std::unique_ptr<message_filters::Synchronizer<CompressedSyncPolicy6>> sync6_compressed_;
230-
231-
rclcpp::Publisher<sensor_msgs::msg::Image>::SharedPtr sync_info_pub_;
126+
std::vector<std::shared_ptr<ImageSubscriber>> image_subscribers_;
127+
std::vector<std::shared_ptr<CompressedImageSubscriber>> compressed_subscribers_;
232128

233129
// Publishers for multi-image messages
234130
rclcpp::Publisher<deep_msgs::msg::MultiImage>::SharedPtr multi_image_raw_pub_;
@@ -238,6 +134,34 @@ class MultiCameraSyncNode : public rclcpp::Node
238134
int64_t sync_count_;
239135
rclcpp::Time last_sync_time_;
240136
std::chrono::steady_clock::time_point start_time_;
137+
138+
struct ImageBuffer
139+
{
140+
std::map<uint64_t, ImageMsg::ConstSharedPtr> buffer;
141+
std::shared_ptr<std::mutex> mutex;
142+
143+
ImageBuffer()
144+
: mutex(std::make_shared<std::mutex>())
145+
{}
146+
};
147+
148+
struct CompressedImageBuffer
149+
{
150+
std::map<uint64_t, CompressedImageMsg::ConstSharedPtr> buffer;
151+
std::shared_ptr<std::mutex> mutex;
152+
153+
CompressedImageBuffer()
154+
: mutex(std::make_shared<std::mutex>())
155+
{}
156+
};
157+
158+
std::vector<ImageBuffer> raw_image_buffers_;
159+
std::vector<CompressedImageBuffer> compressed_image_buffers_;
160+
161+
void handleRawImageCallback(size_t camera_idx, const ImageMsg::ConstSharedPtr & msg);
162+
void handleCompressedImageCallback(size_t camera_idx, const CompressedImageMsg::ConstSharedPtr & msg);
163+
void tryPublishSyncedRawImages();
164+
void tryPublishSyncedCompressedImages();
241165
};
242166

243167
} // namespace camera_sync

deep_tools/camera_sync/package.xml

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,8 @@
22
<package format="3">
33
<name>camera_sync</name>
44
<version>0.1.0</version>
5-
<description>ROS2 CLI tool and nodes for ONNX model management and multi-camera synchronization</description>
6-
<maintainer email="hello@watonomous.ca">WATonomous</maintainer>
5+
<description>ROS2 node for multi-camera synchronization</description>
6+
<maintainer email="lereljic@watonomous.ca">Lereljic</maintainer>
77
<license>Apache 2.0</license>
88

99
<buildtool_depend>ament_cmake</buildtool_depend>
@@ -15,6 +15,7 @@
1515
<depend>message_filters</depend>
1616
<depend>image_transport</depend>
1717
<depend>deep_msgs</depend>
18+
<depend>class_loader</depend>
1819

1920

2021

0 commit comments

Comments
 (0)