nexenio / ble-indoor-positioning Goto Github PK
View Code? Open in Web Editor NEWMultilateration using bluetooth beacons
License: Apache License 2.0
Multilateration using bluetooth beacons
License: Apache License 2.0
Implement a solution to make the multilateration results more stable while keeping the delay low.
Position changes should be realistic (not 'jumping around') and probably consider the movement speed.
Hello,
The below code doesn't allow us to change the path loss parameter, the building type is
Office with hard partition
by default.
public static float calculateDistanceTo(Beacon beacon, float rssi) {
return calculateDistance(rssi, beacon.getCalibratedRssi(), beacon.getCalibratedDistance(), PATH_LOSS_PARAMETER_OFFICE_HARD_PARTITION);
}
I added getter and setter methods to BeaconDistanceCalculator
class, check this PR
Caused by: java.util.ConcurrentModificationException
at java.util.ArrayList$Itr.next(ArrayList.java:831)
at com.nexenio.bleindoorpositioning.ble.beacon.Beacon.getAdvertisingPacketsBetween(Beacon.java:73)
at com.nexenio.bleindoorpositioning.ble.beacon.signal.WindowFilter.getRecentAdvertisingPackets(WindowFilter.java:46)
at com.nexenio.bleindoorpositioning.ble.beacon.signal.KalmanFilter.filter(KalmanFilter.java:57)
at com.nexenio.bleindoorpositioning.ble.beacon.Beacon.getRssi(Beacon.java:143)
at com.nexenio.bleindoorpositioning.ble.beacon.Beacon.getDistance(Beacon.java:155)
at com.nexenio.bleindoorpositioning.ble.beacon.Beacon.getDistance(Beacon.java:151)
public class IndoorPositioningBeaconFilter extends IBeaconFilter {
public static final UUID INDOOR_POSITIONING_UUID = UUID.fromString("03253fdd-55cb-44c2-a1eb-80c8355f8291");
public IndoorPositioningBeaconFilter() {
setProximityUuid(INDOOR_POSITIONING_UUID);
}
}
public abstract class IndoorPositioningBeaconUpdateListener extends FilteredBeaconUpdateListener {
public IndoorPositioningBeaconUpdateListener() {
super(new IndoorPositioningBeaconFilter());
}
}
How can i get .apk file of this project.
Create a class that extends IBeaconLocationProvider
which is capable of extracting geo coordinates from received advertising data.
The classes from the beaconview package in the demo application should be available as a seperate Android library, as well as some convenience classes for bluetooth scanning and location requests.
Is there any chance to drop the singleton pattern and use dependency injection ?
Or at least making the code flexible if someone want to use DI with a third library like Dagger
Hello,
Below an image from google, let's suppose that the black line is our route, is there any plan to filter the coming locations based on the route lines ?
In this way we will get an exact location with less errors, if we have a tree in a mall or an airport, i don't wanna show to the user that he is on top of the tree instead i want to show only locations on that line.
Thank you in advance
Currently, in Beacon.calculateDistanceWithoutAltitudeDeltaToFloor()
, the location altitude is used. However, that property should hold the elevation above sea level, not above floor level.
The current code inside updateLocation()
is like this
if (multilateration.getRMS() < ROOT_MEAN_SQUARE_THRESHOLD_STRICT) {
locationPredictor.addLocation(location);
onLocationUpdated(getMeanLocation(2, TimeUnit.SECONDS));
}
The user should choose between threshold : ROOT_MEAN_SQUARE_THRESHOLD_STRICT
, ROOT_MEAN_SQUARE_THRESHOLD_MEDIUM
, ROOT_MEAN_SQUARE_THRESHOLD_LIGHT
Check the PR here
I am not able to get locations.
Only Getting the following values :
AndroidLocationProvider: Received location result with 1 locations
Last known location set to : Latitude: 30.722795 Longitude: 76.7677966
During performance profiling, I noticed that one of the few methods with high impact (besides beacon update listeners) is Beacon.getAdvertisingPacketsBetween()
.
The current implementation can certainly be improved, e.g. by avoiding all the 'ArrayList.add()' calls:
public List<P> getAdvertisingPacketsBetween(long startTimestamp, long endTimestamp) {
List<P> matchingAdvertisingPackets = new ArrayList<>();
for (P advertisingPacket : new ArrayList<>(advertisingPackets)) {
if (advertisingPacket.getTimestamp() < startTimestamp) {
continue;
}
if (advertisingPacket.getTimestamp() >= endTimestamp) {
continue;
}
matchingAdvertisingPackets.add(advertisingPacket);
}
return matchingAdvertisingPackets;
}
Hello,
I am currently using 4 beacons supplied by Kontakt, (2 Pro and 2 standard).
The beacons (Pro), doesn't meet the specification of IBeaconAdvertisingPacket
class.
I am getting different values of EXPECTED_TYPE
and EXPECTED_BEACON_TYPE
for the pro type of beacon. I don't know if Kontakt change something in these beacons or not.
I used also (aruba, estimote, averos, standard kontakt) and every beacon worked fine except the Kontakt pro beacon.
I guess the problem that some companies who provide beacons, change some bits from the advertising packets to add like battery life, led and sensors. So we cannot just test the ibeacon if it meets specification in a static way.
public static boolean meetsSpecification(byte[] data) {
if (data == null || data.length < 29) {
return false;
}
if (getTypeBytes(data) != EXPECTED_TYPE) {
return false;
}
if (!Arrays.equals(getFlagsBytes(data), EXPECTED_FLAGS)) {
return false;
}
if (!Arrays.equals(getBeaconTypeBytes(data), EXPECTED_BEACON_TYPE)) {
return false;
}
return true;
}
Thank you
Hello,
The registerLocationListener (unregisterLocationListener) method in AndroidLocationProvider
are not nullable
registerLocationListener(@NonNull LocationListener locationListener)
But the same method in the IndoorPositioning
(Which should be named IndoorPositioningProvider - i guess) are nullable.
registerLocationListener(LocationListener locationListener)
Can we follow the same convention in both methods ?
Gate detection is out of the scope of the core library.
Hello,
There is a TODO to get the location from advertising packets, can you explain how you guys can make that happen if iBeacon broadcasts only one advertising packet which has a unique ID number comprising of three parts - UUID, Major, and Minor.
The sample shows that every beacon get the location depending on the minor, but the value of the minor can be changed from any smartphone.
Isn't better to use the Mac Address instead of the minor for now ? Like a HashMap.
public class IBeaconLocationProvider<B extends IBeacon> extends BeaconLocationProvider<B> {
public IBeaconLocationProvider(B beacon) {
super(beacon);
}
@Override
public void updateLocation() {
//AdvertisingPacket advertisingPacket = beacon.getLatestAdvertisingPacket();
//location = new Location();
// TODO: get location from advertising packets
}
}
Beacons that haven't been seen for a while should automatically be removed from BeaconManager.beaconMap
to not fill up the memory.
Probably based on the amount and distance of nearby indoor positioning beacons as well as the result of multilateration.getRMS()
Merge location of multiple locations over given time period
Before having this bug, i was handling all the erros in this function of RxBle library :
override fun onError(e: Throwable?) {
Log.e(e?.message.toString())
}
Now i have removed this function, and i am subscribing only on the onNext()
function of the observable, so all the errors will stop the app ( there is no error handling ).
That's why this problem hasn't appear before, it only appeared in the Logcat
.
It seems that the app crash the first time the location is calculated, the library try to get the mean of last 2 seconds locations, but there is one location only so the returned value is null
.
I am receiving the error showed below, the location is null so there is no .getAltitude()
method => no distance calculated.
I have fixed this error by checking the meanLocation if null or not before pass it to the listener, check this PR.
i installed app on my android phone . can you please suggest how it will work? give a guideP?
Hi, firstly thank you so much for your effort for such a good project. We all have chance to see the implementations of several calculations and algorithms all together.
I have pretty tested the library and app in a real office environment with the beacons installed. Here I have some test results and comments;
Although it was quite difficult to determine the coordinates of the beacons, In the first scenario I have tested with TxPower=0 dBm which is maximum range advertising ~50 m. Each beacon has 7 m distance and 12 beacons installed in total. Mostly showing the right location when I move but sometimes current location dot moves out of the region or to other corner etc. I assumed maybe it shows wrong location on the view but also checked the locations on multilateration result and saw some deviations. Another point that caught my attention is possible wrong calculation of edge locations.
In the second scenario, I have tested by setting TxPower=-20 dBm which supposed to advertise in 4 m range but test is not really successful maybe because of some other needed configurations. Also no good result when I played with deviceAdvertisingRange parameter in BeaconMap(Even the same when I set 50 m for the first scenario).
However, I see that you convert cartesian coordinates to spherical coordinates. Do you confirm that the convert is totally gives the same successful location calculation according to cartesian?
Additionally, I appreciate if you have any other configuration suggestions?
Thank you,
Alper
Use modulo instead of the remainder in:
@ColorInt
public static int getBeaconColor(int beaconIndex) {
int colorIndex = 18 + (beaconIndex * 2);
colorIndex %= MATERIAL_DESIGN_COLOR_RESOURCE_IDS.length;
return getInstance().materialDesignDarkColors[colorIndex];
}
Related to #86
Any plan for an iOS version ?
The code below remove all the beacons with rssi < -70
for (int beaconIndex = usableBeacons.size() - 1; beaconIndex >= 3; beaconIndex--) {
if (usableBeacons.get(beaconIndex).getFilteredRssi() < -70) {
usableBeacons.remove(beaconIndex);
}
}
I have added maxAcceptableRssi
variable with getter and setter in case the developer want to test another value.
Also in the same file rootMeanSquareThreshold
should be double since multilateration.getRMS()
return a double value.
Check this PR.
I saw IBeaconAdvertisingPacket class. I detected wrong parsing data such as: getTypeBytes return data[4], but I try parsing return data[1]
07-16 13:49:37.565 W/NearbyDevicesManager: Device scanning failed
java.lang.ClassCastException: com.nexenio.authenticator.accesscontrol.GateEntranceDetectionBeacon cannot be cast to com.nexenio.authenticator.accesscontrol.GateDetectionBeacon
at com.nexenio.authenticator.accesscontrol.GateDetection$1.onMatchingBeaconUpdated(GateDetection.java:93)
at com.nexenio.bleindoorpositioning.ble.beacon.FilteredBeaconUpdateListener.onBeaconUpdated(FilteredBeaconUpdateListener.java:25)
at com.nexenio.bleindoorpositioning.ble.beacon.BeaconManager.notifyBeaconUpdateListeners(BeaconManager.java:102)
at com.nexenio.bleindoorpositioning.ble.beacon.BeaconManager.processAdvertisingPacket(BeaconManager.java:79)
at com.nexenio.bleindoorpositioning.ble.beacon.BeaconManager.processAdvertisingData(BeaconManager.java:55)
at com.nexenio.authenticator.networking.bluetooth.NearbyDevicesManager.onScanResult(NearbyDevicesManager.java:213)
at com.nexenio.authenticator.networking.bluetooth.NearbyDevicesManager.lambda$startScanning$2(NearbyDevicesManager.java:147)
at com.nexenio.authenticator.networking.bluetooth.-$$Lambda$NearbyDevicesManager$3z2AY2Ysie8a5mXIbx0mQPopEkY.accept(lambda)
at io.reactivex.internal.observers.LambdaObserver.onNext(LambdaObserver.java:63)
at io.reactivex.internal.operators.observable.ObservableDoFinally$DoFinallyObserver.onNext(ObservableDoFinally.java:82)
at io.reactivex.internal.operators.observable.ObservableFlatMap$MergeObserver.tryEmit(ObservableFlatMap.java:266)
at io.reactivex.internal.operators.observable.ObservableFlatMap$InnerObserver.onNext(ObservableFlatMap.java:570)
at io.reactivex.internal.operators.observable.ObservableMap$MapObserver.onNext(ObservableMap.java:64)
at io.reactivex.internal.operators.observable.ObservableUnsubscribeOn$UnsubscribeObserver.onNext(ObservableUnsubscribeOn.java:60)
at io.reactivex.internal.operators.observable.ObservableCreate$CreateEmitter.onNext(ObservableCreate.java:67)
at com.polidea.rxandroidble2.internal.serialization.FIFORunnableEntry$1.onNext(FIFORunnableEntry.java:60)
at io.reactivex.internal.operators.observable.ObservableUnsubscribeOn$UnsubscribeObserver.onNext(ObservableUnsubscribeOn.java:60)
at io.reactivex.internal.operators.observable.ObservableSubscribeOn$SubscribeOnObserver.onNext(ObservableSubscribeOn.java:58)
at io.reactivex.internal.operators.observable.ObservableCreate$CreateEmitter.onNext(ObservableCreate.java:67)
at com.polidea.rxandroidble2.internal.operations.ScanOperationApi21$1.onScanResult(ScanOperationApi21.java:63)
at android.bluetooth.le.BluetoothLeScanner$BleScanCallbackWrapper$1.run(BluetoothLeScanner.java:694)
at android.os.Handler.handleCallback(Handler.java:751)
at android.os.Handler.dispatchMessage(Handler.java:95)
at android.os.Looper.loop(Looper.java:154)
at android.app.ActivityThread.main(ActivityThread.java:6157)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:926)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:788)
Check in beacon.
Using WindowFilter(long duration, TimeUnit timeUnit)
results in a wrong minimumTimestamp
if the timeUnit
is not MILLISECONDS
Hello,
I found that the App crash when the number of my beacons is 4 in updateLocation()
method inside the IndoorPositioning
class
No interface method sort(Ljava/util/Comparator;)V in class Ljava/util/List; or its super classes (declaration of 'java.util.List' appears in /system/framework/core-libart.jar)
Here is the 4 beacons from usableBeacons
ArrayList :
PS: I am working with the dev branch
'implementation 'com.github.neXenio:BLE-Indoor-Positioning:dev-SNAPSHOT'
Every call to Beacon.getDistance()
will invoke a new distance calculation, even if the RSSI didn't change. Make sure to cache the result and invalidate if when required.
2018-06-06 09:14:24.253 19160-19160/com.nexenio.bleindoorpositioning E/BluetoothClient: Bluetooth scanning error
org.apache.commons.math3.exception.TooManyEvaluationsException: illegal state: maximal count (1,000) exceeded: evaluations
at org.apache.commons.math3.optim.AbstractOptimizationProblem$MaxEvalCallback.trigger(AbstractOptimizationProblem.java:85)
at org.apache.commons.math3.util.Incrementor.incrementCount(Incrementor.java:157)
at org.apache.commons.math3.fitting.leastsquares.LevenbergMarquardtOptimizer.optimize(LevenbergMarquardtOptimizer.java:445)
at com.lemmingapex.trilateration.NonLinearLeastSquaresSolver.solve(NonLinearLeastSquaresSolver.java:41)
at com.lemmingapex.trilateration.NonLinearLeastSquaresSolver.solve(NonLinearLeastSquaresSolver.java:80)
at com.lemmingapex.trilateration.NonLinearLeastSquaresSolver.solve(NonLinearLeastSquaresSolver.java:88)
at com.nexenio.bleindoorpositioning.location.multilateration.Multilateration.findOptimum(Multilateration.java:65)
at com.nexenio.bleindoorpositioning.location.multilateration.Multilateration.findOptimum(Multilateration.java:58)
at com.nexenio.bleindoorpositioning.location.multilateration.Multilateration.getOptimum(Multilateration.java:123)
at com.nexenio.bleindoorpositioning.location.multilateration.Multilateration.getLocation(Multilateration.java:109)
at com.nexenio.bleindoorpositioning.IndoorPositioning.updateLocation(IndoorPositioning.java:93)
at com.nexenio.bleindoorpositioning.IndoorPositioning.onBeaconUpdated(IndoorPositioning.java:73)
at com.nexenio.bleindoorpositioning.ble.beacon.BeaconManager.notifyBeaconUpdateListeners(BeaconManager.java:102)
at com.nexenio.bleindoorpositioning.ble.beacon.BeaconManager.processAdvertisingPacket(BeaconManager.java:79)
at com.nexenio.bleindoorpositioning.ble.beacon.BeaconManager.processAdvertisingData(BeaconManager.java:55)
at com.nexenio.bleindoorpositioningdemo.bluetooth.BluetoothClient.processScanResult(BluetoothClient.java:126)
at com.nexenio.bleindoorpositioningdemo.bluetooth.BluetoothClient.access$100(BluetoothClient.java:28)
at com.nexenio.bleindoorpositioningdemo.bluetooth.BluetoothClient$1.onNext(BluetoothClient.java:92)
at com.nexenio.bleindoorpositioningdemo.bluetooth.BluetoothClient$1.onNext(BluetoothClient.java:79)
Hello,
It will be better if the location still the same if i am not moving around, a quick solution to add setMinimumMovementSpeed
method.
Hello,
Thank you, for supplying us with this open source indoor position solution.
We have been working on your solution for a few days and were able to reach the users locations using the beacons; however, there seems to be some accuracy issues, as we are getting many location responses that are varying in location even though we are not moving.
We are currently using 4 beacons supplied by Kontakt, (2 Pro and 2 standard). Each beacon has been set with a TX power of -8dBm.
Also note that we have set the scanning mode of the BLE to SCAN_MODE_LOW_POWER
.
See below image, which is a screenshot of our region surrounded by beacons (A, B, C, and D) which are mounted on columns at a height of about 2.5m, also note that the items in the middle are benches found in the area and not columns that might possibly interfere with the beacons signals.
We have set the beacons locations exactly from our maps coordinates, that have also been used in our code.
This is a screenshot showing the right recordings for our location by the beacons.
We have also attached a video screen recording of our sample application showing the location error, and dots (our location) vastly varying in the whole map.
Thank you in advance for your help.
You should be able to listen for beacon updates that match a given filter.
Calculation used in Location
to get the rotation angle between 2 locations must convert the location values lat and long to radians before calculating Math.cos()
and Math.sin()
.
Hello,
if someone use the LocationProvider
to get the location from api or based on the mac address ( and not from the minor ) the sample app will crash when pressing the chart button because he may get a negative value of minor and he cannot get a color from the materialDesignXColors array.
@ColorInt
public static int getBeaconColor(Beacon beacon, @ColorUtil.ColoringMode int coloringMode, int beaconIndex) {
int colorIndex = 0;
switch (coloringMode) {
case ColorUtil.COLORING_MODE_INSTANCES: {
if (beacon instanceof IBeacon) {
colorIndex = ((IBeacon) beacon).getMinor();
} else {
colorIndex = beaconIndex;
}
break;
}
...
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.