I want to know how I can use accelerometer sensor to determine distance that I an walk it at Android device If it is possible, then how can I implement it?
I use this code but not run. Any answer please??
#Override
public void onSensorChanged(SensorEvent event) {
float[] values = event.values;
int value = -1;
if (values.length > 0) {
value = (int) values[0];
}
if(event.sensor.getType()==Sensor.TYPE_STEP_DETECTOR) {
steps++;
}
}
float distance = (float)(steps*68.475)/(float)100000;
It is not possible: due to the low sensitivity of the built-in accelerometers and the so weak accelerations that are created when a person walks.
Not having network does not mean that GPS does not work ...
Related
So i'm currently having an issue whereby i need to populate a cuboid with certain blocks , now basically its a mine containing different ores in minecraft , but it needs to be randomly based off of some compositions for example :
public class Composition {
private ItemStack stack;
private float percentage;
public Composition(ItemStack stack, float percentage) {
this.stack = stack;
this.percentage = percentage;
}
public ItemStack getStack() {
return stack;
}
public float getPercentage() {
return percentage;
}
public void setStack(ItemStack stack) {
this.stack = stack;
}
public void setPercentage(float percentage) {
this.percentage = percentage;
}
}
then the code that resets this mine is as follows :
for ( Block b : region ) {
float chance = r.nextFloat();
int select = random.nextInt(compositions.size());
Composition comp = compositions.get(select);
if (chance <= comp.getPercentage()) {
b.setType(comp.getStack().getType());
b.setData((byte) comp.getStack().getDurability());
} else {
b.setType(defaultType.getType());
b.setData((byte) defaultType.getDurability());
}
Basically the region is a List of blocks , each block has a type.
as u can see what i tried to do was to generate a random chance float /percentage that the single block , can/should be changed
then i randomly pull an element out of this list of Compositions
based on the percentage of the random chance and the composition percentage i myt set the block to the type of the composition , however i feel like this is not accurate at all.
if someone could come up with a better way or idea to do this that would me a lot thanks.
I'm not sure if my explanation makes sense so bottom line is i'm trying to form a mine/cuboid of random blocks of different types based on compositions.
EG :
Mine has 100 x blocks
Compositions :
IRON_ORE 20 % (0.2F) = 20x Blocks should be IRON
STONE 80 % (0.8F) = 80x Blocks should be STONE
so the whole mine should contain 20% IRON_ORE randomly though not like placed 1 after the other.
STONE will basically take up the whole percentage of the mine but there should be bits of iron randomly seen.
Edited.
I think i managed to find a sort of solution , but if anyone has other opinions or ideas please let me know.
Random r = new Random();
float ratio = region.getBlocks().size() / 100;
List<Block> blocks = new ArrayList<>(region.getBlocks());
for (Composition c : compositions) {
double blocksToChange = Math.floor((float)(ratio * c.getPercentage()));
for(int i = 0; i <= blocksToChange ; i++){
if( blocks.size() <= 0 ) break;
Block b = blocks.get(r.nextInt(blocks.size()));
//Change block
b.setType(c.getStack().getType());
b.setData((byte) c.getStack().getDurability());
//Remove it
blocks.remove(b);
}
}
/// This is for the remaining blocks that cant be calculated with the Math.floor.
for(Block b : blocks){
Composition c = compositions.get(r.nextInt(compositions.size()));
b.setType(c.getStack().getType());
b.setData((byte) c.getStack().getDurability());
}
I am putting together a small game in Java, one of the problems I have encountered is increasing the speed of the animation as the player character's movement speed increases.
To increase the speed of animation, the time each frame of the animation is displayed must be decreased, from a maximum of '0.2' for the slowest speed and '0.1' for the highest speed.
My current code works, but it is quite clearly a little clumsy. Unfortunately, I can't think of an elegant solution to replace it.
public float getAnimationSpeed()
{
float _absVel = Math.abs(_vel.x);
if(_absVel > 10 && _absVel <= 50)
{
return 0.1f;
}
else if(_absVel > 50 && _absVel <= 150)
{
return 0.075f;
}
else if(_absVel > 150)
{
return 0.05f;
}
else
{
return 0f;
}
}
You might notice the function may also return a zero, which is used to display the animation as still(For example, when the player character has a velocity of 0, the animation shouldn't be playing).
You can be more dynamic, instead of reasoning with "steps" :
public float getAnimationSpeed()
{
float _absVel = Math.abs(_vel.x);
float offset = 0; //whatever you want
if(_absVel<=10){
return 0f;
}
else{
return ((1/_absVel)+offset)f;
}
}
You can of course change the "1" and the offset to another value that matches the result you want.
I hope it helped !
PS/ You probably also want to check if the result is over your maximum or under your minimum, which I didn't do.
Hey my problem is that in the onUpdate in PhysicsHandler the pSecondsElapsed often jumps from 0.016... to 0.038 which makes the player move in such big steps that it looks like the player would lagg.
Here to the importante Code from the onUpdate :
#Override
protected void onUpdate(final float pSecondsElapsed, final IEntity pEntity) {
if(this.mEnabled) {
/* Apply linear acceleration. */
final float accelerationX = this.mAccelerationX;
final float accelerationY = this.mAccelerationY;
if(accelerationX != 0 || accelerationY != 0) {
this.mVelocityX += accelerationX * pSecondsElapsed;
this.mVelocityY += accelerationY * pSecondsElapsed;
}
/* Apply angular velocity. */
final float angularVelocity = this.mAngularVelocity;
if(angularVelocity != 0) {
pEntity.setRotation(pEntity.getRotation() + angularVelocity * pSecondsElapsed);
}
/* Apply linear velocity. */
final float velocityX = this.mVelocityX;
final float velocityY = this.mVelocityY;
if(velocityX != 0 || velocityY != 0) {
pEntity.setPosition(pEntity.getX() + velocityX * pSecondsElapsed, pEntity.getY() + velocityY * pSecondsElapsed);
}
}
}
btw I am only using the linear velocity. Does anyone have a solution for this? Thanks for your help!
I went ahead and looked through the repository for this engine and I found a class that may be a help to you. The base engine class has an extension called Fixed Step Engine that should allow you to control the delta time per frame, which may be worth trying out (if you haven't already) for smoother physics.
In combination with FixedStepPhysicsWorld you will get the best possible result but: There is a small "mistake" inside the FixedStepPhysicsWorld class:
Change onUpdate as follows:
...
while(this.mSecondsElapsedAccumulator >= stepLength && stepsAllowed > 0) {
world.step(stepLength, velocityIterations, positionIterations);
this.mSecondsElapsedAccumulator -= stepLength;
stepsAllowed--;
}
this.mPhysicsConnectorManager.onUpdate(pSecondsElapsed);
to
...
while(this.mSecondsElapsedAccumulator >= stepLength && stepsAllowed > 0) {
world.step(stepLength, velocityIterations, positionIterations);
this.mSecondsElapsedAccumulator -= stepLength;
stepsAllowed--;
this.mPhysicsConnectorManager.onUpdate(stepLength);
}
The problem in the original code is that the PhysicsConnectors get updated after the PhysicsWorld made multiple steps (most of the cases). My code fixes this issue. Whenever the UiThread draws the connected entities, they are always at the position where their connected bodies are. They do not skip a Physics-step.
Let's say that I am collecting users location data every 20 minutes. At the end of the day I have an ArrayList of objects that contain lat and long fields and other data.
I have two problems that I am facing and trying to figure out:
Some of the locations are taken from inside of a building so they are not very accurate and could be spread around the actual location where the user was at the time.
Some of the locations are taken at different times but from the same location, as the user didn't moved.
What I want to achieve is to find all the locations that are near one another: lets say 70 meters, find the average location of all those locations and replace them only with this one average location.
So I am coming to the two important questions:
What would be the best way to find all near locations < 70 meter distance (Take in mind that the array contains valid changes in location. So I have to find the groups of near ones and leave the others intact).
Is there a method or a way to find the average location of many near ones?
Regarding near positions I previously answered a similar question here: Android Maps v2 - animate camera to include most markers
Specifically I think you would be able to use this piece of code:
private List<Marker> getSurroundingMarkers(List<Marker> markers,
LatLng origin, int maxDistanceMeters) {
List<Marker> surroundingMarkers = surroundingMarkers = new ArrayList<Marker>();
if (markers == null) return surroundingMarkers ;
for (Marker marker : markers) {
double dist = distBetween(origin, marker.getPosition());
if (dist < maxDistanceMeters) {
surroundingMarkers.add(marker);
}
}
return surroundingMarkers;
}
private float distBetween(LatLng pos1, LatLng pos2) {
return distBetween(pos1.latitude, pos1.longitude, pos2.latitude,
pos2.longitude);
}
/** distance in meters **/
private float distBetween(double lat1, double lng1, double lat2, double lng2) {
double earthRadius = 3958.75;
double dLat = Math.toRadians(lat2 - lat1);
double dLng = Math.toRadians(lng2 - lng1);
double a = Math.sin(dLat / 2) * Math.sin(dLat / 2)
+ Math.cos(Math.toRadians(lat1))
* Math.cos(Math.toRadians(lat2)) * Math.sin(dLng / 2)
* Math.sin(dLng / 2);
double c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a));
double dist = earthRadius * c;
int meterConversion = 1609;
return (float) (dist * meterConversion);
}
Possibly rewriting the Marker part to use LatLng instead.
regarding the averaging, it should be a simple matter of (say you have n LatLng's):
lat_avg = (lat1+lat2+...+latn)/n
lng_avg = (lng1+lng2+...+lngn)/n
latlng_avg = new LatLng(lat_avg, lat_lng)
I' not sure how you're getting the user's location - whether your using a traditional LocationManager or play services. I've always modeled my location getting on this approach documented on the android developers blog. If you're flexible in switching between location gathering methods, whether the person is inside or outside should not matter that much. You should be getting the best possible location at any given time.
Assuming you're getting locations on a sufficient time schedule (I don't know when you're checking for updates but since you want everything inside a 70m radius I'm assuming its on a time schedule and not distance change) the basic way to find the average point is:
(1) Convert each lat/long pair into a unit-length 3D vector.
(2) Sum each of those vectors
(3) Normalise the resulting vector
(4) Convert back to spherical coordinates
That approach is documented here as well as in a much earlier SO post on calculating the average of a set of angles
The example code is pretty easy to follow - just plug in the lat long values you get from your location grab and you should be ok.
Well for markers that come from the same location I have created the following method:
public ArrayList<MyLocation> removeSameLocationMarkers(List<ParseObject> objects, int maxDistanceMeters)
{
boolean isLocationExist;
ArrayList<MyLocation> acceptedLocations = new ArrayList<MyLocation>();
if (objects == null) return acceptedLocations;
for (ParseObject location1 : objects)
{
isLocationExist = false;
for (MyLocation location2 : acceptedLocations)
{
if (!location1.equals(location2))
{
float distance = distBetween(location1.getDouble("latitude"), location1.getDouble("longitude"), location2.getLatitude(), location2.getLongitude());
if (distance < maxDistanceMeters)
{
location2.addTimeToLocation(location1.getString("time"));
isLocationExist = true;
}
}
}
if (!isLocationExist)
{
Location newLocation = new Location("");
newLocation.setLatitude(location1.getDouble("latitude"));
newLocation.setLongitude(location1.getDouble("longitude"));
String provider = location1.getString("provider");
if (provider != null)
{
newLocation.setProvider(provider);
}
MyLocation newMyLocation = new MyLocation(newLocation);
newMyLocation.addTimeToLocation(location1.getString("time"));
acceptedLocations.add(newMyLocation);
}
}
return acceptedLocations;
}
Im listening to my phones GPS and post latitude and longitude to my webservice evey time onLocationChanged gets called. My problem is that in about 2% of my posts, it displays a VERY inaccurate result (several miles off). Should i check the accuracy from my location object before i post? Or do you have any other suggestions? Thanks!
public void onLocationChanged(Location location) {
locationManager.removeUpdates(networkLocationListener);
textView.setText(textView.getText().toString() + "New GPS location: "
+ String.format("%9.6f", location.getLatitude()) + ", "
+ String.format("%9.6f", location.getLongitude()) + "\n");
//float accuracy = location.getAccuracy(); check this value?
postLocationToWebservice(location);
}
This is a very common problem while using the Location services of Android.There are few checks you can introduce to make sure that only the accurate location gets posted to you web service.
1.Compare the accuracy of all the location services.
2.Define a minimum limit for accuracy and a maximum limit for time.(Because some times the location obtained is accurate but it is an old one).
Check this code snippet and make necessary changes to accomplish what you want.Make sure you make a
log build that checks the accuracy of your algorithm.
List<String> matchingProviders = myLocation.lm.getAllProviders();
for (String provider: matchingProviders)
{
Location location = myLocation.lm.getLastKnownLocation(provider);
if (location != null) {
float accuracy = location.getAccuracy();
long time = location.getTime();
if ((time > minTime && accuracy < bestAccuracy)) {
bestResult = location;
bestAccuracy = accuracy;
bestTime = time;
}
else if (time < minTime && bestAccuracy == Float.MAX_VALUE && time > bestTime) {
bestResult = location;
bestTime = time;
}
}
}
It could be possible that the updated location is reported by NETWORK_PROVIDER instead of GPS_PROVIDER
you can always get the last updated GPS location by
mLocationMgr.getLastKnownLocation(LocationManager.GPS_PROVIDER);