How to use Python to predict satellite locations…

Occasionally I get to talk to hams who are just getting into using amateur satellites, and many of them ask the quite reasonable question “How do I figure out when the next pass occurs?”. For most of them, I suggest that they simply use a program like predict, which is probably what most people expect from a satellite prediction program.

I used just such a program for quite a while, until I first worked NH7WN in Hawaii, myself standing in my front yard, he standing on a beach in Hawaii, and I asked myself the quite normal question: “How often can I work Hawaii from here in California?” The (frankly excellent, don’t get me wrong) predict program didn’t provide a convenient way to answer that question.

Faced with this, I decided to write my own code for satellite prediction, so I could easily adapt it to answering questions like these. Because I like Python, and find it convenient for scripting applications, I chose Python as the implementation language. The algorithm I used was James Miller, G3RUH’s Plan 13 which was originally written in BASIC, and was relatively easy to port. I ended up creating a simple Python library implementation of Plan 13, which I’ve used for all my own satellite prediction needs. The nice thing about Python is that it has a bunch of useful libraries you can use (I used the sqlite3 library to build a database of orbital elements, and urllib to download them automatically from celestrak), and it’s been quite adaptable.

Still there were a few warts with it, and I haven’t had the chance to tidy it up. But recently I discovered that the PyEphem library includes a lot of the same functionality, and with a better version of the orbital model that I implemented. And, it’s pretty easy to use. As an example, here is a small chunk of code that figures out the next three passes of the ISS, using the current (for today) orbital elements. Even if you aren’t an amazing programmer, you can probably figure out how it works.


import sys
import math
import ephem

iss = ephem.readtle("ISS (ZARYA)",
	"1 25544U 98067A   09270.78646569  .00012443  00000-0  87997-4 0  6860",
	"2 25544  51.6377 140.0905 0009007 135.9273 312.2213 15.74420558622113")

obs = ephem.Observer() = '38.0'
obs.long = '-122.0'

for p in range(3):
	tr, azr, tt, altt, ts, azs = obs.next_pass(iss)
	while tr < ts : = tr
		print "%s %4.1f %5.1f" % (tr, math.degrees(iss.alt), math.degrees(
		tr = ephem.Date(tr + 60.0 * ephem.second)
	print = tr + ephem.minute

Running it produces a dump of times, altitude and azimuths for three passes. Here’s a resulting run.

2009/9/28 04:12:18 -0.0 268.5
2009/9/28 04:13:18  1.4 257.6
2009/9/28 04:14:18  2.4 244.9
2009/9/28 04:15:18  2.5 231.3
2009/9/28 04:16:18  1.8 218.3
2009/9/28 04:17:18  0.4 206.7

2009/9/28 17:27:22 -0.1 169.1
2009/9/28 17:28:22  2.1 159.4
2009/9/28 17:29:22  4.0 147.1
2009/9/28 17:30:22  5.2 132.6
2009/9/28 17:31:22  5.1 117.1
2009/9/28 17:32:22  3.9 102.7
2009/9/28 17:33:22  1.9  90.7

2009/9/28 19:00:26  0.0 227.2
2009/9/28 19:01:26  3.8 226.9
2009/9/28 19:02:26  9.2 226.4
2009/9/28 19:03:26 17.8 225.3
2009/9/28 19:04:26 35.8 222.0
2009/9/28 19:05:26 80.4 152.7
2009/9/28 19:06:26 37.7  57.0
2009/9/28 19:07:26 18.5  53.3
2009/9/28 19:08:26  9.6  52.2
2009/9/28 19:09:26  4.1  51.8
2009/9/28 19:10:26  0.2  51.5

I did notice that this simple program may not work properly if the ISS is currently visible from your location, but I am sure that with just a little more work we could figure that out. I’ll probably port my existing software to this framework, because it also includes a bunch of useful functions (like figuring out when the sun rises and sets, and other fun things) which would be a pain for me to add. So here’s my radical suggestion: if you need to compute the location of satellites, write some scripts of your own using pyephem! It’s the homebrewer way. 🙂

Addendum: A few more minutes of work added some more interesting outputs…


import sys
import math
import ephem

iss = ephem.readtle("ISS (ZARYA)",
	"1 25544U 98067A   09270.78646569  .00012443  00000-0  87997-4 0  6860",
	"2 25544  51.6377 140.0905 0009007 135.9273 312.2213 15.74420558622113")

obs = ephem.Observer() = '38.0'
obs.long = '-122.0'

for p in range(3):
	tr, azr, tt, altt, ts, azs = obs.next_pass(iss)
	print """Date/Time (UTC)       Alt/Azim	  Lat/Long	Elev"""
	print """====================================================="""
	while tr < ts: = tr
		print "%s | %4.1f %5.1f | %4.1f %+6.1f | %5.1f" % \
		tr = ephem.Date(tr + 20.0 * ephem.second)
	print = tr + ephem.minute

And some output:

Date/Time (UTC)       Alt/Azim	  Lat/Long	Elev
2009/9/28 04:12:18 | -0.0 268.4 | 34.9 -145.6 | 335.6
2009/9/28 04:12:38 |  0.5 265.0 | 34.0 -144.5 | 335.7
2009/9/28 04:12:58 |  1.0 261.3 | 33.2 -143.4 | 335.9
2009/9/28 04:13:18 |  1.5 257.4 | 32.3 -142.3 | 336.0
2009/9/28 04:13:38 |  1.9 253.4 | 31.4 -141.3 | 336.2
2009/9/28 04:13:58 |  2.2 249.1 | 30.5 -140.2 | 336.3
2009/9/28 04:14:18 |  2.4 244.7 | 29.5 -139.2 | 336.5
2009/9/28 04:14:38 |  2.6 240.2 | 28.6 -138.3 | 336.6
2009/9/28 04:14:58 |  2.6 235.7 | 27.7 -137.3 | 336.8
2009/9/28 04:15:18 |  2.5 231.1 | 26.7 -136.3 | 337.0
2009/9/28 04:15:38 |  2.4 226.7 | 25.8 -135.4 | 337.1
2009/9/28 04:15:58 |  2.1 222.3 | 24.8 -134.5 | 337.3
2009/9/28 04:16:18 |  1.7 218.1 | 23.9 -133.6 | 337.5
2009/9/28 04:16:38 |  1.3 214.0 | 22.9 -132.7 | 337.7
2009/9/28 04:16:58 |  0.9 210.2 | 21.9 -131.8 | 337.9
2009/9/28 04:17:18 |  0.3 206.6 | 20.9 -131.0 | 338.1

Date/Time (UTC)       Alt/Azim	  Lat/Long	Elev
2009/9/28 17:27:24 |  0.0 168.7 | 19.0 -118.4 | 346.7
2009/9/28 17:27:44 |  0.7 165.7 | 20.0 -117.5 | 346.4
2009/9/28 17:28:04 |  1.4 162.5 | 21.0 -116.7 | 346.2
2009/9/28 17:28:24 |  2.1 158.9 | 22.0 -115.8 | 345.9
2009/9/28 17:28:44 |  2.8 155.1 | 22.9 -115.0 | 345.6
2009/9/28 17:29:04 |  3.5 151.0 | 23.9 -114.1 | 345.3
2009/9/28 17:29:24 |  4.1 146.6 | 24.9 -113.2 | 345.0
2009/9/28 17:29:44 |  4.6 141.9 | 25.8 -112.3 | 344.7
2009/9/28 17:30:04 |  4.9 137.0 | 26.8 -111.3 | 344.4
2009/9/28 17:30:24 |  5.2 131.9 | 27.7 -110.4 | 344.1
2009/9/28 17:30:44 |  5.3 126.8 | 28.6 -109.4 | 343.9
2009/9/28 17:31:04 |  5.3 121.6 | 29.6 -108.4 | 343.6
2009/9/28 17:31:24 |  5.1 116.4 | 30.5 -107.4 | 343.3
2009/9/28 17:31:44 |  4.8 111.5 | 31.4 -106.4 | 343.0
2009/9/28 17:32:04 |  4.3 106.7 | 32.3 -105.4 | 342.7
2009/9/28 17:32:24 |  3.8 102.1 | 33.2 -104.3 | 342.4
2009/9/28 17:32:44 |  3.2  97.9 | 34.0 -103.2 | 342.2
2009/9/28 17:33:04 |  2.5  93.9 | 34.9 -102.1 | 341.9
2009/9/28 17:33:24 |  1.8  90.2 | 35.8 -101.0 | 341.6
2009/9/28 17:33:44 |  1.1  86.9 | 36.6  -99.8 | 341.3
2009/9/28 17:34:04 |  0.4  83.8 | 37.4  -98.6 | 341.1

Date/Time (UTC)       Alt/Azim	  Lat/Long	Elev
2009/9/28 19:00:26 |  0.1 227.2 | 23.8 -137.4 | 345.3
2009/9/28 19:00:46 |  1.2 227.1 | 24.8 -136.5 | 345.1
2009/9/28 19:01:06 |  2.4 227.0 | 25.7 -135.6 | 344.8
2009/9/28 19:01:26 |  3.8 226.9 | 26.7 -134.7 | 344.5
2009/9/28 19:01:46 |  5.4 226.8 | 27.6 -133.7 | 344.2
2009/9/28 19:02:06 |  7.2 226.6 | 28.6 -132.8 | 343.9
2009/9/28 19:02:26 |  9.2 226.4 | 29.5 -131.8 | 343.6
2009/9/28 19:02:46 | 11.6 226.2 | 30.4 -130.8 | 343.3
2009/9/28 19:03:06 | 14.4 225.8 | 31.3 -129.7 | 343.0
2009/9/28 19:03:26 | 17.9 225.3 | 32.2 -128.7 | 342.8
2009/9/28 19:03:46 | 22.2 224.7 | 33.1 -127.6 | 342.5
2009/9/28 19:04:06 | 28.1 223.6 | 34.0 -126.5 | 342.2
2009/9/28 19:04:26 | 36.1 221.9 | 34.8 -125.4 | 341.9
2009/9/28 19:04:46 | 47.7 218.5 | 35.7 -124.3 | 341.6
2009/9/28 19:05:06 | 64.1 209.2 | 36.5 -123.1 | 341.4
2009/9/28 19:05:26 | 80.5 149.1 | 37.4 -121.9 | 341.1
2009/9/28 19:05:46 | 66.7  71.9 | 38.2 -120.7 | 340.8
2009/9/28 19:06:06 | 49.6  60.7 | 39.0 -119.5 | 340.6
2009/9/28 19:06:26 | 37.4  57.0 | 39.8 -118.2 | 340.3
2009/9/28 19:06:46 | 29.0  55.1 | 40.5 -116.9 | 340.1
2009/9/28 19:07:06 | 23.0  54.0 | 41.3 -115.5 | 339.8
2009/9/28 19:07:26 | 18.4  53.3 | 42.0 -114.1 | 339.6
2009/9/28 19:07:46 | 14.9  52.8 | 42.7 -112.7 | 339.3
2009/9/28 19:08:06 | 12.0  52.5 | 43.4 -111.3 | 339.1
2009/9/28 19:08:26 |  9.5  52.2 | 44.1 -109.8 | 338.8
2009/9/28 19:08:46 |  7.5  52.0 | 44.7 -108.3 | 338.6
2009/9/28 19:09:06 |  5.7  51.9 | 45.4 -106.7 | 338.4
2009/9/28 19:09:26 |  4.1  51.7 | 46.0 -105.1 | 338.1
2009/9/28 19:09:46 |  2.6  51.7 | 46.5 -103.5 | 337.9
2009/9/28 19:10:06 |  1.3  51.6 | 47.1 -101.9 | 337.7
2009/9/28 19:10:26 |  0.2  51.5 | 47.6 -100.2 | 337.5

Addendum2: As another example of what can be done, consider the command line voice synthesizer that is included in Mac OS. Using the os.system command, you can have your computer speak voice updates almost as easy as printing them. For example:


# Mac OS includes a voice synthesis command called "say".   It's pretty
# easy to make a simple program like this that will use voice to announce
# the current position of the satellite.   With a little work, you could
# easily make it announce the altitude and azimuth repeatedly during a pass.

import sys
import os
import math
import ephem

iss = ephem.readtle("ISS (ZARYA)",
	"1 25544U 98067A   09270.78646569  .00012443  00000-0  87997-4 0  6860",
	"2 25544  51.6377 140.0905 0009007 135.9273 312.2213 15.74420558622113")

obs = ephem.Observer() = '38.0'
obs.long = '-122.0'

if iss.alt < 0:
	os.system('say The ISS is not currently visible.')
	os.system('say "The ISS is at altitude %d, azimuth %d."' % \
		(int(math.degrees(iss.alt)+0.5), int(math.degrees(

Here’s an example of the voice it outputs:
Voice synthesis example

Gutenberg Gems: Encyclopædia Britannica, Volume VIII slice III – Destructor to Diameter

img154bIt’s been a while since I posted a link to a Gutenberg Gem. I am subscribed to the Project Gutenberg feed, and scan it from time to time. Today’s Gem is volume 8 from the Encyclopædia Britannica: which includes topics from Destructor to Diameter. Interestingly, it includes an entry for “Dialing”, which is also known as gnomonics: the construction of sun dials. I was thinking about constructing a high accuracy sun dial just the other day. Anyway, lots of good stuff to check out.

The Project Gutenberg eBook of Encyclopædia Britannica, Volume VIII slice III – Destructor to Diameter

Addendum: When I find something in Project Gutenberg which interests me, I somethings will just go search Google Books or the Internet Archive for other books on the same topic. Kind of bombed out on Google Books, but had the following:

Gnomonique by Bigourdan. In French, but it seems awesome.
Sundials: How to Know, Use and Make Them by Mayhall & Mayhall

Recently Launched Cubesat Frequencies

Andrew, VK4TEC posted this list of frequencies for four recently launched cubesats. Archiving for future reference. I’ve added links to some relevent info for each.

ITUpsAT1 is on 437.325 MHz CW ITUpSAT1 is a student-built Turkish satellite.
UWE-2 is on 437.385 MHz, 1200 bps Ax.25 packet Universität Würzburg Experimental-Satellit2
BEESAT is on 436.000 MHz CW using the call DP0BEE
SwissCube is on 437.505 Mhz CW using the call HB9EG/1More info.

Bouncing APRS packets off the ISS…

My wife mentioned to me that there was a visual pass of the ISS this evening. Wow, is she awesome or what? She found out about it by subscribing to the twitter feed “twisst”, which is apparently automated, and will send you messages when a ISS pass is about to occur. This pass had a maximum altitude of about 35 degrees, so I decided to get out my TH-D7A radio and my Arrow antenna and see if I could not only see it visually, but could bounce some packets off it. While waving my antenna around, I heard the telltale sound of a digital packet, and then, suddenly rising above the hill behind my house, there it was, looking nice and bright. I got my wife to look at it, and while I was looking down at my radio, it apparently went into eclipse, because when I looked back up, not a trace of it could be seen. Nevertheless, I bounced three packets off it, which were logged onto the Internet by gateways. Check it!

Picture 1

2009-09-23 03:47:51 UTC: K6HX-1>37UXPW,RS0ISS-3*,qAS,W6MSU-4:'2+9l <0x1c>-/>THD7A,5w,arrow
2009-09-23 03:48:52 UTC: K6HX-1>37UXPW,RS0ISS-3*,qAo,N6VIG:'2+9l <0x1c>-/>THD7A,5w,arrow
2009-09-23 03:50:51 UTC: K6HX-1>37UXPW,RS0ISS-3*,qAR,N0AN:'2+9l <0x1c>-/>THD7A,5w,arrow

via Raw packets of K6HX-1

Is mobile operation of a ham radio really safe?

The federal government is currently considering the possibility of legislation banning the use of cell phones and texting. I’m mostly okay with that, because, quite frankly, it’s obvious that people aren’t very good at operating a cell phone or texting while driving, a fact which has been reinforced by study after study. But while many radio amateurs accept this conclusion with respect to cell phones, radio amateurs as a whole seem to think that it doesn’t apply to operation of an amateur radio transmitter while the vehicle is in motion. Witness the quotation from ARRL CEO David Sumner:

According to ARRL Chief Executive Officer David Sumner, K1ZZ, it boils down to the difference between simplex — when only one message can be sent in either direction at one time — and duplex — a communications mode, such as a telephone system, that provides simultaneous transmission and reception in both directions. Harrison, citing Sumner's 40-plus years of experience as an Amateur Radio operator, puts it this way: “Simplex, two-way radio operation is simply different than duplex, cell phone use. Two-way radio operation in moving vehicles has been going on for decades without highway safety being an issue. The fact that cell phones have come along does not change that.”

via ARRLWeb: ARRL NEWS: ARRL President Presents League’s Views on Distracted Driving Laws to Safety Advocacy Group.

But here’s the thing that bothers me. This is just a bold assertion: that operation of simplex radios is inherently safer than duplex radios. Here is what the NSC President Janet Froetscher had to say about the subject:

The NSC position is grounded in science. There is significant evidence that talking on cell phones while driving poses crash risk four times that of other drivers. We are especially concerned with cell phone use because more than 100 million people engage in this behavior, with many doing so for long periods of time each day. This exposes these 100 million people and everyone who shares the road with them to this increased crash risk every day. This combination of risk and exposure underlies our specific focus on cell phones.

We are not aware of evidence that using amateur radios while driving has significant crash risks. We also have no evidence that using two-way radios while driving poses significant crash risks. Until such time as compelling, peer-reviewed scientific research is presented that denotes significant risks associated with the use of amateur radios, two-way radios, or other communication devices, the NSC does not support legislative bans or prohibition on their use.

That is not to say that there is no risk associated with drivers using amateur or two-way radios. Best safety practice is to have one’s full attention on their driving, their hands on the wheel and their eyes on the road. Drivers who engage in any activity that impairs any of these constitutes an increased risk. While the specific risk of radio use while driving is unmeasured and likely does not approach that of cell phones, there indeed is some elevated risk to the drivers, their passengers and the public associated with 650,000 amateur radio operators who may not, at one time or another, not concentrate fully on their driving.

This is widely being circulated as vindication of the idea that operation of a ham radio while simultaneously operating a motor vehicle is safe. Unfortunately, I don’t think that is an accurate representation of Froetscher’s position. Froetscher merely said that she was unaware of any scientific, peer reviewed studies that demonstrated a significant safety risk. As we should all know, absence of evidence is not evidence of absence. David Sumner’s assertion that simplex is inherently safer than duplex is just that: an assertion, and is not evidence.

The fact is that humans are very bad at evaluating risks and their own performances at tasks. That’s why we have scientific studies like the ones that we have for operating cell phones. Because there are 100 million cell phones being used literally every day, there is plenty of data to sift through on their potential role in accidents. Even so, it’s taken about a decade for the true extent of the risks involved in cell phone operation to become documented.

There are only about 660,000 or so hams licensed in the U.S. The vast majority of these do not operate mobile. The vast majority of those do probably spend most of their time listening. In such a case, we’d expect that the number of accidents caused to be much lower than those caused by cell phones, even if mobile operation was every bit as dangerous as using a cell phone. The overall instance of accidents may be only 0.1% or less of the levels we see from cell phones. One study estimated that 6000 accidents might have been caused by cell phones in California in 2001. Even if ham radio were as dangerous, we might expect to see only six accidents in the entire year from ham radio operation.

I’m not saying that we should outlaw mobile ham radio operation. Without evidence that it is dangerous, I think it is premature to make it illegal. But I also think that it is inappropriate to confidently assert that we understand what the risks are, and that we actually present no significant risk to ourselves or to others on the road.

Addendum: Ben makes an additional point which I think is worthy of mention. The ARRL is in part justifying their opposition to bans on mobile radio by suggesting that amateur radio serves a vital purpose in supporting emergency communications. I think this is a somewhat odd claim to make, since it should be fairly obvious that the overwhelming majority of emergencies are reported by calling 911 on the cell phone. Many states have exemptions for mobile cell phone use in times of emergencies: you can report an accident while calling 911 while your car is in motion. The ARRL could choose to suggest to its members that only emergency communications be carried out while the car is in motion, but instead, they suggest that the possibility of using a mobile radio to report an emergency justifies their free use for routine communications while the vehicle is in motion. I agree with Ben, I don’t think this is a reasonable “best practice” suggestion.

One slightly convincing argument that I haven’t heard, but which I can imagine someone making is that without the incentive of being allowed mobile operation, radio amateurs won’t install mobiles in their vehicles, and therefore we lose a valuable resource for reporting accidents and dealing with emergencies. This is an argument which I might seriously consider, and could be made compelling with the right sort of quantifiable evidence to determine the tradeoffs of different regulatory strategies.

Why work for a game any company like this?

This link is making the rounds of a couple of different mailing lists I’m on.

Activision games to bypass consoles – News at GameSpot

When he wasn’t promoting the company’s games or technology, Kotick was celebrating its laserlike focus on the bottom line. He pointed to changes he implemented in the past as being particularly beneficial, such as designing the employee incentive program so it “really rewards profit and nothing else.”

“You have studio heads who five years ago didn’t know the difference between a balance sheet and a bed sheet who are now arguing allocations in our CFO’s office pretty regularly,” Kotick said.

He later added, “We have a real culture of thrift. The goal that I had in bringing a lot of the packaged goods folks into Activision about 10 years ago was to take all the fun out of making video games.”

Oh, goody. And…

The executive said that he has tried to instill into the company culture “skepticism, pessimism, and fear” of the global economic downturn, adding, “We are very good at keeping people focused on the deep depression.”

In a way, I do understand. We are all in business to pay for our housing, our food and our health insurance. If we are lucky, we get to put some away for retirement, and even get to enjoy some of life’s little pleasures (many of which, despite the claim that the best things are free, often seem to require money). We have to look at things like costs in our planning, and we have to be aware of global changes in the market for our products to ensure that we remain employed. That kind of planning isn’t always the funnest thing to do, nor does cheerful optimism keep companies afloat.

But seriously, it needn’t be a death march. Fear can be a strong motivator, but it’s not sustainable, and it’s no great muse when it comes to creativity and innovation. Kotick’s entire strategy is to acquire and market sequels to existing products, and to milk them on every platform in every way possible. I can understand why bean counters like this: it’s essentially a low risk way to maximize profits. And, in fact, he’s been pretty darned successful doing precisely that. And, he’s not alone: a great deal of the film industry works precisely this way.

I’ve recently gained a slightly more charitable view toward sequels. They are successful, and it’s not entirely because people are sheep. It is because they saw something in the original work which they liked, and they want more of it. Their desire to slap down money on sequels is a compliment to the original work, and to their trust in you to continue to deliver that kind of positive experience that they originally remembered. But here is the tricky thing: it doesn’t last. We see this time and time again in the film industry. A great movie becomes a good franchise, then an okay franchise, and ultimately peters out into a dreadful mess. Occasionally, these franchises can be resurrected, but it usually takes a completely new approach by a completely new director/producer who isn’t afraid to bring something new to the table and take risks. Witness Abrams’ revival of the moribund Star Trek franchise if you need a recent example.

Great movies (and great games) are the result of great direction and great technical staff doing the work they love. People who are that good at their job aren’t going to be content with just doing the same thing over again: they are going to be looking for ew challenges and new opportunities. Hence, you generally end up with paler and paler imitations of the original painting, until it’s just something to wrap your fish and chips.


Codec2 – Open Source Low Bit Rate Speech Codec

David Rowe is working on a very cool project that should be of interest to hams with an interest in digital communications. He’s creating an open source, low bit rate speech codec. His target is a usable 2400 bps codec that is free from patent issues, and that can be used in situations similar to the patented algorithm AMBE that is currently used in D-Star networks. He’s not quite at the point where he has a full codec yet, but he’s begun to make some code available that can encode and decode using his sinusoidal encoder. He’s also writing up a lot of the theory behind the encoder on his blog, which is frankly a bit beyond me, but not a huge amount beyond me, which means that it’s very interesting reading.

Codec2 – Open Source Low Bit Rate Speech Codec

David has also done some very interesting VOIP work, including a high quality echo canceler. His blog is always worth reading.

Upcoming launch of SumbandilaSat

It looks like the launch of the South African amateur satellite is on track!

The launch of SumbandilaSat is on track for 15 September 2009. In an interview with SA AMSAT, Johan Erasmus, SunSpace systems engineer speaking from Baikonur, said that the satellite travelled well and that all system performed to specification during the testing phase. Tests were carried out in the clean room at the Baikonur launch facility in Kazakhstan. “All payloads operated well and we were able to test the amateur payload from a little distance away. The parrot, voice repeater and the voice beacon responded well.

Via AMSAT South Africa Homepage

As soon as we get a confirmed launch, I’ll try to get some audio and/or work the bird. Stay tuned!

Addendum: The launch didn’t go off today. From AMSAT-SA’s website.

Due to high winds at the launch site and some telemetry issues on the rocket the launch has been delayed for 24 hours and will now take place on 16 September at around 15:45 UTC.

That’s about 9 hours from now. Fingers crossed.

Project Icarus

A group of MIT students did a high altitude balloon launch. That’s really not all that unusual: radio amateurs do similar launches several times per year. What is unusual is the price tag: $150 total. They used an inexpensive Canon camera running the CHDK firmware to snap images, and a cheap no-contract Motorola phone to communicate coordinates back. It’s not the greatest engineering choice really: the cell phone lost contact after gaining only 2500 feet in altitude, but it is a pretty interesting idea. They managed to do just about the minimum possible and still create a recoverable high altitude payload. There was no custom hardware at all. Check it out:



HAKMEM is a legendary technical memo from MIT that’s packed full of interesting bits. On this occasion, I ran across item #175, which you can find here:


This is a little chunk of code which given an integer, computes the next highest integer with the same number of one bits. This code is expressed somewhat sub-optimally for modern audiences, since it is PDP-10 assembly code, but encompasses a neat, but subtle algorithm. One might ask what use such a seemingly esoteric function is, but it is quite useful in quickly generating all subsets with a given number of elements. Nifty.

Parrondo’s Paradox

earl53_1909pennyfront2webI was reading Nahin’s Digital Dice, which I bought a while ago but which I didn’t really dive into deeply, and he had a nice exposition of Parrondo’s Paradox, which is very neat. Here’s the idea:

  1. We are going to play two different coin tossing games. In each case, if we win, we gain one unit. If we lose, we lose one unit.
  2. In Game A, we will toss a coin, and if it comes up heads, we win, otherwise we lose. Unfortunately for us, the coin is not a fair coin, it is more likely to come up tails than heads. Let’s call the probability of winning this game as 0.5 – ε. Clearly, this game is a losing one for ε > 0.
  3. In Game B, we have two coins. One is clearly biased against us: the chance of winning is just 0.1 – ε, the second is biased for us, and has probability of winning as 0.75 – ε. Here’s the wrinkle: if our bankroll is an exact multiple of three, we toss coin the first coin, otherwise we toss the second coin.

Game B is a bit harder to analyze, but let’s give it a try (it’s wrong, but it’s not too far wrong): 1/3 of the time, we gain one unit wth probability 0.1-ε and 2/3 of the time, we gain one unit with probability 0.75-ε. This means that our probability of winning is 8/15 – ε. If we set ε to be 0.005, we maintain a narrow advantage.

Or do we? Let’s go ahead and simulate this. I wrote some Python code that played both games for one million rounds. The results from a typical round:

GAME A: played 1000000 rounds, started with 0, ended with -8642
GAME B: played 1000000 rounds, started with 0, ended with -8532

So, here’s the first thing issue: Game B appears to be a loser as well. Why would that be? (Think about it).

But if we accept the fact that Game A and Game B are losing propositions, let’s play a new game called the combination game. It’s very simple, we randomly pick (perhaps by tossing a fair coin) which of the games we want to play in each round. If we simulate this game, we get the following (again, from a run of 1000000):

COMBINATION: played 1000000 rounds, started with 0, ended with 16620

What’s this about? We’re alternating between two losing games, and yet, we emerge as winners? What’s going on here?


Addendum: Here’s some python code that I wrote to simulate the game.

#!/usr/bin/env python
# $Id$

import random

def play_game_a(capital, eps):
    return random.uniform(0, 1) < (0.5 - eps)

def play_game_b(capital, eps):
    if capital % 3 == 0:
	return random.uniform(0, 1) < 0.1 - eps
	return random.uniform(0, 1) < 3.0/4.0 - eps

def play_game_combo(capital, eps):
    if random.randint(0, 1):
	return play_game_a(capital, eps)
	return play_game_b(capital, eps)

def play(name, f, n, icap, eps):
    cap = icap
    for i in range(n):
	if f(cap, eps):
	    cap = cap + 1 
	    cap = cap - 1 
    print "%s: played %d rounds, started with %d, ended with %d" % (name, n, icap, cap)

play("GAME A", play_game_a, 1000000, 0, 0.005)
play("GAME B", play_game_b, 1000000, 0, 0.005)
play("COMBINATION", play_game_combo, 1000000, 0, 0.005)