makcar/app/src/main/java/com/aros/apron/tools/ArucoViewModel.kt

588 lines
24 KiB
Kotlin
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

package com.aros.apron.tools//package com.shd.nest.viewmodel
//
//import android.annotation.SuppressLint
//import android.graphics.Bitmap
//import android.graphics.BitmapFactory
//import android.graphics.ImageFormat
//import android.graphics.Rect
//import android.graphics.YuvImage
//import androidx.lifecycle.viewModelScope
//import com.shd.nest.base.BaseViewModel
//import com.shd.nest.dji.AircraftInfoManager
//import com.shd.nest.extension.toDegree
//import com.shd.nest.util.LogFileManager
//import dji.sdk.keyvalue.key.FlightControllerKey
//import dji.sdk.keyvalue.value.flightcontroller.FlightCoordinateSystem
//import dji.sdk.keyvalue.value.flightcontroller.RollPitchControlMode
//import dji.sdk.keyvalue.value.flightcontroller.VerticalControlMode
//import dji.sdk.keyvalue.value.flightcontroller.VirtualStickFlightControlParam
//import dji.sdk.keyvalue.value.flightcontroller.YawControlMode
//import dji.v5.common.callback.CommonCallbacks
//import dji.v5.common.error.IDJIError
//import dji.v5.et.create
//import dji.v5.manager.KeyManager
//import dji.v5.manager.aircraft.virtualstick.VirtualStickManager
//import kotlinx.coroutines.Dispatchers
//import kotlinx.coroutines.launch
//import org.opencv.android.OpenCVLoader
//import org.opencv.android.Utils
//import org.opencv.aruco.Aruco
//import org.opencv.aruco.Dictionary
//import org.opencv.calib3d.Calib3d
//import org.opencv.core.Core
//import org.opencv.core.CvType
//import org.opencv.core.Mat
//import org.opencv.core.MatOfInt
//import org.opencv.core.Scalar
//import org.opencv.imgproc.Imgproc
//import java.io.ByteArrayOutputStream
//import kotlin.math.abs
//import kotlin.math.atan2
//import kotlin.math.sqrt
//
//
//class ArucoViewModel : BaseViewModel() {
//
// override val TAG: String = "ArucoViewModel"
//
// //Aruco字典
// private lateinit var mDictionary: Dictionary
//
// //是否正在识别Aruco
// private var isDetectingAruco: Boolean = false
//
// //识别得到的所有Aruco码
// private val mArucoCornerList: MutableList<Mat> = mutableListOf()
//
// //要查找相应Aruco码list
// private val mFindArucoList: MutableList<ArucoMarker> = mutableListOf()
//
//
// //加载opencv
// fun initOpenCV() {
// if (OpenCVLoader.initDebug()) {
// mDictionary = Aruco.getPredefinedDictionary(Aruco.DICT_6X6_50)
// }
// }
//
//
// /**
// * aruco 二维码检测
// */
// fun detectArucoTag(
// yuvData: ByteArray,
// width: Int,
// height: Int,
// ) {
// if (isDetectingAruco) {
// return
// }
// if (yuvData.size < width * height) {
// return
// }
// isDetectingAruco = true
// viewModelScope.launch(Dispatchers.IO) {
// try {
// val length = width * height
// val u = ByteArray(width * height / 4)
// val v = ByteArray(width * height / 4)
// for (i in u.indices) {
// u[i] = yuvData[length + i]
// v[i] = yuvData[length + u.size + i]
// }
// for (i in u.indices) {
// yuvData[length + 2 * i] = v[i]
// yuvData[length + 2 * i + 1] = u[i]
// }
//
// val yuvImage = YuvImage(yuvData, ImageFormat.NV21, width, height, null)
// val outputStream = ByteArrayOutputStream()
// yuvImage.compressToJpeg(Rect(0, 0, width, height), 100, outputStream)
// val bitmap = BitmapFactory.decodeByteArray(outputStream.toByteArray(), 0, outputStream.size())
//
// //bitmap转mat
// val bmp32 = bitmap.copy(Bitmap.Config.ARGB_8888, true)
// val source = Mat()
// Utils.bitmapToMat(bmp32, source)
//
// //灰度化处理
// val grayImgMat = Mat()
// Imgproc.cvtColor(source, grayImgMat, Imgproc.COLOR_RGBA2GRAY)
//
// val ids = MatOfInt()
// mFindArucoList.clear()
// mArucoCornerList.clear()
//
// //aruco码检测
// Aruco.detectMarkers(grayImgMat, mDictionary, mArucoCornerList, ids)
//
// //没有检测到aruco二维码飞机高度升高扩大相机视野范围
// if (ids.empty() || mArucoCornerList.isEmpty()) {
// val verticalThrottle = if (AircraftInfoManager.aircraftAltitude < 12.0) { 64 } else { 0 }
// VirtualStickManager.getInstance().leftStick.apply {
// horizontalPosition = 0
// verticalPosition = verticalThrottle
// }
// VirtualStickManager.getInstance().rightStick.apply {
// horizontalPosition = 0
// verticalPosition = 0
// }
//
// isDetectingAruco = false
// grayImgMat.release()
// bitmap.recycle()
// bmp32.recycle()
// source.release()
// ids.release()
// return@launch
// }
//
// val idArray = ids.toArray()
// //查找id等于19的Aruco码
// if (mFindArucoList.isEmpty()) {
// for (markerIndex in idArray.indices) {
// val markerId = idArray[markerIndex]
// if (markerId == 19) {
// mFindArucoList.add(
// ArucoMarker(
// markerId,
// ArucoMarker.MARKER_19_SIZE_CM,
// mArucoCornerList[markerIndex]
// )
// )
// break
// }
// }
// }
// //查找id等于43的Aruco码
// if (mFindArucoList.isEmpty()) {
// for (markerIndex in idArray.indices) {
// val markerId = idArray[markerIndex]
// if (markerId == 43) {
// mFindArucoList.add(
// ArucoMarker(
// markerId,
// ArucoMarker.MARKER_43_SIZE_CM,
// mArucoCornerList[markerIndex]
// )
// )
// break
// }
// }
// }
// //查找id等于1的Aruco码
// if (mFindArucoList.isEmpty()) {
// for (markerIndex in idArray.indices) {
// val markerId = idArray[markerIndex]
// if (markerId == 1) {
// mFindArucoList.add(
// ArucoMarker(
// markerId,
// ArucoMarker.MARKER_1_SIZE_CM,
// mArucoCornerList[markerIndex]
// )
// )
// break
// }
// }
// }
// //查找id等于2的Aruco码
// if (mFindArucoList.isEmpty()) {
// for (markerIndex in idArray.indices) {
// val markerId = idArray[markerIndex]
// if (markerId == 2) {
// mFindArucoList.add(
// ArucoMarker(
// markerId,
// ArucoMarker.MARKER_2_SIZE_CM,
// mArucoCornerList[markerIndex]
// )
// )
// break
// }
// }
// }
// //查找id等于3的Aruco码
// if (mFindArucoList.isEmpty()) {
// for (markerIndex in idArray.indices) {
// val markerId = idArray[markerIndex]
// if (markerId == 3) {
// mFindArucoList.add(
// ArucoMarker(
// markerId,
// ArucoMarker.MARKER_3_SIZE_CM,
// mArucoCornerList[markerIndex]
// )
// )
// break
// }
// }
// }
// //查找id等于4的Aruco码
// if (mFindArucoList.isEmpty()) {
// for (markerIndex in idArray.indices) {
// val markerId = idArray[markerIndex]
// if (markerId == 4) {
// mFindArucoList.add(
// ArucoMarker(
// markerId,
// ArucoMarker.MARKER_4_SIZE_CM,
// mArucoCornerList[markerIndex]
// )
// )
// break
// }
// }
// }
//
// val arucoMarker = mFindArucoList[0]
// //aruco二维码尺寸(单位m)
// val markerSize = arucoMarker.arucoMarkerSize / 100
//
// //旋转矩阵
// val rvecs = Mat()
// //位移矩阵
// val tvecs = Mat()
//
// //相机内参
// val cameraMatrix = Mat.zeros(3, 3, CvType.CV_64F).apply {
// put(0, 0, 1035.501071149292) //fx
// put(1, 1, 1035.4725889980984) //fy
// put(0, 2, 713.2867513159875) //cx
// put(1, 2, 542.4491896129153) //cy
// put(2, 2, 1.0)
// }
// //畸变
// val distCoeffs = Mat.zeros(5, 1, CvType.CV_64FC1).apply {
// put(0, 0, 0.3519238102526651) //k1
// put(1, 0, -1.4538841685400365) //k2
// put(2, 0, 0.00022919790876455443) //p1
// put(3, 0, 0.0012223205821680879) //p2
// put(4, 0, 2.0070528327672754) //k3
// }
//
// //姿态预估
// Aruco.estimatePoseSingleMarkers(
// mutableListOf(arucoMarker.corner),
// markerSize,
// cameraMatrix,
// distCoeffs,
// rvecs,
// tvecs
// )
//
// //单个aruco码姿态预估得到的旋转向量、平移向量
// val rvec = rvecs.row(0)
// val tvec = tvecs.row(0)
//
// //罗德里变换
// val R = Mat(3, 3, CvType.CV_32FC1)
// Calib3d.Rodrigues(rvec, R)
// val camR = R.t()
//
// //左乘
// val _camR = Mat()
// val _1 = Scalar(-1.0)
// Core.multiply(camR, _1, _camR)
//
// //无人机偏航旋转角度
// val eulerAngles = rotationMatrixToEulerAngles(camR)
// val yawCamera: Double = eulerAngles[2].toDegree()
// var resultYaw: Double = if (abs(yawCamera).toInt() in 5..175 && (arucoMarker.markerId == 19 || arucoMarker.markerId == 43)) {
// val scaleFactor = when (abs(yawCamera).toInt()) {
// in 0..90 -> 5.0
// in 90..135 -> 15.0
// else -> 40.0
// }
// if (yawCamera < 0) (abs(yawCamera) / scaleFactor) * 1.5 else -(abs(yawCamera) / scaleFactor) * 1.5
// } else {
// 0.0
// }
//
// var x = tvec[0, 0][0]
// var y = tvec[0, 0][1]
//
// /*LogFileManager.getInstance().log(
// TAG,
// "降落 ID:${arucoMarker.markerId} x: $x y: $y yawCamera:$yawCamera altitude: ${AircraftInfoManager.aircraftAltitude} "
// )
// isDetectAruco = false
// return@launch*/
//
// if ((arucoMarker.markerId == 19 && x < 0 && abs(x) in 0.035..0.075 && y in 0.0685..0.0865 && AircraftInfoManager.aircraftAltitude <= 1.8f)
// || (arucoMarker.markerId == 43 && x < 0 && abs(x) in 0.035..0.075 && y in 0.0685..0.0865 && AircraftInfoManager.aircraftAltitude <= 1.8f)
// ) {
// exitVirtualStick()
// isDetectingAruco = false
// grayImgMat.release()
// bitmap.recycle()
// bmp32.recycle()
// source.release()
// ids.release()
// rvecs.release()
// tvecs.release()
// rvec.release()
// tvec.release()
// camR.release()
// _camR.release()
// R.release()
// mFindArucoList.clear()
// mArucoCornerList.clear()
// LogFileManager.getInstance().log(
// TAG,
// "降落 ID:${arucoMarker.markerId} x: $x y: $y altitude: ${AircraftInfoManager.aircraftAltitude} "
// )
// return@launch
// }
// //x 正:飞机偏左 负:飞机偏右
// //y 正:飞机偏前 负:飞机偏后
// var downwardSpeed = if (abs(x) <= 0.45 && abs(y) <= 0.45 && AircraftInfoManager.aircraftAltitude > 4.0f) {
// //-3.5f
// -5.65f
// } else if ((abs(x) <= 0.12 || abs(y) <= 0.12) && (AircraftInfoManager.aircraftAltitude in 2.5f..4.0f)) {
// -2.85f
// } else if (AircraftInfoManager.aircraftAltitude in 1.5f..2.5f) {
// -1.75f
// } else if (AircraftInfoManager.aircraftAltitude <= 1.5f) {
// 0f
// } else {
// 0f
// }
//
// //如果识别到周围4个角的Aruco二维码尽量控制飞机向降落板中心移动
// if ((arucoMarker.markerId == 1 || arucoMarker.markerId == 4)) {
// if (y < 0 && abs(y) < 0.22) {
// y = -1 * (0.22 - abs(y))
// } else {
// y -= 0.22
// }
// }
// if ((arucoMarker.markerId == 2 || arucoMarker.markerId == 3)) {
// if (y > 0 && y < 0.22) {
// y = 0.22 - y
// } else {
// y += 0.22
// }
// }
// if ((arucoMarker.markerId == 1 || arucoMarker.markerId == 2)) {
// if (x > 0 && x < 0.355) {
// x = -1 * (0.355 - x)
// } else {
// x -= 0.355
// }
// }
// if ((arucoMarker.markerId == 3 || arucoMarker.markerId == 4)) {
// if (x > 0 && x < 0.355) {
// x = 0.355 - x
// } else {
// x += 0.355
// }
// }
// //调准机体中心位置相对于aruco码偏前以达到y轴方向上降落居中
// if ((arucoMarker.markerId == 19 || arucoMarker.markerId == 43) && (y <= 0 || y in 0.0..0.0965)) {
// y -= (0.0965f * 4 / 5)
// //y -= 0.0965f
// }
// //调准机体中心位置相对于aruco码偏前以达到x轴方向上降落居中 0.065..0.07685 -0.08360405179000563
// if ((arucoMarker.markerId == 19 || arucoMarker.markerId == 43) && (x >= 0 || y in 0.0..0.07685)) {
// //x = (0.07685 * 4 / 5) + abs(x)
// x += (0.0685 * 4 / 5)
// }
// if ((arucoMarker.markerId == 19 || arucoMarker.markerId == 43) && x <= 0 && abs(x) <= 0.065) {
// x = 0.0685 - abs(x)
// }
//
//
// /*if (y > 0 && y < 0.0965) {
// y -= 0.0965f
// }*/
// var outputX = updateOutSpeed(abs(x))
// var outputY = updateOutSpeed(abs(y))
// /*if (arucoMarker.markerId == 43) {
// if (outputX > 0.075f) {
// outputX = 0.075f
// }
// if (outputY > 0.075f) {
// outputY = 0.075f
// }
// }*/
// outputX = if (x < 0) -outputX else outputX
// outputY = if (y > 0) -outputY else outputY
//
// //如果识别到四个角aruco码升高扩大相机视野
// if (arucoMarker.markerId in 1..4 && AircraftInfoManager.aircraftAltitude <= 2.0f) {
// downwardSpeed = 1.95f
// }
// //如果角度偏差大于10度不移动飞机先旋转好角度
// if (abs(yawCamera).toInt() in 15..165 && AircraftInfoManager.aircraftAltitude >= 3.0f) {
// outputX = 0f
// outputY = 0f
// downwardSpeed = 0f
// }
// if (AircraftInfoManager.aircraftAltitude <= 3.0f) {
// resultYaw = 0.0
// }
// //如果高度小于1.8米,飞机不再下降高度
// if (AircraftInfoManager.aircraftAltitude <= 1.8f) {
// downwardSpeed = 0f
// }
// if ( x < 0 && x in -0.035..-0.07685) {
// outputX = 0f
// }
// if (y > 0.0685 && y <= 0.0865) {
// outputY = 0f
// }
// //使用虚拟摇杆控制飞机移动
// val leftHorizontal = calculateActualOffset(resultYaw, 100.0).toInt()
// val leftVertical = calculateActualOffset(downwardSpeed.toDouble(), 100.0).toInt()
// VirtualStickManager.getInstance().leftStick.apply {
// horizontalPosition = leftHorizontal
// verticalPosition = leftVertical
// }
//
// val rightHorizontal = calculateActualOffset(outputX.toDouble(), 23.0).toInt()
// val rightVertical = calculateActualOffset(outputY.toDouble(), 23.0).toInt()
// VirtualStickManager.getInstance().rightStick.apply {
// verticalPosition = rightVertical
// horizontalPosition = rightHorizontal
// }
// /*LogFileManager.getInstance().log(
// TAG,
// "ID:${arucoMarker.markerId} X:$x Y:$y outputX:$outputX outputY:$outputY rightHorizontal:$rightHorizontal rightVertical:$rightVertical Altitude:${AircraftInfoManager.aircraftAltitude}"
// )*/
// grayImgMat.release()
// bitmap.recycle()
// bmp32.recycle()
// source.release()
// ids.release()
// rvecs.release()
// tvecs.release()
// rvec.release()
// tvec.release()
// camR.release()
// _camR.release()
// R.release()
// isDetectingAruco = false
// mFindArucoList.clear()
// mArucoCornerList.clear()
// } catch (e: Exception) {
// e.printStackTrace()
// isDetectingAruco = false
// mFindArucoList.clear()
// mArucoCornerList.clear()
// }
// }
// }
//
//
// /**
// * 计算实际偏移量
// */
// private fun calculateActualOffset(
// speed: Double,
// maxSpeed: Double,
// ): Double {
// return speed * 660.0 / (0.25 * maxSpeed)
// }
//
//
// /**
// * 根据预估距离获取移动速度
// */
// private fun updateOutSpeed(estimatedDistance: Double): Float {
// val targetSpeed = if (estimatedDistance >= 4.0) {
// 0.6f
// } else if (estimatedDistance in 1.5..4.0) {
// 0.3f
// } else if (estimatedDistance > 0.9 && estimatedDistance < 1.5) {
// 0.25f
// } else if (estimatedDistance in 0.15..0.9) {
// 0.125f
// } else if (estimatedDistance >= 0.1 && estimatedDistance < 0.15) {
// //0.125f
// //0.0925f
// 0.0825f
// } else if (estimatedDistance >= 0.07 && estimatedDistance < 0.1) {
// //0.0375f
// //0.085f
// //0.0725f
// 0.0685f
// } else {
// //0.0f
// 0.0375f
// }
// return targetSpeed
// }
//
//
// /**
// * 旋转矩阵 --> 欧拉角
// */
// private fun rotationMatrixToEulerAngles(R: Mat): MutableList<Double> {
// val sy = sqrt(R[0, 0][0] * R[0, 0][0] + R[1, 0][0] * R[1, 0][0])
// val singular = sy < 1e-6
//
// return if (!singular) {
// val x = atan2(R[2, 1][0], R[2, 2][0])
// val y = atan2(-R[2, 0][0], sy)
// val z = atan2(R[1, 0][0], R[0, 0][0])
// mutableListOf(x, y, z)
// } else {
// val x = atan2(-R[1, 2][0], R[1, 1][0])
// val y = atan2(-R[2, 0][0], sy)
// val z = 0.0
// mutableListOf(x, y, z)
// }
// }
//
//
// /**
// * 退出虚拟摇杆控制,并开始降落
// */
// @SuppressLint("CheckResult")
// private fun exitVirtualStick() {
// VirtualStickManager.getInstance()
// .disableVirtualStick(object : CommonCallbacks.CompletionCallback {
// override fun onSuccess() {
// //开始降落
// KeyManager.getInstance().performAction(
// FlightControllerKey.KeyStartAutoLanding.create(),
// null,
// null
// )
// }
//
// override fun onFailure(error: IDJIError) {
// }
// })
// }
//
//
// /**
// * 发送虚拟摇杆控制数九
// */
// private fun sendVirtualStickCommands(pX: Float, pY: Float, pZ: Float, pYaw: Float) {
// val verticalJoyControlMaxSpeed = 0.15f
// val yawJoyControlMaxSpeed = 1f
// val pitchJoyControlMaxSpeed = 1f
// val rollJoyControlMaxSpeed = 1f
//
// val yawResult = (yawJoyControlMaxSpeed * pYaw).toDouble()
// val throttleResult = (verticalJoyControlMaxSpeed * pZ).toDouble()
// val pitchResult = (pitchJoyControlMaxSpeed * pX).toDouble()
// val rollResult = (rollJoyControlMaxSpeed * pY).toDouble()
//
// val param = VirtualStickFlightControlParam().apply {
// rollPitchCoordinateSystem = FlightCoordinateSystem.BODY
// verticalControlMode = VerticalControlMode.VELOCITY
// yawControlMode = YawControlMode.ANGULAR_VELOCITY
// rollPitchControlMode = RollPitchControlMode.VELOCITY
// pitch = pitchResult
// roll = rollResult
// yaw = yawResult
// verticalThrottle = throttleResult
// }
// VirtualStickManager.getInstance().sendVirtualStickAdvancedParam(param)
// }
//
//}