Gradle: Checking for SNAPSHOT dependencies on a release build

I swear that Gradle used to prevent you from uploading a SNAPSHOT dependency to Maven central in the past. If it ever did, it no longer does as I have screwed up a two times. The reason this is bad is that the SNAPSHOT will eventually expire breaking your project. Thought I was careful on my latest release of BoofCV, but I missed one reference.  Now I have to do a new incremental release, which is a pain and confusing for the users.

To overcome this problem I added the following code to my build.gradle file.  What it does is check all dependencies in each subproject for the word SNAPSHOT.  If one is found it throws an error explaining what happened.

subprojects {
    task checkDependsOnSNAPSHOT << {
        if (version.endsWith("SNAPSHOT"))

        project.configurations.compile.each {
            if (it.toString().contains("SNAPSHOT"))
                throw new Exception("Release build contains snapshot dependencies: " + it)
    jar.dependsOn checkDependsOnSNAPSHOT

This works in Gradle 3.2

Rovio to 3D Stereo Point Clouds


This disparity image was created using a single Rovio robot by taking pictures from two different locations.

I’m a bit late to the game of Rovio hacking, but here I am experimenting with using a Rovio I bought two years ago.  The Rovio by Wowwee is a remote control car that has a camera mounted on it that can be controlled over wireless web based interface.  When it was discontinued, the existing stock was liquidated in a fire sale, where they were sold for around $100 each.  You can still buy them now, for about $400, on Amazon. Keep in mind you might need to buy a new battery and power supply.

WowWee Rovio Wi-Fi Enabled Robotic WebCam

Picture of a Rovio

Picture of a Rovio

One of the things that makes Rovio so great, and more than a simple toy, is that it can move in any direction! Which means, that unlike your standard remote control car, it can move sideways. This is exactly what you need if you want to do stereo vision and create a point cloud.

The figure to the left shows a disparity image created using a single Rovio by driving it a few inches to the right.  In this disparity image warmer colors are closer and cooler colors are farther away.  See below for the input images.  From this disparity image you can create a point cloud, which can then be used for making 3D models or obstacle detection.  This process is entirely automated using BoofCV and the source code is available online on my Rovio Github project:
So how does this work?  Well a full explanation would be quite detailed.  The image processing code is for the most part cut and pasted from examples on BoofCV’s website.  A list of relevant example is found below:

 Initial Setup

You will need to do the following once so that your camera is calibrated and that the software knows your robots parameters.

  1. Checkout source code from Github
  2. Calibrate the camera.
    1. Look at this first BoofCV Camera Calibration
    2. Collect images in 640×480 using ManualControlApp by pressing ‘m’
    3. Select good images, run calibration app.  Pixel error should be around 0.3
  3. Get your robots MAC address using ManualControlApp by pressing ‘a’
  4. Create directory for your robot in robots.  Place intrinsic.xml and file “mac” with the MAC address.  See existing examples

Creating Point Cloud

Once you have done all of that all you need to do now is place the Rovio in a well lit room in front of something with lots of texture and run AutoPointCloudApp.  That app will automatically figure out which robot it is controlling, loading calibration, collect and image, move the robot, and collect another image.  The two images are then processed and the results displayed.  Don’t forget to change the IP address in the main() function of AutoPointCloudApp.



Associated points between the two views using SURF features.


Rectified Stereo Images from Rovio



Synthetic top view created using 3D points computed from the disparity image.


Will Liquidlogic Stand by their Drain Plugs?

Stomper missing its drain plug

Loiquidlogic Stomper missing its drain plug.

At the end of October 2012 my boat finally lost its drain plug. The drain plug had issues almost from the start and never really liked being attached of the boat.  Sometimes it would take a minute or so to screw it in, unless you aligned things just right.  While a minor issue really, things changed when it finally left the boat entirely.  After taking a picture of the boat (right) I felt it was time to contact Liquidlogic and see if they would stand behind their products and provide a new drain plug.  E-mail exchange is posted below.



E-mail exchange with liquidlogic

E-mail exchange with liquidlogic



While Liquidlogic was very quick to help out and provide a new drain plug, they seemed less inclined to consider related structural damage.  Would have been nice if they replied to the last e-mail. Just in case you are wondering, the drain plug was lost while the boat was stuck underwater for several days.  Swam after my paddle just stuck in a rock on the first rapid in Greatfalls Virginia.

Incorrect Equations in “Review and Analysis of Solutions of the Three Point Perspective Pose Estimation Problem”

In the 1994 paper “Review and Analysis of Solutions of the Three Point Perspective Pose Estimation Problem” by R. M. Haralick, C-N Lee, K. Ottenberg, and M. Nolle, I found a couple of important typos in the equations for the Finsterwalder solution.  This paper describes several solutions to the Perspective Three Point (P3P) problem, two of those solutions I ended up implementing.  The Grunert solution is correct and easy to implement, while the Finsterwalder solution is a little bit more involved.  However since the equations are incorrect for Finsterwalder you could be in for a bit of frustration.

I could not find an e-mail address on the first author’s website.  The paper is also a bit old (but still relevant) and the problem was most likely already reported.  If I’m the first person to notice or try to report the problem after 18 years then it’s a non issue.  However, to help others out there (the one or two which have found this website) here are the corrections:

After it has been corrected, the first line in equation (16) should be:

(b^2 - m^2c^2)u^2 + 2(c^2(cos\beta -n)m - b^2cos\gamma)u

Note that a power of 2 has been added to ‘m’. The equations on the top of the right column of page 337 also needs to be correct and should be:

A = b^2 - m^2c^2
B = c^2(cos\beta -n)m -b^2cos\gamma
C = -c^2 n^2 + 2c^2 n cos\beta + b^2 - c^2

Here a power of two was added to ‘m’ in the first line and ‘c’ in the third line.  Hopefully this post will save someone a few hours of aggravation and deriving equations.