Access Ping360 data for post processing, Python

Hey!
I have a bin file from a Ping360 sonar and i am trying to access the data in order to post process it using Python (3.9). I am looking into the decode_pingviewer_sensor_log_file.py script found here: Needs Python 3.7+ · GitHub, however I cant seem to figure out how to access the sonar data by itself or what format this is in. I am assuming the “data” that is printed from this script is the backscattering values in dB and that they are arranged by range from closest to the sonar to furthest.

Does anyone have any tips on how I might access the data directly?
Thanks in advance :slight_smile:

Hi @Winter, welcome to the forum :slight_smile:

I’d recommend you instead use/refer to the decode_sensor_binary_log.py file from our Ping Viewer repository, since it actually gets updated. I believe the one you linked to was originally a one-off example - not sure where you found that link, but if it’s on our forums or in our documentation then please let me know so I can update it :slight_smile:

The .bin files produced by Ping Viewer are described in the Ping Viewer documentation, as:

The relevant data message specification for the ping360 is device_data, in the Ping Protocol docs.

The decode_sensor_binary_log.py script parses a binary log file into PingMessage instances (using/from the bluerobotics-ping library), and filters them into only the messages containing scan data. For the Ping360 that’s the device_data message, which has a data attribute that is a bytearray of the intensity values returned by the sonar. You can index into that directly if you want to (e.g. decoded_message.data[0] for the first intensity value), but for processing purposes I’d recommend converting the data to a numpy array instead (e.g. np.frombuffer(decoded_message.data, np.uint8)).

You can look at the message specification for the other available attributes, but of particular note are the angle (for direction) and sample_period (used to determine distance).

A few gotchas:

  1. the ping angles are measured in gradians, so the angle attribute is a value from 0 to 399
  2. the ping360 zero angle is at the back where the penetrator is, so ‘forwards’ (the direction of the arrow on the bottom of the Ping360) is at angle 200 gradians
  3. Sonar (and all time of flight sensors) measure the time it takes for the pulse to return, so while d_{sound} = v_{sound} * t_{sample}, the target is half of that: d_{target} = \frac{d_{sound}}{2}

The following function can be used to determine the target distance per sample:

def meters_per_sample(ping_message, v_sound=1500):
    """ Returns the target distance per sample, in meters. 
    
    'ping_message' is the message being analysed.
    'v_sound' is the operating speed of sound [m/s]. Default 1500.

    """
    # sample_period is in 25ns increments
    # time of flight includes there and back, so divide by 2
    return v_sound * ping_message.sample_period * 12.5e-9

If you have the sample index (from within the data array) the distance at the start of the sample time is just

sample_start_distance = sample_index * meters_per_sample(ping_message, v_sound)

(i.e. the first sample (index 0) has distance 0m).
Alternatively, you can get the distance to the middle of the sample time with

sample_average_distance = (sample_index + 0.5) * meters_per_sample(ping_message, v_sound)

We’re currently looking to add some more thorough examples of using our ping libraries - is there anything in particular you’d be interested in? :slight_smile:

Thank you so much! this answered pretty much all of my questions brilliantly. Just one last thing, am a correct in assuming that the intensity signals are the volumetric backscattering strength in decibel? (usually referred to as “S_v” in fishery acoustics literature).

Thank you again so much for all your help! I cant think of anything particular at the moment, but I will let you know if i do :slight_smile:

Glad to hear it :slight_smile:

I’m actually not certain what the intensity signal measurement unit is (I suspect it may just be the ADC value from the measured voltage of the transducer). I’ve asked about it internally and will get back to you when I’ve got a response :slight_smile:

Update on this, the returned intensity data is in fact from the measured voltage, and we don’t have a known/calibrated conversion between the measurement and a physical quantity/unit of intensity. The transducers we use are custom, and the amplification circuitry involved for receiving further complicates a potential theoretical estimate.

I’m told we’re aiming to get experimental calibration data, which should include the relevant conversion factors and also map out the transmit and receive profiles across direction and sound frequency, but there isn’t yet a definitive timeline on when that will be completed :slight_smile:

I see, in that case i will keep an eye out for whenever this is finished. I think using the measured voltages will be fine for the application i have in mind, but it is always good to know what kind of signals i am working with :slight_smile: Thank you so much for all of your help!

1 Like

Hi @EliotBR can I get the backscattering strength in terms of time domain values. I have seen the received strength are converted in range of 0 - 255 to plot it as a grey sclae image. However, I am interested in the signal itself.

Can you help me with this?

Picture attached: