Skip to content

Commit 57918a2

Browse files
committed
Add copy utilities for apriltag_detection_t and apriltag_detector_t
- Add apriltag_detection_copy() and apriltag_detections_copy() to deep copy detection results including the matd_t* H homography matrix. - Add apriltag_detector_copy() to clone detector configuration by copying all scalar fields and reinitializing pointer fields (tag_families, tp, wp) to independent default values to avoid shared ownership and double-free issues on destruction.
1 parent 02674c1 commit 57918a2

File tree

3 files changed

+72
-0
lines changed

3 files changed

+72
-0
lines changed

README.md

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -193,6 +193,14 @@ Note: The tag size should not be measured from the outside of the tag. The tag s
193193
### Coordinate System
194194
The coordinate system has the origin at the camera center. The z-axis points from the camera center out the camera lens. The x-axis is to the right in the image taken by the camera, and y is down. The tag's coordinate frame is centered at the center of the tag. From the viewer's perspective, the x-axis is to the right, y-axis down, and z-axis is into the tag.
195195

196+
Utility Functions
197+
=================
198+
AprilTag 3 now includes helper functions for deep-copying structures, which is essential for multi-threaded applications or when you need to store detections beyond the detector's lifecycle.
199+
200+
* `apriltag_detector_copy(td)`: Creates a clone of the detector configuration.
201+
* `apriltag_detections_copy(detections)`: Returns a new `zarray_t` with deep copies of all `apriltag_detection_t` objects.
202+
* `apriltag_detection_copy(src, dst)`: Performs a deep copy of a single detection into an existing structure.
203+
196204
Debugging
197205
=========
198206

apriltag.c

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1496,3 +1496,58 @@ image_u8_t *apriltag_to_image(apriltag_family_t *fam, uint32_t idx)
14961496
}
14971497
return im;
14981498
}
1499+
1500+
void apriltag_detection_copy(apriltag_detection_t* src, apriltag_detection_t* dst)
1501+
{
1502+
assert(src != NULL);
1503+
assert(dst != NULL);
1504+
1505+
if (dst->H) {
1506+
matd_destroy(dst->H);
1507+
}
1508+
dst->H = matd_copy(src->H);
1509+
1510+
dst->c[0] = src->c[0];
1511+
dst->c[1] = src->c[1];
1512+
1513+
for (int i = 0; i < 4; i++) {
1514+
for (int j = 0; j < 2; j++) {
1515+
dst->p[i][j] = src->p[i][j];
1516+
}
1517+
}
1518+
1519+
dst->id = src->id;
1520+
dst->family = src->family;
1521+
dst->hamming = src->hamming;
1522+
dst->decision_margin = src->decision_margin;
1523+
}
1524+
1525+
zarray_t* apriltag_detections_copy(zarray_t* detections)
1526+
{
1527+
zarray_t* detections_copy = zarray_create(sizeof(apriltag_detection_t*));
1528+
for (int i = 0; i < zarray_size(detections); i++) {
1529+
apriltag_detection_t* det;
1530+
zarray_get(detections, i, &det);
1531+
1532+
apriltag_detection_t* det_copy = (apriltag_detection_t*)calloc(1, sizeof(apriltag_detection_t));
1533+
apriltag_detection_copy(det, det_copy);
1534+
zarray_add(detections_copy, &det_copy);
1535+
}
1536+
1537+
return detections_copy;
1538+
}
1539+
1540+
apriltag_detector_t *apriltag_detector_copy(apriltag_detector_t *src)
1541+
{
1542+
apriltag_detector_t *dst = (apriltag_detector_t *)malloc(sizeof(apriltag_detector_t));
1543+
// Shallow copy of all scalar fields
1544+
*dst = *src;
1545+
1546+
// Reinitialize pointer fields to independent default values to avoid shared ownership and double-free issues
1547+
dst->tag_families = zarray_create(sizeof(apriltag_family_t *));
1548+
dst->tp = timeprofile_create();
1549+
dst->wp = workerpool_create(src->nthreads);
1550+
1551+
return dst;
1552+
}
1553+

apriltag.h

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -267,6 +267,15 @@ void apriltag_detection_destroy(apriltag_detection_t *det);
267267
// destroys the array AND the detections within it.
268268
void apriltag_detections_destroy(zarray_t *detections);
269269

270+
// Performs a deep copy of an AprilTag detection structure from a source to a destination.
271+
void apriltag_detection_copy(apriltag_detection_t* src, apriltag_detection_t* dst);
272+
273+
// Creates a complete deep copy of a list of AprilTag detections.
274+
zarray_t* apriltag_detections_copy(zarray_t* detections);
275+
276+
// Clones an AprilTag detector configuration into a new instance.
277+
apriltag_detector_t *apriltag_detector_copy(apriltag_detector_t *src);
278+
270279
// Renders the apriltag.
271280
// Caller is responsible for calling image_u8_destroy on the image
272281
image_u8_t *apriltag_to_image(apriltag_family_t *fam, uint32_t idx);

0 commit comments

Comments
 (0)