【问题标题】:Calculate distance traveled (not distance between)计算行进距离(不是之间的距离)
【发布时间】:2019-02-11 10:34:04
【问题描述】:

我需要计算汽车行驶的距离!没有距离,没有距离没有。如果我们通过 Google 提供的 API 计算距离,距离可能会完全不同。谷歌可以从一个点到另一个点 1 公里,但汽车可以按照骑手想要的方式行驶 800 米。使用加速度计没有帮助。它适用于步行,但不适用于更快的速度。

关于如何获得汽车行驶距离的任何建议?

我尝试过使用 Google 的 Location API:distanceTo 或 distanceBetween 根本不是一个选项。它可以给出与 IN REAL 截然不同的结果。在真正的汽车中,可以通过非常短的地方并在 800 米内到达目标,而 Google 可以提供 1KM 的位置之间的距离。

以下是我的应用程序的代码。速度惊人的正确。

class HomeScreen : AppCompatActivity(), GoogleApiClient.ConnectionCallbacks,
    GoogleApiClient.OnConnectionFailedListener, SensorEventListener {
    override fun onSensorChanged(event: SensorEvent?) {
        val sensor = event?.sensor
        val values = event?.values
        var value = -1

        if (values != null && values.size ?: 0 > 0) {
            value = values[0].toInt()
        }


        if (sensor != null &&
            sensor.type == Sensor.TYPE_STEP_DETECTOR
        ) {
            val finalSteps = getDistanceRun(steps)
            val finalStepsTruncated = String.format("%.2f", finalSteps)
            distanceTV.text = "$finalStepsTruncated"
            steps++
        }
    }

    override fun onAccuracyChanged(p0: Sensor?, p1: Int) {

    }

    override fun onConnectionFailed(p0: ConnectionResult) {
        val failed = p0
    }

    @SuppressLint("MissingPermission")
    override fun onConnected(p0: Bundle?) {
        if (locationPermissionsGranted(this)) {
            fusedLocationClient?.requestLocationUpdates(locationRequest, object : LocationCallback() {
                override fun onLocationResult(p0: LocationResult?) {
                    val location = p0
                    val metersPerSecond: Float = location?.lastLocation?.speed ?: 0f
                    val speed = metersPerSecond * 3600 / 1000
                    speedTV.text = "${Math.round(speed)} KM/H"
                }
            }, null)

        } else {
            requestPermission(
                this, 0,
                Manifest.permission.ACCESS_COARSE_LOCATION, Manifest.permission.ACCESS_FINE_LOCATION
            )
        }
    }

    override fun onConnectionSuspended(p0: Int) {
        val suspended = p0
    }

    private var fusedLocationClient: FusedLocationProviderClient? = null
    private var mGoogleApiClient: GoogleApiClient? = null
    private lateinit var locationRequest: LocationRequest
    private var steps: Long = 0

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_home_screen)
        locationRequest = LocationRequest()
        locationRequest.priority = LocationRequest.PRIORITY_HIGH_ACCURACY;
        locationRequest.interval = 1000
        locationRequest.fastestInterval = 500

        if (PermissionManager.locationPermissionsGranted(this)) {
            mGoogleApiClient = GoogleApiClient.Builder(this)
                .addConnectionCallbacks(this)
                .addOnConnectionFailedListener(this)
                .addApi(LocationServices.API)
                .build()

            mGoogleApiClient?.connect()
            fusedLocationClient = LocationServices.getFusedLocationProviderClient(this)
            createLocationRequest()
        } else {
            requestPermission(
                this, 0,
                Manifest.permission.ACCESS_COARSE_LOCATION, Manifest.permission.ACCESS_FINE_LOCATION
            )
        }

        val sManager = getSystemService(Context.SENSOR_SERVICE) as SensorManager
        val stepSensor = sManager.getDefaultSensor(Sensor.TYPE_STEP_DETECTOR)
        sManager.registerListener(this, stepSensor, SensorManager.SENSOR_DELAY_FASTEST);
    }

    override fun onRequestPermissionsResult(requestCode: Int, permissions: Array<out String>, grantResults: IntArray) {
        super.onRequestPermissionsResult(requestCode, permissions, grantResults)
        if (PermissionManager.locationPermissionsGranted(this)) {
            mGoogleApiClient = GoogleApiClient.Builder(this)
                .addConnectionCallbacks(this)
                .addOnConnectionFailedListener(this)
                .addApi(LocationServices.API)
                .build()
            mGoogleApiClient?.connect()
            fusedLocationClient = LocationServices.getFusedLocationProviderClient(this)
            createLocationRequest()
        }
    }

    protected fun createLocationRequest() {
        val builder = LocationSettingsRequest.Builder()
            .addLocationRequest(locationRequest)

        val client = LocationServices.getSettingsClient(this)
        val task = client.checkLocationSettings(builder.build())

        task.addOnSuccessListener(this) {

            // All location settings are satisfied. The client can initialize
            // location requests here.
            // ...
        }

        task.addOnFailureListener(this) { e ->

            if (e is ResolvableApiException) {
                // Location settings are not satisfied, but this can be fixed
                // by showing the user a dialog.
                try {
                    // Show the dialog by calling startResolutionForResult(),
                    // and check the result in onActivityResult().
                    e.startResolutionForResult(
                        this@HomeScreen,
                        0
                    )
                } catch (sendEx: IntentSender.SendIntentException) {
                    // Ignore the error.
                }

            }
        }
    }

    fun getDistanceRun(steps: Long): Float {
        return (steps * 78).toFloat() / 100000.toFloat()
    }
}

【问题讨论】:

  • 也许每秒或每 20 米获取 GPS 更新,并总结整个距离的所有位移(?)如果您每 20 米请求它们,那么您甚至不需要计算位移。

标签: java android kotlin distance


【解决方案1】:

我已经实现了一个基于 gps 读数的里程表,并且通过一秒钟的读数,我能够获得远低于 1% 的准确度误差的里程表讲座。远在 50-70 公里的距离内,我无法检测到与道路标记超过 50 米的差异(我什至能够检测到标记何时移动)所使用的程序涉及整合速度读数(速度由 gps 给出一个向量,所以不需要计算它的模数)和设备给出的时间戳的精确读数。永远不要使用位置读数......因为这些读数足以让您的里程表偏离读数超过 20%。但是使用速度并将它们整合可以为您提供良好的低音带通滤波。

使用的 GPS 是具有 NMEA.0183 输出的标准 OEM gps。速度读数的分辨率为 0.1 值,因此我没想到准确度会低于 1%,目前的 gps 设备提供的速度读数分辨率低于 0.001。

【讨论】:

    【解决方案2】:

    你好,我不知道这是否有帮助,但我曾经写过一个类,我通过将参数输入到相应的方法来手动计算它:

    import android.Manifest;
    import android.app.Activity;
    import android.content.pm.PackageManager;
    import android.os.Looper;
    import android.support.v4.app.ActivityCompat;
    import android.util.Log;
    import android.widget.Toast;
    
    import com.google.android.gms.location.FusedLocationProviderClient;
    import com.google.android.gms.location.LocationCallback;
    import com.google.android.gms.location.LocationRequest;
    import com.google.android.gms.location.LocationResult;
    import com.google.android.gms.location.LocationServices;
    import com.karumi.dexter.Dexter;
    import com.karumi.dexter.MultiplePermissionsReport;
    import com.karumi.dexter.PermissionToken;
    import com.karumi.dexter.listener.PermissionRequest;
    import com.karumi.dexter.listener.multi.MultiplePermissionsListener;
    
    import java.util.List;
    
    /**
     * Created by Ibkunle Adeoluwa on 1/8/2019.
     */
    
    
    public class LocationManager {
    
        private FusedLocationProviderClient fusedLocationProviderClient;
        private LocationCallback locationCallback;
        private LocationRequest locationRequest;
    
    
    
        //TODO Import these Libraries in gradle
        /*
        implementation 'com.google.android.gms:play-services-location:11.8.0'
        implementation 'com.karumi:dexter:5.0.0'
        */
    
        private Activity myActivity;
    
        public LocationManager(Activity myActivity) {
            this.myActivity = myActivity;
        }
    
    
        public void requestLocationPermissions() {
            //Request required permissions using Dexter Library ACCESS_COARSE_LOCATION & ACCESS_FINE_LOCATION
            Dexter.withActivity(myActivity)
                    .withPermissions(Manifest.permission.ACCESS_COARSE_LOCATION,
                            Manifest.permission.ACCESS_FINE_LOCATION)
                    .withListener(new MultiplePermissionsListener() {
                        @Override
                        public void onPermissionsChecked(MultiplePermissionsReport report) {
                            if (report.areAllPermissionsGranted()) {
                                buildLocationRequest();
                                buildLocationCallback();
                                if (ActivityCompat.checkSelfPermission(myActivity, Manifest.permission.ACCESS_FINE_LOCATION)
                                        != PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission(myActivity, Manifest.permission.ACCESS_COARSE_LOCATION)
                                        != PackageManager.PERMISSION_GRANTED) {
                                    return;
                                }
                                fusedLocationProviderClient = LocationServices.getFusedLocationProviderClient(myActivity);
                                fusedLocationProviderClient.requestLocationUpdates(locationRequest, locationCallback, Looper.myLooper());
                            }
                        }
    
                        @Override
                        public void onPermissionRationaleShouldBeShown(List<PermissionRequest> permissions, PermissionToken token) {
                            Toast.makeText(myActivity, "Location Permission Denied", Toast.LENGTH_SHORT).show();
    
                        }
                    }).check();
        }
    
    
        private void buildLocationRequest() {
            //Get Location
            locationRequest = new LocationRequest();
            locationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
            locationRequest.setInterval(5000);
            locationRequest.setSmallestDisplacement(10.0f);
        }
    
        private Location buildLocationCallback() {
            //Process location response
            final Location location = new Location();
    
            locationCallback = new LocationCallback() {
                @Override
                public void onLocationResult(LocationResult locationResult) {
                    super.onLocationResult(locationResult);
                    //Log
                    Log.d("Location", locationResult.getLastLocation().getLatitude()
                            + "/" + locationResult.getLastLocation().getLongitude());
    
                    location.setLatitude(locationResult.getLastLocation().getLatitude());
                    location.setLongitude(locationResult.getLastLocation().getLongitude());
    
    
                }
            };
            return location;
        }
    
        //TODO How to Use
    
        /***
         * Sample Request
         *
         System.out.println(distance(32.9697, -96.80322, 29.46786, -98.53506, 'M') + " Miles\n");
         System.out.println(distance(32.9697, -96.80322, 29.46786, -98.53506, 'K') + " Kilometers\n");
         System.out.println(distance(32.9697, -96.80322, 29.46786, -98.53506, 'N') + " Nautical Miles\n");
    
         System.out.println(distance(10.46786, -98.53506,32.9697, -96.80322,  'M') + " Initial Miles\n");
         System.out.println(distance(32.9697, -96.80322, 29.46786, -98.53506, 'M') + " Covered Miles\n");
    
         System.out.println(coveredDistance(distance(10.46786, -98.53506,32.9697, -96.80322), distance(32.9697, -96.80322, 29.46786, -98.53506))+ " Left Distance\n");
    
         System.out.println(percentageCoveredDistance(262.6777938054349,1558.5453389875424)+ " Covered Distance Percentage \n");
         *
         *
         ***/
    
    
        /**
         * Expected Output
         *
         262.6777938054349 Miles
         422.73893139401383 Kilometers
         228.10939614063963 Nautical Miles
    
         1558.5453389875424 Initial Miles
         262.6777938054349 Covered Miles
    
         1295.8675451821075 Left Distance
         17% Covered Distance Percentage
         *
         *
         **/
    
    
        /**
         *
         * @param lat1
         * @param lon1
         * @param lat2
         * @param lon2
         * @param unit
         * @return
         */
        private static double distance(double lat1, double lon1, double lat2, double lon2, char unit) {
            double theta = lon1 - lon2;
            double dist = Math.sin(deg2rad(lat1)) * Math.sin(deg2rad(lat2)) + Math.cos(deg2rad(lat1)) * Math.cos(deg2rad(lat2)) * Math.cos(deg2rad(theta));
            dist = Math.acos(dist);
            dist = rad2deg(dist);
            dist = dist * 60 * 1.1515;
            if (unit == 'K') {
                dist = dist * 1.609344;
            } else if (unit == 'N') {
                dist = dist * 0.8684;
            }
            return (dist);
        }
    
        /**
         *
         * @param lat1
         * @param lon1
         * @param lat2
         * @param lon2
         * @return
         */
        private static double distance(double lat1, double lon1, double lat2, double lon2) {
            double theta = lon1 - lon2;
            double dist = Math.sin(deg2rad(lat1)) * Math.sin(deg2rad(lat2)) + Math.cos(deg2rad(lat1)) * Math.cos(deg2rad(lat2)) * Math.cos(deg2rad(theta));
            dist = Math.acos(dist);
            dist = rad2deg(dist);
            dist = dist * 60 * 1.1515;
            return (dist);
        }
    
        /*:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/
        /*::  This function converts decimal degrees to radians             :*/
        /*:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/
    
        /**
         *
         * @param deg
         * @return
         */
        private static double deg2rad(double deg) {
            return (deg * Math.PI / 180.0);
        }
    
        /*:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/
        /*::  This function converts radians to decimal degrees             :*/
        /*:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/
    
        /**
         *
         * @param rad
         * @return
         */
        private static double rad2deg(double rad) {
            return (rad * 180.0 / Math.PI);
        }
    
        /*:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/
        /*::  This function converts subtracts initial from current distance:*/
        /*:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/
    
        /**
         *
         * @param initialDistance
         * @param currentDistance
         * @return
         */
        private static double coveredDistance(double initialDistance, double currentDistance) {
            return (initialDistance - currentDistance);
        }
    
        /*:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/
        /*::This function converts the covered distance to percentage of the total :*/
        /*:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/
    
        /**
         *
         * @param coveredDistance
         * @param totalDistance
         * @return
         */
        private static String percentageCoveredDistance(double coveredDistance, double totalDistance) {
            double percent = (100 * coveredDistance) / totalDistance;
            return String.format("%.0f%%", percent);
        }
    
    
    }
    

    【讨论】:

    • 不是我要找的那个:(
    猜你喜欢
    • 2014-11-29
    • 2013-12-16
    • 2012-12-31
    • 2014-02-28
    • 2010-10-30
    • 2013-07-17
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多