minor fixes

This commit is contained in:
SaiD 2025-12-19 22:08:05 +05:30
parent c58696f1c8
commit d5902cba08
6 changed files with 90 additions and 47 deletions

View File

@ -59,38 +59,41 @@ class DefaultOrientationChecker : OrientationChecker {
/* ============================================================= */ /* ============================================================= */
class DefaultTiltChecker : TiltChecker { class DefaultTiltChecker : TiltChecker {
override suspend fun analyze(input: PipelineInput): Instruction { override suspend fun analyze(input: PipelineInput): Instruction {
val tolerance = 25f val tolerance = 20f
var levelMessage = "Keep the phone straight"
Log.d("TiltChecker", "Device Roll: ${input.deviceRoll}, Device Pitch: ${input.devicePitch}, Device Azimuth: ${input.deviceAzimuth}") val (targetPitch, targetRoll) = Pair(-90f, 0f)
Log.d("TiltCheckerMessage", "targetPitch: ${input.devicePitch}, targetRoll: ${input.deviceRoll}, targetAz: ${input.deviceAzimuth}, tP: $targetPitch, tR: $targetRoll")
val pitchError = abs(input.devicePitch - targetPitch)
val rollError = abs(input.deviceRoll - targetRoll)
val isLevel = when (input.requiredOrientation) { val isLevel = pitchError <= tolerance && rollError <= tolerance && input.deviceAzimuth > 0
CameraOrientation.PORTRAIT -> val isRollError = rollError > tolerance
abs(input.devicePitch + 90f) <= tolerance val isPitchError = pitchError > tolerance
CameraOrientation.LANDSCAPE ->
abs(input.devicePitch) <= tolerance
}
val standardPitch = when (input.requiredOrientation) { val message = if (isLevel) {
CameraOrientation.PORTRAIT -> -90f "Device is level"
CameraOrientation.LANDSCAPE -> 0f } else {
} when {
input.deviceAzimuth < 0 -> "Tilt phone forward"
if (!isLevel) { input.deviceAzimuth >= 0 && !isRollError && isPitchError -> "Tilt phone backward"
if (input.devicePitch > standardPitch) { input.deviceRoll > 0 -> "Rotate phone left"
levelMessage = "Rotate the phone Right" input.deviceRoll <= 0 -> "Rotate phone right"
} else if (input.devicePitch < standardPitch) { else -> "Device is level"
levelMessage = "Rotate the phone Left"
} }
} }
return Instruction( return Instruction(
message = if (isLevel) "Device is level" else levelMessage, message = message,
isValid = isLevel, isValid = isLevel,
result = TiltResult(input.deviceRoll, input.devicePitch, isLevel) result = TiltResult(
roll = input.deviceRoll,
pitch = input.devicePitch,
isLevel = isLevel
)
) )
} }
} }

View File

@ -57,7 +57,8 @@ fun AddProfileScreen(
// If opened for edit, attempt to load existing animal details // If opened for edit, attempt to load existing animal details
LaunchedEffect(Unit) { LaunchedEffect(Unit) {
val existing = viewModel.savedStateHandle?.get<String>("animalId") val existing = viewModel.savedStateHandle?.get<String>("animalId")
if (existing != null) viewModel.loadAnimal(existing) val loadEntry = viewModel.savedStateHandle?.get<Boolean>("loadEntry")
if (existing != null && loadEntry == true) viewModel.loadAnimal(existing)
} }
val speciesList = stringArrayResource(id = R.array.species_list).toList() val speciesList = stringArrayResource(id = R.array.species_list).toList()

View File

@ -134,6 +134,9 @@ fun CameraCaptureScreen(
} }
if (uri != null) { if (uri != null) {
// This screen can be called from AddProfileScreen or ViewImageScreen (for retakes).
// In both cases, we pop the back stack and set the result on the previous entry.
// The NavGraph logic for each screen handles the received URI accordingly.
navController.previousBackStackEntry?.savedStateHandle?.set("newImageUri", uri.toString()) navController.previousBackStackEntry?.savedStateHandle?.set("newImageUri", uri.toString())
navController.previousBackStackEntry?.savedStateHandle?.set("newImageOrientation", orientation) navController.previousBackStackEntry?.savedStateHandle?.set("newImageOrientation", orientation)
navController.popBackStack() navController.popBackStack()

View File

@ -150,6 +150,7 @@ fun NavGraph(
composable<Route.ViewImageScreen> { backStackEntry -> composable<Route.ViewImageScreen> { backStackEntry ->
val args: Route.ViewImageScreen = backStackEntry.toRoute() val args: Route.ViewImageScreen = backStackEntry.toRoute()
ViewImageScreen( ViewImageScreen(
imageUri = args.imageUri, imageUri = args.imageUri,
shouldAllowRetake = args.shouldAllowRetake, shouldAllowRetake = args.shouldAllowRetake,
@ -160,7 +161,7 @@ fun NavGraph(
orientation = args.orientation, orientation = args.orientation,
onRetake = { onRetake = {
navController.popBackStack() navController.popBackStack()
// navController.navigate(Route.CameraScreen(...)) args.orientation?.let { navController.navigate(Route.CameraScreen(orientation = it, animalId = args.animalId)) }
}, },
onAccept = { uri -> onAccept = { uri ->
// If it's a segmented result, add to segmented list // If it's a segmented result, add to segmented list

View File

@ -14,33 +14,29 @@ class TiltSensorManager(
context: Context context: Context
) : SensorEventListener { ) : SensorEventListener {
private val sensorManager = context.getSystemService(Context.SENSOR_SERVICE) as SensorManager private val sensorManager =
private val rotationVectorSensor = sensorManager.getDefaultSensor(Sensor.TYPE_ROTATION_VECTOR) context.getSystemService(Context.SENSOR_SERVICE) as SensorManager
private val windowManager =
context.getSystemService(Context.WINDOW_SERVICE) as android.view.WindowManager
private val rotationVectorSensor =
sensorManager.getDefaultSensor(Sensor.TYPE_ROTATION_VECTOR)
private val _tilt = MutableStateFlow(Triple(0f, 0f, 0f)) // pitch, roll, azimuth private val _tilt = MutableStateFlow(Triple(0f, 0f, 0f)) // pitch, roll, azimuth
val tilt: StateFlow<Triple<Float, Float, Float>> = _tilt.asStateFlow() val tilt: StateFlow<Triple<Float, Float, Float>> = _tilt.asStateFlow()
init {
Log.d("TiltSensorManager", "TiltSensorManager initialized.")
if (rotationVectorSensor == null) {
Log.e("TiltSensorManager", "Rotation Vector Sensor not available on this device.")
}
}
fun start() { fun start() {
Log.d("TiltSensorManager", "start() called.")
rotationVectorSensor?.let { rotationVectorSensor?.let {
val registered = sensorManager.registerListener( sensorManager.registerListener(
this, this,
it, it,
SensorManager.SENSOR_DELAY_UI SensorManager.SENSOR_DELAY_UI
) )
Log.d("TiltSensorManager", "Listener registration attempted. Success: $registered") }
} ?: Log.e("TiltSensorManager", "Cannot start listener, sensor is null.")
} }
fun stop() { fun stop() {
Log.d("TiltSensorManager", "stop() called.")
sensorManager.unregisterListener(this) sensorManager.unregisterListener(this)
} }
@ -49,25 +45,64 @@ class TiltSensorManager(
if (event.sensor.type != Sensor.TYPE_ROTATION_VECTOR) return if (event.sensor.type != Sensor.TYPE_ROTATION_VECTOR) return
val rotationMatrix = FloatArray(9) val rotationMatrix = FloatArray(9)
val adjustedMatrix = FloatArray(9)
val orientationAngles = FloatArray(3) val orientationAngles = FloatArray(3)
// Convert rotation vector to rotation matrix
SensorManager.getRotationMatrixFromVector(rotationMatrix, event.values) SensorManager.getRotationMatrixFromVector(rotationMatrix, event.values)
// Convert rotation matrix to orientation angles // 🔑 Get screen rotation
SensorManager.getOrientation(rotationMatrix, orientationAngles) val rotation = windowManager.defaultDisplay.rotation
when (rotation) {
android.view.Surface.ROTATION_0 -> {
SensorManager.remapCoordinateSystem(
rotationMatrix,
SensorManager.AXIS_X,
SensorManager.AXIS_Y,
adjustedMatrix
)
}
android.view.Surface.ROTATION_90 -> {
SensorManager.remapCoordinateSystem(
rotationMatrix,
SensorManager.AXIS_Y,
SensorManager.AXIS_MINUS_X,
adjustedMatrix
)
}
android.view.Surface.ROTATION_180 -> {
SensorManager.remapCoordinateSystem(
rotationMatrix,
SensorManager.AXIS_MINUS_X,
SensorManager.AXIS_MINUS_Y,
adjustedMatrix
)
}
android.view.Surface.ROTATION_270 -> {
SensorManager.remapCoordinateSystem(
rotationMatrix,
SensorManager.AXIS_MINUS_Y,
SensorManager.AXIS_X,
adjustedMatrix
)
}
}
SensorManager.getOrientation(adjustedMatrix, orientationAngles)
// orientationAngles: [azimuth, pitch, roll] in radians
val azimuth = Math.toDegrees(orientationAngles[0].toDouble()).toFloat() val azimuth = Math.toDegrees(orientationAngles[0].toDouble()).toFloat()
val pitch = Math.toDegrees(orientationAngles[1].toDouble()).toFloat() val pitch = Math.toDegrees(orientationAngles[1].toDouble()).toFloat()
val roll = Math.toDegrees(orientationAngles[2].toDouble()).toFloat() val roll = Math.toDegrees(orientationAngles[2].toDouble()).toFloat()
Log.d("TiltSensor", "Pitch: $pitch, Roll: $roll, Azimuth: $azimuth")
_tilt.value = Triple(pitch, roll, azimuth) _tilt.value = Triple(pitch, roll, azimuth)
Log.d("TiltSensor",
"Standardized → Pitch=$pitch Roll=$roll Azimuth=$azimuth"
)
} }
override fun onAccuracyChanged(sensor: Sensor?, accuracy: Int) { override fun onAccuracyChanged(sensor: Sensor?, accuracy: Int) {}
Log.d("TiltSensorManager", "Accuracy changed to $accuracy for sensor ${sensor?.name}") }
}
}