1.功能概述
下位机读取传感器四元数(四元数是一种用于表示三维空间中旋转的方法,它由一个实部和三个虚部组成),通过串口通信,实时将多个传感器读取到的四元数数据传给上位机。blender中使用python脚本,使用定时器,接收并处理四元数数据,并绑定给对应的骨骼,实时更新骨骼选旋转。下位机代码在上一篇帖子。
2.代码解析部分
以下是代码的主要功能和组成部分的解释:
①导入必要的模块
import sys
import os
import json
import logging
import bpy
import numpy as np
import serial
sys.path.append(os.path.join(bpy.path.abspath("//"), "scripts"))
from uartcomm import UARTTable
MCU_COM_PORT = "COM6"
#FPS = 30 # use 30 if system performance is poor
FPS = 60
sys
和os
用于操作系统路径和参数。json
用于处理JSON数据。logging
用于日志记录。bpy
是Blender的Python API,用于访问和操作Blender的数据和功能。numpy
用于数值计算。serial
用于与串行端口通信。FPS
(Frames Per Second,每秒帧数)是一个用于控制或指示动画、视频或模拟等以何种速率更新的变量。实际上并没有用到。
②设置日志记录
# set up logging
logger = logging.getLogger("BPY")
logger.setLevel(logging.DEBUG)
if not logger.handlers:
ch = logging.StreamHandler()
ch.setStream(sys.stdout)
ch.setLevel(logging.DEBUG)
# ch.setFormatter(logging.Formatter("%(asctime)s %(levelname)s [%(name)s::%(threadName)s]: %(message)s", datefmt="%Y-%m-%d %H:%M:%S"))
ch.setFormatter(logging.Formatter("%(asctime)s %(levelname)s [%(name)s]: %(message)s", datefmt="%Y-%m-%d %H:%M:%S"))
logger.addHandler(ch)
- 创建一个日志记录器,设置其级别为DEBUG,并添加一个控制台处理程序以输出日志。
③Blender场景设置
# get scene armature object
armature = bpy.data.objects["骨架"]
# get the bones we need
bone_root = armature.pose.bones.get("root")
bone_upper_arm_R = armature.pose.bones.get("armUp.R")
bone_lower_arm_R = armature.pose.bones.get("armDown.R")
- 获取场景中的特定骨骼对象及其骨骼。
④UART通信
uart_table = UARTTable(MCU_COM_PORT, logging_level=logging.DEBUG)
- 使用
UARTTable
类与MCU进行通信,获取关节数据。
UARTTable是uartcomm中的一个类,在uartcomm.py中定义了一个名为 UARTTable
的类,它用于通过UART(通用异步收发传输器)与串行端口进行通信。这个类提供了连接、停止和启动串行通信等功能,以及用于记录日志的设施。uartcomm.py如下
import sys
import json
import logging
import queue
import threading
import time
import serial
class UARTTable:
def __init__(self, port, baudrate=115200, logging_level=logging.INFO):
self.port = port
self.baudrate = 115200
self.ser = None
self.stop_sig = threading.Event()
self.stop_sig.clear()
self.data_table = {}
self.logger = logging.getLogger(self.__class__.__name__)
self.logger.setLevel(logging_level)
if not self.logger.handlers:
ch = logging.StreamHandler()
ch.setStream(sys.stdout)
ch.setLevel(logging.DEBUG)
# ch.setFormatter(logging.Formatter("%(asctime)s %(levelname)s [%(name)s::%(threadName)s]: %(message)s", datefmt="%Y-%m-%d %H:%M:%S"))
ch.setFormatter(logging.Formatter("%(asctime)s %(levelname)s [%(name)s]: %(message)s", datefmt="%Y-%m-%d %H:%M:%S"))
self.logger.addHandler(ch)
def connect(self):
self.logger.info("Connecting to serial port {0}...".format(self.port))
# close any ex