通过python语言来实现一个freeD协议的简单实现,在示例中角度参数都采用的角度制(单位:度),位置坐标位右手坐标系(单位:毫米mm),摄像机的推拉聚焦采用的是采用的百分比(范围:[0~1]),依据实际取样点的个数不同,最好精确到千分位,可以在函数中自己定义实际的取样点数。
def generateZoom(perzvalue,rvalue = 13765):
def generateFocus(perfvalue,rvalue = 18723):
示例中的取样点为13765 和 18723。
示例中的最终传送数据为文本Bytes型,如果实际需要,可以将结果转换为对应的ASCII码,进行二进制传输【 strshexToChrs(strs_hex) 】,直接调用转换函数即可。
示例依据国内的PAL制式,将流模式的30帧/秒,改为了50帧/秒【 Delayms(20) 】。
所有数据的采集来自以Excel表格,数据顺序为'pan','tile','roll','x','y','z','zoom','focus'。后续将会用脚本语言实现一个数据自动生成工具。
数据的接收端实现:
import serial
com_rec = serial.Serial("COM2",38400)
for i in range(1000):
com_rec.read(58)
com_rec.flushInput()
暂定接收十秒的数据数据发送端:
def generatePan(panvalue):
pan = float(panvalue)
#if the value of pan NOT in range [-180~180]
while abs(pan) > 180:
if pan < -180:
pan += 360
else:
pan -= 360
return angleToByte(pan)
def generateTile(tilevalue):
tile = float(tilevalue)
#tile in [-90~90],now it's not a perfect solution
while abs(tile) > 90:
if tile < -90:
tile += 180
else:
tile -= 180
return angleToByte(tile)
def generateRoll(rollvalue):
return generatePan(rollvalue)
def angleToByte(anglevalue):
value = float(anglevalue)
#to binary two's complement
vbinary = bin(int(value*32768) & 0xffffff)[2:]
#to hex
res = hex(int(vbinary,2))[2:]
res = "{:0>6}".format(res)
return res
def posToByte(posvalue):
value = float(posvalue)
#to binary two's complement
vbinary = bin(int(value*64) & 0xffffff)[2:]
#to hex
res = hex(int(vbinary,2))[2:]
res = "{:0>6}".format(res)
return res
def generatePos(pos_axis):
axis = float(pos_axis)
#if the value of position NOT in range (-131072~131072)mm
while abs(axis) > 131072:
if axis < -90:
axis = -131072
else:
axis = 131072
return posToByte(axis)
def generateCoordiante(poslist):
pos_res = ""
print(poslist)
if len(poslist) != 3:
print("position argument error.")
for i in poslist:
print(i)
pos_res += str(generatePos(i))
print(pos_res)
return pos_res
def intToByte(intvalue):
value = int(intvalue)
#to binary two's complement
vbinary = bin(value & 0xffffff)[2:]
#to hex
res = hex(int(vbinary,2))[2:]
res = "{:0>6}".format(res)
return res
# perfvalue is the range of focus [0~1]
# rvalue is max sample point of focus
def generateFocus(perfvalue,rvalue = 18723):
fvalue = perfvalue * rvalue
return intToByte(fvalue)
# perzvalue is the range of zoom [0~1]
# rvalue is max sample point of zoom
def generateZoom(perzvalue,rvalue = 13765):
zvalue = perzvalue * rvalue
return intToByte(zvalue)
# input:the string of all protocal info NOT include checksum
def generateCheckSum(proto_info):
prstr = proto_info
res = int('40',16)
for i in range(0,len(prstr),2):
subtrack_num = prstr[i:i+2]
res -= int(subtrack_num,16)
res %= 256
res = hex(res)[2:]
return res
def Delayms(delaytime):
delayT = int(delaytime)
startT = time.perf_counter() * 1000
while True:
offset = int(time.perf_counter() * 1000 - startT)
if offset >= delayT:
break
def hexascToChr(str_hex):
numDec = int(str(str_hex),16)
return chr(numDec)
def strshexToChrs(strs_hex):
res = []
for i in range(0,len(strs_hex),2):
str = strs_hex[i:i+2]
res.append(hexascToChr(str))
return ''.join(res)
if __name__ =='__main__':
import time
import xlrd
import serial
data = xlrd.open_workbook_xls(r'***\axis_data.xls')
table = data.sheets()[0]
com = serial.Serial("COM1",38400)
start_time = time.time()
for rown in range(table.nrows):
t1 = time.time()*1000000
#lcam = ['pan','tile','roll','x','y','z','zoom','focus']
lcam1 = []
for i in range(8):
lcam1.append(table.cell_value(rown,i))
prlist = ['d1','ff']
prlist.append(generatePan(lcam1[0]))
prlist.append(generateTile(lcam1[1]))
prlist.append(generateRoll(lcam1[2]))
prlist.append(generatePos(lcam1[3]))
prlist.append(generatePos(lcam1[4]))
prlist.append(generatePos(lcam1[5]))
prlist.append(generateZoom(lcam1[6]))
prlist.append(generateFocus(lcam1[7]))
prlist.append('0000')
prstr = "".join(prlist)
CKSum = generateCheckSum(prstr)
#print(CKSum)
prres = prstr + CKSum
t2 = time.time()*1000000
com.write(prres.encode())
print("transmit:",prres)
Delayms(20)