···264264 struct xrt_frame_sink cam_sinks[XRT_TRACKING_MAX_SLAM_CAMS]; //!< Sends camera frames to the SLAM system
265265 struct xrt_imu_sink imu_sink = {}; //!< Sends imu samples to the SLAM system
266266 struct xrt_pose_sink gt_sink = {}; //!< Register groundtruth trajectory for stats
267267+ struct xrt_hand_masks_sink hand_masks_sink = {}; //!< Register latest masks to ignore
268268+267269 bool submit; //!< Whether to submit data pushed to sinks to the SLAM tracker
268270 uint32_t cam_count; //!< Number of cameras used for tracking
269271···275277 struct openvr_tracker *ovr_tracker; //!< OpenVR lighthouse tracker
276278277279 // Used mainly for checking that the timestamps come in order
278278- timepoint_ns last_imu_ts; //!< Last received IMU sample timestamp
279279- vector<timepoint_ns> last_cam_ts; //!< Last received image timestamp per cam
280280+ timepoint_ns last_imu_ts; //!< Last received IMU sample timestamp
281281+ vector<timepoint_ns> last_cam_ts; //!< Last received image timestamp per cam
282282+ struct xrt_hand_masks_sample last_hand_masks; //!< Last received hand masks info
283283+ Mutex last_hand_masks_mutex; //!< Mutex for @ref last_hand_masks
280284281285 // Prediction
282286···12731277 xrt_sink_push_pose(t.euroc_recorder->gt, sample);
12741278}
1275127912801280+//! Receive and register masks to use in the next image
12811281+extern "C" void
12821282+t_slam_hand_mask_sink_push(struct xrt_hand_masks_sink *sink, struct xrt_hand_masks_sample *hand_masks)
12831283+{
12841284+ XRT_TRACE_MARKER();
12851285+12861286+ auto &t = *container_of(sink, TrackerSlam, hand_masks_sink);
12871287+ unique_lock lock(t.last_hand_masks_mutex);
12881288+ t.last_hand_masks = *hand_masks;
12891289+}
12901290+12761291//! Receive and send IMU samples to the external SLAM system
12771292extern "C" void
12781293t_slam_receive_imu(struct xrt_imu_sink *sink, struct xrt_imu_sample *s)
···13651380 default: SLAM_ERROR("Unknown image format"); return;
13661381 }
1367138213681368- // TODO masks
13831383+ {
13841384+ unique_lock lock(t.last_hand_masks_mutex);
13851385+ for (auto &view : t.last_hand_masks.views) {
13861386+ if (!view.enabled) {
13871387+ continue;
13881388+ }
13891389+13901390+ for (auto &hand : view.hands) {
13911391+ if (!hand.enabled) {
13921392+ continue;
13931393+ }
13941394+ // TODO@mateosss: add_mask(hand.rect);
13951395+ }
13961396+ };
13971397+ }
1369139813701399 {
13711400 XRT_TRACE_IDENT(slam_push);
···15511580 t.gt_sink.push_pose = t_slam_gt_sink_push;
15521581 t.sinks.gt = &t.gt_sink;
1553158215831583+ t.hand_masks_sink.push_hand_masks = t_slam_hand_mask_sink_push;
15841584+ t.sinks.hand_masks = &t.hand_masks_sink;
15851585+15541586 t.submit = config->submit_from_start;
15551587 t.cam_count = config->cam_count;
15561588···1563159515641596 t.last_imu_ts = INT64_MIN;
15651597 t.last_cam_ts = vector<timepoint_ns>(t.cam_count, INT64_MIN);
15981598+ t.last_hand_masks = xrt_hand_masks_sample{};
1566159915671600 t.pred_type = config->prediction;
15681601
+35
src/xrt/include/xrt/xrt_tracking.h
···140140};
141141142142/*!
143143+ * Masks (bounding boxes) of different hands from current views
144144+ */
145145+struct xrt_hand_masks_sample
146146+{
147147+ struct xrt_hand_masks_sample_camera
148148+ {
149149+ bool enabled; //!< Whether any hand mask for this camera is being reported
150150+ struct xrt_hand_masks_sample_hand
151151+ {
152152+ bool enabled; //!< Whether a mask for this hand is being reported
153153+ struct xrt_rect rect; //!< The mask itself in pixel coordinates
154154+ } hands[2];
155155+ } views[XRT_TRACKING_MAX_SLAM_CAMS];
156156+};
157157+158158+/*!
143159 * @interface xrt_imu_sink
144160 *
145161 * An object to send IMU samples to.
···168184};
169185170186/*!
187187+ * @interface xrt_hand_masks_sink
188188+ *
189189+ * An object to push @ref xrt_hand_masks_sample to.
190190+ */
191191+struct xrt_hand_masks_sink
192192+{
193193+ void (*push_hand_masks)(struct xrt_hand_masks_sink *, struct xrt_hand_masks_sample *hand_masks);
194194+};
195195+196196+197197+/*!
171198 * Container of pointers to sinks that could be used for a SLAM system. Sinks
172199 * are considered disabled if they are null.
173200 */
···177204 struct xrt_frame_sink *cams[XRT_TRACKING_MAX_SLAM_CAMS];
178205 struct xrt_imu_sink *imu;
179206 struct xrt_pose_sink *gt; //!< Can receive ground truth poses if available
207207+ struct xrt_hand_masks_sink *hand_masks;
180208};
181209182210/*!
···291319xrt_sink_push_pose(struct xrt_pose_sink *sink, struct xrt_pose_sample *sample)
292320{
293321 sink->push_pose(sink, sample);
322322+}
323323+324324+//! @public @memberof xrt_hand_masks_sink
325325+static inline void
326326+xrt_sink_push_hand_masks(struct xrt_hand_masks_sink *sink, struct xrt_hand_masks_sample *hand_masks)
327327+{
328328+ sink->push_hand_masks(sink, hand_masks);
294329}
295330296331//! @public @memberof xrt_tracked_psmv