肌肉骨骼模拟

news2024/11/19 19:43:49

前言

对于角色动画,目前的技术主要包括这两种方式:基于运动学模拟的动画,和基于动力学模拟、即基于物理模拟的动画。第一种方式的应用相当广泛,我们接触的游戏大部分都采用了基于运动学的方式去实现动画,这种方式性能优秀,便于实现,然而却缺少了许多真实性。基于物理模拟的方式来实现动画,对性能的要求比较高,且实现起来比较复杂,优点是交互效果更真实。对人体的肌肉骨骼进行模拟,属于物理模拟的动画实现。

肌肉的模拟较为复杂,涉及到生物力学这门交叉学科的内容。目前较为通用的肌肉模拟的模型是希尔模型(Hill model)。接下来我会根据一篇2013年的TOG论文对肌肉模型的模拟进行介绍。

本篇博客参考自《Flexible Muscle-Based Locomotion for Bipedal Creatures》。

肌肉骨骼模型

希尔模型将肌肉表示成三元素结构,它由下列要素组成:

  • 一个收缩单元(contractile element, CE),表示根据肌肉激活状态收缩的肌肉纤维,这个单元可以产生主动力。
  • 一个并行弹性单元(parallel elastic element, PEE),表示肌肉纤维周围的被动弹性组织,这个单元可以产生被动力。
  • 一个串行弹性单元(parallel elastic element, SEE),代表连接肌肉和骨骼的肌腱,这个单元可以产生被动力。
    在这里插入图片描述

CE产生的力 F C E F_{CE} FCE,取决于肌肉的恒定最大等距力 F m a x F_{max} Fmax、肌肉激活 a a a、肌肉纤维的长度 L C E L_{CE} LCE,以及收缩速度 V C E V_{CE} VCE
F C E = a F m a x f L ( L C E ) f V ( V C E ) \begin{align} F_{CE} = aF_{max}f_L(L_{CE})f_V(V_{CE}) \end{align} FCE=aFmaxfL(LCE)fV(VCE)
其中, f L f_L fL表示力与肌肉长度之间的关系, f V f_V fV表示力与当前收缩速度之间的关系,下图即为这两个函数:

在这里插入图片描述

弹性元件PEE和SEE产生的被动力 F P E E F_{PEE} FPEE F S E E F_{SEE} FSEE根据其长度可以建模为非线性弹簧:
F S E E = f S E E ( L M − L C E ) F P E E = f P E E ( L C E ) \begin{align} F_{SEE} &= f_{SEE}(L_M-L_{CE}) \\ F_{PEE} &= f_{PEE}(L_{CE}) \end{align} FSEEFPEE=fSEE(LMLCE)=fPEE(LCE)
其中 f S E E f_{SEE} fSEE f P E E f_{PEE} fPEE是非线性的力-长度关系, L M L_M LM为肌肉的总长度。

由于SEE与CE和PEE串联在一起,因此总肌肉力 F M F_M FM服从力平衡方程:
F M = F C E + F P E E = F S E E \begin{align} F_M = F_{CE} + F_{PEE} = F_{SEE} \end{align} FM=FCE+FPEE=FSEE
SEE的初始化长度为其最优长度, L C E o p t L_{CE}^{opt} LCEopt。结合肌腱的松弛长度 L S E E s l a c k L_{SEE}^{slack} LSEEslack,可以定义肌肉的休息长度 L M r e s t L_M^{rest} LMrest:
L M r e s t = L S E E s l a c k + L C E o p t \begin{align} L_M^{rest} = L_{SEE}^{slack} + L_{CE}^{opt} \end{align} LMrest=LSEEslack+LCEopt
在实际进行模拟的时候,输入参数为激活状态 a a a以及肌肉的总长度 L M L_M LM

激活状态的动态更新

肌肉的激活状态 a a a是一个相对缓慢的电化学过程的结果,该过程基于控制系统输出的神经兴奋信号 u u u。这个过程称为激活动力学,其模型为:
∂ a ∂ t = c a ( a − u ) \begin{align} \frac{\partial a}{\partial t} = c_a(a-u) \end{align} ta=ca(au)
其中 c a c_a ca是恒定的激活和失活速率。

肌肉几何以及肌肉与骨骼的相互作用

骨骼和肌肉具有双向的作用:肌肉施加改变骨骼姿势的力量,而骨骼姿势决定肌肉的长度 L M L_M LM,进而影响收缩动力。整个肌肉的路径是由它的肌腱附着在骨头上的位置、肌肉环绕的骨性标志以及随时间变化的肌肉跨越的关节决定的。在原文的模型中,将肌肉路径定义为一组线段。这个模型是一种简化,具有高性能的优势,并且省略了对肌肉的几何形状建模的需要。如下图,长方体代表着肌肉附着的骨骼,红色连线代表着对肌肉的简化:

在这里插入图片描述

任何肌肉 M M M​的路径都是由 n n n​个附着点数组定义的, [ { b 1 , p 1 } . . . , { b n , p n } ] \left[ \left\{ b_1, p_1 \right\}...,\left\{b_n,p_n\right\} \right] [{b1,p1}...,{bn,pn}],每一个附着点由一个偏移量 p i \mathbf p_i pi以及一个附着在的骨骼 b i b_i bi定义。偏移量 p i \mathbf p_i pi定义为物体 b i b_i bi坐标系中的一个固定偏移量,它和它附着着的骨骼一起移动和旋转。多个附着点可以附着在一个骨骼上。第一个点和最后一个点 p 1 p_1 p1 p n p_n pn表示肌肉肌腱附着在骨骼上的位置,其他点都是通过点。

肌肉的总长度 L M L_M LM等于 n − 1 n - 1 n1个肌肉段长度之和, [ s 1 , . . . , s n − 1 ] [s_1,...,s_{n-1}] [s1,...,sn1],这些肌肉段的长度由世界坐标系中每个点的位置 p i W p_i^W piW求出:
L M = ∑ i = 1 n − 1 ∣ ∣ s i ∣ ∣ , s i = p i + 1 W − p i W \begin{align} L_M = \sum_{i=1}^{n-1} || s_i ||, s_i = p_{i+1}^W - p_i^W \end{align} LM=i=1n1∣∣si∣∣,si=pi+1WpiW
这些附着点在这篇文章的定义中,可以有四种活动方式:要么是固定的,要么被限制在一条线、一个平面或一个盒子上:

在这里插入图片描述

肌肉如何产生作用

由肌肉总长度 L M L_M LM以及激活状态 a a a可以计算肌肉收缩力 F M F_M FM。由于受力平衡,这个力被传递到肌肉在骨骼上的每个附着点上,并在它跨越的每个关节上产生扭矩。对于每个关节 k k k,在力臂 r k r_k rk定义的方向上可以产生一个扭矩 τ k \tau_k τk。这个力臂对应于穿过关节的肌肉段方向 s c s_c sc与关节中心 j k j_k jk到附着点 p c W p_c^W pcW的矢量之间的叉积:
τ k = F M ∣ ∣ r k ∣ ∣ , r k = ( p c W − j k ) × s c ∣ ∣ s c ∣ ∣ \begin{align} \tau_k = F_M||r_k||, r_k = (p_c^W - j_k) \times \frac{s_c}{||s_c||} \end{align} τk=FM∣∣rk∣∣,rk=(pcWjk)×∣∣sc∣∣sc

在Unity中实现肌肉骨骼模拟

在unity资源商店中有一个资源,实现了上述的肌肉骨骼模型:

https://assetstore.unity.com/packages/tools/physics/kinesis-physical-muscle-model-based-movement-206089

比较贵,$69.99,忍痛割刀买了。接下来讲解一下这个资源里是如何实现肌肉骨骼模型的。

在这个资源里,实现了调节肌肉激活状态,驱动人物的关节运动的物理模拟。

底层模拟基础

为了实现添加扭矩,驱动关节移动和旋转的功能,利用unity提供的Rigidbody以及Character Joint组件实现底层的模拟。

模拟实现

在每一个时步的模拟中,首先,参考公式 ( 6 ) (6) (6),根据输入的激活值更新激活状态 a a a。然后,更新SEE部分的长度(如果是初始调用,则不更新)。根据SEE的长度计算归一化后CE的长度,以及归一化后CE的收缩速度(如果是初始调用,则为0)。根据激活状态 a a a、归一化后CE的长度、归一化后CE的收缩速度,计算CE部分产生的主动力,参考公式 ( 1 ) (1) (1)。同时,根据CE的长度,计算PEE部分的被动力。CE部分产生的主动力,加上PEE部分产生的被动力,等于SEE部分产生的被动力,也等于肌肉产生的力,参考公式 ( 4 ) (4) (4)。其中,SEE部分产生的被动力,可以用来更新SEE部分的长度。接下来,利用肌肉产生的力,计算肌肉穿过的关节的扭矩,参考公式 ( 8 ) (8) (8)

在这里插入图片描述

补充

之前在实习时,leader让我做过这样一件事情,根据人物的运动序列,反向计算肌肉的激活状态,当时没能实现。现在想想,可以这样实现:

1、从人物的运动学模型转换到动力学模型,通过PD微分,求解人物每个关节所需要的扭矩。

2、根据每块肌肉和关节的关系,计算出每块肌肉应该产生的发力,通过每块肌肉产生的发力,反求出肌肉的激活状态。(根据公式 ( 1 ) (1) (1),并对激活状态的反推做简化,用 a = F C E / F m a x a = F_{CE} / F_{max} a=FCE/Fmax计算)

参考

Geijtenbeek T, Van De Panne M, Van Der Stappen A F. Flexible muscle-based locomotion for bipedal creatures[J]. ACM Transactions on Graphics (TOG), 2013, 32(6): 1-11.

https://assetstore.unity.com/packages/tools/physics/kinesis-physical-muscle-model-based-movement-206089

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1418889.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Python算法题集_和为K的子数组

本文为Python算法题集之一的代码示例 题目560:和为K的子数组 说明:给你一个整数数组 nums 和一个整数 k ,请你统计并返回 该数组中和为 k 的子数组的个数 。 子数组是数组中元素的连续非空序列。 示例 1: 输入:nu…

【idea插件开发】idea插件访问浏览器web地址

背景 以往在eclipse上面开发插件,有兴致想尝试Idea上玩一下插件开发。想要在idea上面访问web地址 概要 记录在idea上面访问web地址 正文 1、点击File->New->Project… 选择IntelliJ Platform Plugin 2、点击下一步后,输入Project Name&#…

(M)unity受伤反弹以及死亡动画

受伤反弹 1.在人物控制脚本中添加受伤后速度将为0,并添加一个反弹的力 在刷新移动时,需要在没有受伤的状态 public bool isHurt; public float hurtForce; private void FixedUpdate() {if(!isHurt)Move(); }public void GetHurt(Transform attacker) …

数据结构·单链表经典例题

1. 移除链表元素 OJ链接:力扣(LeetCode)官网 - 全球极客挚爱的技术成长平台 本题是说给出一个链表的头节点head和一个整数val,如果发现节点中存的数据有val就删掉它,最后返回修改后的链表头节点地址 如果题目中没有明确…

【LeetCode每日一题】56. 合并区间插入区间

一、判断区间是否重叠 力扣 252. 会议室 给定一个会议时间安排的数组 intervals ,每个会议时间都会包括开始和结束的时间 intervals[i] [starti, endi] ,请你判断一个人是否能够参加这里面的全部会议。 思路分析 因为一个人在同一时刻只能参加一个会…

掌握使用 React 和 Ant Design 的个人博客艺术之美

文章目录 前言在React的海洋中起航安装 Create React App安装Ant Design 打造个性化的博客风格通过路由实现多页面美化与样式定制部署与分享总结 前言 在当今数字时代,个人博客成为表达观点、分享经验和展示技能的独特平台。在这个互联网浪潮中,选择使用…

Unity 外观模式(实例详解)

文章目录 示例1:初始化游戏场景中的多个子系统示例2:管理音频播放示例3:场景加载流程示例4:UI管理器示例5:网络服务通信 在Unity中使用外观模式(Facade)时,主要目的是为了简化复杂子…

如何配置MacLinuxWindows环境变量

这里写目录标题 什么是环境变量什么是PATH为什么要配置环境变量 如何配置环境变量环境变量有哪些环境变量加载顺序环境变量加载详解 配置参考方法一: export PATHLinux环境变量配置方法二:vim ~/.bashrcLinux环境变量配置方法三:vim ~/.bash_…

使用程序设计流程图解析并建立神经网络(不依赖深度学习library)

介绍: ## Flow chart for a simple neural network: #(1)Take inputs 输入 #(2)Add bias (if required) #(3)Assign random weights to input features 随机一个权重 #(4)Run the code for training. 训练集训练 #(5)Find the error in prediction. 找预测损失 #(6…

RAG应用-七个最常见的故障点

近日,国外研究者发布了一篇论文《Seven Failure Points When Engineering a Retrieval Augmented Generation System》,探讨了在实际工程落地RAG应用过程中容易出的七类问题。 论文地址:https://arxiv.org/pdf/2401.05856.pdf 一、丢失内容&…

网络协议与攻击模拟_10DHCP攻击与DHCP欺骗

一、DHCP的报文格式 Message type:消息类型(1表示请求,2表示响应)Hardware type:硬件类型Hardware address length:硬件地址长度Hops:DHCP报文经过中继的数目。Transaction ID:事务…

树莓派部署Nginx服务结合内网穿透实现远程访问本地站点

文章目录 1. Nginx安装2. 安装cpolar3.配置域名访问Nginx4. 固定域名访问5. 配置静态站点 安装 Nginx(发音为“engine-x”)可以将您的树莓派变成一个强大的 Web 服务器,可以用于托管网站或 Web 应用程序。相比其他 Web 服务器,Ngi…

springboot mongodb简单教程

(1)依赖 compile(org.springframework.boot:spring-boot-starter-data-mongodb) (2)application.properties配置文件 spring.data.mongodb.host127.0.0.1 spring.data.mongodb.port27017 spring.data.mongodb.databasetest &a…

如何成为一个更好的沟通者?

新年伊始,我想跟大家分享9条我给自己定下的「沟通准则」。 这9条准则,是我对自己的要求,也是我身体力行践行了许多年的做法。我可能也没能践行得非常完美,但这也是我一直在努力的目标。 如果你希望能够跟别人「好好说话」&#xf…

Linux——磁盘和文件系统(一)

Linux——磁盘和文件系统 磁盘机械式磁盘固态硬盘 机械式磁盘结构磁盘,磁道,扇区柱面 文件系统的初始化划卷(划盘) 挂载C盘放了什么东西Boot Block(启动模块) 0号组放了什么东西Super Block(超级…

[m1pro ] ssh: connect to host localhost port 22: Connection refused

在学习Hadoop 的时候,使用 ssh localhost 遇到以下问题 原因: 本地没有打开远程登录 解决办法:打开远程登录 成功结果

leetcode刷题(剑指offer) 191.位1的个数

191.位1的个数 编写一个函数,输入是一个无符号整数(以二进制串的形式),返回其二进制表达式中数字位数为 ‘1’ 的个数(也被称为汉明重量)。 提示: 请注意,在某些语言(…

【Linux网络编程】网络编程套接字(1)

【Linux网络编程】网络编程套接字(1) 目录 【Linux网络编程】网络编程套接字(1)源IP地址和目的IP地址端口号端口号和进程ID的关系 网络通信TCP协议UDP协议网络字节序socket编程接口简单的UDP网络程序 作者:爱写代码的刚子 时间:2024.1.29 前言&#xff1…

时序预测 | Python基于Multihead-Attention-TCN-LSTM的时间序列预测

目录 效果一览基本介绍程序设计参考资料 效果一览 基本介绍 时序预测 | Python基于Multihead-Attention-TCN-LSTM的时间序列预测 Multihead-Attention-TCN-LSTM(多头注意力-TCN-LSTM)是一种结合了多个注意力机制、时序卷积网络(TCN&#xff0…

ORB-SLAM策略思考之RANSAC

ORB-SLAM策略思考之RANSAC 1. 初始化器的RANSAC ORB-SLAM中的初始化器是一个端到端的地图初始化策略,即不需要人的参与双线程同时计算本质矩阵和单应性矩阵使用基于RANSAC和卡方检验的评价方法 为了保证两种算法评价的一致性,计算本质矩阵F和单应性矩阵…