Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Improve gyroscope functionality #446

Merged
merged 8 commits into from
Nov 29, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 0 additions & 24 deletions .idea/kotlinScripting.xml

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,8 @@ import app.grapheneos.camera.ui.activities.MainActivity
import java.lang.ref.WeakReference
import kotlin.math.abs
import kotlin.math.atan
import kotlin.math.atan2
import kotlin.math.round

import kotlin.math.floor
import kotlin.math.sqrt

class SensorOrientationChangeNotifier private constructor(
private val mainActivity: MainActivity
Expand All @@ -36,8 +35,8 @@ class SensorOrientationChangeNotifier private constructor(
// The gyroscope shall be explicitly made visible only if it's within the ENTRY_
// CRITERIA and if the device isn't moving too fast i.e. (lastX - currentX) is below
// threshold
private const val X_ENTRY_MIN = -10F
private const val X_ENTRY_MAX = 10F
private const val X_ENTRY_MIN = -8F
private const val X_ENTRY_MAX = 8F

// If the current angle for a given axis is beyond the EXIT_CRITERIA the listener
// will just hide the gyroscope (and just return the control back from the method as
Expand All @@ -48,11 +47,11 @@ class SensorOrientationChangeNotifier private constructor(

private const val Z_THRESHOLD = 5

private const val Z_ENTRY_MIN = -60F
private const val Z_ENTRY_MAX = 60F
private const val Z_ENTRY_MIN = -25F
private const val Z_ENTRY_MAX = 25F

private const val Z_EXIT_MIN = -60F
private const val Z_EXIT_MAX = 60F
private const val Z_EXIT_MIN = -45F
private const val Z_EXIT_MAX = 45F
}

var mOrientation = mainActivity.getRotation()
Expand Down Expand Up @@ -86,10 +85,18 @@ class SensorOrientationChangeNotifier private constructor(
var lastX = 0f
var lastZ = 0f

private val ALPHA = 0.7f
private val filteredValues = FloatArray(3)

override fun onSensorChanged(event: SensorEvent) {
val x = event.values[0]
val y = event.values[1]
val z = event.values[2]

filteredValues[0] = ALPHA * filteredValues[0] + (1 - ALPHA) * event.values[0]
filteredValues[1] = ALPHA * filteredValues[1] + (1 - ALPHA) * event.values[1]
filteredValues[2] = ALPHA * filteredValues[2] + (1 - ALPHA) * event.values[2]

var x : Float = filteredValues[0]
var y : Float = filteredValues[1]
var z : Float = filteredValues[2]

var newOrientation = mOrientation
if (x < 5 && x > -5 && y > 5) newOrientation =
Expand All @@ -102,54 +109,51 @@ class SensorOrientationChangeNotifier private constructor(
notifyListeners()
}

if (!mainActivity.camConfig.shouldShowGyroscope()) return
if (!mainActivity.camConfig.shouldShowGyroscope()) {
mainActivity.gCircleFrame.visibility = View.GONE
return
}

val dAngle = if (mainActivity.gCircleFrame.rotation == 270f) {
90f
} else {
mainActivity.gCircleFrame.rotation
if (newOrientation == 90 || newOrientation == 270) {
val t = x
x = y
y = t
}

val zAngle = (atan(z) / (Math.PI / 180)).toFloat()
x = ((180 / Math.PI) * atan(x / sqrt(y * y + z * z))).toFloat()
z = ((180 / Math.PI) * atan(z / sqrt(y * y + x * x))).toFloat()

if (zAngle < Z_EXIT_MIN || zAngle > Z_EXIT_MAX) {
if (z < Z_EXIT_MIN || z > Z_EXIT_MAX) {
mainActivity.gCircleFrame.visibility = View.GONE
return
}

val hAngle = atan2(x, y) / (Math.PI / 180)
val aAngle = abs(hAngle)
val rAngle = (round(aAngle) - dAngle) % 90

val fAngle = if (hAngle < 0) {
-rAngle
} else {
rAngle
}.toFloat()


if (fAngle < X_EXIT_MIN || fAngle > X_EXIT_MAX) {
if (x < X_EXIT_MIN || x > X_EXIT_MAX) {
mainActivity.gCircleFrame.visibility = View.GONE
return
}

if (fAngle in X_ENTRY_MIN..X_ENTRY_MAX) {
if (abs(fAngle - lastX) < X_THRESHOLD) {
if (zAngle in Z_ENTRY_MIN..Z_ENTRY_MAX) {
if (abs(zAngle - lastZ) < Z_THRESHOLD) {
if (x in X_ENTRY_MIN..X_ENTRY_MAX) {
if (abs(x - lastX) < X_THRESHOLD) {
if (z in Z_ENTRY_MIN..Z_ENTRY_MAX) {
if (abs(z - lastZ) < Z_THRESHOLD) {
mainActivity.gCircleFrame.visibility = View.VISIBLE
}
}
}
}

updateGyro(fAngle, zAngle)
updateGyro(x, z)
}

fun updateGyro(fAngle: Float, zAngle: Float) {
mainActivity.onDeviceAngleChange(fAngle, zAngle)
fun updateGyro(xAngle: Float, zAngle: Float) {

val xAngle = floor(xAngle)
val zAngle = floor(zAngle)

mainActivity.onDeviceAngleChange(xAngle, zAngle)

lastX = fAngle
lastX = xAngle
lastZ = zAngle
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -206,6 +206,14 @@ open class MainActivity : AppCompatActivity(),

private var bottomNavigationBarPadding: Int = 0

private var shouldGyroVibrate = true
private var hasGyroVibrated = false

private val gyroVibRunnable = Runnable {
vibrateDevice()
hasGyroVibrated = true
}

val thumbnailLoaderExecutor = Executors.newSingleThreadExecutor()

private val runnable = Runnable {
Expand Down Expand Up @@ -562,12 +570,6 @@ open class MainActivity : AppCompatActivity(),
requestLocation()
}

gCircleFrame.visibility = if (camConfig.gSuggestions) {
View.VISIBLE
} else {
View.INVISIBLE
}

// If the preview of video capture activity isn't showing
if (!(this is VideoCaptureActivity && thirdOption.visibility == View.VISIBLE)) {
if (!isQRDialogShowing) {
Expand Down Expand Up @@ -1360,6 +1362,8 @@ open class MainActivity : AppCompatActivity(),

private const val SWIPE_THRESHOLD = 100
private const val SWIPE_VELOCITY_THRESHOLD = 100

private const val GYRO_VIBE_WAIT_TIME = 250L
}

override fun onDown(e: MotionEvent): Boolean {
Expand Down Expand Up @@ -1550,11 +1554,22 @@ open class MainActivity : AppCompatActivity(),
if (gCircle.rotation != xAngle) {
gCircle.rotation = xAngle
gLineZ.rotation = xAngle
gAngleTextView.text = getString(R.string.degree_format, abs(xAngle).toInt())

val absXAngle = abs(xAngle).toInt()

gAngleTextView.text = getString(R.string.degree_format, absXAngle)
if (xAngle == 0f) {
setThicknessOfGLines(4)
vibrateDevice()
if (shouldGyroVibrate) {
shouldGyroVibrate = false
hasGyroVibrated = false
handler.postDelayed(gyroVibRunnable, GYRO_VIBE_WAIT_TIME)
}
} else {
handler.removeCallbacks(gyroVibRunnable)
if (!hasGyroVibrated || absXAngle > 5) {
shouldGyroVibrate = true
}
setThicknessOfGLines(2)
}
}
Expand Down
3 changes: 2 additions & 1 deletion app/src/main/res/layout/activity_main.xml
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,8 @@
android:id="@+id/g_circle_frame"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_gravity="center">
android:layout_gravity="center"
android:visibility="gone">

<LinearLayout
android:id="@+id/g_circle"
Expand Down