Archive for the ‘Uncategorized’ Category.

Fractal Slippy Map in golang and LeafletJS

fractalmap

Recently I’ve been playing with golang and LeafletJS. As a small project I decided to knock together a fractal slippy map with a golang based map server which dynamically creates the fractal tile images. The whole thing can be reverse proxied via nginx to take the load off the server. The projects totals less than 200 lines of golang as JS and these are my design notes. You can see the final project here and grab the code on github here.

The HTML

The HTML is extremely simple, the map is a single div:

<div id="map" style="width: 100px; height: 100px; display: inline-block;"></div>

Which is then populated by LeafletJS as follows:

<script src="leaflet.js"></script>
<script>
  document.getElementById('map').style.width  = window.innerWidth-321 + "px";
  document.getElementById('map').style.height = window.innerHeight-20 + "px";
  
  var map = L.map('map').setView([-10, -360], 2);

  L.tileLayer('http://gu.pe/map/map/{z}/{x}/{y}.png', {
    maxZoom: 18,
    attribution: 'gu.pe',
    id: 'example'
  }).addTo(map);
</script>

The first couple of lines ensure that the map is sized to fill the whole window. The rest just initialises LeafletJS and tells it where to fetch map files from. Map tiles are just simple 256×256 png images.

The golang server

Both the static html and the dynamically generated tiles are served via golang. Here’s the main function that initializes everything:

func main() {
  http.HandleFunc("/map/", handler)
  http.Handle("/", httpgzip.NewHandler(http.FileServer(http.Dir("."))))
  http.ListenAndServe(":8080", nil)
}

I’m using the httpgzip package which allows golang to server serve gzip compressed content. This wraps the standard golang file server on line 3 above. A hander is registered on /map/ and this is where the png tile images are generated.

func handler(w http.ResponseWriter, r *http.Request) {

  // URLs here look like http://localhost:8080/map/13/4100/2724.png
  //                                               z  x    y

  tile_size   := 256
  tile_size_f := float64(256)

  // splits out the URL to get the x,y,z coordinates
  spliturl := strings.Split(r.URL.Path, "/")
  tile_zi, _ := strconv.Atoi(spliturl[2])
  tile_z := float64(tile_zi)
  tile_xi, _ := strconv.Atoi(spliturl[3])
  tile_x := float64(tile_xi)-1
  tile_yi, _ := strconv.Atoi(strings.Split(spliturl[4],".")[0])
  tile_y := float64(tile_yi)-1
  fmt.Printf("Input: %f %f %f\n", tile_z,tile_x,tile_y)

  w.Header().Set("Content-Type","image/png")

  myimage := image.NewRGBA(image.Rectangle{image.Point{0,0},image.Point{tile_size,tile_size}})

  // This loop just fills the image tile with fractal data
  for cx := 0; cx < tile_size; cx++ {
    for cy := 0; cy < tile_size; cy++ {

      cx_f := float64(cx)
      cy_f := float64(cy)

      i := complex128(complex(0,1))

      zoom := float64(math.Pow(2,float64(tile_z-2)))

      tile_range   := 1/zoom
      tile_start_x := 1/zoom + (tile_range*tile_x)
      tile_start_y := 1/zoom + (tile_range*tile_y)

      x := -2 + tile_start_x + (cx_f/tile_size_f)*tile_range
      y := -2 + tile_start_y + (cy_f/tile_size_f)*tile_range

      // x and y are now in the range ~-2 -> +2

      z := complex128(complex(x,0)) + complex128(complex(y,0))*complex128(i)

      c := complex(0.274,0.008)
      for n := 0; n < 100; n++ {
        z = z*z + complex128(c)
      }

      z = z *10
      ratio := float64(2 * (real(z)/2))
      r     := math.Max(0, float64(255*(ratio - 1)))
      b     := math.Max(0, float64(255*(1 - ratio)))
      g     := float64(255 - b - r)
      col := color.RGBA{uint8(r),uint8(g),uint8(b),255}
      myimage.Set(cx,cy,col)
    }
  }

  png.Encode(w, myimage)
}

The bulk of the code is related to the Julia set generation. PNGs are relatively easy to generate and serve in golang, and I previously wrote up my notes on doing that here. The code that splits out the URL is also a mess, I guess something like sscanf would have made a better job of this? However I’m not sure what the canonical way of doing this in golang is.

Serving server generated PNGs over HTTP in golang

Building on the PNG generation code. We can easily expand this to serve the content over HTTP.

The following example will serve content from the filesystem for everything but “/images”. This path will generate and send a random 100×100 PNG to the client.

package main

import (
    "github.com/daaku/go.httpgzip"
    "net/http"
    "image"
    "image/png"
    "image/color"
    "math/rand"
)

func handler(w http.ResponseWriter, r *http.Request) {
  myimage := image.NewRGBA(image.Rectangle{image.Point{0,0},image.Point{100,100}})

  // This loop just fills the image with random data
  for x := 0; x < 100; x++ {
    for y := 0; y < 100; y++ {
      c := color.RGBA{uint8(rand.Intn(255)),uint8(rand.Intn(255)),uint8(rand.Intn(255)),255}
      myimage.Set(x,y,c)
    }
  }

  png.Encode(w, myimage)
}

func main() {
  http.HandleFunc("/images", handler)  
  http.Handle("/", httpgzip.NewHandler(http.FileServer(http.Dir("."))))

  http.ListenAndServe(":8080", nil)
}

Creating a PNG image in golang

The following very simple example creates a PNG image file in golang. It first creates a Image structure and then populates this with random data.

A file is then creating using os.Create, this is used as a io.Writer to which golang’s PNG encoder in image/png writes the encoded PNG data via the png.Encode function.

package main

import (
    "image"
    "image/png"
    "image/color"
    "os"
    "math/rand"
)


func main() {

  myimage := image.NewRGBA(image.Rectangle{image.Point{0,0},image.Point{100,100}})

  // This loop just fills the image with random data
  for x := 0; x < 100; x++ {
    for y := 0; y < 100; y++ {
      c := color.RGBA{uint8(rand.Intn(255)),uint8(rand.Intn(255)),uint8(rand.Intn(255)),255}
      myimage.Set(x,y,c)
    }
  }

  myfile, _ := os.Create("test.png")

  png.Encode(myfile, myimage)
}

A short review of linear motion

This is a very short review of linear motion actuators and guides. This is I’m sure, far from complete. My hope is that people will comment and help fill out the information here.

In this post I want to address linear motion in terms of resolution, for nanoscale to millimeter scale and beyond (I know almost nothing beyond millimeter scale but would welcome contributions).

Nanoscale

I wont cover MEMS devices here, I’m rather interested in nanoscale resolution over millimeter travel. I have a short review of various piezo actuator types elsewhere.

Piezo actuators

Nanoscale resolution actuators are dominated by Piezos. Piezo electric materials directly convert electricity into motion and easily handle these kinds of tasks. In addition to this they provide high force.

Basic stacked actuators

These devices use multiple layers of Piezo electric material connected in parallel in a stack. They provide deflection in the micron range, in general 10s to 100s of microns.

They may be combined with a mechanical advantage to increase output force.

Inchworm actuators

Inchworms use piezo stacks to push a rod along. In this way they retain their nanoscale resolution, but vastly extend the travel of the system. Inchworms with 25mm travel and beyond are available and can be purchased for a few hundred dollars.

LEGS actuators

I strongly recommend you check out the video linked above, it’s awesome. LEGS (R) is a trademark of Piezomotor (R) I believe. They use a slightly different mechanism to the normal Inchworm, using bimorphic benders to walk along a shaft. Similarly with microstepping they can achieve nanometer resolution, and millimeters of travel.

legs

Magnetostrictive actuators

Magnetostrictive actuators have recently begun viable for nanoscale linear motion. These actuators use magnetostrictive materials (notably Terfenol-D) which when exposed to a magnetic field, change shape.

magnetstrictive

While nanometer precision can be achieved, magnetostrictive actuators exhibit hysteresis and non-linearity. While this issues are also present in stacked Piezo actuators they are mitigated against in Inchworm and LEGs actuators.

Electrostatic actuators

A far am I’m aware these have never been used commercially, but have been proposed as academic research tools.

Micron scale

Nanoscale actuators are dominated by DC driven Piezos largely because of their inherent precision and low vibration characteristics. Once we reach the micron scale things get much easier as we can begin to use motors again. A typical low force application at this scale would be a motorized microscope stage.

Vibration characteristics are again a concern here, and will need to be considered carefully.

Coreless DC motors

AMH-13

Coreless DC motors, coupled with a leadscrew are often employed for micron scale actuation. Unlike normal motors coreless motors have no Iron core to confirm the magnetic field. This lack of a core allows the magnetic field to be built up and broken down much more quickly resulting in faster and more precise acceleration. Chuo Seiki sell these with gearing and a leadscrew in a micrometer style configuration, and they often appear to be used as “motorised micrometers”.

I have a used Chuo Seiki actuator on order and will update here when it appears.

Steppers

Stepper motors are also employed for micron scale resolution actuation. In particular 5-phase steppers are favored here. oriental motors have a great write-up on why 5-phase motors are better, but overall it comes down to their reduced vibration:

vibration_steppers

They should of course also be operated in microstepping mode. Oriental motors appear to supply the majority of 5-phase steppers for micron resolution actuation. Again this are commonly employed for use as XYZ microscope stages or semiconductor fab applications. When coupled with a leadscrew and rail guides, micron resolution can be achieved. An example is again the Chuo Seiki stage. I have again purchased one of these second hand and will be updating with my experiences here.

Micron resolution can also be achieved here with 2-phase steppers, as can be seen in commodity electronics such as DVD players where the track spacing is on the order of 1micron. However the accuracy is likely low.

Millimeter scale and beyond

Steppers

At the millimeter scale (~100micron) things appear to be much easier and commodity 2-phase steppers coupled with a linear guide and lead screw are generally employed. Of course in commodity electrics belt driven systems as also used.

Servos

Servos have a number of advantages, in particular for CNC applications. Servos are able to operate at higher speeds. Because of their inherent feedback there is little potential for “missed steps”. And as servos do not operate a step at a time, their vibrational characteristics are different (and generally better) than those of steppers.