Package jaid.ais

Source Code of jaid.ais.DataSource$TableEntry

/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
package jaid.ais;

import gov.nasa.worldwind.geom.LatLon;
import gov.nasa.worldwind.render.SurfaceIcon;
import jaid.ais.data.ActiveTargetsMap;
import jaid.ais.data.Target;
import jaid.ais.message.AISMsg;
import jaid.com.Client;
import java.awt.Color;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import nav.position.Position;
import nav.util.math.NavCalculator;
import ui.layers.TargetLayer;

/**
* This class represents the notion of an AIS receiver.
*
* The class also defines an anonymous class for wrapping coverage permiter data.
*
* @author Benjamin Jakobus
* @since 1.0
* @version 1.0
*/
public class DataSource {

    /* The AIS receiver's position. */
    private Position location;

    /* The receiver's rxID. */
    private String rxID;

    /* The IP address of the server that forwards the receiver's messages. */
    private String ipAddress;

    /* The port on which the server that forwards the receiver's messages runs. */
    private int port;

    /* Flag indicating whether or not the receiver is enabled (data from disabled
     * receivers will be discarded).
     */
    private boolean isEnabled;

    /* The color of the receiver's coverage polygon. */
    private Color color;

    /* The client used to connect to the AIS server. */
    private Client client;

    /* Contains positions for the base station's coverage. */
    private Map<Double, TableEntry> distanceMap;

    /* Contains all targets received. */
    private ActiveTargetsMap targetsMap;

    /* A list of positions that define the source's coverage. */
    private List<Position> coveragePerimeter;

    /* The icon denoting the station's location on the map. */
    private SurfaceIcon icon;

    /**
     * Constructs a new <code>AISSource</code> object.
     *
     * @param ipAddress     The IP Address of the remote server that
     *                      provides the AIS data.
     * @param port          The port on which the remote server listens to.
     * @param rxID          The remote server's rxID. The rxID string is
     *                      used to identify the individual AIS source.
     * @param latitude      The latitude coordinate of the AIS source.
     * @param longitude     The longitude coordinate of the AIS source.
     * @param color         The color that is to be associated with the
     *                      source's coverage polygon.
     * @since 1.0
     */
    public DataSource(final Position location, String rxID, String ipAddress, int port,
            boolean isEnabled, Color color, ActiveTargetsMap targetsMap) {
        this.location = location;
        this.rxID = rxID;
        this.ipAddress = ipAddress;
        this.port = port;
        this.targetsMap = targetsMap;
        this.isEnabled = isEnabled;
        this.color = color;
        client = new Client(port, ipAddress, targetsMap, rxID);
        distanceMap = initDistanceMap(new ConcurrentHashMap<Double, TableEntry>(3600));
        Thread coverageCalculatorThread = new Thread(new Runnable() {

            public void run() {
                List<Double> tmpList;
                Position pos;
                while (true) {
                    try {
                        coveragePerimeter = new ArrayList<Position>(3600);
                        coveragePerimeter.add(location);
                        calculateCoveragePerimiter();
                        tmpList = new ArrayList<Double>(3600);
                        // Add any non-null positions to the geo-position list so
                        // that they can later form the points for the coverage polygon
                        for (Double key : distanceMap.keySet()) {
                            if (distanceMap.get(key).getPosition() != null) {
                                tmpList.add(key);
                            }
                        }
                        // Sort the positions according to their appearance from 0 to 360 degrees
                        Collections.sort(tmpList);
                        for (Double key : tmpList) {
                            pos = new Position(distanceMap.get(key).getPosition().getLatitude(),
                                    distanceMap.get(key).getPosition().getLongitude());
                            coveragePerimeter.add(pos);
                        }
                        pos = new Position(getLocation().getLatitude(),
                                getLocation().getLongitude());

                        coveragePerimeter.add(pos);
                        // Sleep two seconds
                        pos = null;
                        Thread.sleep(2000);
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                }
            }
        });
        // Re-calculate the coverage perimiter every 30 seconds
        coverageCalculatorThread.start();
        icon = new SurfaceIcon(getClass().getResource("/assets/icons/ais/antenna.png"), LatLon.fromDegrees(getLocation().getLatitude(), getLocation().getLongitude()));
        TargetLayer.getInstance().addRenderable(icon);
    }

    /**
     * Returns the color of the coverage polygon.
     *
     * @return color       The color of the coverage polygon.
     * @since 1.0
     */
    public Color getColor() {
        return color;
    }

    /**
     * Returns the server's IP address.
     *
     * @return IP   The IP address of the server that broadcasts the AIS feeds.
     * @since 1.0
     */
    public String getIpAddress() {
        return ipAddress;
    }

    /**
     * Enables / disables the receiver.
     *
     * @param isEnabled     <code>True</code> if the receiver is to be
     *                      enabled; <code>false</code> if not.
     * @since 1.0
     */
    public void setEnabled(boolean isEnabled) {
        if (!isEnabled) {
            disconnect();
        }
        this.isEnabled = isEnabled;
    }

    /**
     * Determines whether or not the receiver is enabled.
     *
     * @return      <code>True</code> if the receiver is enabled;
     *              else <code>false</code>
     * @since 1.0
     */
    public boolean isEnabled() {
        return isEnabled;
    }

    /**
     * Returns the location of the receiver.
     *
     * @return      <code>Position</code> object denoting the receiver's
     *              position
     * @since 1.0
     */
    public Position getLocation() {
        return location;
    }

    /**
     * Returns the port number on which the server listens.
     *
     * @return port     The port number on which the server listens.
     * @since 1.0
     */
    public int getPort() {
        return port;
    }

    /**
     * Returns the receiver's rxID.
     *
     * @return rxID         The receiver's rxID.
     * @since 1.0
     */
    public String getRxID() {
        return rxID;
    }

    /**
     * Sets the IP address to which to connect.
     *
     * @param ipAddress         Server IP Address.
     * @since 1.0
     */
    public void setIpAddress(String ipAddress) {
        this.ipAddress = ipAddress;
    }

    /**
     * Returns the <code>Target</code> with the given MMSI.
     *
     * @param mmsi
     * @return
     * @since 2.0
     */
    public Target getTargetByMMSI(String mmsi) {
        return targetsMap.get(mmsi);
    }

    /**
     * Returns the <code>Target</code> with the given name.
     *
     * @param name
     * @return
     * @since 2.0
     */
    public Target getTargetByName(String name) {
        for (Target t : targetsMap.values()) {
            if (t.getName().contains(name)) {
                return t;
            }
        }
        return null;
    }

    /**
     * Sets the receiver's location.
     *
     * @param location          <code>Position</code> denoting the receiver's
     *                          destination.
     * @since 1.0
     */
    public void setLocation(Position location) {
        this.location = location;
    }

    /**
     * Sets the port on which to connect.
     *
     * @param port              Port on which to connect.
     * @since 1.0
     */
    public void setPort(int port) {
        this.port = port;
    }

    /**
     * Sets the rxID of the receiver.
     *
     * @param rxID              Receiver rxID.
     * @since 1.0
     */
    public void setRxID(String rxID) {
        this.rxID = rxID;
    }

    /**
     * Returns all targets identified by an individual source.
     *
     * @param rxID      The rxID of the source whose identified targets
     *                  we want to fetch.
     * @return          A collection of targets identified by the source
     *                  matching rxID.
     * @since 1.0
     */
    public Collection<Target> getTargets() {
        Collection<Target> allTargets = targetsMap.values();
        Collection<Target> targets = new ArrayList<Target>();
        for (Target t : allTargets) {
            if (rxID.equals(t.getSourceRxID())) {
                targets.add(t);
            }
        }
        return targets;
    }

    /**
     * Returns the source's client.
     *
     * @return          The client used by the source to obtain data feeds.
     * @since 1.0
     */
    public Client getClient() {
        return client;
    }



    /**
     * Returns the source's coverage.
     *
     * @return          <code>List</code> containg all the waypoints
     *                  defining the source's coverage.
     * @since 1.0
     */
    public List<Position> getCoverage() {
        return coveragePerimeter;
    }

    /**
     * Creates a new distances map used for calculating the
     * perimeter around an AIS source.
     *
     * @param map       The distance map which to initialize.
     * @return          <code>Map</code> containing perimeter data.
     * @since 1.0
     */
    private Map initDistanceMap(Map map) {
        map.clear();
        for (int i = 0; i < 360; i++) {
            for (double j = 0; j < 10; j += 0.1) {
                double key = i + j;
                map.put(key, new TableEntry(0, null));
            }
        }
        return map;
    }

    public void start() {
        client.start();
    }

    /**
     * Calculates the perimeter to be drawn around each AIS base station.
     *
     * @param feed      The AIS feed for which to calculate the coverage area.
     * @since 1.0
     */
    private void calculateCoveragePerimiter() {
        NavCalculator nav = new NavCalculator();
        AISMsg msg;
        // Calculate the distances from each target to the base station
        double distance;
        Position targetPosition;
        double key;
        for (Target t : getTargets()) {
            if (t.getType() == Target.TARGET_BASESTN) {
                continue;
            }
            targetPosition = t.getPosition();
            if (targetPosition == null) {
                if (targetPosition == null) {
                    msg = (t.getLatestDynamicMsg() == null
                            ? t.getLatestMessage()
                            : t.getLatestDynamicMsg());
                    if (msg.getPosition() != null) {
                        targetPosition = msg.getPosition();
                    } else {
                        continue;
                    }
                }
            }
            // Filter: Delete targets that have badly configured positions
            if (targetPosition.getLatitude() <= 0 || targetPosition.getLongitude() <= -50) {
                targetsMap.remove(t.getMMSI());
                continue;
            }

            // Calculate the vessel's distance from the AIS receiver
            nav.mercatorSailing(getLocation(), targetPosition);
            distance = nav.getDistance();

            // Remove targets that are too far away and that are hence the result of badly configured
            // receivers
            if (distance > 300) {
                continue;
            }

            key = Math.round(nav.getTrueCourse());

            if (distanceMap.get(key) == null) {
                continue;
            }

            if (distanceMap.get(key).getDistance() < distance) {
                distanceMap.remove(key);
                distanceMap.put(key, new TableEntry(distance, targetPosition));
            }
        }
    }

    /**
     * Disconnects the source from its server, causing it to
     * no longer receive AIS feeds.
     *
     * @since 1.0
     */
    private void disconnect() {
        client.disconnect();
    }

    /**
     * Wrapper class used when calculating the coverage perimiter.
     * The class maps a distance to a position, therefore allowing
     * us to retrieve the distance between any position and the position
     * of the AIS receiver.
     *
     * @since 1.0
     */
    private class TableEntry {

        private double distance;
        private Position p;

        /**
         * Constructor
         * @param distance
         * @param p
         * @since 1.0
         */
        public TableEntry(double distance, Position p) {
            this.distance = distance;
            this.p = p;
        }

        /**
         * Getter method for the distance between the position and the
         * AIS receiver.
         *
         * @return distance
         * @since 1.0
         */
        public double getDistance() {
            return distance;
        }

        /**
         * Getter method for the position mapped to the distance.
         *
         * @return position
         * @since 1.0
         */
        public Position getPosition() {
            return p;
        }
    }
}
TOP

Related Classes of jaid.ais.DataSource$TableEntry

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.