3D printing apriltags

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))

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?

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)

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.