syntax-highlighter

Friday, August 10, 2012

Optical Tomography Setup

As noted in a previous post, my Stochastic Tomography paper was accepted to SIGGRAPH 2012.  Last Tuesday I was in Los Angeles for the conference to present the paper, including present the synopsis in the conference 'fast-forward' to an appallingly large audience.  The photo below shows the seating but during the actual event it was standing room only. 


A bit nerve-wracking to say the least.  However it went well and after presenting my main talk to a MUCH smaller crowd, I'd like to post some photos of the setup that we used for the paper.  I should point out that this project actually did not contribute much to the capture setup, this was previously in place from work done by Borislav Trifonov, Michael Krimerman, Brad Atcheson, Derek Bradley and a slew of others.  My work on this paper focused on the algorithms primarily, but I thought people might be interested in a quick overview of the tomography capture apparatus.

The goal of the paper was to build 3D animated models of mixing liquids from multiview video.  To accomplish this, we used an array of roughly 16 Hi-Def Sony camcorders arranged in a semi-circle around our capture volume to record video streams of the two fluids mixing.


You can see the cameras in the photo above, all focused on the capture volume which is inside the glass cylinder.  Each of these records a video of the mixing process, producing 16 streams of video that look more or less like the photo shown below:


You can see one of the cameras peeking out at the right side of the frame.  The cameras are controlled by an Arduino based box that talks to each camcorder using the SONY LANC protocol.  This is an unpublished protocol used by SONY editing consoles, however it has been reverse-engineered by others to allow people to control SONY equipment.  We implemented this protocol on an Arduino, which allows us to start all the cameras recording, turn them on and off as arrays, switch them between photo and video mode and so on.  Unfortunately we can't easily set the exposure levels, transfer files to and from the device, instead we have to painstakingly do this by hand through the on-camera menus, which is error-prone and time-consuming.

The two fluids we use are water, for the clear liquid, and Fluoroscein-Sodium fluorescing dye for the mixing liquid.  This fluorescent dye is available in a powder that is soluble in water, which allows us to perform several types of capture.  The image above is dye powder dropped onto the surface of the water, this mixes with the water and is slightly denser, forming the Rayleigh-Taylor mixing process you see in that shot.  We can also pre-mix the dye powder and simple pour or inject it into the domain, this was the process used for the following two captures that were used in the paper.



This shows an unstable vortex propaging downwards, leaving a complex wake.  I recommend watching in high-def (720p or 1080p).  The next is alcohol mixed with the dye powder, injected into the cylinder from the bottom.  Since alcohol is less dense than water, it rises under buoyancy, mixing as it goes.



In the video above you can see a laminar to turbulent transition as well as lots of complex eddies that form as part of the mixing process.

The captures are illuminated with a set of white LED concert strobe panels.  These panels serve two purposes. First they let us get LOTS of light into the scene in a controlled fashion.  Second we actually use a strobed illumination at about 30Hz to optically synchronize the cameras and remove rolling-shutted shear effects.

All captures start in darkness so we can tell the time offset from the start of the video to the first frame where there is significant illumination.  In fact we can do better than alignment to a single frame, since with the rolling shutter used by these cameras, we can actually determine the first scanline that is exposed.  Using a 30Hz illumination pattern, we can also determine the exposure setting of the camera by looking for the last scanline before the light goes off again.

We then have a rolling shutter compensation program that scans through each video and reassembles a new video from the exposed and dark scanlines.  The result is a set of videos that are optically synchronized and that have minimal shearing introduced.

This gives us a set of input data, however we also need to perform some geometric calibration of the scene in order to know from what angle each video was recorded and to be able to obtain the ray inside of the capture volume that corresponds to every observed pixel.

To do this, we use an optical calibration library called CalTag that detects self-identifying marker patterns similar to QR codes in images.  We print a calibration target on overheard transparencies and mount this pattern to a 3D printed calibration jig that is placed in the glass cylinder.


This jig fits tightly in the cylinder and is registered with a set of detents that fit into recesses in a registration plate that is glued to the inside of the capture cylinder.  The marker pattern that you see in the photo above is also registered to a set of registration tabs.  We have a calibrated pattern on the front of the target as shown above, but also on the back.

When a camera takes an image of this jig after placing it into the capture domain (filled with water), an image similar to the following is obtained, although generally with far less blur due to condensation.


CalTag can then give us the corners of the marker patterns, which can be interpolated to associate with every image pixel, the corresponding 3D point on the calibration target that it 'sees'.  We then rotate the target 180 degrees to face away from the camera and take a picture of an identical and carefully aligned target on the back side of the jig, giving another 3D point for each pixel.  Connecting the points gives a ray in 3D space inside the cylinder, without having to account for any optical interactions between the interior liquid and cylinder.

We do this for every camera, by mounting the capture domain on a rotation stage, which is again controlled by an Arduino.  An automated calibration procedure rotates the stage and triggers each camera to image the front calibration plane, then rotates an additional 180 degrees to repeat the process.  The whole mess is controlled by a python script using pySerial, including the strobes, the rotation stage and the embedded camera controller.

This gives us the needed calibration data to express our scene as a tomographic inverse problem.  Here we look for the scene content that would reproduce the measurements (videos) we obtained, given a physical model for the scene.  In this capture case, the scene is simply emissivity adding up along a ray-path, so we get a linear inverse problem, that we solve using our new Stochastic Tomography algorithm.  The result is volumetric 3D fields that you can animate, inspect and slice through and re-render however you like, as seen below in the submission video.



Stochastic Tomography and its Applications in 3D Imaging of Mixing Fluids from al. et Hullin et al. on Vimeo.

3-Axis CNC Controller

In a previous post, I showed the single axis stepper driver boards that I sent out to be made by OSH Park. These seemed to be electrically fine, although it was tricky to properly test without the connectors and other components.  After a quick order from DigiKey, I had the bits I needed.


I'm pleased to say that these work as expected, allowing the microstep mode to be chosen by DIP switch, breaking out all inputs and outputs with screw terminals, and providing the connections needed for high and low limit switches.  I've assembled three of these and screwed them to a piece of MDF to serve as the basis for a 3-Axis CNC controller board based on an Arduino Uno and GRBL.






The start of this board is shown above. Before it's complete I need to add the power connections for the high-power side, along with the limit switches.  I have the GRBL firmware flashed onto the Arduino and have connected a few motors to this setup and everything works great!


Shown below is a closeup of the boards.  The screw terminals in the front connect the limit switches for the high and low endstops.  These have pulldown resistors and are connected to two of the screw-terminal positions on the logic side of the board (the two un-wired stops).  The remaining pulldown resistors are connected to the microstep selection pins, which are set by the red DIP switch.  On the right side of the board are the motor connections (the 4-position terminal block) and the motor power connections (the two position terminals).  All connections are with 3.5mm terminal blocks, which actually meet the power requirements for multi-amp 24V operation.  They also allow multiple connections to be made which allows the daisy-chain type wiring shown above.  The low-power side also has these connections since even though they are not needed it's nice to only need one screwdriver to do the wiring.

I'm quite pleased with my first attempt at getting a board made.  It worked first try, the quality of the boards is excellent and I think these drivers can form the basis of a good many other projects.

Sunday, July 29, 2012

Prusa Build III

In the previous posts you can see the assembly of my Makerfarm Prusa up to the nearly complete frame.


I then installed the heated bed, electronics and extuder, making it look much more like a Reprap.  These were pretty simply assemblies, so I didn't bother taking progress photos.  The result is the hot-mess of wires and cable ties you see above.

Then the all-important first-turning-on, where you hope that you haven't connected something wrong and end up releasing the magic blue smoke that makes electronics go.  Amazingly, no smoke.  Installing the firmware, I had to invert a few axes in the configuration as well as recompute the mm-per-step, since I had used the SAE threaded rods rather than the M8.  All went pretty smoothly.

Finally it became time to test the extruder.  Heating it to 225, for ABS, I clicked 'extrude' in pronterface.  It worked great for a moment, then jammed, started skipping and chewed almost all the way through the filament.  So I increased the preload on the extruder: same result. So I increased the temperature: same result.  So I increased the current to the extruder stepper: same result.

At this point I was running out of ideas, so I piled the whole thing in the car and took it down to VHS.  There I asked the resident printer expert to take a look.  He spent some time looking at it, flipped my Y-axis mounts to give me more build-volume, disassembled the extruder, added thermal paste, but still couldn't figure out what was wrong.

So I contacted Colin from Makerfarm.  Within about thirty minute he had written back saying that he thought the issue might be related to running the extruder too quickly.  This made sense given the symptoms, good extrusion intially, followed by jamming shortly after.  So I dropped the extrusion rate from 300 mm/min (!) to the suggested 30 mm/min, and it worked perfectly!  I then tested to see how fast it could go, up to about 150 mm/min without problem.

So then it was time to start printing.  I could not get the prints to stick and didn't have Kapton tape.  I used some painters tape, connected the heated bed and tried again and got the following, encouraging result:






It came unstuck during the print, but I was pleased to see something resembling the box that I had tried to print.  So I retensioned the X-axis belt and tried again:





Much better, actually pretty good.  Tweaking some settings in Skeinforge improved this, specifically the flow-rate parameters, which I found produce the best prints when set to about 0.8-0.9.  So I tried a more challenging print, from my gear-generation script:




That actually looks pretty darn good!  As good as the Makerbot Thing-o-matic prints from VHS, if not better!  There are some blobs that I have to deal with, particularly where contours start and end.   So overall, as it stands, the printer has gone from left to right:





Overall, a pretty good improvement.  I will continue to try to improve the print quality, hopefully this will become a useful prototyping tool for future projects!



Prusa Build II

The Makerfarm Prusa kit comes with pretty much everything you need to assemble a Reprap, save for motors and power supply.  It also has excellent instructions for every step of the build process, which make assembly a straightforward, if time-consuming, process.

My previous post has the unboxing.  Starting to assemble, I began as everyone does, by assembling the triangles.  This was followed by realizing that I had an excess of zeal and a deficit of care. Turns out I had used the short rods where I needed the long rods. Whoops!  So I disassembled the triangles, and reassembled them:



You can see the PDF build instructions on the computer screen, every step of the way is well described in text and supplemented with clear, helpful photos.  Also to the left are the Y axis mounts, shown assembled below:


These are quickly bolted to the triangles pictured above to form the frame:


Sticking out at the top are the Z-axis motor mounts, and the bits at the bottom are the Z-stabilizers.  At this point, the Y-axis can be installed.  This comes in pretty snazzy laser-cut acrylic:





In the photo above, the Y-axis is installed with motor.  It is incredibly annoying to tension the Y-axis belt and there is plenty of room for a custom part that would make this easy.  However, I digress.


The next step was assembling the X-axis. Here you see the X motor mount and X idler assembled. Apologies for the blurry photos, but you only build this once, and I am NOT taking it apart to get a sharp shot.

With the X-axis ready to go, the Z-axis motors and leadscrews have to be installed to support the X-axis:





This was also incredibly fiddly for no good reason. Why exactly do the upper bracket of the triangle and the Z-motor mount need to be distinct printed parts? Why not install the motors BEFORE assembling the frame, when it's easy, instead of when stuff is upside down, when it's not?  Why are the couplers so freaking fidgety, when they could be a simple C-clamp? It's not like they're actually balanced anyway? But I digress.

In a secret step that I did not even have to perform, the X-axis magically placed itself on the Z-axis leadscrews, leaving me with something that looked distinctly like a Reprap:




Here you can see the close-up view of the Z-axis idler, and shown below is the whole frame, with the additional heated-bed mounting plate installed.  Looks pretty sweet, if I do say so myself:


At this point I decided to call it a day.  A few missteps led to this taking nearly 9 full hours, alignment is finicky, nuts are dropped and a lack of absolute care leads to parts being installed flipped.  In the next post, installation of the extruder, heated bed and early prints!

Prusa Build I

Someone recently licensed the mathematical expression parser I've written about before.  The license fee, combined with some additional features that I added for their application, summed to a not insignificant amount.  Although I'm a poor graduate student, I thought that I should reinvest this money in my hobbies since it effectively fell in my lap as a result of my hobbies.  I decided to buy a Prusa Mendel after all of about 10 minutes of thought.  I had looked at other 3D printers before, e.g. printrbot, solidoodle, and so on, all of which looked attractive, but they had massive leadtimes and crazy-expensive shipping options to Canada.  UPS? Nuts to that! To EBay, and the Makerfarm Prusa kit, for an impulse buy!

Immediately after confirming payment, I regretted my decision. Perhaps I should have researched my options better, been patient with shipping or bought from a more established outfit. Spoiler Alert: My fears were unwarranted, it was an excellent choice and I heartily recommend the Makerfarm Prusa kit.

Approximately ten days later a parcel pickup notice was on my door and after a jaunt to the local post-office, had this box on my coffee table. Opening the box, I spread out everything on the table to take an inventory of what was there:


Note that the motors are my own.  I immediately opened the printed parts bags to see what the quality was like, and was pleasantly surprised to see that it was excellent.


There were two casualties in shipping however.  Two of the retaining legs for the linear bearings on (what I would learn was called) the X-carriage had cracked off.  However a bit of ABS plumbing glue had that fixed in no time.

It was at this point that I looked at the shipping notice and realized that I had in fact bought the metric kit, when I had intended to buy the SAE kit.  I was horrified: it is nearly impossible to source M8 threaded rod in Vancouver, and if you can find it, you will pay through the nose.  Plus I already had a bunch of 5/16-18 threaded rod.

Luckily I already had 8mm precision linear shafting from the ongoing CNC project, and realized that 5/16 of an inch is actually 7.9375mm. In other words all the threaded rod would fit, with slop of about 6 thou. But the prints are nowhere near this accurate, so in fact the cheap, readily available and on-hand 5/16 rod would work just fine, I would just need some appropriate nuts.  Which cost about $5.

Next post: Assembly.

Friday, July 27, 2012

A4988 Single Axis Carrier Board

I recently ordered some simple boards from OSH Park.  These are single-axis versions of my 3-axis carrier board for the Pololu A4988 stepper carriers and (will) include pulldown resistors for the microstepping pins (which can be set using DIP switches), as well power and pull-down resistors for high- and low-limit switches.  All connections are made using 3.5mm screw terminals and the boards have mounting holes for more permanent installation.  They also feature a diode for reverse voltage protection on the logic supply (but not on the motor supply).



A quick test seems to indicate that the boards are electrically sound, although I have yet to fully populate one and test it fully.  If they work properly, I plan to fix a silkscreen error where the logic supply voltage and ground connections are unlabeled.  I also plan to break out the enable pin on the driver and the large capacitor across the motor supply suggested by the Pololu site.  When I'm content with how the boards work, I'll release the Eagle files.

Sunday, July 15, 2012

Sample Code for atmega328p Serial Communication

Nothing special, just a bit of sample code for serial communications with the Atmega328p.  It took a bit of hunting to find code that worked properly on the 328.  The code is taken from https://sites.google.com/site/qeewiki/books/avr-guide/usart.  It worked for me with the Arduino serial console.



#include<avr/io.h>

#define USART_BAUDRATE 9600
#define BAUD_PRESCALE (((F_CPU/(USART_BAUDRATE*16UL)))-1)

int main(void){
 char recieved_byte;
 
 UCSR0B |= (1<<RXEN0)  | (1<<TXEN0);
 UCSR0C |= (1<<UCSZ00) | (1<<UCSZ01);
 UBRR0H  = (BAUD_PRESCALE >> 8);
 UBRR0L  = BAUD_PRESCALE;
 
    for(;;){
  // wait until a byte is ready to read
  while( ( UCSR0A & ( 1 << RXC0 ) ) == 0 ){}

  // grab the byte from the serial port
  recieved_byte = UDR0;
  
  // wait until the port is ready to be written to
  while( ( UCSR0A & ( 1 << UDRE0 ) ) == 0 ){}

  // write the byte to the serial port
  UDR0 = recieved_byte;
    }
    return 0;   /* never reached */
}

Makefile settings for this code were the following, uses a 16MHz external crystal:

DEVICE     = atmega328p
CLOCK      = 16000000
PROGRAMMER = -c dragon_isp -P usb
OBJECTS    = main.o
FUSES      = -U hfuse:w:0xd2:m -U lfuse:w:0xff:m