robotic circumnavigation of earth

categories: blog

Has it even been done before? Searching the internet only finds huge manned solar boats.

Swimming around the earth with solar power should be much easier than flying as one doesnt have to worry about the night (really? see below). Another advantage is, that nations tend to try and protect their airspace whereas swimming through international waters should be fine.

The idea is, to have an autonomous robotic vessel, powered by photovoltaic means and two underwater propellers and doing navigation with gps. While shipping around the world, it would be great to have photos from all the exotic coastlines the robot approached. Image analysis could also be used to avoid getting too close to potential obstacles in the water.

There would be two possible routes. Either hoping to get through panama and suez canal together with other ships (and try not to get stuck by the canal sides) or swimming around cape horn and cape of good hope.

Having an uplink to the vessel would be great and certainly very useful but there doesnt seem to be any solution for satellite navigation that doesnt cost a fortune, isnt a huge installation and works around all the globe? Such an uplink would make lots of things much easier and would avoid loosing the robot.

A quick mockup of how such a robot could look like:

SVG source

Open questions:

  • What about corrosion of the propeller/motors due to salt water?
  • What about extreme temperatures? will the electronics cope with that?
  • Could something cover the solar panels? Ice? Dirt?
  • What about the Night? Build in batteries to keep it powered? Would the robot drift away?
  • Are there currents too strong for the robot to overcome?
  • Will motors wear out?
  • Will someone find it and take it away?
  • Is it legal?
  • Go through suez/panama canal? How to avoid getting stuck there?
  • Could it strand on a coast or riverside being stuck in plants or rocks?
  • Enough power from solar cells? How large do they have to be?

EDIT:

Apparently people are already into this:

  • http://www.engadget.com/2012/03/15/swimming-robots-break-record/
  • http://www.bbc.co.uk/news/technology-17367984
  • http://liquidr.com/files/2012/03/PacX_World-Record_03_13_12.pdf
  • http://www.engadget.com/2011/11/19/wave-glider-robots-set-out-to-explore-the-seven-seas-break-the/
  • http://news.cnet.com/8301-13772_3-57327023-52/ocean-faring-robots-set-sail-on-guinness-record-attempt/
  • http://liquidr.com/
View Comments

windows xp on qemu

categories: blog

Works like a breeze - only note to NOT use a qcow diskimage (will be horribly slow) and use the following qemu options to select network and sound hardware that windows knows about out of the box:

To create a disk image use one of the following commands depending on whether your system has fallocate support or not:

$ dd if=/dev/zero of=windows.img bs=1 count=1 seek=3000MiB
$ fallocate -l 3000MiB windows.img

If your filesystem supports sparse files, then your image will not immediately occupy its full size on your disk. Then start qemu like this:

$ qemu-system-x86_64 -k en-us -enable-kvm -hda windows.img \
> -cdrom windows_xp.iso -net nic,model=rtl8139 -net user \
> -soundhw ac97 -m 1024

For bare Windows XP you do not need to specify the -m 1024 option. Windows XP will be quite happy with the default of 128 MiB RAM. But given the amount of RAM current hosts have available I usually throw in a bit extra.

My roommate akira used this setup to connect to a university distance course which required the students to use the proprietary Adobe Connect software to connect to the classroom. It turns out that with above setup, the speaker and microphone forwarding between the host and the Windows XP guest worked out of the box. Getting a USB webcame to work turned out to be a bit more tricky but can be accomplished by adding the following to the qemu invocation above:

$ qemu-system-x86_64 [...] \
> -readconfig /usr/share/doc/qemu-system-common/ich9-ehci-uhci.cfg \
> -device usb-host,vendorid=0x046d,productid=0x0825,id=webcam,bus=ehci.0

This will attach the hosts usb device with id 046d:0825 (a Logitech webcam in this case) to the qemu guest. It doesn't even seem to be necessary to unload the kernel module responsible for the webcame (uvcvideo in this case) from the host. The guest seems to be able to cooperate well with it. The interesting bit of above invocation is the -readconfig argument which points to /usr/share/doc/qemu-system-common/ich9-ehci-uhci.cfg which is a hardware configuration for qemu written by Gerd Hoffmann. It creates a USB 2.0 adapter with companion USB 1.0 controllers as a multifunction device on one of the guests PCI slots. This has the advantage that attaching any USB device from the host to the guest bus ehci.0 will work no matter whether the device is USB 1.0 or 2.0. If you know what you are doing you can always specify -usb or -device usb-ehci,id=ehci, depending on the USB standard of your device and then attach it to the right bus. But the -readconfig solution will work out of the box in both cases. You can read more about qemu and USB in the excellent documentation which can be found at /usr/share/doc/qemu-system-common/usb2.txt.gz or at docs/usb2.txt in the qemu git which was also written by Gerd Hoffmann.

In case you want to read data from the guest with the virtual machine switched off you can mount the disk image you created earlier by doing:

mount -o loop,offset=32256 windows.img windows

Or find out the offset with fdisk: switch display units to sectors with 'u' and print the partition table with 'p'. Then do the math for the proper partition offset. With a default windows xp install it will be 63 sectors times 512 bytes = 32256 bytes.

View Comments

python for-loop scope and nested functions

categories: blog

I recently stumbled over some nasty problems with respect to python scopes in for loops and nested functions therein.

Firstly, try out this snippet:

>>> a = []
>>> for i in range(10):
... a.append(lambda: i)
>>> for f in a: f()

While I expected it to print 0-9 it printed 9 ten times. The reason is twofold.

Firstly it might not be very straightforward but the following should not be surprising:

>>> for i in range(10): pass
>>> i
9

This is, the loop variable is not local to the for loop. There is no new scope created for loops in python. There is only scope for classes and functions.

Secondly, python does late binding with function or lambda calls. The following might be a bit more surprising:

>>> i = 0
>>> f = lambda: i
>>> i = 1
>>> f()
1

Since there is no scope for loops, the following will also print 81 nine times:

>>> a = []
>>> for i in range(10):
... j = i**2
... a.append(lambda: j)
>>> for f in a: f()

The problem of course presented itself to me in a much weirder manner which made it take quite some time until I figuered out the root cause of my problem. My problem was, that I indeed expected the first example to print the numbers 0-9 which it doesnt for reasons explained above.

What I was struggeling with, were gtk and dbus callbacks. My code looked like this:

for iface in interfaces:
def on_succes_cb(msg):
print iface
iface.MyDBusMethod(reply_handler=on_success_cb)

This of course printed the last value iface had in this loop on every invocation of the reply_handler. On a sidenote is is surprising to see how sparsely documented the use of reply_handler and error_handler in dbus python is and how seldomly it seems to be used.

Another piece of the same code looked like this:

for func in ["RequestScan", "EnableTechnology", "DisableTechnology"]:
button = gtk.Button(func)
def button_onclick(button, event):
print func
button.connect("button_press_event", button_onclick)
hbox.pack_start(button, False, False, 0)

And of course every time the differently named buttons where clicked it would print "DisableTechnology".

So how to fix it?

Lets see how to fix the first example:

>>> lst = []
>>> for i in range(10):
... lst.append(lambda j=i: j)
>>> for f in lst: f()

What's the difference? The lambda now has it's own local variable j and in contrast to i, the scope of j is local to the lambda. This will now successfully print 0-9.

But this doesnt help me with my above dbus and gtk callback problems as I can't freely change the function signature for the callbacks. So what to do?

The solution Michael 'emdete' Dietrich pointed me to, was to just use a wrapper function around my code which gets the loop variables as its arguments. By doing so, the loop variable gets copied into the function scope and will not be changed there by subsequent loop iterations.

>>> lst = []
>>> for i in range(10):
... def bind(j):
... lst.append(lambda: j)
... bind(i)
>>> for f in lst: f()

or

>>> lst = []
>>> def bind(j):
... lst.append(lambda: j)
>>> for i in range(10):
... bind(i)
>>> for f in lst: f()

I agreed with emdete that the second variant looks cleaner. The first variant would have made sense if loops had their own scope but hey, they havent. Using the second variant also avoids confusing with variable usage etc.

So now my code looks like this:

def bind(iface):
def on_succes_cb(msg):
print iface
iface.MyDBusMethod(reply_handler=on_success_cb)
for iface in interfaces:
bind(iface)

and this:

def bind(func):
button = gtk.Button(func)
def button_onclick(button, event):
print func
button.connect("button_press_event", button_onclick)
return button
for func in ["RequestScan", "EnableTechnology", "DisableTechnology"]:
button = bind(func)
hbox.pack_start(button, False, False, 0)

To me it always appeared unintuitive that scope is limited to functions and not extended to code blocks. But on the other hand it mimics other languages with side effects:

int i;
for(i=0; i<10; i++);
printf("%d\n", i);

There was a big discussion (64 mails) with several possible solutions on the python-ideas list three years ago: http://mail.python.org/pipermail/python-ideas/2008-October/002109.html

But it doesnt seem as if anything caught on. Hence, for the time being one has to create just another function for new scope. Works for me. Still, even though understanding why and how it works I have trouble finding the first example easily understandable. I would still expect it to work differently.

View Comments