Tuesday, April 23, 2013

Really, Eclipse?



Is it really likelier that Java source code contains the word "Anteaters" than "Annotators"? You've failed the IDE Turing Test.

Sunday, April 7, 2013

Stack Implementation in Java

Terminology
A stack implements the LIFO principle: Last In, First Out.
This is just a fancy way of saying that a stack behaves like a pipe that contains ping pong balls: you always have access only to the last ball you've dropped into the pipe.

Inserting elements into the stack is also known as pushing on the stack:

Taking out elements from the stack is also known as popping from the stack:
Attempts to pop() from an empty stack lead to stack underflow; symmetrically, attempts to push() on a full stack (with regard to a predefined maximum size) will lead to stack overflow.

Complexity
We have no control about where we insert in the stack, or which element we get out from it. But the reward of this lack of control is that both pushing and popping have O(1) complexity. Also checking whether the stack is empty or full can be done in O(1).

Java Implementation
The implementation of the stack in Java is straightforward:
public class MyStack
{
	private int[] s;
	private int top;
	private final int MAX_SIZE = 10;

	public MyStack()
	{
		top = 0;
		s = new int[MAX_SIZE];
	}

	public void push(int element)
	{
		if (top == MAX_SIZE-1)
			System.out.println("Stack overflow during push()!");
		else
		{
			s[top] = element;
			top = top + 1;
		}
	}

	public int pop()
	{
		if (isEmpty())
		{
			System.out.println("Stack underflow during pop()!");
			return -1;
		}
		else
		{
			top = top - 1;
			return s[top+1];
		}
	}

	public int getTop()
	{
		return top;
	}

	public boolean isEmpty()
	{
		return (top == 0);
	}

	public void printStack()
	{
		System.out.print("Stack: ");
		for (int i = 0; i < top; i++)
			System.out.print(s[i] + " ");
		System.out.println("\n");
	}
}

Friday, March 22, 2013

Implement ROS functionality as part of Qt application

Installing Qt for ROS is very simple: you just need to install the ros-ROSDISTRIBUTION-qt-ros package. For instance, under Groovy, you would do it like this:
$ sudo apt-get install ros-groovy-qt-ros
Then, to create a ROS package with Qt capabilities, you would do:
$ rosrun qt_create roscreate-qt-pkg PACKAGE_NAME
The relevant folders in the created package are the following:
/ui
|---main_window.ui <- This is where the GUI is defined; you can edit this with Qt Creator, for instance.

/src
|---main.cpp <- The main function of the application.
|---main_window.cpp <- This is where you initialize things, connect signals and slots, etc.
|---qnode.cpp <- This is where you define your functionality: for instance, a callback for a ROS subscriber would be defined here.

/include/PACKAGE_NAME
|---main_window.h
|---qnode.h

Sunday, March 10, 2013

Using ROS to save periodic snapshots from Asus Xtion camera

This is a small program that uses ROS (Groovy) to take snapshots from your openni camera and saves them in .ppm format (P3).
Internally, it is just a subscriber to the camera node. It is probably best to have worked through the ROS beginner tutorials before following this.

The data coming from the camera is in this format: http://www.ros.org/doc/api/sensor_msgs/html/msg/Image.html
We want to write it in ppm format: http://en.wikipedia.org/wiki/Netpbm_format#PPM_example

We will take the time stamp of the image and generate the file name as YYYYMMDDThhmms.ppm, with a small detour through posix time because ros::Time can't be converted directly to string.
More on posix time here: http://www.boost.org/doc/libs/1_53_0/doc/html/date_time/posix_time.html

First, create and build the package for this project (I've called it a very uninspired "screenshot", and by the time I realized I was not in fact taking screenshots I was almost finished, so there you have it), adding as dependency image_transport (you can also add it later via the manifest file):
$ roscreate-pkg screenshot std_msgs roscpp image_transport
$ rosmake screenshot
Then create the subscriber (mine is called "cam_listener"), not forgetting to add it to Cmakelists.txt:
$ rosbuild_add_executable(cam_listener src/cam_listener.cpp)
The main() function in cam_listener.cpp looks like this:
int main(int argc, char **argv)
{
 ros::init(argc, argv, "cam_listener");
 ros::NodeHandle n;
 
 image_transport::ImageTransport it(n);
 image_transport::Subscriber sub = it.subscribe("camera/rgb/image_color", 1, imageCallback);

 while (true)
 {
  ros::spinOnce();
  ros::Duration(15).sleep(); // Take screenshots every 15 seconds
 }
 
  return 0;
}
We use image_transport to create a bit more specialized subscriber, in order to get data from the camera. The callback is named "imageCallback", and it looks like this:
void imageCallback(const sensor_msgs::ImageConstPtr& msg)
{
    // Writes the raw image data in a PPM formatted file
    
    // We convert the time stamp that comes in the header of the data from the camera to posix time, in order to use it as part of the ppm filename
    ros::Time stamp = msg->header.stamp;
    boost::posix_time::ptime posix_time = stamp.toBoost();
    // We only take part of the posix time
    std::string filename = boost::posix_time::to_iso_string(posix_time).substr(0, 14) + ".ppm"; 
    std::ofstream f(filename.c_str());
    if (!f)
    {
       std::cout << "Couldn't open file.\n";
    }

    std::cout << "Writing data to file " << filename << "\n";

    // On the first line, the magic marker for a PPM file -- "P3"
    f << "P3\n";
    // On the second line, the number of columns and the number of rows
    f << msg->width << " " << msg->height << "\n";
    // The max colour value
    f << "255\n";

    // Write the triplets of colour
    int row = 0;
    int pixel;
    while (row < msg->height)
    {
        pixel = row * msg->step;
        while (pixel < (row+1)*msg->step)
        {
            // B = pixel, G = pixel + 1, R = pixel + 2 -> we need RGB for the PPM format
            // Since we are working with unsigned char, cast it to int for writing to the file
            f <<  static_cast< int >(msg->data[pixel+2]) << " ";
            f <<  static_cast< int >(msg->data[pixel+1]) << " ";
            f <<  static_cast< int >(msg->data[pixel]) << " ";
            pixel += 3; // Jump to the next bgr triple
        }
        f << std::endl;
        row++;
    }
    f.close();
}
Basically, we write the header of the ppm file and then the plain text values for the pixels. The only tricky aspect is the order of the rgb pixels. The encoding of the data from the image is bgr8 (check it yourself in msg->encoding!), whereas for the ppm file we need rgb. That's why, on lines 35-37, we take the values in reverse order.

In order to run the program, we start roscore in one terminal, and the openni camera in another terminal:
$ roslaunch openni_launch openni.launch
In a third terminal, we start our listener:
$ rosrun screenshot cam_listener
Every 15 seconds, a shot from the camera will be saved in the package's root folder in which you start the listener, so you can see the angry faces you make while debugging the ever-changing ROS packages! :D

Using ROS to view input from Asus Xtion

This post shows how you can use ROS to view the input from your Asus Xtion camera.

My system configuration:
Ubuntu 12.10 32b
ROS Groovy
Asus Xtion


Start roscore in a terminal.

In another terminal, open the openni device (here, the Asus Xtion camera):

$ roslaunch openni_launch openni.launch
Make sure the camera has started ok. You should see at the end something like this:
...
[ INFO] [1362906100.839021507]: Initializing nodelet with 2 worker threads.
[ INFO] [1362906104.029471453]: Number devices connected: 1
[ INFO] [1362906104.029784696]: 1. device on bus 001:09 is a PrimeSense Device (600) from PrimeSense (1d27) with serial id ''
[ INFO] [1362906104.031251209]: Searching for device with index = 1
[ INFO] [1362906104.065753491]: Opened 'PrimeSense Device' on bus 1:9 with serial number ''
[ INFO] [1362906104.097498307]: rgb_frame_id = '/camera_rgb_optical_frame'
[ INFO] [1362906104.097716391]: depth_frame_id = '/camera_depth_optical_frame'
If it doesn't start ok, it might be because the camera is plugged in a USB3 port. In that case, just switch to a normal USB port.

In yet another terminal, run the image_view node:
$ rosrun image_view image_view image:=/camera/rgb/image_color
 A window should pop up, showing the normal video output of the camera.

Sunday, January 20, 2013

iTunes hate

Whenever I think I can't hate this piece of counterintuitive s**t more, it is very helpful in assisting to change my opinion.

In the previous version of iTunes, pressing the Delete button would remove a track from a playlist. As one would expect.
Not so in iTunes 11! Here, you have to press CTRL + Shift + Delete. Yeah, that's "improved my ease of use" alright: by -100% ! (100 is a normalized value, of course -- I did not have 100% ease of use before)

I'm sick of the advice to "read the tutorials and get rid of my Windows-based expectations": I don't care how "intuitive" it is for various happy users -- it's 2013, if I have to spend 5 mins googling to understand how to delete something from a list, it's definitely not intuitive.

Now, on to "adding a track to my iPod".
...What, you thought you could just right-click a track and say "add to iPod"? That's because you are a sane person, not the team behind the iTunes UI design.

EDIT: A helpful soul on the iTunes forums points out that you can restore the iTunes 10 functionality by selecting

View > Show Sidebar
View > Show Status Bar

Thank you, O Grand Benefactor!


Thursday, November 1, 2012

On doing (Machine Learning) research without a supervisor

In two words: it sucks.
In more words: it sucks majorly.

Due to funny circumstances of life, I have been out of academia for a while and I'm forced to do research without a supervisor that is immersed in the field. Even worse, nobody around me is doing AI / ML research.

This manifests into a feeling of being lost in an alien jungle: is that ivy poisonous? Is this leaf good to eat?
Is this paper I'm reading now relevant to my interests in the long term, or is it something rehashed from a ten year old idea?
Is this idea I've had interesting enough to work into a fully fledged paper, or will the reviewers laugh at my quaint approach and light their cigars with the printout?
Is this research problem I've identified something I can tackle as it is, or will it take an army of von Neumann-Feynman hybrid clone grad students 100 years to crack?

I simply have no "feel" for the granularity of open problems in the field.

The field is immense, and every day something new appears. I cannot try everything in every direction, of course. But even the areas that I am interested in (feature selection, cluster analysis, deep learning, and such), which are but a subset of the whole, are still immense and feel like a glass wall on which I cannot find any imperfections to grab on to and climb.

I feel like a child who's been given Thoman Mann's "The Magic Mountain" and was told "well, you can learn how to read by looking at the signs on these pages".
Sure I can, but it will take me years. A supervised, guided learning of the alphabet would be much more efficient.

And to everyone who is working under supervision and is in a hurry to tell me that "this is what research is like" and "this is how everyone struggles to find open research problems" -- no, it's NOT.
Research is not done in a vacuum, but in groups and with supervision. That way, you can stand on the shoulders of giants (or a big pile of dwarfs), instead of merely wasting years reinventing some inefficient wheel.

EDIT:  Well, at least a bad ML pun came out of my rant, if nothing else -- I am doing "unsupervised research" :D