gams103作业1含提高部分

第一部分

检测碰撞

首先需要对所有点进行碰撞检测,判断是否与平面发生碰撞

这里碰撞检测根据读入给定的表面点和表面的法向量求点积判断是否小于0,如果是则证明两个的方向相反,发生碰撞。

同时判断是否速度方向和法线方向相反。

当同时满足以上两个条件的时候,则证明该点发生碰撞,此时需要记录碰撞的位置,按照平均的方式求碰撞点。

Mesh mesh = GetComponent<MeshFilter>().mesh;
Vector3[] vertices = mesh.vertices;//获得所有的顶点
Vector3 x = transform.position;
Matrix4x4 R = Matrix4x4.Rotate(transform.rotation);
Vector3 collosionPoint = new Vector3(0.0f, 0.0f, 0.0f);//根据位置求平均
UInt32 totalPoint = 0;
foreach (Vector3 vertex in vertices)
{Vector3 Rr_i = R.MultiplyVector(vertex);Vector3 x_i = x + Rr_i;float d = Vector3.Dot(x_i - P, N);//判断是否发生碰撞if (d < 0.0f)//发生碰撞{Vector3 v_i = v + Get_Cross_Matrix(w).MultiplyVector(Rr_i);float direction = Vector3.Dot(v_i, N);if (direction < 0.0f){collosionPoint += vertex;totalPoint += 1;}}}

求碰撞点的新的速度

根据算法流程,求出之前的速度,然后进行速度的分解,对不同方向的速度进行处理得到新的速度。

if (totalPoint <= 0) return;
collosionPoint /= totalPoint;
Vector3 Rr_i = R.MultiplyVector(collosionPoint);
Vector3 x_i = x + Rr_i;
Vector3 v_i = v + Get_Cross_Matrix(w).MultiplyVector(Rr_i);//得到点的速度
Vector3 v_N_i = Vector3.Dot(v_i, N) * N;
Vector3 v_T_i = v_i - v_N_i;//得到切线的速度
v_N_i = -restitution * v_N_i;
float a = Math.Max(1.0f - friction * (1.0f + restitution) * v_N_i.magnitude / v_T_i.magnitude, 0.0f);
v_T_i *= a;
Vector3 v_i_new = v_T_i + v_N_i;//新的速度

计算惯性张量和K矩阵

collosionPoint /= totalPoint;
Vector3 Rr_i = R.MultiplyVector(collosionPoint);
Matrix4x4 Rr_i_p = Get_Cross_Matrix(Rr_i);
Matrix4x4 I = R * I_ref * R.transpose;
Matrix4x4 I_inverse = I.inverse;
Matrix4x4 k = Matrix_sub_matrix(Matrix_multiply_float(Matrix4x4.identity, 1.0f / mass), Rr_i_p * I_inverse * Rr_i_p);

计算冲量,然后更新速度和角速度

Vector3 x_i = x + Rr_i;
Vector3 v_i = v + Get_Cross_Matrix(w).MultiplyVector(Rr_i);//得到点的速度
Vector3 v_N_i = Vector3.Dot(v_i, N) * N;
Vector3 v_T_i = v_i - v_N_i;//得到切线的速度
v_N_i = -restitution * v_N_i;
float a = Math.Max(1.0f - friction * (1.0f + restitution) * v_N_i.magnitude / v_T_i.magnitude, 0.0f);
v_T_i *= a;
Vector3 v_i_new = v_T_i + v_N_i;//新的速度Vector3 impulse = k.inverse.MultiplyVector(v_i_new-v_i);
v = v + Vector_multiply(impulse, 1.0f / mass);
w = w + I_inverse.MultiplyVector(Rr_i_p.MultiplyVector(impulse));

更新位置和quaternion

在Unity中Quaternion为(x,y,z,w)

if (launched)
{v += gravity * dt;v *= linear_decay;w *= angular_decay;// Part II: Collision ImpulseCollision_Impulse(new Vector3(0, 0.01f, 0), new Vector3(0, 1, 0));Collision_Impulse(new Vector3(2, 0, 0), new Vector3(-1, 0, 0));// Part III: Update position & orientationtransform.position += v * dt;//Update linear statusVector3 x = transform.position;//Update angular statusQuaternion q = transform.rotation;Vector3 qw = dt / 2.0f * w;Quaternion pq = new Quaternion(qw.x, qw.y, qw.z, 0.0f);q = Add(q, pq * q);// Part IV: Assign to the objecttransform.position = x;transform.rotation = q;
}

第一部分总代码

using UnityEngine;
using System.Collections;
using System.Numerics;
using Matrix4x4 = UnityEngine.Matrix4x4;
using Vector3 = UnityEngine.Vector3;
using Quaternion = UnityEngine.Quaternion;
using UnityEngine.UIElements;
using System;public class Rigid_Bunny : MonoBehaviour 
{bool launched 		= false;float dt 			= 0.015f;Vector3 v 			= new Vector3(0, 0, 0);	// velocityVector3 w 			= new Vector3(0, 0, 0);	// angular velocityfloat mass;									// massMatrix4x4 I_ref;							// reference inertiafloat linear_decay	= 0.999f;				// for velocity decayfloat angular_decay	= 0.98f;				float restitution 	= 0.5f;                 // for collisionfloat friction = 0.2f;Vector3 gravity =new Vector3(0.0f, -9.8f, 0.0f );// Use this for initializationvoid Start () {		Mesh mesh = GetComponent<MeshFilter>().mesh;Vector3[] vertices = mesh.vertices;float m=1;mass=0;for (int i=0; i<vertices.Length; i++) {mass += m;float diag=m*vertices[i].sqrMagnitude;I_ref[0, 0]+=diag;I_ref[1, 1]+=diag;I_ref[2, 2]+=diag;I_ref[0, 0]-=m*vertices[i][0]*vertices[i][0];I_ref[0, 1]-=m*vertices[i][0]*vertices[i][1];I_ref[0, 2]-=m*vertices[i][0]*vertices[i][2];I_ref[1, 0]-=m*vertices[i][1]*vertices[i][0];I_ref[1, 1]-=m*vertices[i][1]*vertices[i][1];I_ref[1, 2]-=m*vertices[i][1]*vertices[i][2];I_ref[2, 0]-=m*vertices[i][2]*vertices[i][0];I_ref[2, 1]-=m*vertices[i][2]*vertices[i][1];I_ref[2, 2]-=m*vertices[i][2]*vertices[i][2];}I_ref [3, 3] = 1;}Matrix4x4 Get_Cross_Matrix(Vector3 a){//Get the cross product matrix of vector aMatrix4x4 A = Matrix4x4.zero;A [0, 0] = 0; A [0, 1] = -a [2]; A [0, 2] = a [1]; A [1, 0] = a [2]; A [1, 1] = 0; A [1, 2] = -a [0]; A [2, 0] = -a [1]; A [2, 1] = a [0]; A [2, 2] = 0; A [3, 3] = 1;return A;}private Matrix4x4 Matrix_multiply_float(Matrix4x4 a,float b){for(int i=0; i<4; i++){for(int j = 0; j < 4; j++){a[i, j] *= b;}}return a;}private Matrix4x4 Matrix_sub_matrix(Matrix4x4 a,Matrix4x4 b){for(int i = 0; i < 4; i++){for(int j = 0; j < 4; j++){a[i, j] -= b[i, j];}}return a;}private Vector3 Vector_multiply(Vector3 a,float b){for(int i = 0; i < 3; i++){a[i] *= b;}return a;}// In this function, update v and w by the impulse due to the collision with//a plane <P, N>void Collision_Impulse(Vector3 P, Vector3 N){Mesh mesh = GetComponent<MeshFilter>().mesh;Vector3[] vertices = mesh.vertices;//获得所有的顶点Vector3 x = transform.position;Matrix4x4 R = Matrix4x4.Rotate(transform.rotation);Vector3 collosionPoint = new Vector3(0.0f, 0.0f, 0.0f);//根据位置求平均int totalPoint = 0;foreach (Vector3 vertex in vertices){Vector3 p_Rr_i = R.MultiplyVector(vertex);Vector3 p_x_i = x + p_Rr_i;float d = Vector3.Dot(p_x_i - P, N);//判断是否发生碰撞if (d < 0.0f)//发生碰撞{Vector3 p_v_i = v + Get_Cross_Matrix(w).MultiplyVector(p_Rr_i);float direction = Vector3.Dot(p_v_i, N);if (direction < 0.0f){collosionPoint += vertex;totalPoint += 1;}}}if (totalPoint <= 0) return;collosionPoint /= (float) totalPoint;Vector3 Rr_i = R.MultiplyVector(collosionPoint);Matrix4x4 Rr_i_p = Get_Cross_Matrix(Rr_i);Matrix4x4 I = R * I_ref * R.transpose;Matrix4x4 I_inverse = I.inverse;Matrix4x4 k = Matrix_sub_matrix(Matrix_multiply_float(Matrix4x4.identity, 1.0f / mass), Rr_i_p * I_inverse * Rr_i_p);Vector3 x_i = x + Rr_i;Vector3 v_i = v + Get_Cross_Matrix(w).MultiplyVector(Rr_i);//得到点的速度Vector3 v_N_i = Vector3.Dot(v_i, N) * N;Vector3 v_T_i = v_i - v_N_i;//得到切线的速度v_N_i = -1.0f*restitution * v_N_i;float a = Math.Max(1.0f - friction * (1.0f + restitution) * v_N_i.magnitude / v_T_i.magnitude, 0.0f);v_T_i *= a;Vector3 v_i_new = v_T_i + v_N_i;//新的速度Vector3 impulse = k.inverse.MultiplyVector(v_i_new-v_i);v = v + Vector_multiply(impulse, 1.0f / mass);w = w + I_inverse.MultiplyVector(Rr_i_p.MultiplyVector(impulse));}private Quaternion Add(Quaternion a,Quaternion b){a.x += b.x;a.y += b.y;a.z += b.z;a.w += b.w;return a;}// Update is called once per framevoid Update () {//Game Controlif(Input.GetKey("r")){transform.position = new Vector3 (0, 0.6f, 0);restitution = 0.5f;launched=false;}if(Input.GetKey("l")){v = new Vector3 (5, 2, 0);launched=true;}// Part I: Update velocitiesif (launched){v += gravity * dt;v *= linear_decay;w *= angular_decay;// Part II: Collision ImpulseCollision_Impulse(new Vector3(0, 0.01f, 0), new Vector3(0, 1, 0));Collision_Impulse(new Vector3(2, 0, 0), new Vector3(-1, 0, 0));// Part III: Update position & orientationtransform.position += v * dt;//Update linear statusVector3 x = transform.position;//Update angular statusQuaternion q = transform.rotation;Vector3 qw = dt / 2.0f * w;Quaternion pq = new Quaternion(qw.x, qw.y, qw.z, 0.0f);q = Add(q, pq * q);// Part IV: Assign to the objecttransform.position = x;transform.rotation = q;}}
}

但是这个地方会不断的颤抖,并且会沿着切平面方向不断的移动

于是可以设定衰减

restitution = Math.Max(restitution - 0.05f, 0.0f);
friction = Math.Max(friction - 0.05f, 0.0f);
float a = 0.0f;
if (v_T_i.magnitude > 0.0f)
{a=Math.Max(1.0f - friction * (1.0f + restitution) * v_N_i.magnitude / v_T_i.magnitude, 0.0f);
}if (friction == 0.0f && restitution == 0.0f)
{a = 0.0f;
}

效果展示

提高部分

提高部分主要就是粒子的模拟,然后重新约束的过程

解读start的代码

这里是为了将质心设定为0,0,0。因为mesh.vertices是相对于局部坐标系的每个顶点的位置,但是不是相对于质心。

Mesh mesh = GetComponent<MeshFilter>().mesh;//拿到mesh的信息
V = new Vector3[mesh.vertices.Length];
X = mesh.vertices;
Q = mesh.vertices;
Debug.Log(mesh.vertices.Length);
//Centerizing Q.
Vector3 c=Vector3.zero;
for(int i=0; i<Q.Length; i++)c+=Q[i];
c/=Q.Length;
for(int i=0; i<Q.Length; i++)Q[i]-=c;

碰撞检测

这里的碰撞检测针对单个点,就没有力矩和惯性张量。

只需要检测一下点与平面是否发生碰撞,更改速度即可

void judgeCollision(int idx,Vector3 P,Vector3 N)
{Vector3 T = transform.position;float d = Vector3.Dot(P - X[idx],N);if (d < 0.0f){float pd = Vector3.Dot(V[idx],N);if (pd < 0.0f){Vector3 v_N = Vector3.Dot(V[idx], N) * N;Vector3 v_T = V[idx] - v_N;float a = Mathf.Max(1-fricion*(1+restitution)*v_N.magnitude/v_T.magnitude,0.0f);v_N = -1.0f * restitution * v_N;v_T = a * v_T;V[idx] = v_N + v_T;}}
}

更新每个点的位置

首先更新“梯形位置”同时计算c,A参数和对应的约束旋转矩阵

void Collision(float inv_dt,float dt)
{for(int i = 0; i < Q.Length; i++){judgeCollision(i, new Vector3(0, 0.01f, 0), new Vector3(0, 1, 0));judgeCollision(i, new Vector3(2, 0, 0), new Vector3(-1, 0, 0));Y[i] = X[i] + dt * V[i];}Vector3 c = new Vector3(0.0f, 0.0f, 0.0f);for(int i = 0; i < Q.Length; i++){c += Y[i];}c /= Q.Length;Matrix4x4 A = Matrix4x4.zero;for(int i = 0; i < Q.Length; i++){Vector3 y_c = Y[i] - c;A[0, 0] += y_c[0] * Q[i][0];A[0, 1] += y_c[0] * Q[i][1];A[0, 2] += y_c[0] * Q[i][2];A[1, 0] += y_c[1] * Q[i][0];A[1, 1] += y_c[1] * Q[i][1];A[1, 2] += y_c[1] * Q[i][2];A[2, 0] += y_c[2] * Q[i][0];A[2, 1] += y_c[2] * Q[i][1];A[2, 2] += y_c[2] * Q[i][2];}A[3, 3] = 1;A = A * QQt.inverse;Matrix4x4 R = Get_Rotation(A);
}

然后更新模型,最终的代码

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using Matrix4x4 = UnityEngine.Matrix4x4;
using Vector3 = UnityEngine.Vector3;
using Quaternion = UnityEngine.Quaternion;public class Rigid_Bunny_by_Shape_Matching : MonoBehaviour
{public bool launched = false;Vector3[] X;Vector3[] Q;Vector3[] V;Vector3[] Y;Matrix4x4 QQt = Matrix4x4.zero;Vector3 gravity = new Vector3(0.0f, -9.8f, 0.0f);float linear_decay = 0.999f;float restitution = 5.0f;float fricion = 0.5f;// Start is called before the first frame updatevoid Start(){Mesh mesh = GetComponent<MeshFilter>().mesh;//拿到mesh的信息V = new Vector3[mesh.vertices.Length];X = mesh.vertices;Q = mesh.vertices;Y = mesh.vertices;Debug.Log(mesh.vertices.Length);//Centerizing Q.Vector3 c=Vector3.zero;for(int i=0; i<Q.Length; i++)c+=Q[i];c/=Q.Length;for(int i=0; i<Q.Length; i++)Q[i]-=c;//Get QQ^t ready.for(int i=0; i<Q.Length; i++){QQt[0, 0]+=Q[i][0]*Q[i][0];QQt[0, 1]+=Q[i][0]*Q[i][1];QQt[0, 2]+=Q[i][0]*Q[i][2];QQt[1, 0]+=Q[i][1]*Q[i][0];QQt[1, 1]+=Q[i][1]*Q[i][1];QQt[1, 2]+=Q[i][1]*Q[i][2];QQt[2, 0]+=Q[i][2]*Q[i][0];QQt[2, 1]+=Q[i][2]*Q[i][1];QQt[2, 2]+=Q[i][2]*Q[i][2];}QQt[3, 3]=1;for(int i=0; i<X.Length; i++)V[i][0]=4.0f;Update_Mesh(transform.position, Matrix4x4.Rotate(transform.rotation), 0);transform.position= new Vector3(0.0f, 0.6f, 0.0f);transform.rotation=Quaternion.identity;}// Polar Decomposition that returns the rotation from F.Matrix4x4 Get_Rotation(Matrix4x4 F){Matrix4x4 C = Matrix4x4.zero;for(int ii=0; ii<3; ii++)for(int jj=0; jj<3; jj++)for(int kk=0; kk<3; kk++)C[ii,jj]+=F[kk,ii]*F[kk,jj];Matrix4x4 C2 = Matrix4x4.zero;for(int ii=0; ii<3; ii++)for(int jj=0; jj<3; jj++)for(int kk=0; kk<3; kk++)C2[ii,jj]+=C[ii,kk]*C[jj,kk];float det    =  F[0,0]*F[1,1]*F[2,2]+F[0,1]*F[1,2]*F[2,0]+F[1,0]*F[2,1]*F[0,2]-F[0,2]*F[1,1]*F[2,0]-F[0,1]*F[1,0]*F[2,2]-F[0,0]*F[1,2]*F[2,1];float I_c    =   C[0,0]+C[1,1]+C[2,2];float I_c2   =   I_c*I_c;float II_c   =   0.5f*(I_c2-C2[0,0]-C2[1,1]-C2[2,2]);float III_c  =   det*det;float k      =   I_c2-3*II_c;Matrix4x4 inv_U = Matrix4x4.zero;if(k<1e-10f){float inv_lambda=1/Mathf.Sqrt(I_c/3);inv_U[0,0]=inv_lambda;inv_U[1,1]=inv_lambda;inv_U[2,2]=inv_lambda;}else{float l = I_c*(I_c*I_c-4.5f*II_c)+13.5f*III_c;float k_root = Mathf.Sqrt(k);float value=l/(k*k_root);if(value<-1.0f) value=-1.0f;if(value> 1.0f) value= 1.0f;float phi = Mathf.Acos(value);float lambda2=(I_c+2*k_root*Mathf.Cos(phi/3))/3.0f;float lambda=Mathf.Sqrt(lambda2);float III_u = Mathf.Sqrt(III_c);if(det<0)   III_u=-III_u;float I_u = lambda + Mathf.Sqrt(-lambda2 + I_c + 2*III_u/lambda);float II_u=(I_u*I_u-I_c)*0.5f;float inv_rate, factor;inv_rate=1/(I_u*II_u-III_u);factor=I_u*III_u*inv_rate;Matrix4x4 U = Matrix4x4.zero;U[0,0]=factor;U[1,1]=factor;U[2,2]=factor;factor=(I_u*I_u-II_u)*inv_rate;for(int i=0; i<3; i++)for(int j=0; j<3; j++)U[i,j]+=factor*C[i,j]-inv_rate*C2[i,j];inv_rate=1/III_u;factor=II_u*inv_rate;inv_U[0,0]=factor;inv_U[1,1]=factor;inv_U[2,2]=factor;factor=-I_u*inv_rate;for(int i=0; i<3; i++)for(int j=0; j<3; j++)inv_U[i,j]+=factor*U[i,j]+inv_rate*C[i,j];}Matrix4x4 R=Matrix4x4.zero;for(int ii=0; ii<3; ii++)for(int jj=0; jj<3; jj++)for(int kk=0; kk<3; kk++)R[ii,jj]+=F[ii,kk]*inv_U[kk,jj];R[3,3]=1;return R;}// Update the mesh vertices according to translation c and rotation R.// It also updates the velocity.void Update_Mesh(Vector3 c, Matrix4x4 R, float inv_dt){for(int i=0; i<Q.Length; i++){Vector3 x=(Vector3)(R*Q[i])+c;V[i]=(x-X[i])*inv_dt;X[i]=x;}	Mesh mesh = GetComponent<MeshFilter>().mesh;mesh.vertices=X;}void judgeCollision(int idx,Vector3 P,Vector3 N){float d = Vector3.Dot(X[idx] - P,N);if (d < 0.0f){float pd = Vector3.Dot(V[idx],N);if (pd < 0.0f){Vector3 v_N = Vector3.Dot(V[idx], N) * N;Vector3 v_T = V[idx] - v_N;float a = Mathf.Max(1.0f-fricion*(1.0f+restitution)*v_N.magnitude/v_T.magnitude,0.0f);v_N = -1.0f * restitution * v_N;v_T = a * v_T;V[idx] = v_N + v_T;}}}void Collision(float inv_dt,float dt){for(int i = 0; i < Q.Length; i++){judgeCollision(i, new Vector3(0, 0.01f, 0), new Vector3(0, 1, 0));judgeCollision(i, new Vector3(2.0f, 0, 0), new Vector3(-1.0f, 0, 0));Y[i] = X[i] + dt * V[i];}Vector3 c = new Vector3(0.0f, 0.0f, 0.0f);for(int i = 0; i < Q.Length; i++){c += Y[i];}c /= Q.Length;Matrix4x4 A = Matrix4x4.zero;for(int i = 0; i < Q.Length; i++){Vector3 y_c = Y[i] - c;A[0, 0] += y_c[0] * Q[i][0];A[0, 1] += y_c[0] * Q[i][1];A[0, 2] += y_c[0] * Q[i][2];A[1, 0] += y_c[1] * Q[i][0];A[1, 1] += y_c[1] * Q[i][1];A[1, 2] += y_c[1] * Q[i][2];A[2, 0] += y_c[2] * Q[i][0];A[2, 1] += y_c[2] * Q[i][1];A[2, 2] += y_c[2] * Q[i][2];}A[3, 3] = 1;A = A * QQt.inverse;Matrix4x4 R = Get_Rotation(A);Update_Mesh(c, R, inv_dt);}// Update is called once per framevoid Update(){float dt = 0.015f;if (Input.GetKey("r")){transform.position = new Vector3(0.0f, 0.6f, 0.0f);transform.rotation = Quaternion.identity;launched = false;for (int i = 0; i < X.Length; i++)V[i][0] = 4.0f;Update_Mesh(transform.position, Matrix4x4.Rotate(transform.rotation), 0);}if (Input.GetKey("l")){launched = true;//Step 1: run a simple particle system.for (int i = 0; i < V.Length; i++){V[i] = new Vector3(5.0f, 2.0f, 0.0f);}}if (launched){for(int i = 0; i < V.Length; i++){V[i] += gravity * dt;V[i] *= linear_decay;}//Step 2: Perform simple particle collision.Collision(1/dt,dt);Debug.Log(V[0]);// Step 3: Use shape matching to get new translation c and // new rotation R. Update the mesh by c and R.//Shape Matching (translation)//Shape Matching (rotation)//Update_Mesh(c, R, 1/dt);}}
}

效果展示

个人觉得刚体用这种方式不太好

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

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

相关文章

我国静止无功发生器(SVG)市场规模逐渐扩大 高压SVG为主流产品

我国静止无功发生器&#xff08;SVG&#xff09;市场规模逐渐扩大 高压SVG为主流产品 静止无功发生器&#xff08;SVG&#xff09;又称为静止同步补偿器、先进静止补偿器、静止调相机等&#xff0c;是利用全控型功率器件组成的桥式变流器来实现动态无功调节的一种先进无功自动补…

Table 表格--分页序号自增

代码&#xff1a; import { Space, Table, Tag } from antd; import type { ColumnsType } from antd/es/table; import React, { useState } from react;interface DataType {key: string;name: string;age: number;address: string;tags: string[]; }const data: DataType[]…

python爬虫入门(四)之Beautiful Soup库

一、什么是Beautiful Soup库 1、Beautiful Soup库是用来做HTML解析的库 Beautiful Soup把看起来复杂的HTML内容&#xff0c;解析成树状结构&#xff0c;让搜索和修改HTML结构变得更容易 2、第三方库&#xff0c;先安装 终端输入pip install bs4 from bs4 import Beautiful…

Linux服务管理(一)SSH服务

Linux服务管理-SSH服务 1、SSH的登录验证2、SSH的登录端口设置3、SSH的登录用户设置4、SSH的登录超时设置5、SSH的尝试登录次数设置6、ssh尝试次数超了&#xff0c;服务器端怎么放行 程序优化是有上限的&#xff0c;比如一个网站的代码量你只会随着需求越写越多不会越写越少。架…

想买开放式耳机怎么选?五款高热度产品甄选推荐!

在追求自由与舒适的今天&#xff0c;开放式蓝牙耳机以其独特魅力&#xff0c;正引领音频设备的新风尚。它们摒弃了传统入耳式的封闭束缚&#xff0c;让音乐与周围世界和谐共存&#xff0c;既保证了音质的清晰与沉浸&#xff0c;又保留了对环境的敏锐感知。开放式设计不仅减轻了…

【2024最新】Arduino通过Python进行串口通信控制电机

1. 背景 最近想研究一下用 Python 控制 Arduino 的技术&#xff0c;通过上网查询&#xff0c;发现可以用 Python 中的 serial 库来实现和 Arduino 主板的串口通信&#xff0c;从而控制 Arduino。 特此记录一下这个小项目的过程及出现的问题。 2. 基础准备 主板&#xff1a;…

景联文科技打造高质量图文推理问答数据集,赋能大语言模型提升推理能力

大语言模型在处理推理任务时&#xff0c;不同于人类能够反思错误并修正思维路径&#xff0c;当它遇到自身知识盲区时&#xff0c;缺乏自我校正机制&#xff0c;往往导致输出结果不仅无法改善&#xff0c;反而可能变得更不准确。 需要依赖外部的知识库和推理能力来克服其在理解和…

蚓链实践告诉你“企业确保达成数字化营销效果的方法”

在如今这个数字化盛行的时代&#xff0c;企业想在激烈的市场竞争里崭露头角&#xff0c;确保数字营销效果那可是至关重要&#xff01;今天就来给大家聊聊实现这一目标的基本条件&#xff0c;来自蚓链数字化营销系统的广大用户体验总结。 一、精准的目标定位 企业一定要清楚地知…

uniapp 表格,动态表头表格封装渲染

1.接口表格数据&#xff1a; {"headers": [{"label": "实例名","name": "v1","order": 1,"hide": false,"dateTypeValue": null},{"label": "所属科室","name&quo…

CentOS 安装 annie/lux,以及 annie/lux 的使用

annie 介绍 如果第一次听到 annie 想必都会觉得陌生&#xff0c;annie 被大家称为视频下载神器&#xff0c;annie 作者介绍说可以下载抖音、哔哩哔哩、优酷、爱奇艺、芒果TV、YouTube、Tumblr、Vimeo 等平台的视频。 githup&#xff1a;https://github.com/pingf/annie 支持…

51单片机嵌入式开发:1、STC89C52环境配置到点亮LED

STC89C52环境配置到点亮LED 1 环境配置1.1 硬件环境1.2 编译环境1.3 烧录环境 2 工程配置2.1 工程框架2.2 工程创建2.3 参数配置 3 点亮一个LED3.1 原理图解读3.2 代码配置3.3 演示 4 总结 1 环境配置 1.1 硬件环境 硬件环境采用“华晴电子”的MINIEL-89C开发板&#xff0c;这…

elasticSearch快速了解

elasticSearch&#xff1a;经常用于搜索引擎&#xff0c;我们用的百度搜索和github上的搜索都是用的搜索引擎&#xff0c;它是对输入内容进行分析&#xff0c;然后查询&#xff0c;不像数据库模糊搜索的like一样必须含用你输入的全部内容。 elasticSearch优势&#xff1a;支持…

一文解决:你与该网站的连接不是私密连接,存在安全隐患

访问网页时&#xff0c;是不是会经常遇到网站不是私密连接的提示&#xff1f;当浏览器提示某个网页不安全时&#xff0c;这通常是因为网页使用的是非加密的HTTP协议&#xff0c;或者其HTTPS协议的SSL/TLS证书存在问题。 通常遇到这类网站时要注意&#xff0c;一来是网站未与证书…

`THREE.Line` 是 Three.js 中用于创建线段的类。

demo案例 THREE.Line 是 Three.js 中用于创建线段的类。以下是 THREE.Line 的详细说明&#xff0c;包括构造函数参数、输出、方法和属性。 构造函数 new THREE.Line(geometry, material, mode) geometry (THREE.BufferGeometry 或 THREE.Geometry): 定义线段的几何体。mater…

[图解]SysML和EA建模住宅安全系统-12-内部块图

1 00:00:00,580 --> 00:00:02,770 接下来我们来画流了 2 00:00:03,100 --> 00:00:05,050 首先第一个是站点状态 3 00:00:05,140 --> 00:00:08,130 从这里到这里&#xff0c;我们画一个过来 4 00:00:10,290 --> 00:00:11,890 这里流到这里 5 00:00:11,900 -->…

汉中茗茶小程序的设计

管理员账户功能包括&#xff1a;系统首页&#xff0c;个人中心&#xff0c;管理员管理&#xff0c;基础数据管理&#xff0c;茶叶管理&#xff0c;论坛管理&#xff0c;公告管理&#xff0c;茗茶历史管理 微信端账号功能包括&#xff1a;系统首页&#xff0c;茗茶信息&#xf…

mac怎么压缩pdf文件大小,mac压缩pdf文件大小不改变清晰度

在数字化时代&#xff0c;pdf格式因其良好的兼容性和稳定性&#xff0c;成为了文档分享和传输的首选。然而&#xff0c;随着文件内容的丰富&#xff0c;pdf文件的体积也越来越大&#xff0c;给存储和传输带来了不小的困扰。本文将揭秘几种简单有效的pdf文件压缩方法&#xff0c…

如何优化 PostgreSQL 中对于自关联表的查询?

文章目录 一、理解自关联表查询二、分析性能问题的可能原因&#xff08;一&#xff09;缺少合适的索引&#xff08;二&#xff09;大量数据的笛卡尔积&#xff08;三&#xff09;复杂的查询逻辑 三、优化策略及解决方案&#xff08;一&#xff09;创建合适的索引&#xff08;二…

OpenGL笔记七之顶点数据绘制命令和绘制模式

OpenGL笔记七之顶点数据绘制命令和绘制模式 —— 2024-07-07 杭州 下午 总结自bilibili赵新政老师的教程 code review! 文章目录 OpenGL笔记七之顶点数据绘制命令和绘制模式1.OpenGL版本号更改和编译更改2.GL_TRIANGLES模式绘制一个三角形、支持NFC坐标随窗口缩放2.1.三个点…

第二周:李宏毅机器学习笔记

第二周学习周报 摘要Abstract一、深度学习1.Backpropagation&#xff08;反向传播&#xff09;1.1 链式法则1.2 Forward pass&#xff08;前向传播&#xff09;1.3 Backward pass&#xff08;向后传播&#xff09;1.4 总结 2. Regression&#xff08;神奇宝贝案例&#xff09;2…