Instantly share code, notes, and snippets.
nmichaud/apriltags.folk Secret
Last active
October 22, 2023 19:48
-
Star
0
(0)
You must be signed in to star a gist -
Fork
0
(0)
You must be signed in to fork a gist
-
-
Save nmichaud/2a43c15a7c1810170c88e4ff37625239 to your computer and use it in GitHub Desktop.
Dual tags
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| if {$::isLaptop} return | |
| set tagfamily "tag36h11" | |
| # Plain detector. Runs on entire camera frame. | |
| set mainDetectorProcess [Start process { | |
| source pi/AprilTags.tcl | |
| Wish $::thisProcess receives statements like \ | |
| [list /someone/ claims the camera frame is /grayFrame/ at /timestamp/] | |
| Wish $::thisProcess shares statements like \ | |
| [list /someone/ claims /process/ detects paired tags /tags/ at /timestamp/ in time /aprilTime/] | |
| set detector [AprilTags new $tagfamily] | |
| When the camera frame is /grayFrame/ at /timestamp/ { | |
| set aprilTime [time { | |
| set tags [$detector detect $grayFrame] | |
| }] | |
| Claim $::thisProcess detects paired tags $tags at $timestamp in time $aprilTime | |
| } | |
| }] |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| proc intersect {a1 b1 a2 b2} { | |
| set as $a1 | |
| set ad [::vec2 sub $b1 $as] | |
| set s [expr {sqrt(pow([lindex $ad 0], 2) + pow([lindex $ad 1], 2))}] | |
| set ad [::vec2 scale $ad $s] | |
| set bs $a2 | |
| set bd [::vec2 sub $b2 $bs] | |
| set s [expr {sqrt(pow([lindex $bd 0], 2) + pow([lindex $bd 1], 2))}] | |
| set bd [::vec2 scale $bd $s] | |
| set det [expr {([lindex $bd 0] * [lindex $ad 1]) - ([lindex $bd 1] * [lindex $ad 0])}] | |
| lassign [::vec2 sub $bs $as] dx dy | |
| set u [expr {(($dy * [lindex $bd 0]) - ($dx * [lindex $bd 1])) / $det}] | |
| ::vec2 add $as [::vec2 scale $ad $u] | |
| } | |
| proc order_tags {x1 x2} { | |
| # determine which tag is on top (relative to the projection axis) | |
| lassign [dict get $x1 corners] a1 b1 c1 d1 | |
| lassign [dict get $x2 corners] a2 b2 c2 d2 | |
| set theta [dict get $x1 angle] | |
| set as [::vec2 sub $a1 $a1] | |
| #set ad [::vec2 sub $d1 $a1] | |
| set bs [::vec2 sub $a2 $a1] | |
| #set bd [::vec2 sub $d2 $a1] | |
| lassign [::vec2 sub $a2 $a1] x y | |
| set bx [expr {$x*cos($theta) - $y*sin($theta)}] | |
| set by [expr {$y*cos($theta) + $x*sin($theta)}] | |
| if {$by > 0} { | |
| return [list $x1 $x2] | |
| } else { | |
| return [list $x2 $x1] | |
| } | |
| } | |
| When /someone/ detects paired tags /tags/ at /ts/ in time /t/ { | |
| try { | |
| for { set i 0 } { $i < [llength $tags] } { incr i 1 } { | |
| set x1 [lindex $tags $i] | |
| set x2 [lindex $tags [expr {$i + 1}]] | |
| set id1 [dict get $x1 id] | |
| # Skip if we don't see this 2 tags with the same id | |
| if {$x2 == ""} { | |
| continue | |
| } else { | |
| set id2 [dict get $x2 id] | |
| if {$id1 != $id2} { | |
| continue | |
| } | |
| } | |
| set i [expr {$i + 1}] | |
| lassign [order_tags $x1 $x2] top bot | |
| lassign [dict get $top corners] a1 b1 c1 d1 | |
| lassign [dict get $bot corners] a2 b2 c2 d2 | |
| set b $d2 | |
| set d $b1 | |
| # calculate opposite corners | |
| set c [intersect $a1 $b1 $a2 $d2] | |
| set a [intersect $c1 $b1 $c2 $d2] | |
| Claim page [dict get $top id] has corners [list $a $b $c $d] | |
| } | |
| } on error err { | |
| puts stderr "Warning: tag-regions ($err)." | |
| } | |
| } | |
| When (non-capturing) page /id/ has corners /corners/ { | |
| set tagCorners [lmap p $corners {::cameraToProjector $p}] | |
| set vecBottom [sub [lindex $tagCorners 1] [lindex $tagCorners 0]] | |
| set vecRight [sub [lindex $tagCorners 2] [lindex $tagCorners 1]] | |
| set corners $tagCorners | |
| #foreach corner $corners v [list a b c d] { Display::text {*}$corner 1 "$v" 0 } | |
| set edges [list] | |
| for {set i 0} {$i < [llength $corners]} {incr i} { | |
| if {$i > 0} { lappend edges [list [expr {$i - 1}] $i] } | |
| } | |
| lappend edges [list [expr {[llength $corners] - 1}] 0] | |
| set angle [expr {atan2(-[lindex $vecBottom 1], [lindex $vecBottom 0])}] | |
| set region [region create $corners $edges $angle] | |
| Claim "page-$id" has region $region | |
| Claim page "page-$id" has a program | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment