PCL C2988 unrecognizable template declaration/definition Visual Studio 2017

If you get this compile error:

Error C2988 unrecognizable template declaration/definition

When you:

#include 

from the Point Cloud Library (PCL) in Visual Studio 2017, then either throw the following in before the #include, like this:

//
#define BOOST_TYPEOF_EMULATION
#include 

or upgrade your version of Visual Studio 2017 (I haven’t tested this yet myself!)

Not sure why, it’s something to do with workarounds for VS 2017 bugs or something…

An implementation of ntohf() with code

I am working on extracting data from some binary navigation messages today. Working with binary data can be difficult and quite confusing – especially when converting byte order from network (big endian) to host byte order (possibly little endian). The integer types are well covered by ntohs() and ntohl() et al. but when dealing with floats things can get a bit harder as ntohf() isn’t always available to the hard pressed programmer!

So I have included a simple implementation below, I have tested it during my own use, but it use at your own risk as this code may well be an example of a rather dubious use of unions!

//
#include 
#ifndef ntohf
// Converts a 32 bit IEEE float represented as
// 4 bytes in network byte order to a float in host byte order
// the 4 bytes are passed as an unsigned 32bit integer
inline float ntohf(uint32_t net32)
{
    union {
        float f;
        uint32_t u;
    } value;
    // Swap bytes if necessary and store to value
    value.u = ntohl(net32);
    // return value as float
    return value.f;
}
#endif
//

This version is slightly adapted from an original implementation by Kevin Bowling (pls. see copyright notice).

ASCII ‘art’ for Camera Calibration Python Script

Working on a python script for a focus calibration (software based) routine for a computer vision camera, in order to spruce it up a bit I decide to add a nice ASCII introduction! #Friday

camera_cal

ExifTool truncates ASCII MakerNote data

ExifTool can be used to output a specific Exif MakerNote from your images’ metadata by using the following command:

exiftool -u -Unknown_0x0013 image.jpg

This will output makernote Id 0x13, however if the makernote that you are interested is long, then ExifTool may truncate it and output only the start with […] at the end!

Unknown 0x0013                  : {"distortion":{"factory":{"version":"1.0","medium":"air[...]

To have ExifTool output the full makernote, use the -b (binary) option like this:

exiftool -u -b -Unknown_0x0013 image.jpg

Using a Virtual USB Serial Port from a Guest OS on VirtualBox

Here is a decent set of instructions on how to access normal COM ports as well as USB Virtual com ports from you Guest OS running on VirtualBox – Thankfully it worked for me but I had to install the FTDI drivers on the Guest for rs232, I got them from here.

Thanks jorgensen!
.

Have ExifTool Display Maker Notes

Phil Harvey’s ExifTool is a fantastic software tool for displaying and interacting with image Exif data, however by default it doesn’t display maker notes and I always forget the command line options to persuade it to list them, so here it is – the -u option gets exiftool to display ‘unknown’ tags and theses include maker notes!

exiftool -u image.jpg

The makernotes will be listed as unknown items by their hex ids.

Happy days – Thanks Phil!

exiftool display maker notes

.

I2C1_Wr / I2C1_Rd functions hang with MikroC for PIC – Need Timeout

In some cases both the MikroC i2c functions I2C1_Wr() and I2C1_Rd() can hang or lockup indefinitely until the PIC is reset. This can happen if the I2C bus isn’t properly terminated, for example if a connection breaks or similar (broken wire or solder joint etc). Having your PIC lockup during operation is generally not very desirable if your are trying to develop a stable software system – if for some reason an i2c device hasn’t been properly connected your system will just lockup for good!

Different posts discuss this problem and its various causes:

https://forum.mikroe.com/viewtopic.php?f=13&t=21270&sid=f45f0199695794c83516f89919183cbb&start=0

and

https://forum.mikroe.com/viewtopic.php?f=88&t=60224

MikroC provided the code to their functions so that software developers (us) could work around the problem, this library implements versions of I2C1_Wr() and I2C1_Rd() that timeout rather than hang, a timeout values is passed as a parameter:

https://libstock.mikroe.com/projects/view/1052/i2c-non-blocking

The library doesn’t implement a C version, so inspired by it (thanks Danny!) I have ported the functions into C, and added some comments – use at your own risk, it works well for me on PIC18F family chips but hasn’t been exhaustively tested!

I have declared the timeouts as constants rather than allowing the timeout to be passed in as a parameter – this is so that the functions can be used as drop-in replacements without having to modify client code.

#define I2C_WRITE_TIMEOUT_US 200
unsigned short tI2C1_Wr(unsigned short d) {
    const unsigned int delay = 2; // us
    unsigned int max_retry = I2C_WRITE_TIMEOUT_US / delay;
    unsigned int retry;
    
    if (max_retry == 0)
        max_retry = 1;
        
    // Interrupt Flag bit - Waiting to transmit/receive
    PIR1.SSP1IF = 0;
    
    // Set data for transmission
    SSP1BUF = (unsigned char)d;
    // Wait for transmission to complete
    // 1 = Transmit is in progress
    // 0 = Transmit is not in progress
    //
    retry = max_retry;
    while (SSP1STAT.r_not_w == 1 && --retry > 0)
        delay_us(delay);
    // Timed-out stop transfer and return error
    if (SSP1STAT.r_not_w == 1) {
        // Enable Stop Condition
        SSP1CON2.PEN = 1;
        return 1;
    }
    
    // Wait for completion
    // 1 = The transmission/reception is complete (must be cleared by software)
    // 0 = Waiting to transmit/receive
    //
    retry = max_retry;
    while (PIR1.SSP1IF == 0 && --retry > 0)
        delay_us(delay);
    // Timed-out stop transfer and return error
    if (PIR1.SSP1IF == 0) {
        // Enable Stop Condition
        SSP1CON2.PEN = 1;
        return 1;
    }
    // Check that we got an ACK
    // 1 = Acknowledge was not received
    // 0 = Acknowledge was received
    //
    if (SSP1CON2.ACKSTAT != 0) {
        // No ACK, abort
        // Enable Stop Condition
        SSP1CON2.PEN = 1;
        return 1;
    }
    // All good...
    return 0;
}

And to Read:

#define I2C_READ_TIMEOUT_US 200
unsigned short tI2C1_Rd(unsigned short ack) {
    unsigned short d = 0;
    const unsigned int delay = 2; // us
    unsigned int max_retry = I2C_READ_TIMEOUT_US / delay;
    unsigned int retry;
    if (max_retry == 0)
        max_retry = 1;
        
    // Interrupt Flag bit - Waiting to transmit/receive
    // 1 = The transmission/reception is complete (must be cleared by software)
    // 0 = Waiting to transmit/receive
    //
    PIR1.SSP1IF = 0;
    // Set receive mode
    // 1 = Enables Receive mode for I2C
    // 0 = Receive idle
    //
    SSP1CON2.RCEN = 1;
    // Wait for read completion
    // 1 = The transmission/reception is complete (must be cleared by software)
    // 0 = Waiting to transmit/receive
    //
    retry = max_retry;
    while (PIR1.SSP1IF == 0 && --retry > 0)
        delay_us(delay);
    // Still not complete, get out...
    if (PIR1.SSP1IF == 0)
        return 0;
    // grab the data
    d = (unsigned short)SSPBUF;
    // ACK required?
    if (ack == 0) {
        // No
        // 1 = Not Acknowledge
        // 0 = Acknowledge
        //
        SSP1CON2.ACKDT = 1;
    } else {
        // Yes
        SSP1CON2.ACKDT = 0;
    }
    // Interrupt Flag bit - Waiting to transmit/receive
    // 1 = The transmission/reception is complete (must be cleared by software)
    // 0 = Waiting to transmit/receive
    //
    PIR1.SSP1IF = 0;
    // Start Ack sequence
    // 1 = Initiate Acknowledge sequence on SDAx and SCLx pins, and transmit ACKDT data bit. Automatically cleared by hardware.
    // 0 = Acknowledge sequence idle
    //
    SSP1CON2.ACKEN = 1;
    // Wait for completion of ack sequence
    retry = max_retry;
    while (PIR1.SSP1IF == 0 && --retry > 0)
        delay_us(delay);
    return d;
}

This works for the first i2c device, it is left as an exercise for the reader to convert it for a second i2c device, i.e. I2C2_Wr() and I2C2_Rd()

libpng – Changing compression level when writing PNG Image

This took me a bit of time to find, but I have been experimenting with libpng for writing software to save 16bit grayscale images and wanted to switch off compression to see if libpng would save the images out any faster than it normally does. When you call png_set_IHDR() you have to set the compression type to PNG_COMPRESSION_TYPE_DEFAULT, there is no alternative (e.g. there is no value like PNG_COMPRESSION_TYPE_NONE), this threw me for a bit…

Anyway after a spell of RTFMing, I eventually found out that you can alter then compression level, and indeed switch it off via a call to:

//
png_set_compression_level()
//

Setting a value of 0 in your code switches off compression, while setting it to 9 causes the lib to use maximum compression. Quick testing revealed that the time taken to save a PNG does decrease as you reduce this value towards 0 (and the saved image size increases!).

PNG is a good file format option for saving 16bit images, it is lossless and faithfully represents grayscale rather than fudging it into an RGB structure, and as it turns out, supports adjustable compression levels. As more cameras natively support higher bit-depth images, formats and software tools that support the greater precision will become more important so that Computer Vision and Machine Vision software can take full advantage.

PS Viewing 16bit grayscale images is harder than you might think, most software tools seem to down-sample them to 8bit grayscale, So far, I have found that good options are a.) ImageJ b.) Gimp 2.9 (not yet released, have to use a development build). These tools allow you to view the images and properly sample the 16bit pixel values etc…

Raspberry Pi and GPS for Testing Camera Image Timestamps with NTP and PPS

raspberry_pi_gps_pps_time_image_timestamp

An image time-stamp will tell you when an image was acquired by its camera, they are typically donated in Coordinated Universal Time (UTC) – accurate time-stamps are very often important in Computer Vision Applications especially those that involve observing or analyzing change over time.

Implementing such time-stamp functionality on a camera is very hard and typically involves both hardware and software support – testing the functionality to make sure that the time-stamps are accurate is nearly even harder!

A time-stamp’s accuracy is partly dependent on how well the camera’s time is synchronized, if it’s time is well synchronized by the Network Time Protocol (NTP) then an accuracy of a few milliseconds can be expected, if full pulse-per-second (PPS) synchronization is used then (with care) an accuracy of tens of microseconds can be achieved.

In order to test time-stamp accuracy it is necessary to have an accurate time source to act as a test base-line for comparison purposes, multiple cameras can the then be synchronized to this via their acquisition triggers and NTP or PPS and their images and image time-stamps can be compared.

To this end we have been prototyping a Stratum 1 time source built using a Raspberry Pi with a GPS shield. This will take its time reference from GPS and provide the following for testing cameras:

+ NTP time server (stratum 1) – Raspberry Pi & NTP syncs its time to GPS time via PPS signal and time packets (ZDA packets), the cameras’ NTP clients can use this for synchronizing their clocks (purley software based synchronization).

+ Electrical PPS output – Can be used by camera for syncing it’s time via PPS and for triggering acquisition on second boundaries

+ Re-transmit PPS time packets (ZDA) via UDP – Can be used by cameras for syncing their time via PPS (software & hardware synchronization)

To build the time source we are following this excellent article which explains the various steps involved:

http://www.satsignal.eu/ntp/Raspberry-Pi-NTP.html

Many thanks to David Taylor, it is a rather complex subject with lots of software setup on the Pi, it hurts our heads but we are making progress, and the initial prototype has already been very helpful in characterizing camera triggering and time-stamping behavior. We expect great things.

In terms of hardware we are using:

Uptronics Raspberry Pi+ GPS Expansion Board – with the GPS Timing Antenna

Raspberry Pi 3

Image Processing with Intel’s SSE SIMD instructions for 12-bit images

Over the last few days I have been working on implementing some low-level 12-bit image processing functions using Intel’s SIMD instruction set – SSE. The aim here is to increase processing time performance as much as possible – initial results are very encouraging, those 128bit register really get things to scream along!

It has been a while since I have done such work on Intel devices (ARM and hence ARM NEON is more common on IoT projects), the last time was before MMX ‘Intrinsics’ were invented and involved hand coding MMX instructions with associated support assembly language. Intrinsics really make coding this stuff so much simpler!

Very often it doesn’t pay for a software engineer to hand-code and optimise image processing algorithms, but when maximum performance is required, huge speed gains can be made with some careful coding on standard hardware!