Jump to content

[TOPIC: topicViewTemplate]
[GLOBAL: userSmallPhoto]
Photo

Accurate speed of a swipe
Started by leojharris Jul 17 2018 08:08 PM

18 replies to this topic

Best Answer davebollinger , 19 July 2018 - 06:13 AM

use event.time instead of system.getTimer - the "duration" portion of your calcs is flawed due to event queue

[TOPIC CONTROLS]
This topic has been archived. This means that you cannot reply to this topic.
[/TOPIC CONTROLS]
[modOptionsDropdown]
[/modOptionsDropdown]
[reputationFilter]
[TOPIC: post.html]
#1

leojharris

[GLOBAL: userInfoPane.html]
leojharris
  • Observer

  • 19 posts
  • Corona SDK

Hi all,
 
I having an issue getting the (max) speed properly for a swipe / gesture along the Y axis in the down movement using the following implementation:
 
local flickStartTime = 0

local function touchListener(event)
if event.phase == "began" then
  flickStartTime = system.getTimer()

  if timerStarted == false then
    timerStarted = true
    Runtime:addEventListener( "enterFrame", timerText )
  end

elseif event.phase == "moved" then
  local flickDuration = system.getTimer() - flickStartTime
  local speedY = (event.yStart - event.y) / flickDuration
  if secondsLeftt > 0 then
    if speedY < 0 then
      myObject.angularVelocity = (speedY * 500 ) * -1
    end
  end
end
end
For the most part this works fine.. HOWEVER the issue is when I try to get the max speed and store that value, the max speed jumps to 135 M/S even though I'm really averaging speed of 15 - 30 M/S see below how I am getting max speed below:
if speed > maxSpeed then
maxSpeed = speed 
  end
Basically if the max Speed is greater then speed it sets that speed to the max and I'm just taking the speed from myObject.wheelAngularVelocity in the line before it.
 
It seems to be a real quick blip that it jumps to 135 speed and then continues on at the proper speed
 
Can someone spot my mistake here? Is there some limitation or a bug / glitch? 
 
Has any one had experience accurately getting the speed of a swipe if doing this quickly over a certain time period?
 
Just need someone to point out what might be the issue here.
 
See example Gif below, I am swiping down at a fairly constant speed then it jumps to 135 for a moment.
 

Attached Files



[TOPIC: post.html]
#2

ldurniat

[GLOBAL: userInfoPane.html]
ldurniat
  • Contributor

  • 389 posts
  • Corona SDK

Hi leojharris,

 

I would measure average speed like that 

local mAbs  = math.abs
local mSqrt = math.sqrt

local function distance ( x1, y1, x2, y2 )

    return mSqrt( ( x1 - x2 ) * ( x1 - x2 ) + ( y1 - y2 ) * ( y1 - y2 ) )

end 
  
local rect = display.newRect( sceneGroup, display.contentCenterX, display.contentCenterY, 100, 100 )

local startTime, endTime, avgSpeed
function rect:touch( event )

    if event.phase == 'began' then

        display.getCurrentStage():setFocus( self )
        self.isFocus = true

        startTime = system.getTimer()
        endTime   = startTime

    elseif self.isFocus then

        if event.phase == 'moved' then

            endTime = system.getTimer() 

            avgSpeed = distance( event.xStart, event.yStart, event.x, event.y ) / ( ( endTime - startTime ) / 1000 )
print( string.format( 'Average speed pixels per seconds=%8.5f, time=%8.5f, distance=%8.5f', 
avgSpeed,  ( endTime - startTime ) / 1000, distance( event.xStart, event.yStart, event.x, event.y ) ) )

        elseif event.phase == 'ended'  or event.phase == 'cancelled' then

            display.getCurrentStage():setFocus( nil )
            self.isFocus = false 

        end
  
    end
end

rect:addEventListener( 'touch' )

Note:

  • If you want more accurate results you need compute average speed in small periods of time. Let say 100ms,
  • If you need compute average speed along only one of axles  your calculations can be simplified.

 

Have a nice day:)

 

 

ldurniat



[TOPIC: post.html]
#3

leojharris

[GLOBAL: userInfoPane.html]
leojharris
  • Observer

  • 19 posts
  • Corona SDK

Unfortunately I am still getting the same issue in that it maxes out at 135. I tried changing the frame rate as well and seemed to have a different value as the max swipe swipe (see gif image - maxes out at 67.5 now and cant get more then that as fast as I swipe down
 
Is there some threshold maxed out value that I cant get over / past? 
 
Perhaps I could compute at 100ms that might fix the issue or get more accurate, how could I go about doing this at 100ms?
 
I cant figure this out at its killing my game atm as my game is using the max speed towards the score and 9/10 my users are getting the same 135 value meaning they are all swiping the same max speed which I highly doubt is correct?
 
See GIF below I changed the frame rate and now wont go beyond 67.5 - in that it maxes at 67.5 slows down then maxes out again there.

Attached Files



[TOPIC: post.html]
#4

nick_sherman

[GLOBAL: userInfoPane.html]
nick_sherman
  • Corona Geek

  • 1,803 posts
  • Corona SDK

Can't you just ignore any values that are above a certain 'impossible' threshold? 

 

To take an average you could calculate the distance moved each frame, and store the last 5/6 values in a table in a FILO fashion, as long as they don't exceed a given amount. 



[TOPIC: post.html]
#5

leojharris

[GLOBAL: userInfoPane.html]
leojharris
  • Observer

  • 19 posts
  • Corona SDK

Can't you just ignore any values that are above a certain 'impossible' threshold? 

 

To take an average you could calculate the distance moved each frame, and store the last 5/6 values in a table in a FILO fashion, as long as they don't exceed a given amount. 

 

I'm not even certain it is maxing out tbh. But as in the original post in the first GIF you can see it doesn't get near 135 until it just jumps right up to it and this is happening 99% of the time. That could be an option though to check if greater or equal to 135 as that's what it seems to like going to for whatever reason. But I don't feel that is the right 'solution' to the problem

 

By my original code nothing points out to me it should be doing that odd behavior, i feel this is possibly independent of the code that's causing the issue.

local flickStartTime = 0

local function touchListener(event)
if event.phase == "began" then
  flickStartTime = system.getTimer()

  if timerStarted == false then
    timerStarted = true
    Runtime:addEventListener( "enterFrame", timerText )
  end

elseif event.phase == "moved" then
  local flickDuration = system.getTimer() - flickStartTime
  local speedY = (event.yStart - event.y) / flickDuration
  if secondsLeftt > 0 then
    if speedY < 0 then
      myObject.angularVelocity = (speedY * 500 ) * -1
    end
  end
end
end


[TOPIC: post.html]
#6

davebollinger

[GLOBAL: userInfoPane.html]
davebollinger
  • Corona Geek

  • 1,337 posts
  • Enterprise

  Best Answer

use event.time instead of system.getTimer - the "duration" portion of your calcs is flawed due to event queue



[TOPIC: post.html]
#7

leojharris

[GLOBAL: userInfoPane.html]
leojharris
  • Observer

  • 19 posts
  • Corona SDK

use event.time instead of system.getTimer - the "duration" portion of your calcs is flawed due to event queue

 

Looks like that has resolved the issue  :)



[TOPIC: post.html]
#8

leojharris

[GLOBAL: userInfoPane.html]
leojharris
  • Observer

  • 19 posts
  • Corona SDK

Sorry one more issue I seem to be having is the device swipe gesture speed across difference device densities, the swipe speed seems to be higher on higher density devices. 

local speedY = ((event.yStart - event.y) / flickDuration)  * -1

So I think I am having an issue attempting to get the same physical distance on difference devices with different screen density.

 

Regarding the below, is this giving me the pixels or the density independent units?

event.yStart - event.y

How can I get from this calculation the DP as the distance? Or is it already measured in that? Then I can use that as the distance as I think this calculation is flawed across device screen densities.

 

Thanks for helping me in the questions above any how as well. Really appreciate the community and support on here :) really helpful!!



[TOPIC: post.html]
#9

roaminggamer

[GLOBAL: userInfoPane.html]
roaminggamer
  • Corona Geek

  • 7,585 posts
  • Corona SDK

What does your config.lua file look like.

 

What kind of scaling are you using?



[TOPIC: post.html]
#10

leojharris

[GLOBAL: userInfoPane.html]
leojharris
  • Observer

  • 19 posts
  • Corona SDK

What does your config.lua file look like.

 

What kind of scaling are you using?

 

This is my  config.lua

application =
{
	content =
	{
		width = 320,
		height = 480,
		scale = "letterbox",
		fps = 60,

		--[[
		imageSuffix =
		{
			    ["@2x"] = 2,
			    ["@4x"] = 4,
		},
		--]]
	},
}

I was thinking I could do something like this:

...

elseif event.phase == "moved" then

local flickDuration = event.time - flickStartTime

local dpi =  system.getInfo("androidDisplayYDpi")

local distanceDpi = (event.yStart - event.y) / dpi

...

Correct me if I am wrong.

 

From the docs : "androidDisplayYDpi" returns the DPI (dots per inch) of the screen along the y axis, relative to the orientation of the application. This can be used to convert pixels to inches and vice-versa. Returns nil on all other platforms.

 

https://docs.coronalabs.com/api/library/system/getInfo.html#androiddisplayxdpi



[TOPIC: post.html]
#11

roaminggamer

[GLOBAL: userInfoPane.html]
roaminggamer
  • Corona Geek

  • 7,585 posts
  • Corona SDK

Using letterbox, events should be scaled too.  So the 'relative rate' should be the same for all device.

 

Note: Others will disagree, but I don't suggest using such a low resolution as your content resolution.  

 

re: androidDisplayYDpi- I don't know about that feature.  I don't use it.



[TOPIC: post.html]
#12

leojharris

[GLOBAL: userInfoPane.html]
leojharris
  • Observer

  • 19 posts
  • Corona SDK

Using letterbox, events should be scaled too.  So the 'relative rate' should be the same for all device.

 

Letterbox only mentions about the fill size space i.e. "letterbox" — scales the content area to fill the screen while preserving the same aspect ratio



[TOPIC: post.html]
#13

roaminggamer

[GLOBAL: userInfoPane.html]
roaminggamer
  • Corona Geek

  • 7,585 posts
  • Corona SDK

You can test this experimentally.

 

1. Make basic app with a touch listener that prints the <x,y> of the touch.

 

2. Set the config.lua content area use letterbox 320x480.

 

3. Install it on your device.

 

4. Touch the screen in the upper left and lower right.

 

5. Look at the xCode debug console or for Android use adb logcat and see what is printed.

(https://docs.coronalabs.com/guide/basics/debugging/index.html)

 

6. Repeat, but use 640x960

 

The numbers, upper-left numbers should be similar.  The lower right should be 2x the prior.  If so, the touch event is being scaled to the content area.



[TOPIC: post.html]
#14

davebollinger

[GLOBAL: userInfoPane.html]
davebollinger
  • Corona Geek

  • 1,337 posts
  • Enterprise

your results vary with density because you divide by a value that varies with density

if you're truly trying to measure in "inches per second" then maybe that's appropriate.

if on the other hand you're measuring in "content pixels per second" then it's not appropriate.

figure out what you want, then write the math to match.



[TOPIC: post.html]
#15

leojharris

[GLOBAL: userInfoPane.html]
leojharris
  • Observer

  • 19 posts
  • Corona SDK

your results vary with density because you divide by a value that varies with density

if you're truly trying to measure in "inches per second" then maybe that's appropriate.

if on the other hand you're measuring in "content pixels per second" then it's not appropriate.

figure out what you want, then write the math to match.

 

I'm looking at inches per second, the physical distance a user swipes along the Y axis and not the amount of pixels on the screen the user has moved across, I am using:

local dpi =  system.getInfo("androidDisplayYDpi")

local distanceDpi = (event.yStart - event.y) / dpi

And the results swiping on 2 devices are that the speeds match pretty closely regarding the swipe speed I apply. This seems sufficient for what I am after.



[TOPIC: post.html]
#16

davebollinger

[GLOBAL: userInfoPane.html]
davebollinger
  • Corona Geek

  • 1,337 posts
  • Enterprise

still appears to be trying to convert content pixels directly into inches (via a ratio that instead converts hardware pixels into inches)



[TOPIC: post.html]
#17

leojharris

[GLOBAL: userInfoPane.html]
leojharris
  • Observer

  • 19 posts
  • Corona SDK

still appears to be trying to convert content pixels directly into inches (via a ratio that instead converts hardware pixels into inches)

 

Are you suggesting the implementation I am using is incorrect? Whats the difference between content pixels and hardware pixels are these not the same thing?

 

I am just trying to understand what you are meaning here :) 



[TOPIC: post.html]
#18

davebollinger

[GLOBAL: userInfoPane.html]
davebollinger
  • Corona Geek

  • 1,337 posts
  • Enterprise

Are you suggesting the implementation I am using is incorrect? 

event coords are in content pixels, they will not vary (except by some potential letterboxing to account for differing content/device aspect ratios) with device resolution.  so if you then divide them by dpi (in device pixels, which will vary with device resolution and physical size) then you get a nonsense value.  the only time it'd work out correctly is if device dimensions exactly equal content dimensions.  so you'd need to first convert content pixels to device pixels (see https://docs.coronalabs.com/api/library/display/contentScaleY.html for example) and then to inches via your dpi.

 

Whats the difference between content pixels and hardware pixels are these not the same thing?

too much to go into here, read this:  https://docs.coronalabs.com/guide/basics/configSettings/index.html#content-scaling



[TOPIC: post.html]
#19

leojharris

[GLOBAL: userInfoPane.html]
leojharris
  • Observer

  • 19 posts
  • Corona SDK

so you'd need to first convert content pixels to device pixels (see https://docs.coronalabs.com/api/library/display/contentScaleY.html for example) and then to inches via your dpi.

 

I see exactly what you mean now regarding the content height.

 

 

I think this is what you mean: 

local dpi =  system.getInfo("androidDisplayYDpi")

local distanceDpi = ((event.yStart- event.y) * display.contentScaleY) / dpi

Having just tested this outputting the result of the distanceDpi it doesnt appear correct.

 

When When I do swipe gesture down the full height of both devices the value of the distanceDpi is 1.75 on my lower resolution device (480x800) and it is a 4.5'' inch screen size, while I get 0.76 on my other device (720 x 1280 pixels) that is 5 inches. The distanceDpi value is about twice as high for my device that is smaller and lower resolution then the other. 

 

My scale mode is letterbox as well




[topic_controls]
[/topic_controls]