Skip to content

Latest commit

 

History

History
250 lines (194 loc) · 6.33 KB

File metadata and controls

250 lines (194 loc) · 6.33 KB

ControllerSDK API 参考

兼容性:ControllerSDK 仅支持山猫 M20 标配的云卓 G20 手柄,不兼容其他型号。

ControllerManager

ControllerManager 是 ControllerSDK 核心入口类,采用单例模式管理手柄生命周期。

初始化

fun init(application: Application)

必须在 Application.onCreate() 中调用,且只需一次。init() 必须先于 connect() 执行,否则无法正确识别设备型号。

示例

class MyApp : Application() {
    override fun onCreate() {
        super.onCreate()
        ControllerManager.init(this)
    }
}

连接与断开

// 连接手柄(在 Activity.onCreate 中调用)
fun connect(
    context: Context,
    scope: LifecycleCoroutineScope,
    onException: ((Exception) -> Unit)? = null
)

// 断开手柄连接
fun disconnect()

// 恢复摇杆指令发送(Activity.onResume 时调用)
fun onResume()

// 暂停摇杆指令发送(Activity.onPause 时调用)
fun onPause()

示例

// 在 Activity.onCreate 中连接
ControllerManager.connect(this, lifecycleScope) { e ->
    Log.e("M20", "手柄连接异常: ${e.message}")
}

// 生命周期管理
override fun onResume() {
    super.onResume()
    ControllerManager.onResume()
}

override fun onPause() {
    super.onPause()
    ControllerManager.onPause()
}

override fun onDestroy() {
    super.onDestroy()
    ControllerManager.disconnect()
}

其他方法

// 当前是否有匹配的手柄实现(G20)
fun hasController(): Boolean

// 软急停按钮是否被触发
fun needSendSoftEmergencyStopMessage(): Boolean

// 设置摇杆死区归一化值(0~0.5),默认 0 无死区
fun setDeadzone(value: Float)

LiveData

属性 类型 说明
joystickDataLive LiveData<JoystickData>? 摇杆实时数据(归一化值 -1.0~1.0)
physicalKeyStatesLive LiveData<List<PhysicalKeyBase>?>? 当前按下的物理按键列表
d2dConnectStateLive LiveData<Boolean>? 手柄连接状态(true=已连接)
d2dSignalLive LiveData<Int>? 信号强度(百分比或 RSRP,-1 表示未知)
softEmergencyStopLive LiveData<Boolean>? 软急停状态(true=软急停中)

注意:以上 LiveData 在 connect() 之前为 null,需确保 connect 后再 observe。


JoystickData

手柄摇杆数据模型,包含原始值和归一化值。

data class JoystickData(
    val leftX: Int = 0,        // 左摇杆 X 轴原始值(范围 1050~1950,中心 1500)
    val leftY: Int = 0,        // 左摇杆 Y 轴原始值
    val rightX: Int = 0,       // 右摇杆 X 轴原始值
    val rightY: Int = 0,       // 右摇杆 Y 轴原始值
    val leftXNorm: Float = 0f, // 左摇杆 X 轴归一化值(-1.0 ~ 1.0,应用死区后)
    val leftYNorm: Float = 0f, // 左摇杆 Y 轴归一化值
    val rightXNorm: Float = 0f,// 右摇杆 X 轴归一化值
    val rightYNorm: Float = 0f // 右摇杆 Y 轴归一化值
)

摇杆数据映射到 RobotSDK AxisData

JoystickData 字段 映射到 AxisData 说明
leftYNorm x 前后移动(向前为正)
-leftXNorm y 左右移动(向左为正)
-rightYNorm z 升降(暂不支持)
-rightXNorm yaw 旋转(逆时针为正)

注意:当前基础步态(0x1001)和楼梯步态(0x1003)下,仅 x、y、yaw 三个轴生效,z、roll、pitch 暂不支持。

与 RobotSDK 配合使用示例

ControllerManager.joystickDataLive?.observe(this) { joy ->
    RobotSdkManager.axisDataProvider = {
        AxisData(
            x = joy.leftYNorm,
            y = -joy.leftXNorm,
            z = -joy.rightYNorm,
            yaw = -joy.rightXNorm,
            roll = 0f,
            pitch = 0f
        )
    }
}

物理按键

通过 physicalKeyStatesLive 观察当前按下的物理按键列表。

ControllerManager.physicalKeyStatesLive?.observe(this) { keys ->
    keys?.forEach { key ->
        when (key.name) {
            "G20_KEY_STOP" -> RobotSdkManager.sendEnterDampingMode()
            "G20_KEY_HOME" -> { /* 自定义 HOME 键逻辑 */ }
            else -> { /* 其他按键 */ }
        }
    }
}

云卓 G20 按键枚举(YzG20ConnectUtils.PhysicalKey):

按键 name
L1 G20_KEY_L1
L2 G20_KEY_L2
R1 G20_KEY_R1
R2 G20_KEY_R2
HOME G20_KEY_HOME
STOP(急停) G20_KEY_STOP
CAMERA G20_KEY_CAMERA
PUMP G20_KEY_PUMP

异常处理

手柄连接异常

ControllerManager.connect(this, lifecycleScope) { e ->
    Log.e("M20", "手柄连接异常", e)
}

未匹配到手柄

if (!ControllerManager.hasController()) {
    Toast.makeText(this, "当前设备不支持云卓 G20 手柄", Toast.LENGTH_SHORT).show()
}

与 RobotSDK 联动完整示例

class MainActivity : AppCompatActivity() {

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)

        // 连接手柄(init 已在 Application 中完成)
        ControllerManager.connect(this, lifecycleScope) { e ->
            Log.e("M20", "手柄连接异常: ${e.message}")
        }

        // 观察摇杆数据并映射为 AxisData 提供给 RobotSDK
        ControllerManager.joystickDataLive?.observe(this) { joy ->
            RobotSdkManager.axisDataProvider = {
                AxisData(
                    x = joy.leftYNorm,
                    y = -joy.leftXNorm,
                    z = -joy.rightYNorm,
                    yaw = -joy.rightXNorm,
                    roll = 0f,
                    pitch = 0f
                )
            }
        }

        // 观察物理按键
        ControllerManager.physicalKeyStatesLive?.observe(this) { keys ->
            keys?.forEach { key ->
                if (key.name == "G20_KEY_STOP") {
                    RobotSdkManager.sendEnterDampingMode()
                }
            }
        }
    }

    override fun onResume() {
        super.onResume()
        ControllerManager.onResume()
    }

    override fun onPause() {
        super.onPause()
        ControllerManager.onPause()
    }

    override fun onDestroy() {
        super.onDestroy()
        ControllerManager.disconnect()
    }
}