Pointgrey Cameras

For anyone who doesn't know my research, I'm looking into stereo vision algorithms in an underwater camera array. What I'm hoping to do is a rough scene reconstruction that has improved results over blindly using an existing stereo algorithm.

Now on to what this post is about. I found a little subtle and, as far as I can tell, undocumented feature of the Pointgrey cameras. If you use the FlyCapture API then you would normally call flycaptureStart and flycaptureStop to start/stop grabbing images, respectively. For our purposes, we only need to grab single shots from the camera array, not streamed video. On top of that, we want the shots to be (for the most part) synchronized across the whole array.

Here's the twist, the start/stop calls aren't really what starts the "image grabbing" process, but simply powering up/down the camera (via the CAMERA_POWER register). The start/stop calls appear to only lock down/release a DMA context for the purposes of streaming. That means, if you have a firewire card with the TI chipset you can only start 4 cameras simultaneously.

So how do we grab a synchronized set of images using this knowledge? Well this is only applicable to the Grasshopper line of cameras since they have an on-board framebuffer that you can control. Here's what we do:
  1. Place the cameras in "image hold" mode by setting bit 6 to 1 in the IMAGE_RETRANSMIT (0x12F8) register. This will store images on the camera.
  2. Power up the cameras by setting bit 31 to 1 using the CAMERA_POWER register.
  3. Simply wait around long enough for the frame buffers to fill up
  4. Put each camera in trigger mode by setting bit 6 to 1 in the TRIGGER_MODE (0x830) register. What this does is prevent any more images from getting stored in the frame buffer.
  5. For each camera
    1. Start the camera so you can transfer data over to your system
    2. Set bits 24-31 to 0x01 in the IMAGE_RETRANSMIT register to transfer an image.
    3. Stop the camera

This works great for using the cameras in a non-streaming context where you only have a single firewire bus/system to work with. If you want the images to be synchronized, be sure to set them all to the same FPS, and enable image timestamping (FRAME_INFO register, 0x12E8). Now all you do is find the set of images across all cameras which are closest together.

One other subtle thing I found with is that if you start the camera with the same dimensional parameters, but with a different bandwidth parameter, the on-board frame buffer will be flushed. Anyways, that's it for this post. I thought it would be nice to post this information just in case someone else out there has had, or will have, a similar issue. Cheers!

First Look

So what's this score editing application I've been talking about in my posts? We've decided to give a pre-beta teaser. Minus a couple of rendering issues, here's what she looked like a couple of days ago (click image for larger preview):

Score Editor

For our first release we focused on guitar tabs, and making sure the application as a whole works together properly. Unfortunately this release will be a private beta, so everyone will have to wait. I think we have a pretty good app for ~4 months of work (sparse work too, since we're both busy with school and work). Hopefully I've tweaked your interest!

Java Annotations: A [Somewhat] Brief Introduction

So in my last post where I described a messaging system we implemented, I also mentioned our use of annotations. I thought it would be appropriate to write a follow-up post with a brief introduction to them, so here it is. I'm going to talk about annotations in the Java sense, but a lot of this propagates to other [reflective] languages too.

Annotations are often defined as "notes of explanation or comments added to text". In Java, one can regard an annotation as metadata attached to code, a piece of code describing code. Well, the first question that one might ask is "Why do I need this when I can just use comments?" and indeed, this question makes for an excellent starting point when writing an introduction. Well, probably the main reason to have annotations over comments is that annotations are part of the language, with a specific syntax, which in turn allows parsers to easily understand them. Comments, on the other hand, could be in any form and would be a huge mess to understand by a compiler, unless a certain standard was specified.

"So what good are they for?" you might ask next. Well, they can let you do some pretty neat stuff. First I should describe the three flavors of annotations in Java:

source code

Present at the source code level only and will be discarded by the compiler during compilation. These guys are useful to give hints to compilers and programs as to the nature of the code itself. For example, one may have seen @Override or @Deprecated annotations when using Eclipse or other code. The former specifies that an error should be produced if the method doesn't override one in a super class, and the latter indicates a class, method, etc. as deprecated.

class

This is the default flavor. Compilers will produce bytecode containing these annotations, but you probably won't be able to access these during runtime. Useful if you are doing bytecode analysis of code.

runtime

To me, possibly one of the more useful flavors of annotations for developers. These annotations can be requested at runtime, which allows you to do neat tricks. The reason this is possible is due to the reflective nature of Java. You can access this through the Class.getAnnotations() method


So how do we create an annotation? Well, it's pretty straightforward. Note that I'll be using the messaging system from my previous post as an example. Here's what the Message annotation looks like:

@Retention(value = RetentionPolicy.RUNTIME)
@Target(value = {ElementType.FIELD})
public @interface Message {
Class<?>[] signature() default {};
}

So the first line says we want to be able to retrieve this annotation at runtime. Note the use of the @ symbol here. This is the notation used for annotations. The second line says what type of things this annotation can be applied to. In the above example, it can only be applied to a field in a class, but not methods, or classes themselves. Note the @ symbol before the interface keyword in the third line. This is how we define an annotation. Finally, the fourth line specifies the one and only property in our annotation, and that's an array of classes that specify the signature of the message (i.e., the types for the data that will accompany a message). We specify the default signature to be an empty array. What's interesting in this example is that we used annotations to describe an annotation itself (@Retention and @Target describe @Message).

For our messaging system, the field itself is a static member that is a String, and that string defines the name of the message. For example,

@Message(signature = {String.class})
public final static String MYMESSAGE = "myMessageName";

describes a message with the name "myMessageName" which sends a String argument to all receiving functions. If we wanted to, we could have defined a second property in the annotation for the message name. In our message delivery class, we can then loop through all the fields in a class to register messages like this:

public void registerSender(Class<? extends MessageSender> sender) {
MessageData msgData = getData(sender);
for(Field field : sender.getDeclaredFields()) {
if(field.isAnnotationPresent(Message.class)) {
if((field.getModifiers() & Modifier.STATIC) == 0)
continue;

Message msg = field.getAnnotation(Message.class);
msgData.addMessage(field.get(null).toString(), msg.signature());
}
}
}

Note that, for simplicity, I excluded the try/catch blocks and log messages in the above. A fairly straightforward piece of code: for each field in the class, if the field is static and has the Message annotation, we add the message to the set of messages we understand. This is far more convenient than having to register each individual message. For message receivers we have a ReceiverMethod annotation that I won't explain, but it looks something like this:

@Retention(RetentionPolicy.RUNTIME)
@Target(value = { ElementType.METHOD })
public @interface ReceiverMethod {
// Special message name which allows catching all messages from a sender
public static final String CATCHALL = "<<all>>";

// Properties
public Class senderClass();
public String message();
}

We can then do something similar to the registerSender method above to register our receiver. So that's my quick introduction to annotations. Maybe you can find other interesting ways to make use of these little critters in your own programs.