I am at work.
I don't remember deciding to come in today.
I wonder how many choices I actually make.
I wonder how a collection of cells can make choices at all.
Perhaps the concept of personal continuity is just a convenient fiction.
An evolutionary artifact devised by my selfish genes
To further their own agenda.
The evidence suggests that I am just a loose connection of divisible parts.
Perhaps it is not so much that I think therefore I am,
But that someone thinks.
Or perhaps something.
Can things think?
Am I someone or something?
Is there a difference?
Perhaps I am just an emergent property of an indifferent universe
Which is expanding into nothingness at an accelerating rate.
Even universes die.
I will die too.
In a sense I have already died countless times.
As the person I am gives way to an imperfect copy.
I am an impostor in my own skin,
Coasting in the wake of my previous self:
The previous self who decided I should come to work today.
But life is much shorter than I had supposed.
The haskell gd module provides bindings to a small but useful subset of libgd. It's a nice enough module and I am grateful that Björn Bringert took the time to put it together but it's just not... functional enough for my tastes. Consider setPixel.
setPixel :: Point -> Color -> Image -> IO ()
This function takes a point, a color, and an image, returning the unit type from the IO monad, which means that somewhere inside of Image there must lie a mutable reference. As good as GHC's garbage collection and algebraic trickery are for optimizing away many sorts of unused intermediate state, I can understand the appeal of these in-place updates, especially considering how much the underlying C library caters to this programming style.
Not all of the actions are performed in-place, however.
rotateImage :: Int -> Image -> IO Image
The rotateImage function creates and returns a new Image type which has been rotated some integer number of degrees. However, this return type is still wrapped up in the IO monad and threading this Image type around looks tedious. Luckily, there is a more functional way to handle both types of updates efficiently while providing a handy way to automatically thread the state at the same time.
-- State.hs
module Graphics.GD.State where
import Control.Monad.State.Lazy (State(..),modify,execState)
import qualified Graphics.GD as GD
data GDCmd = SetPixel GD.Point GD.Color
data GD' = GD' { gdCmds :: [GDCmd] }
type GD a = State GD' a
Here, the GD type lets us create State monads that operate on GD' data. The GD' type contains the image and a list of operations to perform on the image. For simplicity, only SetPixel is defined. With these types, we can write a helper function consCmd that adds a command to the gdCmds of the state and a function setPixel that registers a SetPixel action.
consCmd :: GDCmd -> GD ()
consCmd cmd = modify $ \gd -> gd { gdCmds = cmd : (gdCmds gd) }
setPixel :: GD.Point -> GD.Color -> GD ()
setPixel = (consCmd .) . SetPixel
Finally, a newImage function is defined that takes a size and GD () action and executes the commands in the IO monad using runCmd.
newImage :: GD.Size -> GD () -> IO GD.Image
newImage size f = do
im <- GD.newImage size
-- run each of the commands for the image
mapM_ (flip runCmd $ im) $ gdCmds $ execState f $ GD' []
return im
runCmd :: GDCmd -> GD.Image -> IO ()
runCmd (SetPixel pt c) = GD.setPixel pt c
With just these pieces, it's possible to build something useful! This program creates a file noise.png filled with random color values.
-- Main.hs
module Main where
import Graphics.GD.State
import qualified Graphics.GD as GD
import System.Random (newStdGen,randomRs)
import Control.Monad (mapM_,liftM2)
main = do
g <- newStdGen
let (w,h) = (400,300)
(GD.savePngFile "noise.png" =<<) . newImage (w,h)
$ mapM_ (uncurry setPixel)
$ zip (liftM2 (,) [0..w-1] [0..h-1]) -- all the pixel coordinates
$ map fromInteger $ randomRs (0,256^3-1) g -- random colors
The code here is just enough to demonstrate a use of the state monad to create a mini-domain specific language on top of another library. I forked dancor's haskell-gd to include a more complete version of this Graphics.GD.State module. You can check out the code here.
With the extended module, here's code that computes a gradient:
import Graphics.GD.State
main = (savePngFile "gradient.png" =<<) . newImage (400,300) $ do
(w,h) <- getSize
eachPixel $ \(x,y) ->
let
r = ((128 * x) `div` w) + ((128 * y) `div` h)
g = 127 + ((128 * x) `div` w)
b = 127
in rgb r g b
And this one draws a circle and a line:
import Graphics.GD.State
main = (savePngFile "circle.png" =<<) . newImage (400,300) $ do
(w,h) <- getSize
fill $ rgb 100 63 127 -- dark purple background
drawArc
(w `div` 2,h `div` 2) -- centered
(180,180) -- (width,height)
0 360 -- a circle
(rgb 255 255 255) -- white
drawLine (0,0) (w-1,h-1) (rgb 127 255 127)
This might seem like a lot of effort for something that doesn't matter very much, but writing beautiful code is important. Clean, abstract interfaces save precious mental horsepower for the bigger, harder problems.
"Beauty is a consequential thing, a product of solving problems correctly." -- Joseph Esherick
My Thinkpad's battery life had gotten pathetic. When I first bought my R61i in April 2008, its 7 cells could endure 4 solid hours of continuous use before needing to be recharged. But after 22 months of heavy use, it could hold a charge for about 25 minutes. Lenovo sells replacement batteries for $143, but I found a seller on Amazon who was selling the same 9-cells listed on Lenovo's site for $45. My laptop's battery only has 7 cells, but I didn't process this before ordering.
The battery sat in the mailbox I never check for a week before I thought to check for it there. Sitting in a mailbox for a week in Fairbanks, Alaska in January probably wasn't great for the life of the battery, but thankfully lithium-ion electrolytes won't freeze above -40 C. After I got the battery, I finally noticed that it didn't fit in my Thinkpad R61i. Rather than return the battery, I decided it would be less hassle to figure out how to make this battery work than to return it.
Li-ion batteries are pretty dangerous, as it happens. Consumers should never open an Li-ion battery's protective case, but I did anyways. Note: this is very dangerous, and probably a bad idea. Knowing full well that Li-ion batteries can ignite or explode if mishandled or punctured, I very carefully opened the new battery I bought online with a pocket knife to see what was inside.
I first tried to make this new battery fit into my laptop's battery slot by trimming the plastic, but realized that the locking mechanism and dimensions couldn't be made to fit easily. Once I got the case apart, I was able to test that the new battery would work with my laptop by plugging in the short connector cord, fully expecting both the battery and my laptop to burst into a spectacular carmine blaze.
However, the new battery worked fine without so much as a beep or an entry in the system log. At this point I decided to replace my original laptop's innards with the guts of the new battery.
Getting the original 7-cell battery apart was much more difficult and time-consuming than the new 9-cell, but I finally succeeded and didn't break too much plastic in the process.
I was cautiously optimistic that I could just swap out the Li-ion cells directly, but the original battery had electronics around every cell. Probably these electronics are to keep the battery from exploding.
It was pretty obvious beforehand that not all the cells would fit in the original case. After removing the old cells, I removed excess plastic inside that was getting in the way and cut slots on the back so that 3 cells could just hang from the back of the case. Note: this is also probably a bad idea, since puncturing an Li-ion could cause it to ignite, and metal fires are serious business.
Those warnings aside, I covered everything in electrical tape, including some stripes to match the art on the back of my display, plugged in the frankensteinian battery, and it continues to work! At the time of this writing, it hasn't even exploded yet. I will update this post if/when it does ignite or explode, supposing I survive the incident. The TSA screeners will probably have some questions for me if I ever decide to board an airplane with this thing, but it probably looks just like any other laptop battery on an X-ray scanner.
I spent this winter break down on the Kenai peninsula with the folks. A few days before the new year, my father, little brother, and I took my little brother's cheap telescope out to look at the full moon.
I had forgotten how difficult it is to actually use a telescope to look at distant objects. For one, it's really difficult to use a telescope while wearing glasses, and without glasses the focus needs to be changed if someone else wants to look into the eyepiece. It's also quite difficult to position a cheap telescope by hand while bending over sideways or kneeling on the ground to use the eyepiece.
These sorts of manual adjustments are best left to machines, I thought, so I decided to use my little brother's Lego NXT brick, webcam, and a USB game controller I had recently bought at a thrift shop for a few bucks to put together a robotic control system for the telescope.
With a bucket of LEGOs, NXT parts, and lots of rubber bands, I set to work building this robotic telescope control system.
To swivel the telescope from side to side, I built a double-spool to wind up string in one direction while unwinding in the other. This string was tied to some legos attached to the telescope body, so the telescope would swivel about the pivot when the spool pulled it in a direction.
To lift the telescope, I first dangled a plastic cup from some rubber bands on the end with the eyepiece to act as a counter-balance. I stuck a motor to a simple gear system that lifted the bigger end of the telescope. By balancing the telescope so that the bigger end didn't take much force to lift, the motor needed to do much less work to adjust the telescope pitch.
With the hardware in place, I wrote some code to drive the NXT directly with my laptop over the NXT's USB interface. Using nxt-python, this task was pretty straight-forward. On the laptop, I used pygame to read events from the USB gamepad. I had used this model of gamepad before to control an underwater ROV for a contest in California, so I knew it would be pretty simple to get it working for this telescope project. I've also put the controller script that ran on the laptop up on github for others to build upon.
Construction and programming took about a day, but I spent altogether too much time getting the first webcam I found lying around the house to work with Linux to no avail. Luckily there was another webcam around that worked without any fuss in cheese.
I took the whole setup outside in the cold and used the gamepad and laptop screen to hunt for the moon. Unfortunately, when I found the moon, none of the moon's features were distinguishable in the video output.
At first I thought this was due to the focus of the webcam. I had read some posts online about people mounting webcams to telescope who took off the webcam's lens in order to focus properly. The webcam had no obvious way to take apart and I didn't want to risk damaging it since it didn't belong to me anyways, so the next day I tinkered with putting other camera lenses in between the webcam and the eyepiece and a number of other things that didn't work.
However, in the process of trying to figure out how to focus the camera during the day, I pointed the robotic telescope out a window facing some trees and captured these images. This was the same camera setup that I'd used previously to look at the moon.
I've uploaded a video of footage from the webcam and of the telescope in action. Download or watch below.
telescope.ogv [Ogg Theora, 13 M]
I showed both of my little brothers how to get the code I wrote and the necessary software onto their eee-pcs so that they could drive the telescope around too. The older of my two little brothers, Ross, who is 11, dismantled the telescope control system and built a robot car with the parts. He figured out how to modify the telescope script to drive the car around pretty well and after that he read through Invent With Python and is having all sorts of fun building games and ciphers.
The telescope may not have been very useful for looking at the moon or other astronomical objects, but it was a fun little project that could at least capture some interesting daytime images. However, as a motivational tool to get my siblings more interested in robotics and computer programming, this project was very successful.



