13

I have a step counter app in which I am running a service which counts steps taken and then sends a broadcast to the fragment which is then updated on the fragment. The step counting is working fine but I want to calculate speed based on the steps. Here is what I am trying right now.

The receiver to get step count:

receiver = new BroadcastReceiver() {
    @Override
    public void onReceive(Context context, Intent intent) {
        int steps = intent.getIntExtra(StepCounterService.STEP_INCREMENT_KEY, 0);
        if (firstStepTime.equals("0")) {
            firstStepTime = intent.getStringExtra(StepCounterService.TIME_STAMP_KEY);
        } else if (secondStepTime.equals("0")) {
            secondStepTime = intent.getStringExtra(StepCounterService.TIME_STAMP_KEY);
        } else {
            firstStepTime = secondStepTime;
            secondStepTime = intent.getStringExtra(StepCounterService.TIME_STAMP_KEY);
        }

        updateAllUI(steps);
    }
};

So what I am doing is as soon as I start getting steps, I see if the variable firstStepTime is empty. If it is, I save the time in firstStepTime variable. The in the next step I see if secondStepTime is empty, and if it is, I save that time in secondStepTime variable. Now for the next steps both these are updated.

public void updateAllUI(int numberOfSteps) {

    if (!(firstStepTime.equals("0")) && !(secondStepTime.equals("0"))) {
        try {
            Calendar c = Calendar.getInstance();
            SimpleDateFormat timeFormat = new SimpleDateFormat("HH:mm:ss.SSS");
            timeDifference = timeFormat.parse(secondStepTime).getTime() - timeFormat.parse(firstStepTime).getTime();

            speed = (float) ((0.0254 / (timeDifference * 0.001)) * 3.6);
        } catch (Exception e) {
            timeDifference = 0;
            speed = 0;
        }

        textview.settext(speed +"Km/h);
    }
}

So in this I just check if both are not empty, I take the values and calculate the difference in times. The problem here is sometimes it doesn't count speed properly. And a bigger problem is if the user stops, the speed remains constant and doesn't drop to zero.

Is there any better way to do the speed calculation?

Ivar
  • 6,138
  • 12
  • 49
  • 61
Aishvarya Jaiswal
  • 1,793
  • 6
  • 34
  • 72
  • If you are using the FineLocation it shouldn't be too hard tr using the getSpeed with the google maps api. I made a spedometer using the api, works well but a little delayed and sometimes a little off when the user doesn't move faster than 1mph. – DrBrad Apr 19 '17 at 14:20
  • This 0.0254 would be a fixed distance for each step? What is 3.6? – Juan Apr 20 '17 at 13:34
  • Also, how are you collecting the timestamps? Is it using the accelerometer? – Juan Apr 20 '17 at 13:41
  • Your speed is only displayed or updated whenever `updateAllUI` is called, which is whenever your receiver variable calls its `onReceive` method. So my question is, when is it called? Is it called after each step (which would explain why when a person stops it won't update to 0) or is there a set time-interval (in which case you would want a "time-out" window that will update the speed to 0)? On a side note: Why are you updating variables in a catch? Shouldn't you handle the exception at hand? – Andrew Hyun Apr 21 '17 at 08:37
  • @Juan He is displaying it in km/h but calculating it in m/s. 3.6 is for conversion. m/s * (60*60/1000) = m/s*3.6 = km/h – Caspar Noree Apr 21 '17 at 15:46
  • 1
    Am I missing something, or is this not at all possible? To get a measurement of speed you need to divide the distance traveled by the time taken to get there (i.e. `speed = distance / time`). The `StepCounterService` you are using seems to only give you the time between steps, not the distance of the step; so how can you possibly calculate the speed? – Bryan Apr 21 '17 at 20:04
  • Bryan, he is condireing a fixed distance per step. – Juan Apr 21 '17 at 21:29
  • onReceive method will only be called whenever there is a step. This could be a problem with your zero speed. For wrong calculations of speed, you have fixed your distance. So, you will not get accurate results. You can try GPS to calculate speed. http://stackoverflow.com/questions/21644990/which-is-best-way-to-calculate-speed-in-android-whether-manual-calculation-usin And the hardest way to calculate speed will be to integrate accelerometer readings. But the results won't be accurate due to signal noise. –  Apr 22 '17 at 06:24
  • `Speed = steps * average_step_length / time`. Obviously you can only estimate the user's average step length. So the speed measure is not going to be very accurate. – Stephen C Apr 22 '17 at 07:38
  • @DanishAmjad But will location.getspeed work if the user is running at the same place.? Like a treadmill.? – Aishvarya Jaiswal Apr 23 '17 at 07:00
  • No. It won't work. Due to the fact that GPS tracks your position and with that it calculates speed. If someone is running on a treadmill the position will be the same. Although GPS may say that you are moving due to noise in sensors. –  Apr 24 '17 at 05:37

3 Answers3

10

As you're only counting steps and would like to calculate speed with steps taken only i am assuming that you would not like to use GPS for counting speed or you would like to provide backup speed counter if GPS is not there.

You can start a new thread by doing

    int interval=1*1000; //specifying interval to check steps
    Handler.postDelayed(mySpeedChecker(),1000);

You'll need to do this for every step taken

public void mySpeedChecker(){
// assuming steps taken stored in a global variable
// and there is one more variable which is updated by this function 
// to store number of steps before as global variable to calculate number of steps in time interval. 
// this should check if another step has been taken in the interval to check
// if stepsTaken>0 then speed is not zero and you'll know how much steps are taken
// if zero steps are taken then speed is zero 
// also it will tell you number of steps taken in last second 
// so you can use this to calculate and update speed 
// increase the interval for high accuracy but lower frequency of updates 
}

Also, it's a good idea to calculate user stride length when GPS is available so, whenever user is using GPS the step length can be calculated by finding out the distance covered/number of steps taken with the help of GPS, this will help your system calculate accurately the distance covered by user with the help of number of steps taken.

Ankit Arora
  • 509
  • 2
  • 18
4

The usual way to calculate speed ideally would be using Location.getSpeed(), or some analysis on Accelerometer values. but I'm assuming you want to get it based on steps counted.

To solve one of the problems: " if the user stops, the speed remains constant and doesn't drop to zero."

You can use the Android Activity Recognition Api to see the users current activity. Use

ActivityRecognition.getMostProbableActivity()

If the DetectedActivity is type STILL, you can set your speed to be zero.

You can also get the confidence DetectedActivity.getConfidence() to be sure.

For the other problem when you said it doesn't count speed properly, could you elaborate more on that question?

sai
  • 434
  • 5
  • 13
0

Every information coming from the sensors has an amount of error and even loose of data.

You should store the information received in a queue or database including the time stamp.

Periodically, you will pick the data and analyze it, including filtering to get a more accurate information.

Hope it helps.

Walter Palladino
  • 479
  • 1
  • 3
  • 8