Humminbird Side Imaging Forums

General => General Discussion => Topic started by: peterv6i on October 30, 2014, 07:57:46 AM

Title: bachelor thesis on side scan sonars
Post by: peterv6i on October 30, 2014, 07:57:46 AM
Hello,
In short time I will start to write a bachelor thesis on side scan sonars.. (my second thesis)
So if someone could help me I need to find some material to work on (pdf, url link, ...how the sonar works, differnet frequencies, sonar lobes, etc. etc...).


thank you..
regards

Peter
Title: Re: bachelor thesis on side scan sonars
Post by: Rickard on October 30, 2014, 10:40:27 AM
Hi Peter,

This is where I found most of what I know about this technology. The zipped PP slides are fantastic!
http://www.omg.unb.ca/GGE/SE_3353.html (http://www.omg.unb.ca/GGE/SE_3353.html)

Good luck with the thesis!

Rickard
Title: Re: bachelor thesis on side scan sonars
Post by: peterv6i on November 01, 2014, 05:52:15 PM
Thank you!
Title: Re: bachelor thesis on side scan sonars
Post by: peterv6i on February 03, 2015, 06:32:15 AM
Is there or has enyone some example in java or other languages to read humminbird sonar files?
Is there some specification of humminbird file format?

Title: Re: bachelor thesis on side scan sonars
Post by: peterv6i on February 04, 2015, 07:00:39 AM
Some other link I have found:
http://www.ldeo.columbia.edu/res/pi/MB-System/sonarfunction/SeaBeamMultibeamTheoryOperation.pdf (http://www.ldeo.columbia.edu/res/pi/MB-System/sonarfunction/SeaBeamMultibeamTheoryOperation.pdf)
http://www.farsounder.com/files/NavigationSonarForTheShipOperator_ForwardLookingSonarsAndMultibeamEchosoundersExplained.pdf (http://www.farsounder.com/files/NavigationSonarForTheShipOperator_ForwardLookingSonarsAndMultibeamEchosoundersExplained.pdf)
http://scholar.lib.vt.edu/theses/available/etd-02182005-150817/unrestricted/luan_thesis.pdf (http://scholar.lib.vt.edu/theses/available/etd-02182005-150817/unrestricted/luan_thesis.pdf)
http://www.ldeo.columbia.edu/res/pi/MB-System/sonarfunction/ (http://www.ldeo.columbia.edu/res/pi/MB-System/sonarfunction/)
https://www.scribd.com/doc/226451930/Sonar-for-Practising-Engineers-3rd-Edition (https://www.scribd.com/doc/226451930/Sonar-for-Practising-Engineers-3rd-Edition)

konsberg
http://www.km.kongsberg.com/ks/web/nokbg0240.nsf/AllWeb/D5682F98CBFBC05AC1257497002976E4?OpenDocument (http://www.km.kongsberg.com/ks/web/nokbg0240.nsf/AllWeb/D5682F98CBFBC05AC1257497002976E4?OpenDocument)
http://www.km.kongsberg.com/ks/web/nokbg0240.nsf/AllWeb/E9983CAD4C90F531C1257BDA002FDFBC?OpenDocument (http://www.km.kongsberg.com/ks/web/nokbg0240.nsf/AllWeb/E9983CAD4C90F531C1257BDA002FDFBC?OpenDocument)

http://www.km.kongsberg.com/ks/web/nokbg0240.nsf/AllWeb/818A4E43391B5005C125738D004D831F?OpenDocument (http://www.km.kongsberg.com/ks/web/nokbg0240.nsf/AllWeb/818A4E43391B5005C125738D004D831F?OpenDocument)

http://www.km.kongsberg.com/ks/web/nokbg0240.nsf/AllWeb/73A0263F9581BF0AC125719B004E0053?OpenDocument (http://www.km.kongsberg.com/ks/web/nokbg0240.nsf/AllWeb/73A0263F9581BF0AC125719B004E0053?OpenDocument)

http://www.km.kongsberg.com/ks/web/nokbg0240.nsf/AllWeb/96066CED6C722354C125738D004DCD85?OpenDocument (http://www.km.kongsberg.com/ks/web/nokbg0240.nsf/AllWeb/96066CED6C722354C125738D004DCD85?OpenDocument)

https://www.scribd.com/doc/93012013/EM120-Multibeam-Echo-Sounder-Maintenance-Manual-Rev-A (https://www.scribd.com/doc/93012013/EM120-Multibeam-Echo-Sounder-Maintenance-Manual-Rev-A)

https://www.scribd.com/doc/60905669/164709-g-Sis-Operator-Manual (https://www.scribd.com/doc/60905669/164709-g-Sis-Operator-Manual)
Title: Re: bachelor thesis on side scan sonars
Post by: N9Phil on February 04, 2015, 08:41:19 AM
Great information Peter.  Great research and thanks for sharing.

Phil
Title: Re: bachelor thesis on side scan sonars
Post by: peterv6i on February 05, 2015, 03:24:23 PM
Ok.. I must also write some pice of code in the thesis to show how to draw sonar images..
I have asked if someone has some file specification about humminbird files (son, idx, dat)..
meanwhile I have decompiled HumViewer and used code from github to display side scan recorded file..

Here is source code in java (modified source from github sonnarwidget)..

What you need is to change path to your DAT file... and the code will generate jpg file on the c:\ drive..
You can change the height variable to modify image width.. and also you can change RGB value for different color (barva variable)

Code: [Select]
import java.io.DataInputStream;
import java.io.File;
import java.io.*;
import java.util.ArrayList;
import java.util.List;
import com.data.Ping;
import java.awt.Color;
import java.awt.image.BufferedImage;
import javax.imageio.ImageIO;

/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
/**
 *
 * @author Peter
 */
public class Main {

    private static final double RAD_CONVERSION = 180 / Math.PI;
    private static final double EARTH_RADIUS = 6356752.3142;
    private static File datafile = null;
    private static File seconddatafile = null;
    private static int blocksize = 0;
    private static List<Integer> index = null;
    private static List<Integer> secondindex = null;
    private static int timestamp;
    private static int longitude;
    private static int latitude;

    //output picture height (modify this)
    static int height = 1024;

    //modify this to obtain different color (RGB value)
    static Color barva = new Color(179, 255, 153);

    /**
     * @param args the command line arguments
     */
    public static void main(String[] args) {
        try {
            File file = new File("C:/Documents and Settings/Peter/Desktop/peter/RECORD/maona.dat");
            String name = initFromDAT(file);
            String dirname = name.substring(0, name.length() - 4);
            String path = file.getParent() != null ? file.getParent() + "/" + dirname : dirname;

            System.out.println("name: " + name);
            System.out.println("dirname: " + dirname);
            System.out.println("path: " + path);

            index = getIDXData(new File(String.format("%s/B002.idx", path)));
            datafile = new File(String.format("%s/B002.SON", path));

            secondindex = getIDXData(new File(String.format("%s/B003.idx", path)));
            seconddatafile = new File(String.format("%s/B003.SON", path));

            System.out.println("Index length: " + getLength() + " pings");

            Ping[] pingRange = getPingRange(0, (int) getLength() - 1);
            for (int i = 0; i < pingRange.length; i++) {
                System.out.println("ping range: " + i);
                System.out.println("speed: " + pingRange[i].getSpeed());
                System.out.println("lat: " + pingRange[i].getLatitude());
                System.out.println("lon: " + pingRange[i].getLongitude());
                byte[] soundings = pingRange[i].getSoundings();
               

                System.out.println("===================================");
            }

            //shranimo sliko
           
           
            BufferedImage image = new BufferedImage((int)getLength() - 1, height, BufferedImage.TYPE_INT_RGB);
            for (int loop = 0; loop < (int)getLength() - 1; loop++) {
                byte[] soundings = pingRange[loop].getSoundings();

                //gremo čez podatke iz zapisa
                for (int i = 0; i < height; i++) {
                    int mapped = (int) ((i * soundings.length) / (double) height);
                    byte sounding = soundings[mapped];
                 
                    int color = (barva.getRGB() & sounding) | (barva.getRGB() & (sounding << 8))
                            | (barva.getRGB() & (sounding << 16));


                    //set pixel color
                    image.setRGB(loop, i, color);
                }

            }
            File outputfile = new File("c:/image.jpg");
            ImageIO.write(image, "jpg", outputfile);



        } catch (Exception ex) {
            ex.printStackTrace();
        }
    }

   

    static long getLength() {
        return index.size();
    }

    public int getTimeStamp() {
        return this.timestamp;
    }

    static double getLongitude() {
        return toLongitude(longitude);
    }

    static double getLatitude() {
        return toLatitude(latitude);
    }

    static List<Integer> getIDXData(File idxfile) throws FileNotFoundException,
            IOException {
        DataInputStream stream = new DataInputStream(new FileInputStream(idxfile));
        try {
            List<Integer> index = new ArrayList<Integer>();

            while (stream.available() > 0) {
                int time = stream.readInt(); //no need
                int offset = stream.readInt();
                index.add(offset);
            }

            return index;
        } finally {
            stream.close();
        }
    }

    /**
     *
     * @param file
     * @return
     * @throws FileNotFoundException
     * @throws IOException
     */
    static String initFromDAT(File file) throws FileNotFoundException, IOException {

        System.out.println("File: " + file.toString());
        DataInputStream stream = new DataInputStream(new FileInputStream(file));
        try {
            stream.skipBytes(20);
            timestamp = stream.readInt();
            longitude = stream.readInt();
            latitude = stream.readInt();

            System.out.println("timestamp: " + timestamp);
            System.out.println("longitude: " + longitude + " " + toLongitude(longitude));
            System.out.println("latitude: " + latitude + " " + toLatitude(latitude));


            byte[] namebytes = new byte[10];
            stream.read(namebytes, 0, 10);
            String filename = new String(namebytes);
            stream.skipBytes(2); //skip null character \0000

            int ks = stream.readInt(); //don't know what this is
            int tk = stream.readInt(); //don't know what this is
            blocksize = stream.readInt();
            return filename;
        } finally {
            stream.close();
        }
    }

    /**
     * Convert Lowrance/Humminbird mercator meter format into WGS84.
     * Used this article as a reference: http://www.oziexplorer3.com/eng/eagle.html
     * @return
     */
    static double toLongitude(int mercator) {
        return mercator / EARTH_RADIUS * RAD_CONVERSION;
    }

    static double toLatitude(int mercator) {
        double temp = mercator / EARTH_RADIUS;
        temp = Math.exp(temp);
        temp = (2 * Math.atan(temp)) - (Math.PI / 2);
        return temp * RAD_CONVERSION;
    }

    static void reverseBytes(byte[] array) {
        int lastindex = array.length - 1;
        for (int loop = 0; loop < array.length / 2; loop++) {
            byte temp = array[loop];
            array[loop] = array[lastindex - loop];
            array[lastindex - loop] = temp;
        }
    }

    static Ping[] getPingRange(int offset, int length) throws IOException {

        //With side images soundings needs to be combined into one array.
        //Assumption is that both channels have same amount of samples.
        HumminbirdPing[] firstChannel = getPingRangeFromFile(offset, length, datafile, index);
        HumminbirdPing[] secondChannel = getPingRangeFromFile(offset, length, seconddatafile, secondindex);

        for (int loop = 0; loop < firstChannel.length; loop++) {
            HumminbirdPing first = firstChannel[loop];
            HumminbirdPing second = secondChannel[loop];

            //združi oba kanala v en array in vrne rezultat
            byte[] firstsoundings = first.getSoundings();
            byte[] secondsoundings = second.getSoundings();
            reverseBytes(firstsoundings);

            byte[] soundings = new byte[firstsoundings.length + secondsoundings.length];
            System.arraycopy(firstsoundings, 0, soundings, 0, firstsoundings.length);
            System.arraycopy(secondsoundings, 0, soundings, firstsoundings.length, secondsoundings.length);
            first.setSoundings(soundings);
        }


        return firstChannel;

    }

    static HumminbirdPing[] getPingRangeFromFile(int offset, int length, File file, List<Integer> index) throws IOException {
        RandomAccessFile raf = new RandomAccessFile(file, "r");

        try {
            HumminbirdPing[] pings = new HumminbirdPing[length];
            for (int loop = 0; loop < length; loop++) {
                raf.seek(index.get(offset + loop));
                HumminbirdPing ping = new HumminbirdPing(raf, blocksize);
                pings[loop] = ping;
            }
            return pings;
        } finally {
            raf.close();
        }
    }

    static class HumminbirdPing implements Ping {

        private int time;
        private int longitude;
        private int latitude;
        private short speed;
        private short heading;
        private byte[] soundings;

        public HumminbirdPing(RandomAccessFile stream, int blocksize) throws IOException {
         
           /*
            System.out.println("block size: " + blocksize);
            byte[] vrstica = stream.readLine().getBytes();
            for (int x=0; x < vrstica.length; x++)
            {
                System.out.print(vrstica[x]+"|");
            }
            System.out.println("-----------");
           */

            stream.skipBytes(10);
            time = stream.readInt();
            stream.skipBytes(1);
            longitude = stream.readInt();
            stream.skipBytes(1);
            latitude = stream.readInt();
            stream.skipBytes(3);
            heading = stream.readShort();
            stream.skipBytes(3);
            speed = stream.readShort();
            stream.skipBytes(5);
            int freq = stream.readInt();
            stream.skipBytes(10);
            int son = stream.readInt();
            stream.skipBytes(1);

            //vrnemo zapis, ki ga izrisujemo
            System.out.println(blocksize-58);
            soundings = new byte[blocksize - 58];
            stream.read(soundings, 0, blocksize - 58);
        }

        public byte[] getSoundings() {
            return soundings;
        }

        public void setSoundings(byte[] soundings) {
            this.soundings = soundings;
        }

        public float getLowLimit() {
            // Humminbird file does not provide this
            return 0;
        }

        public float getTemp() {
            // Humminbird file does not provide this
            return 0;
        }

        public float getDepth() {
            // Humminbird file does not provide this
            return 0;
        }

        public int getTimeStamp() {
            return this.time;
        }

        public float getSpeed() {
            return this.speed * 3.6f;
        }

        public float getTrack() {
            return this.heading / 10.0f;
        }

        public double getLongitude() {
            return toLongitude(longitude);
        }

        public double getLatitude() {
            return toLatitude(latitude);
        }
    }
}
Code: [Select]
package com.data;

/**
 *
 * @author Peter
 */
public interface Ping {
byte[] getSoundings();
float getLowLimit();
float getTemp();
float getDepth();
int getTimeStamp();
float getSpeed();
float getTrack();
double getLongitude();
double getLatitude();
}
Title: Re: bachelor thesis on side scan sonars
Post by: peterv6i on February 05, 2015, 03:30:43 PM
(http://shrani.si/t/2K/48/XttiIA0/image.jpg) (http://shrani.si/?2K/48/XttiIA0/image.jpg)
Title: Re: bachelor thesis on side scan sonars
Post by: peterv6i on February 18, 2015, 02:36:06 AM
https://www.duo.uio.no/bitstream/handle/10852/41724/Kiyani-Master.pdf?sequence=1 (https://www.duo.uio.no/bitstream/handle/10852/41724/Kiyani-Master.pdf?sequence=1)
SimplePortal 2.3.3 © 2008-2010, SimplePortal