重新发明车轮:用PyTorch发现最佳滚动形状(2019)

2020-06-03 16:54:57

人们认为轮子是在五千多年前发明的,而现代机器学习工具是在过去几十年才开发出来的。我们都曾在某种程度上对这一悖论感到疑惑。如果没有现代的计算机和软件,古代苏美尔人的车轮建造者怎么能计算出理想的形状呢?我们可能永远不会知道。幸运的是,有了今天的技术,重新发现轮子的最佳形状是相对容易的。我会告诉你我是怎么做的。

这个愚蠢的项目的目标是找到轮子的最佳形状,它可能是一个圆圈。我将轮子参数化为一个二十边多边形,每个顶点的半径都是可变的,\(r_i\)。车轮的性能是基于假想汽车加速所达到的最终速度\(v_f\)。轮子是以恒定扭矩驱动的,没有打滑。我使用PyTorch来模拟轮子的效果,并计算最终速度相对于半径\(\frac{dv_f}{dr_i}\)的梯度。我使用这些渐变来更新半径,使用渐变下降。上图中,您可以看到最初随机生成的轮子的形状,轮子随着对象函数的变化而不断演变。

我用一个相对简单的模型来表示轮子。在每个时间步中,我根据车轮的力更新汽车的速度,然后根据速度旋转车轮。最低的顶点与地面接触,并固定在空间中。车轮在汽车上产生一个力\(τ/r_i\),其中\(r_i\)是顶点的半径。这个力的一个分量,如下图所示,加速了汽车并提高了它的速度。

接下来,我想尝试一下不平坦的表面会很有趣。如果我使用那个滚动的正方形表面,最佳形状会是正方形吗?

将手电筒导入numpy作为nP导入matplotlib.pylot为plt n=20#轮点数n_step=1000#测试轮子性能的步骤数#Radii=torch.tensor([2.]+[1.]*(n-1),Requires_grad=True)#使用一个凹凸半径=TORCH初始化轮子半径。张量(np.。随机的。正常(1.,.4,大小=n)。ASTYPE(NP.。Float32),Requires_grad=True)#init随机轮点半径dtheta=2.*np。Pi/n#轮点之间的角度θ=火炬。排列(0,2*np.。pi,dtheta)#轮点角度列表dt=0.1#动力学扭矩=1的时间步长=1。#车轮质量上的扭矩=10。#汽车重力的质量=.1#重力引起的加速度#根据半径def test_车轮(半径)查找车轮的最终速度:#规格化半径,以便更改大小不会影响NORM_RADIi=半径/火炬。Mean(Radii)#查找轮点的坐标vertex_Position=车轮坐标(Norm_Radii)速度=手电筒。零(N_Step)+1.#每个台阶角度后的手推车速度=0#模拟范围(1,n_step)内i的车轮性能:#查找轴心点属性PIVOT_INDEX=TORCH。argmin(VERTEX_POSITIONS[:,1])PIVOT_RADIUS=NORM_RADI[PIVOT_INDEX]PIVOT_VECTOR=VERTEX_POSITIONS[PIVOT_INDEX]PIVOT_ANGLE=火炬。atan2(Pivot_Vector[1],Pivot_Vector[0])#不要使用枢轴角度,只需取枢轴的高度#计算枢轴点的力force=扭矩/Pivot_Radius#force_graight=重力*quality*torch.sin(Pivot_angle+np.pi/2)force_graight=0#计算推动汽车前进的枢轴力分量force_component=torch。COS(PIVOT_ANGLE+NP。Pi/2)#计算汽车的新速度和车轮的转速[i]=速度[i-1]+((force*force_component+force_graight)*dt/quality)ROTIONAL_SPEED=速度[i]*force_component/轴心半径悬挂=ROTIONAL_SPEED*DT角度+=悬挂#旋转车轮VERTEX_POSITIONS=ROTATE(VERTEX_POSITIONS,DRANLE)#print(角度)返回速度def DRAFT_WELES(VERTEX_POSITIONS)。Ys=顶点位置。转置(0,1)。分离()。Numpy()PLT。Scatter(xs,ys)#返回旋转矩阵def rotation_Matrix(Theta):返回手电筒。张量([[手电筒。因为(θ),火炬。Sin(Theta)],[-Torch.。罪恶(θ),火炬。cos(Theta)]])#返回基于半径定义的车轮坐标(Radii):VERTEX_POSITIONS=(Radii.。松开(1)*手电筒。猫((手电筒。Cos(Thetas.。重塑((-1,1)),火炬。Sin(Thetas.)。rehape((-1,1),1))return vertex_position#返回旋转后的顶点位置集合def Rotate(vertex_position,θ):ROT_Matrix=Rotation_Matrix(Theta)vertex_Position=torch。matmul(旋转矩阵,顶点位置。转置(0,1))。TRASPOSE(0,1)返回VERTEX_POSITIONS#LIST以跟踪目标进度最终速度=[]#目标图fig_obj=plt。