I’ve recently managed to 3D print an apriltag with the help of folks on slack. Since there was some interest in how it worked, I wrote what I did here.
Apriltags consist of two colors, black and white. So I need the printer to be able to do that (it needs to have two heads). The printer I have access to is the Ultimaker 3 extended
. It needs two separate stl
files, one for each color. The two files are then merged in the slicer program (Cura
in my case). So first I needed to create these.stl
files.
Here I save two stl files, one for each color, and plot the result just to be sure it looks right. To create the apriltag itself I use the excellent AprilTags.jl package made by the good folks at JuliaRobotics
. They have been instrumental in this whole (and more) process! Huge thanks to them!!! For building the meshes and plotting them I used Makie, so convenient.
using GLMakie, AprilTags, GeometryBasics
function get_meshes(tag, color, scale)
meshes = GeometryBasics.Mesh[]
for (xy, c) in pairs(IndexCartesian(), tag)
if c == color # include only white pixels
x, y = Tuple(xy)
cube = Rect3D(Vec3f0(scale*x, scale*y, 0), Vec3f0(scale))
push!(meshes, triangle_mesh(cube))
end
end
merge(meshes)
end
fig = Figure()
id = 9
tag = getAprilTagImage(id) # a 10×10 grayscale image of the tag
colors = Dict("black" => zero(tag[1]), "white" => one(tag[1]))
for (i, (k, c)) in enumerate(colors)
merged = get_meshes(tag, c, 2)
ax = Axis3(fig[i, 1], aspect = :data, title = k)
mesh!(ax, merged, color = c)
save("$id $k.stl", merged) # "worked" without MeshIO?
end
I then tested the printed result by photographing the tag with my cellphone. Again using AprilTags.jl
:
using AprilTags, FileIO
img = load("img.jpg")
detector = AprilTagDetector()
tags = detector(img)
freeDetector!(detector)
tag = only(tags)
drawTagBox!(img, tag)
Which looks like this (you’ll have to really zoom in on the tag to see the superimposed tag-box drawn on it):
So this whole thing worked really well. We’ll be printing these tags to mount on dung beetles for pose tracking.