# 3D printing apriltags

**URL:** <https://discourse.julialang.org/t/3d-printing-apriltags/73128>\
**Category:** General Usage\
**Created:** [December 15, 2021, 9:55am UTC](https://discourse.julialang.org/t/3d-printing-apriltags/73128 "2021-12-15T09:55:04Z")\
**Posts on this page:** 1\
**Page:** 1

<div class="post-metadata">

**Author:** ![yakir12](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/yakir12/32/297_2.png) [@yakir12](https://discourse.julialang.org/u/yakir12)\
**Post date:** [December 15, 2021, 9:55am UTC](https://discourse.julialang.org/t/3d-printing-apriltags/73128/1 "2021-12-15T09:55:04Z")

</div>

I’ve recently managed to 3D print an [apriltag](https://april.eecs.umich.edu/software/apriltag.html) 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](https://github.com/JuliaRobotics/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.

```julia
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`:

```julia
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):

 ![detected](https://global.discourse-cdn.com/julialang/original/3X/d/a/da472fbec2a36b77cdf4c1a8f0534f85868672ac.jpeg)

So this whole thing worked really well. We’ll be printing these tags to mount on dung beetles for pose tracking.
