Constraint API

This page details all of the available NEON API functionality contained within the static API class NeonConstraint.

Adding a User Check-in

Once you are bound to the NEON Location Service, the best estimate of your initial location will be provided. If you are outside and receiving GPS, you may quickly get a position with small error. If you are inside or in an area with poor GPS, the system will only be able to provide a general location with large error. To specify location with greater accuracy, a check-in can be added that will more precisely determine location. Usually, this is based on a user pressing a location on a satellite map displayed on the Android screen. Coordinates can be provided in (latitude, longitude) format, and error can be specified in meters. The error should indicate how accurately the user is able to specify a location on a map (this can be correlated with zoom level).

/**
* Add a user check-in to help solve the user’s location
*
* @param unixTimeMs Unix time in ms
* @param latitude WGS-84 Latitude
* @param longitude WGS-84 Longitude
* @param locationError Location Error in meters
* @param elevation Elevation information
* @see com.trx.neon.api.neonConstraint.model.ElevationInfo
*/
void addUserCheckin(long unixTimeMs, double latitude, double longitude, float locationError, ElevationInfo elevation)

The latitude, longitude, and location error in meters specify the 2D area where the user is currently located. The Elevation Information specifies where the user is in 3D. If the check-in should only specify the location in 2D, pass ElevationInfo.None(). If the check-in is outside on the terrain, specify ElevationInfo.OnTerrain(). If the user is on a known building and floor and checking-in on a floorplan retrieved from the Environment API, then you can specify building ID and floor with ElevationInfo.OnFloor(buildingID, floor).

The following code shows how to apply a check-in at the center of the screen on a google map with each of these cases:

//get latitude and longitude of correction
LatLng target = new LatLng(googleMap.getCameraPosition().target.latitude, googleMap.getCameraPosition().target.longitude);

//check-in with 2D location only
NeonConstraint.addUserCheckin(System.currentTimeMills(), target.latitude, target.longitude, 1.0f, ElevationInfo.None());

//OR check-in outside on the terrain
NeonConstraint.addUserCheckin(System.currentTimeMills(), target.latitude, target.longitude, 1.0f, ElevationInfo.OnTerrain());

//OR check-in on the displayed floor of a building with a known building ID
UUID buildingID = getCurrentlySelectedBuilding();   //user is checking-in inside this building 
int floor = getCurrentlySelectedFloor();           //user is checking-in on this floorplan (0 is ground floor, + is aboveground, - is belowground)

NeonConstraint.addUserCheckin(System.currentTimeMills(), target.latitude, target.longitude, 1.0f, ElevationInfo.OnFloor(buildingID, floor));

Adding a Ranging Constraint

The Constraint API can accept externally resolved ranges to a known ranging device. A range in meters, the location of the device, and elevation information is required.

/**
* Add a ranging constraint to help solve the user's location
* @param unixTimeMs Unix time in ms
* @param latitude WGS-84 Latitude of ranging device
* @param longitude WGS-84 Longitude of ranging device
* @param placementError Error in placement of ranging device in meters
* @param range Range to ranging device in meters
* @param type Range type of the ranging device
* @see com.trx.neon.api.neonConstraint.model.types.RangeType
* @param elevation Elevation information for the ranging device
* @see com.trx.neon.api.neonConstraint.model.ElevationInfo
**/
void addRangingConstraint(long unixTimeMs, double latitude, double longitude, float placementError, float range, RangeType type, ElevationInfo elevation)

The latitude, longitude, placement error, and elevation information have to do with the location of the ranging device, while the RangeType and range in meters are based on a received range to that device.

RangingType Description
TOF Time-of-flight ranging
RSSI Received-signal-strength ranging
UWB Ultra-wideband ranging
NFC Near-field-communication ranging

The elevation information is used to specify whether the ranging device should not affect elevation (ElevationInfo.None()), should constrain elevation to the outside terrain (ElevationInfo.OnTerrain()), or should constrain elevation to a building and floor (ElevationInfo.OnFloor(buildingID, floor)).

The following code shows how to apply a sample ranging constraint:

NeonConstraint.addRangingConstraint(
    System.currentTimeMills(),  //current time
    rangingDevice.latitude,     //device latitude
    rangingDevice.longitude,    //device longitude
    2.0f,                       //placement error in meters
    range,                      //range in meters
    RangeType.TOF,              //TOF ranging device
    ElevationInfo.onFloor(rangingDevice.buildingID, rangingDevice.floor) //building and floor
);

Adding GPS NMEA sentences to constrain location

NEON will use any GPS or Network Location provided by Android. If you have an additional source of GPS from an external device that provides the NMEA standard, you can add sentences from the device using this function to generate GPS constraints. You will need to send all of the following NMEA messages to generate a constraint: RMC, GGA, GSV, and GSA.

/**
* Add a GPS NMEA sentence to help solve the user's location
* In order to generate GPS Constraints via this method,
* send at least the following NMEA sentences: RMC, GGA, GSV, and GSA.
* @param sentence A single and complete NMEA sentence
**/
void addNMEASentence(String sentence)

The following code shows how to apply a NMEA constraint:

String nmeaSentence = getLastNMEASentence();
NeonConstraint.addNMEASentence(nmeaSentence);

Adding a GPS Constraint

NEON will use any GPS or Network Location provided by Android. If you have an additional source of GPS from an external device that does not use a standard NMEA interface, you can use this function to add a GPS constraint.

/**
* Ass a GPS Constraint to help solve the user's location
* @param unixTimeMs Unix time in ms
* @param latitude WGS-84 Latitude
* @param longitude WGS-84 Longitude
* @param fixQuality The GPS fix quality
* @see com.trx.neon.api.neonConstraint.model.types.GPSFixQuality
* @param errorCEP CEP50 Error in meters
*/
void addGPSConstraint(long unixTimeMs, double latitude, double longitude, GPSFixQuality fixQuality, float errorCEP)
GPSFixQuality Description
GPS Standard GPS
DGPS Differential GPS
RTK Real-time kinematic positioning
FLOAT_RTK Float Real-time kinematic
MULTI Multi-constellation fix
SECURE Secure GPS source

The following code shows how to apply a sample GPS constraint:

NeonConstraint.addGPSConstraint(
    measurement.unixTimeMs,     //measurement time in Unix Time Milliseconds
    measurement.latitude,       //latitude
    measurement.longitude,      //longitude
    GPSFixQuality.RTK,          //Gps fix quality Type
    measurement.error,          //CEP50 error in meters
);

Dropping a UWB Beacon

If you have an ulta-wideband capable tracking unit, you can program a UWB beacon with location and elevation information, which it will then share with nearby users in the same UWB configuration channel. To drop a UWB beacon, you need to scan and discover nearby Bluetooth Devices. The device name, which is in the form TRX_9XXX, can be checked with the function canDropUWBBeacon() to determine whether everything is configured to successfully drop the beacon. A UWB Channel Configuration must be set with NeonSettings.setUWBConfiguration() in order to drop beacons.

/**
* Program an UWB beacon with location and elevation information so it can then
* beacon to improve nearby users' location. An UWB-enabled tracker is required.
* @param unixTimeMs Unix time in ms
* @param beaconName The device name of the UWB beacon, in the form "TRX_9XXX". Can be retrieved from BluetoothDevice.name
* @param latitude WGS-84 Latitude of UWB beacon
* @param longitude WGS-84 Longitude of UWB beacon
* @param locationError Error in placement of UWB beacon in meters
* @param elevationInfo Elevation information for UWB beacon
* @see com.trx.neon.api.neonConstraint.model.ElevationInfo
**/
void dropUWBBeacon(long unixTimeMs, String beaconName, double latitude, double longitude, float locationError, ElevationInfo elevationInfo)

/**
* Determines whether user can drop an UWB beacon
* @param beaconName bluetooth device name of the beacon to be dropped, in the form "TRX_9XXX"
* @return whether or not the beacon is able to be dropped
**/
boolean canDropUWBBeacon(String beaconName)

The following code shows how to drop a UWB beacon. You can use the last NEON location received to seed the location or provide your own.


//device.getName() = "TRX_9000"
NeonLocation lastLocation = getLastLocation();

if(NeonConstraint.canDropBeacon(device.getName()))
{
    NeonConstraint.dropUWBBeacon(
        System.currentTimeMills(),   //Unix Time Milliseconds
        device.getName(),            //beacon Name
        lastLocation.longitude,      //latitude
        lastLocation.longitude,      //longitude
        lastLocation.errorRadius,    //placement error
        ElevationInfo.onTerrain()    //outside on terrain
    );
}

Adding a Custom Constraint

For constraints that don’t fit into any of the above models, a custom constraint can be applied using this function.

/**
* Add a custom constraint to help solve the user’s location
* @param constraint A CustomConstraint object that represent a location with error and elevation info
* @see com.trx.neon.api.neonConstraint.model.CustomConstraint
**/
public static void addCustomConstraint(CustomConstraint constraint)

The CustomConstraint object has the following fields:

/**
* Creates a custom constraint
*
* @param unixTimeMs Unix time in ms
* @param latitude WGS-84 Latitude
* @param longitude WGS-84 Longitude
* @param errorModel Error model for this constraint
* @param elevation Elevation information for this constraint
*/
CustomConstraint(long unixTimeMs, double latitude, double longitude, ErrorModel errorModel, ElevationInfo elevation)

The error model specifies how the constraint should be applied to the solution. ErrorModel.Uniform(radius) will apply the constraint uniformly in a circle with the provided radius in meters, while ErrorModel.Gaussian(stdDev) will apply a Gaussian model with the provided standard deviation in meters.

The elevation information is used to specify whether the constraint should not affect elevation (ElevationInfo.None()), should constrain elevation to the outside terrain (ElevationInfo.OnTerrain()), or should constrain elevation to a building and floor (ElevationInfo.OnFloor(buildingID, floor)).

The following code shows how to apply a constraint which has a Gaussian error model with a standard deviation of 5 meters on the terrain:

//construct a Custom constraint
ConstraintConstraint customConstraint = new CustomConstraint(
    System.currentTimeMills(),  //current time
    constraint.latitude,       //latitude
    constraint.longitude,      //longitude
    ErrorModel.Gaussian(5.0f),  //Gaussian with 5 meters standard deviation
    ElevationInfo.OnTerrain()  //Elevation of constraint is on terrain
);

NeonConstraint.addCustomConstraint(customConstraint);

Monitoring Constraints with Constraint Events

To receive constraints from the NEON Location Service, you need to implement the INeonEventListenerConstraint interface in your main activity.

You can then register and unregister the listener with the following:

NeonConstraint.registerEvents(this);
NeonConstraint.unregisterEvents(this);

INeonEventListenerConstraint provides an onEvent function that is called whenever a constraint event is received. The following code shows how to extract the relevant events and cast them to the appropriate types:

@Override
public void onEvent(NeonEventTypeConstraint type, INeonEventConstraint ne) 
{
    switch(type)
    {
        case REMOTE_RANGE:
            RemoteRangeEvent rre = (RemoteRangeEvent)ne;
            //use this remote range event
            break;
        case GPS:
            GPSEvent ge = (GPSEvent)ne;
            //use this gps event
            break;
        case GPS_STATUS:
            GPSStatusEvent gse = (GPSStatusEvent)ne;
            //use this gps status event
            break;
        case DROPPED_BEACON_STATUS:
            DroppedBeaconStatusEvent dbse = (DroppedBeaconStatusEvent)ne;
            //use this dropped beacon status event
            break;
    }
}

Remote Range Event

The remote range event is emitted whenever the NEON Location Service receives a range from a ranging device. If the ranging device is registered with the NEON Cloud, the location of the ranging device will be included with this event. Otherwise, the latitude, longitude, and elevationInfo fields will be null.

/**
* Creates a remote range event
*
* @param unixTimeMs Unix time in ms
* @param remoteID Identifier for the ranging device
* @param range The computed range in meters to the ranging device
* @param rangeType Ranging technology used
* @param placementError Uncertainty in meters of the placement location of the ranging device
* @param latitude Latitude if device is registered with NEON, otherwise null
* @param longitude Longitude if device is registered with NEON, otherwise null
* @param elevationInfo ElevationInfo if device is registered with NEON, otherwise null
*/
public RemoteRangeEvent(long unixTimeMs,  String remoteID, float range, RangeType rangeType, float placementError, Double latitude, Double longitude, ElevationInfo elevationInfo)

GPS Event

The GPS Event is emitted for every GPS point received from Android or input via the API. The status field indicates the overall state of GPS in the NEON Location Service.

/**
* Creates a custom constraint
*
* @param unixTimeMs Unix time in ms
* @param sourceType Hardware source of this constraint
* @param fixQuality Fix quality of the GPS Constraint
* @param latitude WGS-84 Latitude
* @param longitude WGS-84 Longitude
* @param errorCEP Error radius in meters CEP50
* @param status GPS status for this constraint
* @param statusFlags (ignore) source information for the status
*/
public GPSEvent(long unixTimeMs, GPSSourceType sourceType, GPSFixQuality fixQuality, double latitude, double longitude, float errorCEP, GPSStatus status, long statusFlags)

GPS Status

An overall GPS status is kept by the NEON Location Service that indicates the current state of the GPS being received. A GPS Status Event will be emitted whenever this status changes.

GPSStatus Description
UNKNOWN No GPS received - state is unknown
NORMAL_STRONG_SIGNAL GPS is being received and contributing to the position
NORMAL_WEAK_SIGNAL GPS is being received but is of low quality and is not being used to compute a position
NORMAL_NO_SIGNAL GPS was received previously but a new point hasn’t been received for several seconds
WARNING_JAM Similar to NORMAL_NO_SIGNAL, except intentional jamming is suspected
WARNING_REPEATER GPS is being received repeatedly at the same location - there is possibly a GPS repeater in the area
WARNING_SPOOF GPS is being detected that does not match expected locations - there is possibly a GPS simulator in the area

Dropped Beacon Status Event

A Dropped Beacon Status Event is emitted when NeonConstraint.dropUWBBeacon() is called. It indicates whether the beacon was successfully dropped and any error message.

/**
* Creates a dropped beacon status event
* @param unixTimeMs Unix time in ms
* @param beaconID Name of the beacon trying to be dropped, in the form "TRX_9XXX"
* @param success Whether the beacon was successfully dropped
* @param errorMessage Any error message
*/
public DroppedBeaconStatusEvent(long unixTimeMs, String beaconID, boolean success, String errorMessage)