70 MSP_CMD_PREAMBLE = MSP_PREAMBLE + MSP_DIR_TO
71 MSP_RSP_PREAMBLE = MSP_PREAMBLE + MSP_DIR_FROM
78 MSP_CMD_HDR_LEN = len(MSP_CMD_PREAMBLE) + 2
81 MSP_CMD_MIN_LEN = MSP_CMD_HDR_LEN + 1
84 MSP_RSP_HDR_LEN = len(MSP_RSP_PREAMBLE) + 2
87 MSP_RSP_MIN_LEN = MSP_RSP_HDR_LEN + 1
109 DEG_TO_RAD = math.pi / 180.0
111 MSP_ACCEL_RAW_TO_G = 1.0 / 512.0
112 MSP_GYRO_RAW_TO_DEG_PER_S = 1.0 / 4.096
113 MSP_ATTITUDE_RAW_TO_DEG = 0.1
117 UNITS_M_PER_S2 =
'm/s^2' 118 UNITS_DEG_PER_S =
'deg/s' 119 UNITS_RAD_PER_S =
'rad/s' 120 UNITS_DEG =
'degrees' 121 UNITS_RAD =
'radians' 143 return "ImuException(%s)" % (repr(self.
message))
170 def open(self, device, baudrate):
173 devName = os.readlink(device)
174 dirName = os.path.dirname(device)
175 dev = os.path.join(dirName, devName)
179 self.
m_port = serial.Serial(dev, baudrate=baudrate, timeout=0.5)
180 except serial.SerialException
as inst:
182 self.m_port.flushInput()
183 self.m_port.flushOutput()
197 return self.m_port.isOpen()
206 lenData = len(cmdData)
209 for b
in MSP_CMD_PREAMBLE:
212 cmdBuf += chr(lenData)
223 cmdBuf += chr(chksum)
225 self.m_port.write(cmdBuf)
234 rspLen = MSP_RSP_HDR_LEN + lenData + 1
235 rspBuf = self.m_port.read(rspLen)
240 if msgLen < MSP_RSP_MIN_LEN:
242 "Only %d bytes received." % (msgLen))
244 fldSize = ord(rspBuf[MSP_POS_SIZE])
245 if fldSize != lenData:
247 "Received %d bytes, expected %d bytes." % (fldSize, lenData))
249 fldCmdId = ord(rspBuf[MSP_POS_CMD_ID])
250 if fldCmdId != cmdId:
252 "Received %d, expected %d." % (fldCmdId, cmdId))
255 for b
in rspBuf[MSP_POS_CMD_ID:-1]:
259 fldChkSum = ord(rspBuf[-1])
261 if chksum != fldChkSum:
263 "Received 0x%02x, calculated 0x%02x." % (fldChkSum, chksum))
266 return rspBuf[MSP_POS_DATA:-1]
278 return struct.pack(
'<B', val)
288 return struct.pack(
'<b', val)
298 return struct.pack(
'<H', val)
308 return struct.pack(
'<h', val)
318 return struct.pack(
'<I', val)
328 return struct.pack(
'<i', val)
338 return struct.unpack(
'<B', buf)[0]
348 return struct.unpack(
'<b', buf)[0]
358 return struct.unpack(
'<H', buf)[0]
368 return struct.unpack(
'<h', buf)[0]
378 return struct.unpack(
'<I', buf)[0]
388 return struct.unpack(
'<i', buf)[0]
396 multiType = self.
unpackU8(rspData[1])
397 mspVersion = self.
unpackU8(rspData[2])
400 return {
'version':version,
'multi_type':multiType,
401 'msp_version':mspVersion,
'caps':caps}
403 def readRawImu(self, accel_units='raw', gyro_units='raw', mag_units='raw'):
404 accel = NUM_AXES * [0]
405 gyro = NUM_AXES * [0]
424 if accel_units == UNITS_G:
425 accel[X] *= MSP_ACCEL_RAW_TO_G
426 accel[Y] *= MSP_ACCEL_RAW_TO_G
427 accel[Z] *= MSP_ACCEL_RAW_TO_G
428 elif accel_units
in [UNITS_M_PER_S2, UNITS_SI]:
429 accel[X] = accel[X] * MSP_ACCEL_RAW_TO_G * G
430 accel[Y] = accel[Y] * MSP_ACCEL_RAW_TO_G * G
431 accel[Z] = accel[Z] * MSP_ACCEL_RAW_TO_G * G
433 if gyro_units == UNITS_DEG_PER_S:
434 gyro[X] *= MSP_GYRO_RAW_TO_DEG_PER_S
435 gyro[Y] *= MSP_GYRO_RAW_TO_DEG_PER_S
436 gyro[Z] *= MSP_GYRO_RAW_TO_DEG_PER_S
437 elif gyro_units
in [UNITS_RAD_PER_S, UNITS_SI]:
438 gyro[X] = gyro[X] * MSP_GYRO_RAW_TO_DEG_PER_S * DEG_TO_RAD
439 gyro[Y] = gyro[Y] * MSP_GYRO_RAW_TO_DEG_PER_S * DEG_TO_RAD
440 gyro[Z] = gyro[Z] * MSP_GYRO_RAW_TO_DEG_PER_S * DEG_TO_RAD
442 return {
'accel':accel,
'gyro':gyro,
'mag':mag}
444 def readAttitude(self, units='raw'):
454 if units == UNITS_DEG:
455 roll *= MSP_ATTITUDE_RAW_TO_DEG
456 pitch *= MSP_ATTITUDE_RAW_TO_DEG
457 elif units
in [UNITS_RAD, UNITS_SI]:
458 roll = roll * MSP_ATTITUDE_RAW_TO_DEG * DEG_TO_RAD
459 pitch = pitch * MSP_ATTITUDE_RAW_TO_DEG * DEG_TO_RAD
460 yaw = yaw * DEG_TO_RAD
462 return (roll, pitch, yaw)
468 if __name__ ==
'__main__':
469 print "IMU Unit Test Example" 472 device =
"/dev/ttyUSB0" 475 print "Get raw IMU data:" 479 imu.open(device, baudrate=baud)
481 ident = imu.readIdent()
483 print "IMU Identity:" 484 print " Version: %u" % (ident[
'version'])
485 print " Multi-Type: %u" % (ident[
'multi_type'])
486 print " MSP Version: %u" % (ident[
'msp_version'])
487 print " Caps: 0x%04x" % (ident[
'caps'])
490 meas = imu.readRawImu()
492 print "accel_raw(x,y,z) = %6d, %6d, %6d" % \
493 (meas[
'accel'][X], meas[
'accel'][Y], meas[
'accel'][Z])
494 print "gyro_raw(x,y,z) = %6d, %6d, %6d" % \
495 (meas[
'gyro'][X], meas[
'gyro'][Y], meas[
'gyro'][Z])
497 meas = imu.readRawImu(
'g',
'deg/s')
499 print "accel_g(x,y,z) = %.3f, %.3f, %.3f" % \
500 (meas[
'accel'][X], meas[
'accel'][Y], meas[
'accel'][Z])
501 print "gyro_dps(x,y,z) = %.3f, %.3f, %.3f" % \
502 (meas[
'gyro'][X], meas[
'gyro'][Y], meas[
'gyro'][Z])
504 rpy = imu.readAttitude(
'degrees')
505 print "roll,pitch,yaw = %.3f, %.3f, %.3f" % \
506 (rpy[ROLL], rpy[PITCH], rpy[YAW])
510 except KeyboardInterrupt:
def __init__(self)
Constructor.
def packS8(self, val)
Pack a signed 8-bit value.
def unpackS16(self, buf)
Unpack a signed 16-bit value from buffer.
def unpackS32(self, buf)
Unpack a signed 32-bit value from buffer.
def unpackU16(self, buf)
Unpack an unsigned 16-bit value from buffer.
def packU16(self, val)
Pack an unsigned 16-bit value.
def close(self)
Close connection with IMU.
def packS16(self, val)
Pack a signed 16-bit value.
def isOpen(self)
Check if connecton is open.
def unpackU32(self, buf)
Unpack an unsigned 32-bit value from buffer.
def packU8(self, val)
Pack an unsigned 8-bit value.
def unpackU8(self, buf)
Unpack an unsigned 8-bit value from buffer.
def packS32(self, val)
Pack a signed 32-bit value.
def sendCmd(self, cmdId, cmdData="")
Send command.
def packU32(self, val)
Pack an unsigned 32-bit value.
message
error message attribute
def receiveRsp(self, cmdId, lenData=0)
Receive response.
def unpackS8(self, buf)
Unpack a signed 8-bit value from buffer.
international system of units (m, s, radians, m/s, m/s^2, radians/s)
def open(self, device, baudrate)
Open connection to IMU.
def __init__(self, msg)
Constructor.