rbp is currently certified at Journeyer level.

Name: Rodrigo Pimentel
Member since: 2000-03-15 21:20:56
Last Login: 2009-07-28 23:11:26

FOAF RDF Share This

Homepage: http://isnomore.net

Notes:

I've been a Linux and Free Software user and advocate since 1995 (and developer since a bit later). Currently, my main activity is programming (in Python, whenever I can). I was president of LinuxSP, a Linux Users Association, throughout its existence. There's more about me and stuff I'm working at (including a blog) at http://isnomore.net

Recent blog entries by rbp

Syndication: RSS 2.0

ASE is now SL4A! Upgrade (and here's how)!

So, SL4A r0 is out! This is good old Android Scripting Environment, or ASE (remember?), renamed to Scripting Layer for Android, but that's not all. The release also brings a lot of really cool features, such as:

  • Interpreters distributed on their own APKs. Plus the coolness factor of seeing "Python for Android" on the installer. Downloading them is bit weird, though, as it opens the browser and hitting the Back buttons takes you to the homepage, not back to AS4L.

  • Scripts themselves can be packed into an APK

  • Support for multiple scripts running simultaneously, on the background.

And a lot more. Do read the announcement.

So, yeah, head over to the project's page (BTW, why isn't it on the Market?) and install the new version.

However, if you already used ASE, you'll notice that the new package no longer replaces the old ASE installation. It installs as a different app. No problems so far.

But it also won't find your old scripts! Oops... SL4A now stores (and looks for) its scripts on /sdcard/sl4a, instead of the previously used /sdcard/ase.

Fortunately, that's very easy to fix, with a small shell script running on SL4A itself:

  # Just install this on your sl4a and run it once.
old="/sdcard/ase/scripts"
new="/sdcard/sl4a/scripts"
enough () {
    echo $1
    echo "Press ENTER to exit... "
    read foo
    exit $2
}

if ! cd "$old" ; then
    enough "Could not cd to old scripts directory $old. Sorry." 1
fi
if [ ! -d "$new" ]; then
    if ! mkdir "$new"; then
        enough "Could not create new scripts directory $new. Sorry." 1
    fi
fi
find . -type d -mindepth 1 -exec mkdir "$new/{}" \; 2>/dev/null
find . -type f | while read line; do
    if [ ! -e "$new/$line" ]; then
        echo "$line -> $new/$line"
        cp "$line" "$new/$line"
    fi

done
enough "Done." 0

ase_scripts_to_sl4a.sh

This basically just copies the files over (including from any subdirectories you might have), without overwriting any files that already exist on the SL4A scripts directory. You can install it from the QR Code on the right (click it for a larger version). I realise that I should put SL4A's new functionality to test and pack the script in an APK file, but I'm feeling a bit lazy for that right now. If enough people actually use the script, I'll give it a shot :)

I'm using shell because it comes with SL4A, so you don't have to download any specific interpreter. Also, I'm hardcoding the /sdcard path, since I believe SL4A doesn't expose the getExternalStorageDir() call. If your SD card's mount point is somewhere else, please adjust the script accordingly (or, if there's another commonly used path, let me know and I'll fix it here).

Enough for now. Let me know if this script has been useful, or if you have suggestions.

Have fun with SL4A!

Syndicated 2010-08-05 23:50:11 from Bits of rbp - isnomore.net

Automated Python testing with nose and tdaemon

If you're testing your code at all (and you are, right?), it's awfully convenient to automatically have your test suite run whenever something in your project changes. This is particularly handy if you're doing test-driven development (TDD), where you'll be writing a lot of tests and need immediate feedback on them.

With Python this is made easy with the help of nose and tdaemon.

In a hurry? Jump straight to the summary!

Installing

Both tdaemon and nose can be installed via Cheeseshop (or "PyPI", for the suits), using pip:

  sudo pip install nose tdaemon

(You might not need sudo, depending on your setup).

An interlude: pip versus easy_install

You can use easy_install instead of pip. It should work just fine, for what we're trying to do here. But do yourself a favor and switch over to pip. It's as simple as

  sudo easy_install pip

Another interlude: whither tdaemon?

If you google "tdaemon", the first result is a github tree from Bruno Bord, tdaemon's author. The version at Cheeseshop (yes, I'll keep calling it "Cheeseshop", damn it!) lists John Paulett as author and points back to the github repository as its home page. Both versions are almost exactly alike, except that the Cheeseshop one has a slight enhancement (a command-line argument to ignore specific directories). John Paulett took tdaemon, added that feature and packaged it for Cheeseshop. So we'll use his version.

Getting cute notifications

So far, if you simply execute tdaemon on a terminal, it'll monitor the current directory and run nosetests whenever it detects a change. Which is fine, but I don't want to switch to the terminal all the time while I'm programming, if I don't have to. So let's arrange our environment so that we get visual alerts every time the tests are run.

On Mac OS X

I assume you already have Growl on your Mac. If you don't, install it, it makes your life easier (if you don't know, it should be at the bottom row on your System Preferences panel).

The NoseGrowl nose plugin provides Growl notifications. Unfortunately, NoseGrowl installation is currently broken: there is only an egg for Python 2.5 on Cheeseshop, and the source code on bitbucket has a bug on setup.py. But the latter is easy to fix:

  hg clone http://bitbucket.org/crankycoder/nosegrowl
cd nosegrowl/nose-growl
# This next command simply removes a specific line from setup.py
# If you want to, edit setup.py and remove it yourself
# (and blame OSX for not shipping GNU sed)
echo -e "/install_requires=\['py-Growl'\],$/d\nw" | ed setup.py
python setup.py install

By the way, NoseGrowl's author, Victor "crankycoder" Ng, told me a few months ago that he was looking for someone to take over for him. So, if you find the project useful, please consider talking to Victor and volunteering to maintain it. Might make him less cranky :)

On Linux (Gnome)

Michael Gundlach adapted NoseGrowl to use Gnome's notification system. His version is called NoseNotify and can be installed directly from Cheeseshop:

  sudo pip install NoseNotify

I don't know if there is a notification plugin for KDE. If you do, let me know and I'll add it here!

Putting it all together

Open a terminal window and cd to the root directory of your project (tdaemon recursively looks at everything down from there).

If you're on OS X, type:

  tdaemon --custom-args="--with-growl"

If you're on Linux, type:

  tdaemon --custom-args="--with-notify"

Since you're passing custom arguments to nosetests, tdaemon will ask you to confirm that this is the command you want to run. Simply type "y".

Now you can create a file called, say, "tests.py", add tests to it and watch what happens as you save it!

tdaemon-red

tdaemon-green

 

Summary

Install nose and tdaemon:

  sudo pip install nose tdaemon

On Mac OS X, install NoseGrowl:

  hg clone http://bitbucket.org/crankycoder/nosegrowl
cd nosegrowl/nose-growl
# This next command simply removes a specific line from setup.py
# If you want to, edit setup.py and remove it yourself
# (and blame OSX for not shipping GNU sed)
echo -e "/install_requires=\['py-Growl'\],$/d\nw" | ed setup.py
sudo python setup.py install

and run as:

  tdaemon --custom-args="--with-growl"

On Linux, install NoseNotify:

  sudo pip install NoseNotify

and run as:

  tdaemon --custom-args="--with-notify"

That's it. Happy coding!

Syndicated 2010-08-01 17:57:23 from Bits of rbp - isnomore.net

Yahoo! Open Hack Day Brasil 2010

On March 20th and 21st, Yahoo! Brazil brought us our second Open Hack Day. I'd been to the previous one, in 2008, and it was amazing! Our project even won at a newly-created category, aptly named "What the Hack?"

This year, I wanted once again to try a hardware hack, using whichever parts I could get my hands on. Not necessarily anything useful, though. That's what I love about the Hack Day. I can do useful stuff throughout the rest of the year :)

Image © brhackday, used with permission

Yahoo! Hack Days

Before the 2008 Hack Day, I had pretty much written off Yahoo! as a company that was no more. I wasn't even particularly interested on the event, and only decided to go at the last minute. Boy, what a change in perspective. Of course, Yahoo!'s São Paulo team has some very clever people. But, more generally, I was very impressed with the data-gathering tools that Yahoo! had started offering. YQL is simply fantastic. It perfectly captures what the Internet is about, data-wise (I'm not saying it's perfect, but it embodies the right spirit). I hadn't had that much geek fun in a long time. So you can probably tell my expectations were high for this year's edition. Could Yahoo! deliver?

Not to fret, they knew what they were doing. Just put some 250 hackers in a fish bowl, give them food, coffee, wifi (surprisingly good, some silly proxy restrictions excluded), show them Monty Python, and wait for it!

Our hack, and our hackers

Image © brhackday, used with permission

Even before the announcement of this year's Hack Day, I'd been toying with the (admittedly silly) idea of a firefighting robot, that lurked online waiting for people to report fires anywhere in the world. It would then bravely roll over to wherever the fire was, and put it out. Bravely.

Trouble is, it'd probably have to be one gargantuan robot. So I thought I'd settle for a more modest, Lego-built, Arduino-controlled one. With the Hack Day approaching, I suggested this project to a few friends and we created a Wave to discuss the idea. I was planning to use a box of old Lego pieces from my childhood (see mom? I told you I'd have eventually use those again!) and a couple of servo motors I had lying around, but Rodolpho brought his Mindstorms NXT into the picture, making the project much cooler (and, incidentally, much more manoeuvrable).

On Saturday morning I rode with Gola to the (really cool) auditorium of Senac University, where the previous Hack Day had already been hosted. There we met Rodolpho and Mobi, our original team. We had found out the day before that there would be a limit of 4 people on each team, this year. In 2008 our team had been comprised of... 12? 15? I never even knew. We'd simply started building weird, blinking stuff, and people had gathered around for the fun. We got, therefore, a bit disappointed with this edition's limit. But, since we weren't really expecting to win anything (and therefore disqualification wasn't an issue), we bent the rules a bit, and Werneck, Lucmult and Mauro hacked with us. Also, Aline joined us a bit later. Since Werneck and Lucmult eventually had to leave and didn 't return for Sunday, and Aline and Mobi didn't program, I think we were sort of in the clear. Technically. Sort of.

And then we started building.

What we built

The robot, in construction. Photo by alickel

The body of the robot ended up using mainly the Mindstorms parts. We had started building a larger, sturdier body with assorted Lego pieces on top of a rigid board, pulled by front-wheel drive with four wheels in the front and a loose trailing one. But, after a lot of testing, the loose wheel kept veering the robot out of track, so we rebuilt everything with a lighter, smaller frame, and a pair of caterpillars tracks. In hindsight, I think we should have kept the larger body (even if rethinking wheel traction), as it gave the robot more stability, which we would come to miss later. But we had to make a quick decision, and we worked with what we had. The NXT controller sat on the robot and communicated with an external server via bluetooth, relaying control input to the wheels and sending back odometry information.

This external server (actually, Rodolpho's notebook) continuously used YQL to query Twitter, Yahoo! Meme and news feeds (which I originally wanted to aggregate using Yahoo! Pipes, but we didn't have time for it), searching for people reporting fires - a simple string search, filtered by the Yahoo! Term Extraction API. Whenever there were reports, the server would send them through the Placemaker API to extract location information. It then determined which location in the world was in most urgent need of aid (by number of reports).

Now, the tricky part: the robot needed to be aware of a rectangular projection of the world onto the room, and to know its own location on it. I don't mean a visual projection. We did consider it, but realised that it would be unfeasible for the Hack Day. We toyed with the idea of printing (or drawing) a world map on large sheets and taping then to the ground, but the robot would surely slip, trip, or tear the sheets. So we settled for an abstract projection, and, based on information sent back from the robot, plotted its estimated current position in the "world", at each instant, using Yahoo! Maps and the Yahoo! Geocoding API (via geopy).

To locate itself, the robot relied on Mindstorms' odometry feedback, and on QR Code markers distributed around the room, read by an Android phone using Python (from the ASE) and the Barcode Scanner app. The Android phone sent the information encoded in each QR Code to a custom service built with Python's SimpleHTTPServer, which our server polled. The server then sent back new movement controls, according to the robot's current position and desired target. We tried to use Mindstorms' sonar and colour sensors, but they just wouldn't work reliably with the Python interface (which we needed to send commands programatically via bluetooth).

A happy robot. Image © codepo8 CC BY 2.0

No one likes an impersonal robot, and ours, accordingly, had a face in order to convey emotions. We used an XO laptop as the head, and defined that the robot would have pre-determined emotions depending on the situation: it would be "at rest" when there were no fires going on, "worried" when it was going towards a fire, and "happy" when it had put the fire out. A Python script running in the background continuously searched Flickr (using YQL) for expressions associated with each of these emotions, and downloaded a number of related pictures. Another script queried the robot's current emotional state (set by the server), and displayed an appropriate random subset of these pictures. For every few of them, we'd display a face that Aline had drawn specifically for that emotion, to make up for the fact that we couldn't be sure if the pictures would depict it (people give the weirdest tags and descriptions to their Flickr uploads...).

We originally meant to use an Arduino to control a servo that would squish some water from a syringe, thus putting out the fire once the robot got to its destination. But all that proved too much for a mere 24h, and we had to settle for a manual pump.

A camera-shy robot, and a sleepy presenter

Of course, we'd tested (almost) everything, and the robot worked (almost) perfectly. (Almost) Great. But, when it was time to go up on the stage, we hit a few snags.

First, there was only one large screen. Of course, we'd known that, but it hadn't occurred to us that people would need to see not only the robot (which was tiny, especially at a distance), but also the map showing its movement towards the fire, at several different moments. Yahoo! had predicted even such an eventuality (seriously, guys, kudos!) and provided us with a way to switch between our server's screen and the feed from a video camera which Aline used to film the robot. But I didn't manage to coordinate the switch properly, and we didn't get to show the animated map.

Also, we had already noticed that the XO weighed a lot compared to the rest of the robot (remember what I said about the previous, sturdier version?), and that, in order to steer, we needed to balance it carefully. I didn't, and the robot soon went out of its path.

Finally, we had used so many different technologies and APIs on this project, and most of them simply vanished from my mind when I started presenting! Note to self: next time, write some hints on the back of my hand...

All I have to say for myself is that I had slept for only about 1 hour since the previous morning, ours was one of the last projects to be presented, and by then I was very sleepy and barely able to react. I should have switched from the camera to the map more often, so people could see what was going on. I should have grabbed the robot when it went off track and restarted the demo. I should have asked my teammates for help when trying to list everything at work on the robot. Shame on me.

But, all in all, I think it was a great project, and I'm very proud of it. I'm especially proud of my team, you rock much more than I was able to show :)

And, next year, I promise to take a nap before presenting!

The Robot. Image © brhackday, used with permission

Syndicated 2010-04-05 22:26:24 from Bits of rbp - isnomore.net

25 Oct 2009 (updated 21 Feb 2010 at 02:04 UTC) »

Google Wave invite giveaway result!

Thanks to everyone who participated in the Google Wave invite giveaway!

I've just drawn a random name from those who followed the giveaway rules (on Google Reader, "like" one of the other two posts on this site, and share the giveaway one). I've recorded the drawing process, so you can see it was done in all fairness:

*[I had embedded a video here, but some people reported problems with it. So now here's a screenshot, and you can see the video separately, if you want; sorry]*

Giveaway drawing

Congratulations, Sviatoslav S, you get the Google Wave invite! Please add some contact information (at least temporarily) to your Google profile, so I can send you your invite. If you have any questions please send me an email or leave a comment on this post. I hope to hear from you soon!

[Update]

It turns out I do have a second invite! And, ironically enough, I found it quite hard to get rid of it...

Once I found out I had the extra invite, I quickly drew another name from the list:

Second giveaway, first drawing - it sank into the swamp

Congratulations, Maurizio! You... Oh, wait. Apparently he's not following the rules of the giveaway. I can't really tell whether he never has or if he gave up after the first invite went out, but rules are rules. So let's draw another one:

Second giveaway, second drawing - that sank into the swamp

Hooray! Brian was one of the first to participate when I announced the giveaway. So I contacted him. But he had already been invited by somebody else, and graciously allowed me to hand the invite over to another participant. So...

Second giveaway, third drawing - intermission

Right. Daniduc is already in Google Wave. He had actually "liked" and "shared" the posts before I announced the giveaway, and had already told me he wouldn't need the extra invite. Next!

Second giveaway, fourth drawing - burnt down, fell off, then sank into the swamp

Ah! I'd talked to Leonardo just yesterday, and he didn't have a Wave account yet! So congr... Ah, he got his from someone else this morning. Right. But the fifth one...

Second giveaway, fifth drawing - stayed up!

So that's what you're going to get, Badá! The strongest castle in these islands A Google Wave invite! I've already added you to the list, hopefully Google will send you the invite soon.

As for the others, thank you so much for participating!

Hope to see you all soon on Google Wave :)

Syndicated 2009-10-25 02:18:25 (Updated 2009-10-25 03:18:25) from Bits of rbp - isnomore.net

Giving away one Google Wave invite (or two)

[A quick note for the lazy: read at least the "But how?" section below. It explains what you need to do to qualify for the giveaway]

So, Google Wave is quickly reaching a stage of being actually useful for daily communication. I've used it for planning trips and dinner parties, coordinating server maintenance, doing collaborative translation and just generally chatting, with varying levels of success.

I got my invite to the sandbox (a developer preview, not integrated with the rest of Google's services) after attending Google Developer Day São Paulo. I played around for a while, but it was too unstable. A few weeks later it had improved considerably, so I started using it again. But too few people I knew were there, and its use as a communications tool was therefore obviously impaired.

A few weeks ago, then, Google promoted Wave to http://wave.google.com, and there was much rejoicing. As a sandbox user, I got an invite to it, and with it 8 more to give away. I distributed them to a few close friends, but ended up with one left!

And that's the one you might get :)


"But how?"

[updated about 1h after originally posting, to correct the rules]

Google Wave invite

It's really simple. After a long period of inactivity, I've resumed writing on isnomore.net. There are currently two posts (not counting this one): one about programming Python on the Android, and a recipe for Spaghetti alla Carbonara. So, access isnomore.net's RSS feed on Google Reader and pick the one you like best. Then "like" it (by clicking the proper button at the bottom of the appropriate post, on the Reader screen), and share this post (the one you're reading right now).

To make it clear: you should "like" one of the other two posts currently published ("Pushing up Python on Android" or "Spaghetti alla Carbonara"), and share this one ("Giving away one Google Wave invite (or two)"). You may also share and like others at will, but that's the minimum to qualify for the giveaway.

Important: if you "share" and "like" from someone's shared items, or some other address you might have (if you used to subscribe to this site's old feed, for instance), it won't show up on my count and I can't know you've done it! So the safest bet is to go straight to the feed on Google Reader and choose from there (like so). In any event, if you feel that there is any confusion, let me know.

Within three days (that is, on Saturday the 24th of October) I'll collect a list of the people who've liked any of the articles and pick one at random. If that person has also shared the article, they get the invite (otherwise, I'll just pick another one from the list, and so on). I'll post the results here on Saturday, and I'll also contact whoever was selected via their Google account (if you want me to use a different email, let me know in the comments or "Share with note" and leave a comment to that effect there).


"What if I share and like both articles?"

Well, you'll make me very happy, please do! But it won't improve your chances, I'm afraid.


"I already have a Wave account (or don't want one), but I'd like an invite for a friend"

Sure, no problem. If you are selected, just let me know the email to which I should send the invite.


"But I don't have a Google Reader account!"

Well, a Google Reader account is just a regular Google account. If you've never used Reader, just give it a try, it's really simple. If you don't have a Google account at all, you'll need one for Google Wave anyway, so you might as well create it now!


"If I'm picked, how long until I have a Google Wave account?"

That's not up to me. Google Wave invites actually mean Google will know that someone invited you when the time comes for them to offer a new round of accounts. But they don't say when that will happen, or even whether everyone on the current invite list will get an account on the next round. In practice, accounts have been handed out at a relatively high pace, but I can't be sure.

All I can promise is that I'll put your email address on my invitation list as soon as you confirm it.


"Wait, the title said or two!"

That's right. I might have an additional invite. It's a bit of a long story, but I can't be sure. So, if it turns out that I do, I'll pick two people. Otherwise, that's just one lucky winner :)


"But... But... I am your friend and didn't get an invite from you! I even asked on Twitter!"

Calm down, don't be offended. First of all, most of my invites went to the people with whom I exchanged the most emails and instant messages. Makes sense, right? Besides, some of the people to whom I had promised invites ended up not needing them (having received one by other means), so I didn't know from the start I still had invites left.

Finally, I specifically avoided giving them out to people asking around on Twitter (as opposed to asking me personally). Asking in broadcast mode meant that, by the time I invited you, someone else might have also done so. From my experience with the other people I've invited, multiple invites don't seem to make your account arrive any sooner. As Google Wave invites are currently somewhat scarce, that would be a waste of one, which would be a shame. And I want the highest number of people on Wave, the sooner the better.


"I have more questions! You can't predict and fake-quote them all!"

True. Leave me a comment!

And good luck! See you on the Wave :)



Sharing and Liking isnomore.net on Google Reader

Syndicated 2009-10-21 03:39:36 from Bits of rbp - isnomore.net

8 older entries...

 

rbp certified others as follows:

  • rbp certified acme as Journeyer
  • rbp certified thiagom as Apprentice
  • rbp certified brain as Journeyer
  • rbp certified bruder as Apprentice
  • rbp certified morcego as Journeyer
  • rbp certified riel as Master
  • rbp certified godoy as Apprentice

Others have certified rbp as follows:

  • morcego certified rbp as Journeyer
  • bruder certified rbp as Journeyer
  • godoy certified rbp as Apprentice
  • rw certified rbp as Journeyer
  • maragato certified rbp as Apprentice
  • jarod certified rbp as Journeyer
  • minami certified rbp as Journeyer

[ Certification disabled because you're not logged in. ]

New Advogato Features

New HTML Parser: The long-awaited libxml2 based HTML parser code is live. It needs further work but already handles most markup better than the original parser.

Keep up with the latest Advogato features by reading the Advogato status blog.

If you're a C programmer with some spare time, take a look at the mod_virgule project page and help us with one of the tasks on the ToDo list!

X
Share this page