The Tough Mudder

This post will be a brief departure from my usual programming/robots/technology ramblings and talk about something else really cool that I did recently. Yesterday me and 2 friends ran and completed the Tough Mudder in Toronto (well actually it was in Barrie but they called it the Toronto Tough Mudder).

Backing up about 3 months when my friend first posted a trailer for the Tough Mudder on my Facebook wall. We decided we had to do it. We decided but we didn’t do much about it we continued with our standard lifting gym routine and aside from my intramural sports team I wasn’t doing much running. It was almost as if we hadn’t noticed that this thing was a half marathon through the mud - no big deal right?

With only a month to go I finally realise that I am going to need to do some running training. I am in decent shape at this point from the lifting but I definately don’t consider myself a runner. In fact that last time I would have said that I thought I was a good runner would have been grade 6 yeah no joke the filler years were mainly filled with mountain biking, skiing and school. But that was about to change and by the end of my 4 week training program I considered myself a runner again.

So I started training running but I was determined to do it my way. People who know me know that I am a strong believer in the primal lifestyle and while I don’t want to debate that here I simply want to share how I trained and the results. My running training program consisted of running 400 meter intervals trying for a time better than 1:40 which translates to being faster than a 7 minute mile. After each interval I would rest for 1:30 each workout was only 10 intervals, sometimes I would finish with a few 100 meter sprints. During this time I also consulted quite a few resources on how to run properly notably Timothy Ferris’s The 4 Hour Body and some YouTube videos. Oh and of course I was running in my vibram five finger shoes.

The vibram five fingers, I had long been wearing them for lifting and my day to day shoes were essentially barefoot shoes too but I had never really ran in them (I still used cleats for the sports I play). After my first week my calves were so tight it was hard ish to walk – apparently this is common when people start barefoot running. I was determined to power through which meant lots of stretching and using the foam roller. 2 weeks to go and I wasn’t sure if I would be able to run the Mudder in my barefoot shoes. At around this time the 100 meter sprint was on in the London 2012 Olympics and I was super excited to watch Usain Bolt do his thing. Watching his stride inspired me and I also realised an important thing – barefoot running is essentially just proper running re-branded  I mean watch Usain Bolt run no heal strikes there. Re Motivated I trained hard for the next 2 weeks and my calve tightness was becoming less of a problem.

Before talking about the Mudder itself I just want to re-iterate the important details here – I trained for this long distance event using high intensity intervals, I followed my primal diet and did not carb load for training or for the race and I ran in vibram five finger shoes.

The Mudder itself was awesome, like so awesome! 10 out of 10 would do again. One thing that really caught me off guard was the elevation change of the course – it took place on a ski hill so there was some serious vert. The run went great I was pretty fast on the flats ahead of my team most of the time. The hills were nice because it was a really big equalizer. The obstacles were a ton of fun too, most of them weren’t too hard. I really enjoyed this one where you had to crawl through this underground tunnel – reminded me of video games and air ducts etc. I certainly will pause and remember how tough that was next time I am running through the vents in Half Life! The famed electric shock finale was also quite awesome, I took one right in the chest which dropped me to the ground like a sack of potatoes but I was up and running again in the blink of an eye. Crossing the finish line was amazing and they immediately hand you a beer! Best beer ever.

My 2 team-mates running through the electro shock finale. I am somewhere to their right unfortunately not in the picture

We submitted our time and later found out that we finished in the top 5% and qualified for the World’s Toughest Tough Mudder! Notbad.jpg don’t think we will be going though.

Our trusty stopwatch after we crossed the finish lie. 2 hours 54 minutes.

read more

ARPool 2.0

After our successful but not stress free demonstration of ARPool at the Ontario Centers of Excellence Discovery Show I took it upon myself to make a rather large structural change to the ARPool program in an effort to avoid similar problems in the future. I wanted to change ARPool from an event driven program to what I refer to as a state machine, a technique I learned through my involvement in First Robotics.

If you read my last blog post on our experience at OCE you’ll know that one of our main problems with the system was difficulty understanding the order in which code was called and our lack of control over changing this process. The ARPool system relied on several timer events as well as signals and slots in an interrupt fashion to get things done in the right order. If things are not executed in the right order then the system simply has no chance – for example if the projector doesn’t illuminate the table before we try to detect the pool balls then it won’t be able to find them. We had many problems with the system becoming out of sync and the whole experience felt rather unstable even after the system was working.

Now don’t get me wrong it’s not that I think event driven programs are bad – they aren’t and in many applications it is the only possible way to make something work, it’s just that in the case of ARPool it doesn’t make any sense. ARPool is a program that only needs to do one thing at a time and it all needs to happen in the right order – so why bother with all the event driven stuff? The final point is that being a University lab we don’t have the resources to maintain a system that complicated and many people who have and will work on the system don’t have the required background to effectively work on such a system. ARPool needed an overhaul.

Introducing the state machine: It is really quite a simple idea - there is a main loop and inside this loop there is a single switch case block. The switch is executed on a “state counter” variable which for extra points should be made an enum with relevant state names. Inside each state (a case block) the program does its thing and then if appropriate changes the state counter to the next state or leaves the state variable as it is. Here is a simple example:


enum State
{
    detectBalls,
    trackCue
};

State state = detectBalls;

while(true)
{
    Switch(state)
    {
Case(detectBalls):
detectBalls();
state = trackCue;
Break;

Case(trackCue):
// code
Break;

// and so on…
    }
}

It’s probably not the first you thing you would think of but after you try it out it’s a pretty nice way to do things. I picked up on this approach earlier this year while working on programming the CRio device for First Robotics – see First Robotics has these built in safety functions around your robot class if your robot’s main function doesn’t finish executing at least several times a second it assumes that you’ve either lost communication or wrote an infinite loop. You’re basically forced into this state machine idea if you want to do anything complicated.

Anyways First’s API and safety functions are a topic of a different rant how did all of this turn out for ARPool? Well surprisingly well it only took me about 2.5 hours of straight coding to completely pull out the Qt gui, remove all the event driven code and re-write the main program to utilize the state machine concept. It compiled and the code was way cleaner, shorter and I could finally see where and in what order my vision functions were called. All in all a great victory – however it was time to return to my other projects and leave my shiny new ARPool program sitting there waiting to be tested on the real system.

*edit* 09/01/2012 I finally got my shot to try the new ARPool code, it actually worked! Every programmer has a few moments they are proud of and this was definitely one of mine, re-structuring an entire program (like major major stuff here) not being able to test it for months and it actually just worked! Not every day gets to be like this.

read more

ARPool OCE Discovery

ARPool (Augmented Reality Pool) was a project I was always very interested in getting involved with so when my supervisor mentioned he need a few of us to get the system ready for a demo I jumped on the opportunity. We were going to be taking ARPool to the Ontario Centers of Excellence Discovery Show – it is kind of a mix between a trade show and a conference poster session. The Queen’s marketing guys were also super excited because they felt Queen’s was out done the previous year and ARPool was our show stealer.

The first thing we had to do was update the travelling version of ARPool, what we needed was an enclosure to keep it dark ish around the system – if it is too bright then the augmented reality projections onto the table are tough to see. We also needed to build a new mount for the projector and camera, our supervisor wanted to try straight projection rather than off of a mirror so it needed to be higher up. We experimented with a few ideas and set up the system in Beamish Monroe Hall and ran a successful demo for Queen’s Admitted Students Day.

At this point I hadn’t had too much exposure to the code behind ARPool but it was already clear that the system was not what I would call rock solid. Near the end of the demonstration the ball detection algorithm was not finding all the balls on the table – fixing the ball detection algorithm would be my first contribution to ARPool. Having learned that testing new algorithms on a live system lacks the quantitative feedback that is necessary to get the best results I took a handful of test images and headed back upstairs to my lab to tackle the issue. A quick look at the old detection algorithm and it was easy to see how the system was suffering from having multiple inexperienced developers. The algorithm went through 4 iterations of finding contours, then drawing the contours to a new image albeit with some filtering each time (area, shape etc.) and then running find contours on this image. I would sincerely hope that the find contours algorithm can find the contours you just drew…

I rewrote the ball detection routine, tested it on my data set and then when I was satisfied brought it back downstairs, ball detection back online. Next I tackled the Background subtraction code – it was actually pretty good but I was able to speed up save and load times dramatically by switching to cv::FileStorage from plain text. We added a simple smoothing filter to the cue tracking just to make the system appear less jumpy to users. The system was working pretty well although there were a few design choices I didn’t care for I thought we were in good shape for OCE.

Raw background subtraction output
Filtered binary image using contour extraction
detected pool balls overlaid on the input image

We packed it all into a single cube van which was seriously pushing it space wise and took off for Toronto. We spent most of the first day schlepping everything from the parking lot to the conference hall and then setting up the structure and pool table etc. We started into the calibration process and while it wasn’t smooth it wasn’t much worse than usual. Calibration finished enter the big problems… We load up the version of the code we had finished with at Queen’s and it isn’t working – wait what this code just worked!? Things are happening out of sync and we can’t figure out why, this is where my frustration with the way the system is set up begins. We eventually load up the code from before we fixed all the various algorithms and it is at least running in the right order… so we slowly add back one feature at a time until the system is working as we left it. I don’t like this – we never figure out the problem and this seems unstable. Oh and by the way it is now the next day at 1:00 the event is starting we got it running just in time. The system runs great for 4 hours straight we’re all a little surprised frankly. We demo to a lot of interested people mostly other demonstrators at the event (I’m still not totally sure I really understand the point of this event). We had back to the hotel after the reception which by the way was pretty fun oh and did I mention the Queen’s put us up at the Royal York (its pretty swanky). After dinner we went to a Jay’s game to relax for the evening.

The next morning (and this is the more important day of the show) we arrive and boot up ARPool – aaaannnd its not working today seriously this system is moody we ran it 4 hours straight no issues yesterday and now its deciding not to work again. I don’t remember exactly how but I do remember that I was the one who fixed it – I added or changed some piece of code that was completely trivial and then the system started working again – hmmm whatever I just want to get through this day now.

Got the system up and running and the day was a success – pics or it didn’t happen!

Our demo booth
A conference attendee playing ARPool

So what was the issue? Well ARPool is an event driven program written in Qt using signals, slots and the works including several timer events. Our best guess is that sometimes they would get our of sync. We had worked really hard on improving the algorithms but what really got us in trouble was the system layout and how tough it was to see and control the order code was executed. The higher level stuff was really poorly organized and documented for example there were 2 functions that were very key to the operation one called “run” the other “run_again” uh yeah that is not how we do things.

All in all a successful but certainly not stress free trip. I vowed to fix the system layout of AR Pool before our next demo because I did not want a repeat of OCE - that and I’m an engineer and I have the problem solving bug and this was a problem screaming to be solved and I already had an idea how…

read more