跳到主要内容
极客日志极客日志面向AI+效率的开发者社区
首页博客我的书GitHub 精选镜像AI 生图工具UI配色美学关于
搜索内容 / 工具 / 仓库 / 镜像...⌘K搜索
注册
博客列表
KotlinAI大前端java算法

AR 健身教练“形随心动”:基于 Rokid CXR-M SDK 的实战开发

居家健身缺乏专业指导及低头看屏体验差是常见痛点,基于 Rokid CXR-M SDK 构建 AR 健身应用“形随心动”可解决这一问题。项目通过手机端与眼镜协同,利用 AI 场景实现动作识别,自定义页面渲染 AR 教练界面,结合提词器进行实时纠正。内容涵盖 SDK 配置、权限管理、架构设计、核心功能代码实现及设备连接、动作捕捉、数据可视化等关键步骤,并分享性能优化方案,为开发者提供 AR 交互落地的参考案例。

狂少发布于 2026/3/24更新于 2026/8/340 浏览
AR 健身教练“形随心动”:基于 Rokid CXR-M SDK 的实战开发

项目背景与创意起源

在快节奏的都市生活中,健身成了保持健康的重要方式。但居家健身有个老毛病:缺乏专业指导,动作不规范容易受伤,而且低头看手机或平板也破坏了沉浸感。

根据《2024 年中国健身行业白皮书》,超过 65% 的居家用户因为'缺乏专业指导'放弃健身。Rokid Glasses 这种轻量级 AR 眼镜,'抬头即见'的交互正好能解决这个问题。

'形随心动'这个想法很简单:把专业教练'投射'到视野里,实时指导动作,还能给数据反馈。利用 Rokid CXR-M SDK 的 AI 场景、自定义页面和提词器功能,这事儿就能落地。

文章配图

文章配图


Rokid CXR-M SDK 相关

1. SDK 介绍

CXR-M SDK 是面向移动端的开发工具包,主要用来构建手机端与 Rokid Glasses 的控制和协同应用。通过它,开发者能和眼镜建立稳定连接,实现数据通信、实时音视频获取以及场景自定义。目前只支持 Android 版本。

2. SDK 开发导入配置

配置 Maven 仓库

CXR-M SDK 采用 Maven 在线管理。找到 settings.gradle.kts,在 dependencyResolutionManagement 节点的 repositories 中添加仓库地址:

https://maven.rokid.com/repository/maven-public/

文章配图

依赖导入

在 build.gradle.kts 的 dependencies 节点添加依赖包:

implementation("com.rokid.cxr:client-m:1.0.1-20250812.080117-2")

注意:SDK 要求 minSdk >= 28。如果项目中已有版本冲突,优先选用 SDK 对应的版本。

文章配图

3. 权限申请

声明权限

CXR-M SDK 需要网络、Wi-Fi、蓝牙等权限(蓝牙权限需同步申请 FINE_LOCATION)。在 AndroidManifest.xml 中声明最小权限集:

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools">
    <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
    <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
    <uses-permission android:name="android.permission.BLUETOOTH" />
    <uses-permission android:name="android.permission.BLUETOOTH_ADMIN" />
    <uses-permission android:name="android.permission.BLUETOOTH_CONNECT" />
    <uses-permission android:name="android.permission.BLUETOOTH_SCAN" />
    <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
    <uses-permission android:name="android.permission.CHANGE_NETWORK_STATE" />
    <uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
    <uses-permission android:name="android.permission.CHANGE_WIFI_STATE" />
    <uses-permission android:name="android.permission.INTERNET" />
</manifest>

动态申请权限

使用前必须先进行必要权限的动态申请,否则 SDK 不可用。

class MainActivity : AppCompatActivity() {
    companion object {
        const val TAG = "MainActivity"
        const val REQUEST_CODE_PERMISSIONS = 100
        private val REQUIRED_PERMISSIONS = mutableListOf(
            Manifest.permission.ACCESS_FINE_LOCATION,
            Manifest.permission.BLUETOOTH,
            Manifest.permission.BLUETOOTH_ADMIN,
        ).apply {
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
                add(Manifest.permission.BLUETOOTH_SCAN)
                add(Manifest.permission.BLUETOOTH_CONNECT)
            }
        }.toTypedArray()
    }

    private val permissionGrantedResult = MutableLiveData<Boolean?>()

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        // 请求权限
        requestPermissions(REQUIRED_PERMISSIONS, REQUEST_CODE_PERMISSIONS)
        
        // 观察权限结果
        permissionGrantedResult.observe(this) { granted ->
            if (granted == true) {
                // 权限全部授予
            } else {
                // 部分拒绝或未开始
            }
        }
    }

    override fun onRequestPermissionsResult(
        requestCode: Int,
        permissions: Array<out String>,
        grantResults: IntArray
    ) {
        super.onRequestPermissionsResult(requestCode, permissions, grantResults)
        if (requestCode == REQUEST_CODE_PERMISSIONS.hashCode()) {
            val allGranted = grantResults.all { it == PackageManager.PERMISSION_GRANTED }
            permissionGrantedResult.postValue(allGranted)
        }
    }
}

技术架构设计

1. 整体架构

'形随心动'采用分层架构,保证稳定性和扩展性:

应用层(Android App) → CXR-M SDK → Rokid Glasses(YodaOS) → 硬件传感器
  • 应用层:提供 UI、健身计划管理、社交功能。
  • CXR-M SDK:负责与眼镜通信、AI 场景处理、AR 界面渲染。
  • Rokid Glasses:执行 AR 渲染、动作捕捉、数据反馈。
  • 硬件传感器:提供姿态、心率等原始数据。

文章配图

架构说明:

  • 应用层:包含业务逻辑。
  • CXR-M SDK:核心通信与功能调用。
  • Rokid Glasses:硬件平台。
  • AR 界面:自定义页面实现的可视化展示。
  • AI 场景:利用 SDK 能力实现动作识别。
  • 社交互动模块:好友挑战、进度分享。

文章配图

2. 核心组件设计
组件功能SDK 实现方式
实时动作识别模块摄像头捕捉动作,分析质量AI 场景、自定义页面
个性化计划模块定制健身计划自定义页面、数据同步
AR 教练界面3D 显示虚拟教练,实时指导自定义页面、提词器
数据可视化模块实时显示心率、卡路里自定义页面、媒体操作
社交互动模块好友挑战、进度分享数据通信、自定义页面

文章配图

3. 架构设计优势
  1. 分层解耦:业务逻辑与硬件交互分离,方便扩展维护。
  2. 硬件能力充分利用:摄像头做动作捕捉,IMU 辅助分析,AR 提供沉浸体验。
  3. SDK 深度整合:AI 场景做识别,自定义页面做界面,提词器做文字指导。
  4. 可扩展性:新功能只需新增模块,不影响底层。

实现关键点:

组件关键技术点SDK 实现方式难度
设备连接蓝牙稳定连接CxrApi.getInstance().initBluetooth()★★☆
AI 场景动作识别与分析setAiEventListener() + controlScene()★★★★
AR 界面3D 指导界面渲染openCustomView() + JSON 布局★★★
数据同步实时数据传输sendStream() + setMediaFilesUpdateListener()★★
社交功能好友挑战实现controlScene() + 数据通信★★★

关键功能实现详解

1. 设备连接与初始化

搞定设备连接是第一步,毕竟没有它后续都免谈。这里要注意权限检查,确保蓝牙扫描正常。

class FitnessApp : AppCompatActivity() {
    private val REQUIRED_PERMISSIONS = mutableListOf(
        Manifest.permission.ACCESS_FINE_LOCATION,
        Manifest.permission.BLUETOOTH,
        Manifest.permission.BLUETOOTH_ADMIN,
    ).apply {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
            add(Manifest.permission.BLUETOOTH_SCAN)
            add(Manifest.permission.BLUETOOTH_CONNECT)
        }
    }.toTypedArray()

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        // 检查并请求必要权限
        if (!hasPermissions(REQUIRED_PERMISSIONS)) {
            requestPermissions(REQUIRED_PERMISSIONS, REQUEST_CODE_PERMISSIONS)
        } else {
            initializeDeviceConnection()
        }
    }

    private fun hasPermissions(permissions: Array<String>): Boolean {
        return permissions.all { ContextCompat.checkSelfPermission(this, it) == PackageManager.PERMISSION_GRANTED }
    }

    private fun initializeDeviceConnection() {
        // 查找 Rokid 设备
        val scanner = BluetoothLeScannerCompat.getScanner()
        scanner.startScan(
            listOf(ScanFilter.Builder()
                .setServiceUuid(ParcelUuid.fromString("00009100-0000-1000-8000-00805f9b34fb"))
                .build()),
            ScanSettings.Builder().build(),
            scanCallback
        )
    }

    private val scanCallback = object : ScanCallback() {
        override fun onScanResult(callbackType: Int, result: ScanResult) {
            super.onScanResult(callbackType, result)
            val device = result.device
            // 找到设备后,初始化蓝牙连接
            CxrApi.getInstance().initBluetooth(this@FitnessApp, device, object : BluetoothStatusCallback {
                override fun onConnectionInfo(socketUuid: String?, macAddress: String?, rokidAccount: String?, glassesType: Int) {
                    Log.d("FitnessApp", "Connection info: $socketUuid, $macAddress, $rokidAccount, $glassesType")
                    // 初始化成功后,连接蓝牙
                    CxrApi.getInstance().connectBluetooth(this@FitnessApp, socketUuid, macAddress, this@FitnessApp)
                }

                override fun onConnected() {
                    Log.d("FitnessApp", "Bluetooth connected successfully")
                    // 连接成功后,初始化 AI 场景
                    initializeAiScene()
                }

                override fun onDisconnected() {
                    Log.e("FitnessApp", "Bluetooth disconnected")
                }

                override fun onFailed(errorCode: ValueUtil.CxrBluetoothErrorCode?) {
                    Log.e("FitnessApp", "Bluetooth connection failed: $errorCode")
                }
            })
        }
    }

    private fun initializeAiScene() {
        // 设置 AI 事件监听
        CxrApi.getInstance().setAiEventListener(object : AiEventListener {
            override fun onAiEvent(eventType: ValueUtil.CxrAiEventType?, data: String?) {
                when (eventType) {
                    ValueUtil.CxrAiEventType.ACTION_RECOGNITION -> {
                        handleActionRecognition(data)
                    }
                }
            }
        })
        // 启动 AI 场景
        CxrApi.getInstance().controlScene(ValueUtil.CxrSceneType.AI_SCENE, true, null)
    }
}
2. 实时动作捕捉与纠正

这是核心功能,利用眼镜的摄像头和 AI 能力实时分析。这里要注意阈值设置,太高了不灵敏,太低了误报多。

private fun startExercise(exerciseType: String) {
    // 设置动作识别参数
    val actionParams = HashMap<String, String>()
    actionParams["exerciseType"] = exerciseType
    actionParams["threshold"] = "0.85" // 识别阈值
    
    // 启动 AI 场景进行动作识别
    CxrApi.getInstance().controlScene(
        ValueUtil.CxrSceneType.AI_SCENE, true, actionParams
    )
    
    // 设置 AI 事件监听
    CxrApi.getInstance().setAiEventListener(object : AiEventListener {
        override fun onAiEvent(eventType: ValueUtil.CxrAiEventType?, data: String?) {
            when (eventType) {
                ValueUtil.CxrAiEventType.ACTION_RECOGNITION -> {
                    val recognitionResult = Gson().fromJson(data, ActionRecognitionResult::class.java)
                    if (recognitionResult.accuracy > 0.8) {
                        showPositiveFeedback(recognitionResult.exerciseName, "动作标准!")
                    } else {
                        showCorrectionFeedback(recognitionResult.exerciseName, recognitionResult.correctionMessage)
                    }
                }
            }
        }
    })
}

private fun showCorrectionFeedback(exerciseName: String, message: String) {
    // 通过提词器场景显示纠正信息
    CxrApi.getInstance().controlScene(
        ValueUtil.CxrSceneType.WORD_TIPS, true, null
    )
    
    val text = "动作纠正:$message"
    CxrApi.getInstance().sendStream(
        ValueUtil.CxrStreamType.WORD_TIPS, text.toByteArray(), "correction_text",
        object : SendStatusCallback {
            override fun onSendSucceed() {
                Log.d("FitnessApp", "Correction message sent successfully")
            }
            override fun onSendFailed(errorCode: ValueUtil.CxrSendErrorCode?) {
                Log.e("FitnessApp", "Failed to send correction message: $errorCode")
            }
        }
    )
}

// 自定义页面场景:AR 教练界面
private fun setupARCoachInterface() {
    // 创建 AR 教练界面的 JSON 布局
    val arCoachJson = """
    {
      "type": "LinearLayout",
      "props": {
        "layout_width": "match_parent",
        "layout_height": "match_parent",
        "orientation": "vertical",
        "gravity": "center_horizontal",
        "paddingTop": "140dp",
        "paddingBottom": "100dp",
        "backgroundColor": "#00000000"
      },
      "children": [
        {
          "type": "TextView",
          "props": {
            "id": "tv_instruction",
            "layout_width": "wrap_content",
            "layout_height": "wrap_content",
            "text": "请保持背部挺直",
            "textSize": "18sp",
            "textColor": "#FF00FF00",
            "textStyle": "bold",
            "marginBottom": "20dp"
          }
        },
        {
          "type": "TextView",
          "props": {
            "id": "tv_count",
            "layout_width": "wrap_content",
            "layout_height": "wrap_content",
            "text": "0/10",
            "textSize": "24sp",
            "textColor": "#FFFFFFFF",
            "textStyle": "bold",
            "marginBottom": "30dp"
          }
        }
      ]
    }
    """.trimIndent()
    
    // 打开自定义页面
    CxrApi.getInstance().openCustomView(arCoachJson)
    
    // 设置自定义页面状态监听
    CxrApi.getInstance().setCustomViewListener(object : CustomViewListener {
        override fun onCustomViewOpened() {
            Log.d("FitnessApp", "Custom view opened successfully")
        }
        override fun onCustomViewClosed() {
            Log.d("FitnessApp", "Custom view closed")
        }
    })
}
3. 个性化健身计划

根据用户身体数据和目标定制计划。这部分逻辑可以放在后端,也可以本地生成,示例中为了简化直接返回预设计划。

class PersonalizedPlanActivity : AppCompatActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_personalized_plan)
        
        // 获取用户输入数据
        val age = findViewById<EditText>(R.id.et_age).text.toString().toInt()
        val weight = findViewById<EditText>(R.id.et_weight).text.toString().toFloat()
        val height = findViewById<EditText>(R.id.et_height).text.toString().toFloat()
        val goal = findViewById<Spinner>(R.id.spinner_goal).selectedItem.toString()
        
        // 根据数据生成计划
        val plan = generatePersonalizedPlan(age, weight, height, goal)
        displayPlan(plan)
        savePlanToGlasses(plan)
    }

    private fun generatePersonalizedPlan(age: Int, weight: Float, height: Float, goal: String): Plan {
        // 实际应用中,这里会根据算法生成计划
        return Plan(
            "30 天减脂计划",
            listOf(
                Exercise("深蹲", "3 组×15 次", "保持膝盖不超过脚尖", "squats"),
                Exercise("平板支撑", "3 组×30 秒", "保持身体成直线", "plank"),
                Exercise("跳绳", "3 组×2 分钟", "保持手腕放松", "jump_rope")
            )
        )
    }

    private fun displayPlan(plan: Plan) {
        val planAdapter = PlanAdapter(plan.exercises)
        findViewById<RecyclerView>(R.id.rv_plan).adapter = planAdapter
    }

    private fun savePlanToGlasses(plan: Plan) {
        // 将计划数据发送到 Rokid Glasses
        val planJson = Gson().toJson(plan)
        CxrApi.getInstance().sendStream(
            ValueUtil.CxrStreamType.PERSONALIZED_PLAN, planJson.toByteArray(), "fitness_plan",
            object : SendStatusCallback {
                override fun onSendSucceed() {
                    Log.d("FitnessApp", "Plan sent to glasses successfully")
                }
                override fun onSendFailed(errorCode: ValueUtil.CxrSendErrorCode?) {
                    Log.e("FitnessApp", "Failed to send plan: $errorCode")
                }
            }
        )
    }
}
4. 数据可视化与实时反馈

让数据浮现在眼前,不用低头看手表。这里要注意主线程更新 UI 的问题,避免卡顿。

class DataVisualizationActivity : AppCompatActivity() {
    private var heartRate = 0
    private var caloriesBurned = 0f
    private var exerciseTime = 0

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_data_visualization)
        
        setupARDataView()
        startExerciseTimer()
        startDataUpdates()
    }

    private fun setupARDataView() {
        val dataViewJson = """
        {
          "type": "LinearLayout",
          "props": {
            "layout_width": "match_parent",
            "layout_height": "match_parent",
            "orientation": "vertical",
            "gravity": "center",
            "backgroundColor": "#00000000"
          },
          "children": [
            {
              "type": "TextView",
              "props": {
                "id": "tv_heart_rate",
                "layout_width": "wrap_content",
                "layout_height": "wrap_content",
                "text": "心率:72",
                "textSize": "20sp",
                "textColor": "#FF00FF00",
                "textStyle": "bold"
              }
            },
            {
              "type": "TextView",
              "props": {
                "id": "tv_calories",
                "layout_width": "wrap_content",
                "layout_height": "wrap_content",
                "text": "卡路里:0",
                "textSize": "20sp",
                "textColor": "#FF00FF00",
                "textStyle": "bold",
                "marginTop": "20dp"
              }
            },
            {
              "type": "TextView",
              "props": {
                "id": "tv_time",
                "layout_width": "wrap_content",
                "layout_height": "wrap_content",
                "text": "时间:00:00",
                "textSize": "20sp",
                "textColor": "#FF00FF00",
                "textStyle": "bold",
                "marginTop": "20dp"
              }
            }
          ]
        }
        """.trimIndent()
        
        CxrApi.getInstance().openCustomView(dataViewJson)
    }

    private fun updateDataView() {
        val updateData = listOf(
            UpdateAction("update", "tv_heart_rate", "text", "心率:$heartRate"),
            UpdateAction("update", "tv_calories", "text", "卡路里:$caloriesBurned"),
            UpdateAction("update", "tv_time", "text", "时间:${formatTime(exerciseTime)}")
        )
        CxrApi.getInstance().updateCustomView(Gson().toJson(updateData))
    }

    private fun formatTime(seconds: Int): String {
        val minutes = seconds / 60
        val remainingSeconds = seconds % 60
        return String.format("%02d:%02d", minutes, remainingSeconds)
    }

    private fun startDataUpdates() {
        val handler = Handler(Looper.getMainLooper())
        handler.postDelayed(object : Runnable {
            override fun run() {
                heartRate = (heartRate + 2).coerceAtMost(160)
                caloriesBurned += 0.5f
                exerciseTime += 2
                updateDataView()
                handler.postDelayed(this, 2000)
            }
        }, 2000)
    }

    private fun startExerciseTimer() {
        val startTime = System.currentTimeMillis()
        val timerHandler = Handler(Looper.getMainLooper())
        timerHandler.postDelayed(object : Runnable {
            override fun run() {
                exerciseTime = ((System.currentTimeMillis() - startTime) / 1000).toInt()
                updateDataView()
                timerHandler.postDelayed(this, 1000)
            }
        }, 1000)
    }
}
5. 社交健身挑战

和朋友一起练更有动力。这里只是模拟发送挑战,实际项目中需要对接社交 API。

class ChallengeActivity : AppCompatActivity() {
    private val challenges = mutableListOf<Challenge>(
        Challenge("7 天深蹲挑战", "完成 7 天深蹲训练,每天 100 次", 7, 100),
        Challenge("30 天心率挑战", "保持心率在 120-150 之间", 30, 0)
    )

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_challenge)
        
        setupChallengeList()
        findViewById<Button>(R.id.btn_add_friend_challenge).setOnClickListener {
            showAddFriendChallengeDialog()
        }
    }

    private fun setupChallengeList() {
        val adapter = ChallengeAdapter(challenges)
        findViewById<RecyclerView>(R.id.rv_challenges).adapter = adapter
    }

    private fun showAddFriendChallengeDialog() {
        val builder = AlertDialog.Builder(this)
        builder.setTitle("添加好友挑战")
        val input = EditText(this)
        input.hint = "输入好友 ID"
        builder.setView(input)
        builder.setPositiveButton("确定") { _, _ ->
            val friendId = input.text.toString()
            createFriendChallenge(friendId)
        }
        builder.setNegativeButton("取消", null)
        builder.show()
    }

    private fun createFriendChallenge(friendId: String) {
        val challenge = Challenge(
            "与$friendId 的挑战", "一起完成 30 天健身挑战", 30, 0
        )
        saveChallengeToGlasses(challenge)
        sendChallengeToFriend(friendId, challenge)
    }

    private fun saveChallengeToGlasses(challenge: Challenge) {
        val challengeJson = Gson().toJson(challenge)
        CxrApi.getInstance().sendStream(
            ValueUtil.CxrStreamType.CHALLENGE, challengeJson.toByteArray(), "challenge_${challenge.id}",
            object : SendStatusCallback {
                override fun onSendSucceed() {
                    Log.d("FitnessApp", "Challenge saved to glasses")
                }
                override fun onSendFailed(errorCode: ValueUtil.CxrSendErrorCode?) {
                    Log.e("FitnessApp", "Failed to save challenge: $errorCode")
                }
            }
        )
    }

    private fun sendChallengeToFriend(friendId: String, challenge: Challenge) {
        Log.d("FitnessApp", "Challenge sent to friend $friendId")
        Toast.makeText(this, "挑战已发送给好友 $friendId", Toast.LENGTH_SHORT).show()
    }
}

挑战与解决方案

1. 动作识别精度问题

挑战:光线变化或动作差异可能导致准确率不足。

解决方案:

  • 多模态数据融合:结合摄像头和传感器数据。
  • 动态阈值调整:根据用户特征自动调整。
  • 用户反馈机制:允许确认或纠正结果。
private fun adjustRecognitionThreshold(userProfile: UserProfile): Float {
    return when {
        userProfile.age < 25 -> 0.85f
        userProfile.age < 40 -> 0.80f
        else -> 0.75f
    }
}
2. AR 界面流畅度优化

挑战:帧率不稳定。

解决方案:

  • 优化 JSON 布局,减少元素。
  • 使用 setCustomViewListener 优化渲染。
  • 异步数据更新,避免阻塞主线程。
CxrApi.getInstance().setCustomViewListener(object : CustomViewListener {
    override fun onCustomViewOpened() {
        // 优化渲染模式
        CxrApi.getInstance().setCustomViewRenderMode(ValueUtil.CxrRenderMode.FAST)
    }
    override fun onCustomViewClosed() {
        // 恢复默认
        CxrApi.getInstance().setCustomViewRenderMode(ValueUtil.CxrRenderMode.DEFAULT)
    }
})
3. 电池消耗问题

挑战:长时间运行耗电快。

解决方案:

  • 智能功耗管理:动态调整。
  • 自动休眠:停止运动后低功耗模式。
  • 优化传输:减少不必要同步。
// 智能功耗管理
CxrApi.getInstance().setPowerOffTimeout(30) // 30 分钟后自动关机
CxrApi.getInstance().setScreenOffTimeout(60) // 60 秒后屏幕关闭

val exerciseTimer = object : CountDownTimer(300000, 1000) {
    override fun onTick(millisUntilFinished: Long) {}
    override fun onFinish() {
        CxrApi.getInstance().setGlassBrightness(3)
        CxrApi.getInstance().setGlassVolume(2)
        Toast.makeText(this@FitnessApp, "进入低功耗模式", Toast.LENGTH_SHORT).show()
    }
}.start()

未来展望

'形随心动'验证了 Rokid CXR-M SDK 在 AR 健身场景的能力。接下来我们会继续拓展:

  1. AI 能力增强:集成更先进的模型,提升精度。
  2. 内容生态扩展:合作专业教练,提供更多课程。
  3. 硬件联动:对接智能设备,获取更全面数据。
  4. 跨平台支持:拓展更多硬件设备。

文章配图

文章配图


结语

'形随心动'不仅是一款应用,更是 Rokid CXR-M SDK 能力的展示。通过深度整合 AI 场景、自定义页面和提词器,我们实现了'抬头即见指导'的体验,解决了居家健身的核心痛点。

这展示了 Rokid 生态的应用前景,也为开发者提供了参考案例。随着 SDK 完善和生态扩展,AR 技术将在更多生活场景中发挥作用。未来将继续深耕 AR 健身领域,为用户提供更专业的健身体验。

目录

  1. 项目背景与创意起源
  2. Rokid CXR-M SDK 相关
  3. 1. SDK 介绍
  4. 2. SDK 开发导入配置
  5. 3. 权限申请
  6. 技术架构设计
  7. 1. 整体架构
  8. 2. 核心组件设计
  9. 3. 架构设计优势
  10. 关键功能实现详解
  11. 1. 设备连接与初始化
  12. 2. 实时动作捕捉与纠正
  13. 3. 个性化健身计划
  14. 4. 数据可视化与实时反馈
  15. 5. 社交健身挑战
  16. 挑战与解决方案
  17. 1. 动作识别精度问题
  18. 2. AR 界面流畅度优化
  19. 3. 电池消耗问题
  20. 未来展望
  21. 结语
  • 免费图片AI生成工具免费生成了解详情
  • Magick API 一键接入全球大模型注册送1000万token查看
  • 免费图片视频在线生成30秒,将你的创意变成现实开始设计
  • X/Twitter免费视频下载器免登陆无限额度免费视频解析下载了解详情
  • 100+免费在线小游戏爽一把
极客日志微信公众号二维码

微信扫一扫,关注极客日志

微信公众号「极客日志V2」,在微信中扫描左侧二维码关注。展示文案:极客日志V2 zeeklog

更多推荐文章

查看全部
  • Linux TCP 协议详解:报文结构、连接状态与流量控制
  • UniApp 结合 Python 开发跨平台房屋租赁系统
  • AI 鸿蒙 App 开发:从页面到能力系统的架构演变
  • FastDFS 分布式存储系统入门详解
  • Youtu-VL-4B-Instruct 基于 Gradio 扩展 WebUI 图片批处理
  • OpenCLAW Linux 系统部署与配置指南
  • Moments 使用 Docker 本地部署与远程访问配置
  • C++ 继承入门:基础概念、访问权限与默认成员函数
  • C++入门:输入输出、缺省参数与函数重载
  • 基于五条标注数据快速完成快递单信息抽取
  • AI 辅助撰写学术论文综述的方法与实践指南
  • 50 道前端核心面试题:HTML/CSS/JS/Vue/React/TS/工程化/网络/跨端
  • 论文解读:使用人类反馈训练语言模型遵循指令
  • LazyLLM 框架搭建代码专家智能体实战
  • C# 通过 HTTP API 集成 GLM-4.6V-Flash-WEB 模型实战
  • 前端组件库:拒绝重复造轮子,提升开发效率
  • ClawPanel:OpenClaw 智能管理面板,支持 20+ 通道接入与多模型配置
  • Python 图像处理实战:生成手绘图、证件照与九宫格
  • OpenClaw 本地 AI 智能体入门与实战部署指南
  • Java 面向对象三大特性:封装、继承与多态

相关免费在线工具

  • 加密/解密文本

    使用加密算法(如AES、TripleDES、Rabbit或RC4)加密和解密文本明文。 在线工具,加密/解密文本在线工具,online

  • RSA密钥对生成器

    生成新的随机RSA私钥和公钥pem证书。 在线工具,RSA密钥对生成器在线工具,online

  • Keycode 信息

    查找任何按下的键的javascript键代码、代码、位置和修饰符。 在线工具,Keycode 信息在线工具,online

  • Escape 与 Native 编解码

    JavaScript 字符串转义/反转义;Java 风格 \uXXXX(Native2Ascii)编码与解码。 在线工具,Escape 与 Native 编解码在线工具,online

  • Mermaid 预览与可视化编辑

    基于 Mermaid.js 实时预览流程图、时序图等图表,支持源码编辑与即时渲染。 在线工具,Mermaid 预览与可视化编辑在线工具,online

  • JavaScript / HTML 格式化

    使用 Prettier 在浏览器内格式化 JavaScript 或 HTML 片段。 在线工具,JavaScript / HTML 格式化在线工具,online