写本次博客的目的主要是记录自己的成果,有什么不足欢迎指教。
四个函数,一个循环
一、 轨道函数
#定义轨道函数
def func_2(x):
if x>0 and x<=50:
y = 400
elif x>50 and x<=250:
y = math.ceil((400**2-(x-50)**2)**0.5)
elif x>250 and x<=350:
y = math.floor(-((3**0.5)*x)/3+850*(3**0.5)/3)
elif x>350 and x<=550:
y = math.floor(-(400**2-(x-550)**2)**0.5+1100*(3**0.5)/3)
else:
y = math.floor(1100*(3**0.5)/3-400)
return y
#定义轨道函数,另一种表现形式
def func_0(x):
interval0 = 1 if x>0 and x<=50 else 0
interval1 = 1 if x>50 and x<250 else 0
interval2 = 1 if x == 250 else 0
interval3 = 1 if x>250 and x<=450 else 0
interval4 = 1 if x>450 and x<=500 else 0
#y = 500*interval0 + 400*interval1 + 300*interval2 + 200*interval3 + 100*interval4
y =500*interval0 + ((200**2-(x-50)**2)**0.5+300)*interval1 +300*interval2 + (-(200**2-(x-450)**2)**0.5+250)*interval3 + 50*interval4
return y
二、定义可转弯小车的方法
#定义一个画可转弯小车的方法
def draw(canvas,result):
result=np.array(result)
x = result[0]
y = result[1]
angle = result[2]
height = result[3]
width = result[4]
angle_Pi = -angle*math.pi/180.0 #转化为弧度
cosA = math.cos(angle_Pi)
sinA = math.sin(angle_Pi)
x1 = x-0.5*width
y1 = y-0.5*height
x0 = x+0.5*width
y0 = y1
x2 = x1
y2 = y+0.5*height
x3=x0
y3=y2
x0n = math.floor((x0 - x)*cosA - (y0 - y)*sinA + x)
y0n = math.floor((x0 - x)*sinA + (y0 - y)*cosA + y)
x1n = math.floor((x1 - x)*cosA - (y1 - y)*sinA + x)
y1n = math.floor((x1 - x)*sinA + (y1 - y)*cosA + y)
x2n = math.floor((x2 - x)*cosA - (y2 - y)*sinA + x)
y2n = math.floor((x2 - x)*sinA + (y2 - y)*cosA + y)
x3n = math.floor((x3 - x)*cosA - (y3 - y)*sinA + x)
y3n = math.floor((x3 - x)*sinA + (y3 - y)*cosA + y)
cv2.line(canvas,(x0n, y0n),(x1n, y1n), (255, 0, 0))
cv2.line(canvas,(x1n, y1n),(x2n, y2n), (255, 0, 0))
cv2.line(canvas,(x2n, y2n),(x3n, y3n), (255, 0, 0))
cv2.line(canvas,(x0n, y0n),(x3n, y3n), (255, 0, 0))
可以把小车看出一个矩形,小车在轨道上运行时,是需要不断转弯的。由于当时用opencv画的,不知道哪种方法可以直接画旋转矩形(后面知道一种方法可以不断框四个点的最小矩形,也能实现),因此必须自己定义一个。
此处写函数的思路是借鉴大佬的方法写的,稍微改了一下,使它与我的代码更加兼容。
参考 https://blog.csdn.net/u013948010/article/details/78318894
三、定义角度函数
def func_angle(x):
if x >0 and x<=50:
ang = 0
elif x>50 and x<=250:
ang = -math.floor(math.atan(((400**2-(x-50)**2)**0.5-(400**2-(x-1-50)**2)**0.5))*180/math.pi)
elif x>=250 and x<=350:
ang = 30
elif x>350 and x<=550:
ang = -math.floor(math.atan((-(400**2-(x-550)**2)**0.5+1100*(3**0.5)/3)-(-(400**2-(x-1-550)**2)**0.5+1100*(3**0.5)/3))*180/math.pi)
else:
ang = 0
return ang
目的使小车在沿轨道运行的过程中能不断的改变角度。
四、定义约束项
def lim(distance):#约束项
x = 0
for i in range(8,830):
if (power_3-i)**2 + (func_2(power_3)-func_2(i))**2 <= (distance+1)**2 and (power_3-i)**2 + (func_2(power_3)-func_2(i))**2 >= (distance-1)**2:
if i < power_3 and i >= power_3 - 11:
x = i
return x
定义这个函数的目的就是使两个小车之间的连杆距离保持不变。
五、一个循环
while True:
power_4 = power_5-8 #34
power_3 = power_4-4 #30
power_2 = lim(10) #20
power_1 = power_2-4 #16
power_0 = power_1-8 #8
power_6 = power_2-8 #12
power_7 = power_5-4 #38
#建立一个背景画布
canvas = np.ones((600,800,3),dtype = 'uint8') #dtype选择 uint8 是为了方便显示图像(0-255)
canvas = canvas*255
#画一条红色直线
red = (0,0,255) #opencv 里面是BGR顺序,不同于常见的RGB顺序
cv2.line(canvas,(0,400),(50,400),red)
#画圆
black = (0,0,0)
(center0_x,center0_y) = (50,0)
cv2.ellipse(canvas,(center0_x,center0_y),(400,400),0,60,90,black)
#画直线
cv2.line(canvas,(250,math.floor(200*(3**0.5))),(350,math.floor(500*(3**0.5)/3)),red)
#画圆
cv2.ellipse(canvas,(550,math.floor(1100*(3**0.5)/3)),(400,400),0,240,270,black)
#画直线
cv2.line(canvas,(550,math.floor(1100*(3**0.5)/3)-400),(650,math.floor(1100*(3**0.5)/3)-400),red)
g = (0,255,0)
b_g = (255,255,0)
#画移动的圆心
cv2.circle(canvas,(power_0,func_2(power_0)),1,g,-1)
cv2.circle(canvas,(power_1,func_2(power_1)),1,g,-1)
cv2.circle(canvas,(power_2,func_2(power_2)),1,g,-1)
cv2.circle(canvas,(power_3,func_2(power_3)),1,g,-1)
cv2.circle(canvas,(power_4,func_2(power_4)),1,g,-1)
cv2.circle(canvas,(power_5,func_2(power_5)),1,g,-1)
#画移动的杆
cv2.line(canvas,(power_2,func_2(power_2)),(power_3,func_2(power_3)),b_g,2)
#画移动的矩形
draw(canvas,(power_6,func_2(power_6),func_angle(power_6),10,20))
draw(canvas,(power_7,func_2(power_7),func_angle(power_7),10,20))
cv2.imshow('train_game',canvas)
power_5 += 1
key = cv2.waitKey(40)
if key == ord('1'):
break
cv2.destroyAllWindows()
#cv2.imwrite('C:\\users\\lenovo\\csdn_dl\\test.png',canvas)
这一部分利用opencv自带的包,通过不断的调用函数,将坐标点导入画弧、直线等方法中。
power_0 power_1 … power_5 代表小车的车轮以及车钩。
power_6 power_7 代表小车的中心。
需要注意的是,opencv中画图的方法需要一个整型,因此函数算出来的坐标都是经过不断向下取整。最后实现起来并不是特别平滑。
以下附上总代码
#导入相关的包
import numpy as np
import cv2
import math
power_5 = 42
#定义坐标点函数
def func_2(x):
if x>0 and x<=50:
y = 400
elif x>50 and x<=250:
y = math.ceil((400**2-(x-50)**2)**0.5)
elif x>250 and x<=350:
y = math.floor(-((3**0.5)*x)/3+850*(3**0.5)/3)
elif x>350 and x<=550:
y = math.floor(-(400**2-(x-550)**2)**0.5+1100*(3**0.5)/3)
else:
y = math.floor(1100*(3**0.5)/3-400)
return y
#定义坐标点函数
def func_0(x):
interval0 = 1 if x>0 and x<=50 else 0
interval1 = 1 if x>50 and x<250 else 0
interval2 = 1 if x == 250 else 0
interval3 = 1 if x>250 and x<=450 else 0
interval4 = 1 if x>450 and x<=500 else 0
#y = 500*interval0 + 400*interval1 + 300*interval2 + 200*interval3 + 100*interval4
y =500*interval0 + ((200**2-(x-50)**2)**0.5+300)*interval1 +300*interval2 + (-(200**2-(x-450)**2)**0.5+250)*interval3 + 50*interval4
return y
#定义一个画可旋转矩形的方法
def draw(canvas,result):
result=np.array(result)
x = result[0]
y = result[1]
angle = result[2]
height = result[3]
width = result[4]
angle_Pi = -angle*math.pi/180.0 #转化为弧度
cosA = math.cos(angle_Pi)
sinA = math.sin(angle_Pi)
x1 = x-0.5*width
y1 = y-0.5*height
x0 = x+0.5*width
y0 = y1
x2 = x1
y2 = y+0.5*height
x3=x0
y3=y2
x0n = math.floor((x0 - x)*cosA - (y0 - y)*sinA + x)
y0n = math.floor((x0 - x)*sinA + (y0 - y)*cosA + y)
x1n = math.floor((x1 - x)*cosA - (y1 - y)*sinA + x)
y1n = math.floor((x1 - x)*sinA + (y1 - y)*cosA + y)
x2n = math.floor((x2 - x)*cosA - (y2 - y)*sinA + x)
y2n = math.floor((x2 - x)*sinA + (y2 - y)*cosA + y)
x3n = math.floor((x3 - x)*cosA - (y3 - y)*sinA + x)
y3n = math.floor((x3 - x)*sinA + (y3 - y)*cosA + y)
cv2.line(canvas,(x0n, y0n),(x1n, y1n), (255, 0, 0))
cv2.line(canvas,(x1n, y1n),(x2n, y2n), (255, 0, 0))
cv2.line(canvas,(x2n, y2n),(x3n, y3n), (255, 0, 0))
cv2.line(canvas,(x0n, y0n),(x3n, y3n), (255, 0, 0))
#定义角度
def func_angle(x):
if x >0 and x<=50:
ang = 0
elif x>50 and x<=250:
ang = -math.floor(math.atan(((400**2-(x-50)**2)**0.5-(400**2-(x-1-50)**2)**0.5))*180/math.pi)
elif x>=250 and x<=350:
ang = 30
elif x>350 and x<=550:
ang = -math.floor(math.atan((-(400**2-(x-550)**2)**0.5+1100*(3**0.5)/3)-(-(400**2-(x-1-550)**2)**0.5+1100*(3**0.5)/3))*180/math.pi)
else:
ang = 0
return ang
def lim(distance):#约束项
x = 0
for i in range(8,830):
if (power_3-i)**2 + (func_2(power_3)-func_2(i))**2 <= (distance+1)**2 and (power_3-i)**2 + (func_2(power_3)-func_2(i))**2 >= (distance-1)**2:
if i < power_3 and i >= power_3 - 11:
x = i
return x
while True:
power_4 = power_5-8 #34
power_3 = power_4-4 #30
power_2 = lim(10) #20
power_1 = power_2-4 #16
power_0 = power_1-8 #8
power_6 = power_2-8 #12
power_7 = power_5-4 #38
#建立一个背景画布
canvas = np.ones((600,800,3),dtype = 'uint8') #dtype选择 uint8 是为了方便显示图像(0-255)
canvas = canvas*255
#画一条红色直线
red = (0,0,255) #opencv 里面是BGR顺序,不同于常见的RGB顺序
cv2.line(canvas,(0,400),(50,400),red)
#画圆
black = (0,0,0)
(center0_x,center0_y) = (50,0)
cv2.ellipse(canvas,(center0_x,center0_y),(400,400),0,60,90,black)
#画直线
cv2.line(canvas,(250,math.floor(200*(3**0.5))),(350,math.floor(500*(3**0.5)/3)),red)
#画圆
cv2.ellipse(canvas,(550,math.floor(1100*(3**0.5)/3)),(400,400),0,240,270,black)
#画直线
cv2.line(canvas,(550,math.floor(1100*(3**0.5)/3)-400),(650,math.floor(1100*(3**0.5)/3)-400),red)
g = (0,255,0)
b_g = (255,255,0)
#画移动的圆心
cv2.circle(canvas,(power_0,func_2(power_0)),1,g,-1)
cv2.circle(canvas,(power_1,func_2(power_1)),1,g,-1)
cv2.circle(canvas,(power_2,func_2(power_2)),1,g,-1)
cv2.circle(canvas,(power_3,func_2(power_3)),1,g,-1)
cv2.circle(canvas,(power_4,func_2(power_4)),1,g,-1)
cv2.circle(canvas,(power_5,func_2(power_5)),1,g,-1)
#画移动的杆
cv2.line(canvas,(power_2,func_2(power_2)),(power_3,func_2(power_3)),b_g,2)
#画移动的矩形
draw(canvas,(power_6,func_2(power_6),func_angle(power_6),10,20))
draw(canvas,(power_7,func_2(power_7),func_angle(power_7),10,20))
cv2.imshow('train_game',canvas)
power_5 += 1
key = cv2.waitKey(40)
if key == ord('1'):
break
cv2.destroyAllWindows()
#cv2.imwrite('C:\\users\\lenovo\\csdn_dl\\test.png',canvas)
以下效果图