I'm trying to find the optimal minDistance value for my application in the requestLocationUpdates method. I would like to generate 1 location every 10 minutes and when I'm moving something like 100 meters.
I tried to set the minDistance parameter to 100 but I keep getting locations while my phone doesn't move even 1 meter! I keep increasing it and I stoped in 500m as a parameter since it become useless.
My question is, how come I keep getting updates while my phone is moving in the wrost case 5 meters and my minDistance parameter is 500.
Here is some code:
if (mLocationManager.isProviderEnabled(LocationManager.GPS_PROVIDER))
mLocationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, TEN_SECONDS*6*5, TEN_METERS*50, listener);
if (mLocationManager.isProviderEnabled(LocationManager.NETWORK_PROVIDER))
mLocationManager.requestLocationUpdates(LocationManager.NETWORK_PROVIDER, TEN_SECONDS*6*5, TEN_METERS*50, listener);
I'm using a timer task which ran every 10 minutes, here is the listener and the task:
...
#Override
public void onLocationChanged(Location location)
{
handleLocation(location);
}
...
private void handleLocation(Location location)
{
if(isUsable(location))
this.location = location;
}
public boolean isUsable(Location location)
{
return location!=null && location.hasAccuracy() && location.getAccuracy() < 800;
}
public void run()
{
if(location!=null)
{
Timestamp ts1 = new Timestamp(new java.util.Date().getTime());
if (mGeocoderAvailable)
address = reverseGeocode(LocationService.this.location);
if(address != "" && !address.equals(lastAddress))
{
lastAddress = address;
new SendLocation(LocationService.this.id,address,ts1);
}
}
}
I don't think that the task really matters in here, it includes some conditions that I care about and the starting a new thread that sends the information to the db.
The result is: same location provides me diffrent locations while my phone is not moving with 500m as minDistance parameter.
Its because the GPS is setting itself up to be used(During this period it tries to get exact location of you), Thereby few location updates will be noticed.
Try using this in your code:-
public boolean isUsable(Location location)
{
return location!=null && location.hasAccuracy() && location.getAccuracy() < 800 && location.getSpeed() > 0;
}
This one makes sure that the processing should be done only if the speed is > 0. Now your device won't bother if its in the same place and you can use mindistance upto 100m too.
Related
In my app I want to track the distance traveled.
I wanted to check whether the user is moving or not.
I tried to look at the speed values, but location.getSpeed() is always a lot lower than the real speed.
fusedLocationClient = LocationServices.getFusedLocationProviderClient(this);
locationRequest = LocationRequest.create();
locationRequest.setInterval(1000);
locationRequest.setSmallestDisplacement(0);
locationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
locationRequest.setWaitForAccurateLocation(true);
locationCallback = new LocationCallback()
{
#Override
public void onLocationResult(#NonNull LocationResult locationResult)
{
for (Location location : locationResult.getLocations())
{
//OTHER CODE
//...
System.out.println(location.getSpeed());
//OTHER CODE
//...
}
}
};
fusedLocationClient.requestLocationUpdates(locationRequest, locationCallback, Looper.myLooper());
The values I get don't make any sense.
Of course, when I stand still I get really small values.
But when I walk I get values around 1.
And when I'm in a car I get values around 10-15 even though I'm actually going cca 50km/h.
Am I doing something wrong, or is this normal?
Android Location reports speed in m/sec. 15 m/sec = 54 kph.
I am trying to make an AI to play simple Snake game following this article. With my current solution snake is able to come up to score of around 35 points. For some reason it will handle the walls correctly but would almost every time die by hitting its own tail.
I am not able to pinpoint my mistake, but I assume its the way I use fit function on the neural network.
for (int i = 0; i < EPOCHS; i++) {
epsilon = 0.9;
board.initGame();
State state = board.getState();
while (state.isInGame()) {
// Get next action to perform
final Action action = epsilonGreedyAction(state);
// Play action and get reward
final double reward = board.getRewardForAction(state, action);
// Get next state
final State nextState = board.getState();
// Update neural network
update(state, action, reward, nextState);
// Apply next state
state = nextState;
}
}
private Action epsilonGreedyAction(final State state) {
epsilon -=0.001;
double random = SnakeUtil.getRandom();
if (random < epsilon) {
randomActions++;
return Action.randomAction(state);
}
return SnakeUtil.getMaxQAction(state, Q_TABLE);
}
getMaxQAction will return any action that is in the Q_TABLE for this state that has had high reward up until now (max reward).
Q_TABLE is updated also in the update method
private void update(final State state, final Action action, final double reward, final State nextState) {
MaxQ maxQ = SnakeUtil.getMaxQ(nextState, Q_TABLE);
double targetReward = reward + (0.90 * maxQ.getReward());
SnakeUtil.updateQTable(state, action, targetReward, Q_TABLE);
net.fit(buildObservation(state).getData(), Nd4j.create(fromAction(action)));
}
private double[][] fromAction(final Action action) {
return new double[][] {
{
action.equals(Action.UP) ? 1 : 0,
action.equals(Action.RIGHT) ? 1 : 0,
action.equals(Action.DOWN) ? 1 : 0,
action.equals(Action.LEFT) ? 1 : 0
}
};
}
private Observation buildObservation(final State state) {
return new Observation(Nd4j.create(new boolean[][]{
{
state.isCanGoUp(),
state.isCanGoRight(),
state.isCanGoDown(),
state.isCanGoLeft(),
state.isFoodUp(),
state.isFoodUpRight(),
state.isFoodRight(),
state.isFoodDownRight(),
state.isFoodDown(),
state.isFoodDownLeft(),
state.isFoodLeft(),
state.isFoodUpLeft()
}
}));
}
My question is if the fit method is receiving correct parameters. If yes then my problem must be somwhere else.
In addition reward is calculated in a way that every time when snake steps in direction of the food its rewarded with 1, otherwise it's punished with -1.5. If it eats the food it's rewarded with 30.
Any hints and suggestions are welcome.
I want to develop an app on google map that could notify me with some information set by the user when I am close to the exact location. So can I get a link for this that How can I get pop-ups when I am at the exact(user) location?
You'll first need to enable a location manager to start getting the user's current location. Then, every time the user's location updates, the location manager calls the onLocationChanged() method. Here, you would want to check the distance between the user's current location and the destination location. If they are within whatever distance you choose, then you can display your map marker. Here is a little example of how to do that:
#Override
public void onLocationChanged(Location location) {
float distanceInMeters = destLocation.distanceTo(location);
// Distance in miles
double distance_to_dest = (distanceInMeters/1609.344);
int distance_to_dest_int = (int)(distance_to_dest * 100);
distance_to_dest = ((double)distance_to_dest_int/100.00);
tvMilesToGo.setText(String.format("%.2f", distance_to_dest) + "mi");
// About 1/10th of a mile
if ((distanceInMeters > 149) && (distanceInMeters < 176)) {
// I played an alarm sound when close to the target destination
//if (alarmPlayer.isPlaying()) {
// alarmPlayer.stop();
//}
//alarmPlayer.start();
Marker marker = mMap.addMarker(new MarkerOptions()
.position(new LatLng(destLocation.getLatitude(), destLocation.getLongitude()))
.title(“Arrived”)
.snippet(“You have arrived at your destination!”)
.icon(red_descriptor));
Marker.showInfoWindow;
}
}
Note, in your case, you would probably only ever want to add a marker once, so, you would probably want to set a flag such as markerIsVisible = true once you add it to the map, and then check before adding the marker if (markerIsVisible == false) {add the marker, markerIsVisible = true}
I'm trying to create an app for android with little experience programming. I want to use a phones gps to determine a place on google maps then cause an action to happen. The action would be based on the location and I'd also like to have the user designate locations to cause an action.
If there are any resources or websites you can point me to I would really appreciate it.
I'm currently only using android studio, is there anything else I need?
first, you need the current user location. You can follow the steps offered here to obtain it. The locationmanager provides a method onLocationChanged(Location loc) which then is triggered automatically when the location changes. You can implement your "actions" here. Im not quite sure if I have understood what the designation of locations by the user would have to trigger.
If you want to trigger a specific "action", you can implement the method onMapClicked(Location loc) by setting an onMapClickListener to your map.
Depending on how your "predefined places" are built, you have different possibilities.
1) Are those places points? --> you can calculate the euclidian (or spherical) distances, and related to that distance decide if you want to trigger something or not.
2) are those places 2d rectangles? --> use LatLngBounds and its contains(LatLng point) method to decide if the userlocation or user-designated-location is inside
3) are those places any polygons? here is a good example on how to create such a place. there is also a contains() method.
4) Are your places not predefined? We need more information on what you want to do in this case.
edit based upon ur comment :
so you there are 2 things your app should do:
1) do some action (just like popping up a message), when the user is entering a "place" or comming near to a "place"
2) give the user the possibily to create such a place by himself.
secondary can be done by adding a onMapClickListener to your map.
#Override
public void onMapReady(GoogleMap googleMap) {
mMap = googleMap;
mMap.setOnMapClickListener(new GoogleMap.OnMapClickListener() {
#Override
public void onMapClick(LatLng latLng) {
// latLng is the lcoation, tapped by the user on the map. lets save it
chosen_location = new LatLng(latLng.latitude, latLng.longitude);
}
});
}
This will save the single points, tabbed by a user on a map. If you wanna go further later for polygons, you can add this point to an ArrayList of points. However, you probably want the user to add more information about that point. Make use of EditText to let the user e.g. enter a description of that point (or later polygon), and finally, when clicking a button to "save that entered place", you can add it to an ArrayList. You probably also gonna have a server-backend in order to update and retrieve a list of places created by multiple people from anywhere.
but for now, lets go on and check if the user came nearTo such a point or entered such a polygon:
LocationManager lm = (LocationManager) getSystemService(Context.LOCATION_SERVICE);
lm.requestLocationUpdates(LocationManager.GPS_PROVIDER, 35000, 10, new LocationListener() {
#Override
public void onLocationChanged(Location location) {
// the users location changed (e.g. he moved some meters)
current_location = new LatLng(location.getLatitude(), location.getLongitude());
// somehow get all the places ( i guess a server backend is recommended )
// for now, lets say all the places are already obtained into an Arraylist called places:
ArrayList<LatLng> places = new ArrayList<LatLng>;
// Go check for each of the places, if the users current location is near to such a point
for (LatLng place : places) {
if (distance(place,current_location)<100) {
LatLng near_place = place;
// here we are! near_place is near the users current location, lets do some action
Log.d("app","Users location (" + current_location.latitude +","+current_location.longitude+") is near to a place with coordinates "+near_place.latitude+","+near_place.longitude+").");
}
}
}
#Override
public void onStatusChanged(String provider, int status, Bundle extras) {
}
#Override
public void onProviderEnabled(String provider) {
}
#Override
public void onProviderDisabled(String provider) {
}
});
}
and here is a method to calculate (spherical) distance in meters between to LatLng objects:
/**
* method calculate distance between two LatLng points in meter
*/
public float distance(double lat_a, double lng_a, double lat_b, double lng_b) {
double earthRadius = 3958.75;
double latDiff = Math.toRadians(lat_b - lat_a);
double lngDiff = Math.toRadians(lng_b - lng_a);
double a = Math.sin(latDiff / 2) * Math.sin(latDiff / 2) +
Math.cos(Math.toRadians(lat_a)) * Math.cos(Math.toRadians(lat_b)) *
Math.sin(lngDiff / 2) * Math.sin(lngDiff / 2);
double c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a));
double distance = earthRadius * c;
int meterConversion = 1609;
return new Double(distance * meterConversion).floatValue();
}
I can get location using LocationManager taking minDistance and minTime.
But how can I get location every 15 secs, for example? (even if an user didn't move)
if (Utils.hasProvider(LocationManager.GPS_PROVIDER)) {
mLocationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 15000, 100f, this);
}
if (Utils.hasProvider(LocationManager.NETWORK_PROVIDER)) {
mLocationManager.requestLocationUpdates(LocationManager.NETWORK_PROVIDER, 15000, 100f, this);
}
Google docs say that
The minDistance parameter can also be used to control the frequency of
location updates. If it is greater than 0 then the location provider
will only send your application an update when the location has
changed by at least minDistance meters, AND at least minTime
milliseconds have passed. However it is more difficult for location
providers to save power using the minDistance parameter, so minTime
should be the primary tool to conserving battery life.
Thus there is an AND condition involved. So you should set your distance parameter to 0. In that case you will get location update every 15 seconds.
Use AlarmManager to do this.See this answer.Replace the time to 5 minutes.
Or else,you can use
Runnable runnable = new Runnable() {
public void run()
{
//Your code to fetch location
}
};
Handler handler1 = new Handler();
handler1.postDelayed(runnable, 15000);
Here 15000 is 15 seconds.
You can use IntentService and on onstartcommand call runnable to post you location, like this
Handler handler.postDelayed(postGpsRunnable, 15000);