PythonIDE Docs
中文
简体中文

运动传感器仪表盘

motion 姿态采样、气压高度、haptics 反馈和 Chart。

演示 motion 姿态与气压高度采样、haptics 反馈,以及 Chart 展示姿态角。

#预期效果

运行后会出现运动传感器仪表盘,姿态采样、图表和触觉反馈按钮都有明确状态。

#完整示例

python
import math
import time

import appui
import haptics
import motion

state = appui.State(
    status="点击采样读取传感器",
    roll=0.0,
    pitch=0.0,
    yaw=0.0,
    gravity="--",
    rotation="--",
    altitude="--",
    samples=[
        {"axis": "roll", "value": 0},
        {"axis": "pitch", "value": 0},
        {"axis": "yaw", "value": 0},
    ],
)


def degrees(value):
    return float(value or 0) * 180.0 / math.pi


def format_vec(data):
    if not data:
        return "--"
    return f'x {data.get("x", 0):.2f}, y {data.get("y", 0):.2f}, z {data.get("z", 0):.2f}'


def sample_motion():
    if not motion.is_available():
        state.status = "当前设备不支持运动传感器"
        haptics.notification("error")
        return

    motion.start_updates(interval=1 / 30)
    time.sleep(0.15)
    attitude = motion.get_attitude() or {}
    gravity = motion.get_gravity()
    rotation = motion.get_rotation_rate()
    motion.stop_updates()

    roll = degrees(attitude.get("roll", 0))
    pitch = degrees(attitude.get("pitch", 0))
    yaw = degrees(attitude.get("yaw", 0))

    state.batch_update(
        status="采样完成",
        roll=roll,
        pitch=pitch,
        yaw=yaw,
        gravity=format_vec(gravity),
        rotation=format_vec(rotation),
        samples=[
            {"axis": "roll", "value": roll},
            {"axis": "pitch", "value": pitch},
            {"axis": "yaw", "value": yaw},
        ],
    )
    haptics.selection()


def sample_altitude():
    motion.start_altimeter()
    time.sleep(0.2)
    alt = motion.get_altitude()
    motion.stop_altimeter()
    if not alt:
        state.altitude = "未读取到气压高度"
        haptics.notification("warning")
        return
    state.altitude = f'{alt.get("relative_altitude", 0):.2f} m / {alt.get("pressure", 0):.2f} kPa'
    haptics.notification("success")


def body():
    return appui.NavigationStack(
        appui.List(
            [
                appui.Section(
                    [
                        appui.LabeledContent("状态", value=state.status),
                        appui.Button("采样姿态", action=sample_motion)
                            .button_style("bordered_prominent"),
                        appui.Button("采样气压高度", action=sample_altitude),
                    ],
                    header="采样",
                ),
                appui.Section(
                    [
                        appui.LabeledContent("Roll", value=f"{state.roll:.1f}°"),
                        appui.LabeledContent("Pitch", value=f"{state.pitch:.1f}°"),
                        appui.LabeledContent("Yaw", value=f"{state.yaw:.1f}°"),
                        appui.LabeledContent("重力", value=state.gravity),
                        appui.LabeledContent("旋转", value=state.rotation),
                        appui.LabeledContent("气压高度", value=state.altitude),
                    ],
                    header="读数",
                ),
                appui.Section(
                    [
                        appui.Chart(
                            state.samples,
                            x="axis",
                            y="value",
                            type="bar",
                            color="systemTeal",
                        )
                            .frame(height=220),
                    ],
                    header="姿态角",
                ),
            ]
        ).navigation_title("运动")
    )


appui.run(body, state=state, presentation="sheet")

#关键技巧

  • 先用 motion.start_updates() 启动采样,读 get_attitude() 等,再尽快 motion.stop_updates(),避免长时间占用传感器;需要控制采样率时可像示例一样传 interval=1 / 30
  • 气压用 start_altimeter / get_altitude / stop_altimeter
  • 图表数据用 State.batch_update 一次写回;反馈用 haptics API。