Reading Image Data

We will talk to the Image Server via a network connection.  Once we open the connection, the Image Server will constantly transmit to us the position of the target (if any), along with some other useful information.  Let’s create a new class called PiCamera and set it up as follows:

We are going to use the Network class to make the network connection, so in our PiCamera class we create an instance of this class.  We then create a Connect function to allow us to connect to the Image Server.  Note that we will need to supply the IP address as well as the port number.  We also pass in our PiCamera instance which supports the NetworkReceiver class.  This allows the Network class to call our ProcessData function each time it receives new data from the Image Server.

Now to use this new PiCamera class we will need to add it to our Robot class.  First we declare a variable for the camera by adding the following line to the list of variable declarations:

Then we initialize this variable in our robotInit() function with the following line:

Note that we are using constants here for the camera IP and Port so we need to define them at the top of our class:

Your file should now look like:

Now when we run our program, it will immediately connect to the Image Server and that server will start transmitting the target data which will be received by our ProcessData function which simply logs it to the console.  When we run the program, we will then see a constant stream of data printed to the console which looks something like:

Here the R at the beginning of the line tells us that this is data which gives us the bounding rectangle, along with some other information.  The numbers that follow are, in order:

1: Left edge of the target bounding rectangle
2: Top edge of the target bounding rectangle
3: Width of target bounding rectangle
4: Height of target bounding rectangle
5: Vertical position of the upper left corner of the image
6: Vertical position of the upper right corner of the image
7: The target line position (i.e. the position of the horizontal red line)
8: The current frame number
9: The target center position (i.e. the position of the vertical red line)

If you move the robot around, you will be able to see the data change.

Now instead of printing out the data, we want to save the it for later use.  We will need to parse the data out of the string and will use the utility function ParseIntegers from the RobotBase class to do it.  Let’s add a class that will encapsulate that data:

And add an instance of this class that we will used to store the most recently received data from the ImageServer:

Finally we will add a function that will parse the nine integers from the data string and store them in this structure:

Now this function is pretty straightforward. After we parse the integers (note that ParseIntegers can return null if there were not enough integers in the string), we create a new instance of our PiCameraData class and initialize it with the data we just parsed (be careful about the order).  We then store that data set so that we can access it later.

There is one aspect of this function which may not be familiar, however, and that is the call to synchronized(this).  This is needed because the Network receiver will be running in another thread.  If you don’t know anything about threads then you might want to read up on it a bit.  Basically, a thread is a piece of code that is running in parallel (i.e. at the same time) to your regular code.  This means that if there is any shared data, it is possible that both pieces of code may be trying to access it at the same time.  This can lead to data corruption.  To get around this problem we need a way to prevent another thread from accessing shared data while we are working on it.  There are a number of mechanisms that can be used to accomplish this, but for Java one of the most straightforward is the synchronized function.  This function can take pretty much any Java Object as an argument which acts like a lock.  If process A holds the lock, and process B attempts to access it, process B will be suspended until process A releases the lock. The syncronized function grabs the specified object and that lock is held while the code block that follows is executed.  Once the closing ‘}’ of the block is reached, the lock is release allowing other threads to access it.

So in this case, we are using the current instance of the PiCamera class as the lock while we modify the m_data variable.  Now let’s create a function that can retrieve the camera data.  Note that this function will be called from a different thread that that which sets the data.  Add the following function to your PiCamera class:

Once again, we use the current instance of the PiCamera class as the lock before we access the data we are going to return.  This ensures that the data is not being changed while we are trying to return it.

Finally, we need to call our ProcessCameraData function when our ProcessData function is called by the Network class.  Change your ProcessData function as follows:

We first check to see that the first character of the received string is an ‘R’ (we might want to add other command later) and if  is, we send the remainder of the string to our ProcessCameraData function.  If the first character is anything else, we log that as an error.  Note also that we changed the logging level of the first Logger call to -1 so we don’t see all of that output all the time.

You file should now look like:

Next: Auto Alignment

Pierre Pierre, who replica handbag 185cm tall, gucci replica handbags the "Diamond King" in his hermes replica handbags . He has been selected as one of the handbag replica most beautiful 50 people in the "People" magazine. It is also known as replica handbags most elegant and quiet in the world. Unforgettable prince.