diff --git a/Hardware/UPbot-Tools/__pycache__/dataholder.cpython-37.pyc b/Hardware/UPbot-Tools/__pycache__/dataholder.cpython-37.pyc
new file mode 100644
index 0000000..56c3d17
Binary files /dev/null and b/Hardware/UPbot-Tools/__pycache__/dataholder.cpython-37.pyc differ
diff --git a/Hardware/UPbot-Tools/__pycache__/params.cpython-37.pyc b/Hardware/UPbot-Tools/__pycache__/params.cpython-37.pyc
new file mode 100644
index 0000000..b7bd56f
Binary files /dev/null and b/Hardware/UPbot-Tools/__pycache__/params.cpython-37.pyc differ
diff --git a/Hardware/UPbot-Tools/__pycache__/pb.cpython-37.pyc b/Hardware/UPbot-Tools/__pycache__/pb.cpython-37.pyc
new file mode 100644
index 0000000..dce2291
Binary files /dev/null and b/Hardware/UPbot-Tools/__pycache__/pb.cpython-37.pyc differ
diff --git a/Hardware/UPbot-Tools/__pycache__/transport.cpython-37.pyc b/Hardware/UPbot-Tools/__pycache__/transport.cpython-37.pyc
new file mode 100644
index 0000000..e4ea487
Binary files /dev/null and b/Hardware/UPbot-Tools/__pycache__/transport.cpython-37.pyc differ
diff --git a/Hardware/UPbot-Tools/app.py b/Hardware/UPbot-Tools/app.py
new file mode 100644
index 0000000..2e0aaac
--- /dev/null
+++ b/Hardware/UPbot-Tools/app.py
@@ -0,0 +1,434 @@
+# coding:utf-8
+
+import sys
+sys.path.append("..")
+from pypibot import log
+import pypibot
+
+import params
+import dataholder
+from dataholder import MessageID
+from transport import Transport
+from PyQt5.QtWidgets import QApplication, QDialog
+from PyQt5.QtCore import QObject,pyqtSignal
+import pb
+import threading
+
+port = "COM7"
+
+pypibot.assistant.enableGlobalExcept()
+# log.enableFileLog(log_dir + "ros_$(Date8)_$(filenumber2).log")
+log.setLevel("i")
+
+
+class MainDialog(QDialog):
+ encoder_signal = pyqtSignal(list)
+ imu_signal = pyqtSignal(list)
+ pid_debug_signal = pyqtSignal(list)
+
+ def __init__(self, parent=None):
+ super(QDialog, self).__init__(parent)
+ self.ui = pb.Ui_pb()
+ self.ui.setupUi(self)
+ self.model_type_list = {"2wd-diff": dataholder.RobotModelType.MODEL_TYPE_2WD_DIFF,
+ "4wd-diff": dataholder.RobotModelType.MODEL_TYPE_4WD_DIFF,
+ "3wd-omni": dataholder.RobotModelType.MODEL_TYPE_3WD_OMNI,
+ "4wd-omni": dataholder.RobotModelType.MODEL_TYPE_4WD_OMNI,
+ "4wd-mecanum": dataholder.RobotModelType.MODEL_TYPE_4WD_MECANUM}
+
+ self.model_value_list = {0: dataholder.RobotModelType.MODEL_TYPE_2WD_DIFF,
+ 1: dataholder.RobotModelType.MODEL_TYPE_4WD_DIFF,
+ 2: dataholder.RobotModelType.MODEL_TYPE_3WD_OMNI,
+ 3: dataholder.RobotModelType.MODEL_TYPE_4WD_OMNI,
+ 3: dataholder.RobotModelType.MODEL_TYPE_4WD_MECANUM}
+
+ self.model_index_list = {dataholder.RobotModelType.MODEL_TYPE_2WD_DIFF: 0,
+ dataholder.RobotModelType.MODEL_TYPE_4WD_DIFF: 1,
+ dataholder.RobotModelType.MODEL_TYPE_3WD_OMNI: 2,
+ dataholder.RobotModelType.MODEL_TYPE_4WD_OMNI: 3,
+ dataholder.RobotModelType.MODEL_TYPE_4WD_MECANUM: 4}
+
+ self.imu_type_list = {"gy65": 0, "gy85": 1, "gy87": 2}
+ self.imu_value_list = {49: "gy65", 69: "gy85", 71: "gy87"}
+ self.imu_index_list = {0: 49, 1: 69, 2: 71}
+
+ self.init_ui()
+ self.mboard = None
+
+ self.init_dev()
+
+ self.encoder_signal.connect(self.update_encoder)
+ self.imu_signal.connect(self.update_imu)
+ self.pid_debug_signal.connect(self.update_pid_debug)
+
+ self._KeepRunning = True
+ self.encoder_thread = threading.Thread(target=self._read_encoder)
+ self.encoder_thread.start()
+
+ def closeEvent(self, event):
+ self._KeepRunning = False
+
+ def init_ui(self):
+ for model_type in self.model_type_list.keys():
+ self.ui.combox_model.addItem(model_type)
+
+ for imu_type in self.imu_type_list.keys():
+ self.ui.combox_imu_type.addItem(imu_type)
+
+ self.ui.slider_wheel_diameter.setMinimum(10)
+ self.ui.slider_wheel_diameter.setMaximum(500)
+
+ self.ui.slider_wheel_track.setMinimum(50)
+ self.ui.slider_wheel_track.setMaximum(1000)
+
+ self.ui.slider_encoder.setMinimum(1)
+ self.ui.slider_encoder.setMaximum(500)
+
+ self.ui.slider_motor_ratio.setMinimum(1)
+ self.ui.slider_motor_ratio.setMaximum(1000)
+
+ self.ui.slider_pid_interval.setMinimum(1)
+ self.ui.slider_pid_interval.setMaximum(80)
+ self.ui.slider_kp.setMinimum(0)
+ self.ui.slider_kp.setMaximum(10000)
+ self.ui.slider_ki.setMinimum(0)
+ self.ui.slider_ki.setMaximum(32000)
+ self.ui.slider_kd.setMinimum(0)
+ self.ui.slider_kd.setMaximum(1000)
+ self.ui.slider_ko.setMinimum(0)
+ self.ui.slider_ko.setMaximum(1000)
+
+ self.ui.slider_cmd_lasttime.setMinimum(0)
+ self.ui.slider_cmd_lasttime.setMaximum(1000)
+ self.ui.slider_vx_max.setMinimum(0)
+ self.ui.slider_vx_max.setMaximum(500)
+ self.ui.slider_vy_max.setMinimum(0)
+ self.ui.slider_vy_max.setMaximum(500)
+ self.ui.slider_va_max.setMinimum(0)
+ self.ui.slider_va_max.setMaximum(2000)
+
+ self.ui.comboBox_support_model.setVisible(False)
+ self.ui.pushButton_load.setVisible(False)
+
+ self.ui.pushButton_read.clicked.connect(self.read_params)
+ self.ui.pushButton_set.clicked.connect(self.write_params)
+ self.ui.pushButton_start.clicked.connect(self.start_motor)
+ self.ui.pushButton_stop.clicked.connect(self.stop_motor)
+
+ self.ui.pushButton_start_2.clicked.connect(self.start_control)
+ self.ui.pushButton_stop_2.clicked.connect(self.stop_control)
+
+ self.ui.slider_set_pwm1.setMinimum(-5000)
+ self.ui.slider_set_pwm1.setMaximum(5000)
+ self.ui.slider_set_pwm2.setMinimum(-5000)
+ self.ui.slider_set_pwm2.setMaximum(5000)
+ self.ui.slider_set_pwm3.setMinimum(-5000)
+ self.ui.slider_set_pwm3.setMaximum(5000)
+ self.ui.slider_set_pwm4.setMinimum(-5000)
+ self.ui.slider_set_pwm4.setMaximum(5000)
+ self.ui.tabWidget.setTabText(0, '1.参数配置')
+ self.ui.tabWidget.setTabText(1, '2.电机测试')
+ self.ui.tabWidget.setCurrentIndex(0)
+
+ def update_param(self, param):
+ log.i("type:%d %d" % (param.model_type, param.imu_type))
+ try:
+ self.ui.combox_model.setCurrentIndex(self.model_index_list[param.model_type])
+ except Exception as e:
+ print("model type err")
+
+ try:
+ self.ui.combox_imu_type.setCurrentIndex(
+ self.imu_type_list[self.imu_value_list[param.imu_type]])
+ except Exception as e:
+ print("imu type err")
+
+ try:
+ self.ui.slider_wheel_diameter.setSliderPosition(
+ param.wheel_diameter)
+ self.ui.slider_wheel_track.setSliderPosition(param.wheel_track)
+ self.ui.slider_encoder.setSliderPosition(param.encoder_resolution)
+ self.ui.slider_motor_ratio.setSliderPosition(param.motor_ratio)
+
+ self.ui.checkBox_motor1.setChecked(
+ param.motor_nonexchange_flag & 0x1)
+ self.ui.checkBox_motor2.setChecked(
+ param.motor_nonexchange_flag & 0x2)
+ self.ui.checkBox_motor3.setChecked(
+ param.motor_nonexchange_flag & 0x4)
+ self.ui.checkBox_motor4.setChecked(
+ param.motor_nonexchange_flag & 0x8)
+
+ self.ui.checkBox_encoder1.setChecked(
+ param.encoder_nonexchange_flag & 0x1)
+ self.ui.checkBox_encoder2.setChecked(
+ param.encoder_nonexchange_flag & 0x2)
+ self.ui.checkBox_encoder3.setChecked(
+ param.encoder_nonexchange_flag & 0x4)
+ self.ui.checkBox_encoder4.setChecked(
+ param.encoder_nonexchange_flag & 0x8)
+ except Exception as e:
+ print("motor dir param err")
+
+ try:
+ self.ui.slider_cmd_lasttime.setSliderPosition(param.cmd_last_time)
+ self.ui.slider_vx_max.setSliderPosition(param.max_v_liner_x)
+ self.ui.slider_vy_max.setSliderPosition(param.max_v_liner_y)
+ self.ui.slider_va_max.setSliderPosition(param.max_v_angular_z)
+ except Exception as e:
+ print("pid param err")
+
+ try:
+ self.ui.slider_pid_interval.setSliderPosition(
+ param.do_pid_interval)
+ self.ui.slider_kp.setSliderPosition(param.kp)
+ self.ui.slider_ki.setSliderPosition(param.ki)
+ self.ui.slider_kd.setSliderPosition(param.kd)
+ self.ui.slider_ko.setSliderPosition(param.ko)
+ except Exception as e:
+ print("velocity limit param err")
+
+ def read_params(self):
+ # get robot parameter
+ robotParam = self.DataHolder[MessageID.ID_GET_ROBOT_PARAMETER]
+ p = self.mboard.request(MessageID.ID_GET_ROBOT_PARAMETER)
+ if p:
+ log.info("model_type:%d wheel_diameter:%d wheel_track:%d encoder_resolution:%d"
+ % (robotParam.param.model_type,
+ robotParam.param.wheel_diameter,
+ robotParam.param.wheel_track,
+ robotParam.param.encoder_resolution
+ ))
+
+ log.info("do_pid_interval:%d kp:%d ki:%d kd:%d ko:%d"
+ % (robotParam.param.do_pid_interval,
+ robotParam.param.kp,
+ robotParam.param.ki,
+ robotParam.param.kd,
+ robotParam.param.ko))
+
+ log.info("cmd_last_time:%d imu_type:%d"
+ % (robotParam.param.cmd_last_time,
+ robotParam.param.imu_type
+ ))
+
+ log.info("max_v:%d %d %d"
+ % (robotParam.param.max_v_liner_x,
+ robotParam.param.max_v_liner_y,
+ robotParam.param.max_v_angular_z
+ ))
+
+ log.info("motor flag:%d encoder flag: %d"
+ % (robotParam.param.motor_nonexchange_flag,
+ robotParam.param.encoder_nonexchange_flag
+ ))
+ else:
+ log.error('get params err')
+ return False
+
+ self.update_param(robotParam.param)
+
+ def get_input_param(self):
+ params = dataholder.RobotParameters()
+
+ params.wheel_diameter = self.ui.slider_wheel_diameter.sliderPosition()
+ params.wheel_track = self.ui.slider_wheel_track.sliderPosition()
+ params.encoder_resolution = self.ui.slider_encoder.sliderPosition()
+ params.do_pid_interval = self.ui.slider_pid_interval.sliderPosition()
+ params.kp = self.ui.slider_kp.sliderPosition()
+ params.ki = self.ui.slider_ki.sliderPosition()
+ params.kd = self.ui.slider_kd.sliderPosition()
+ params.ko = self.ui.slider_ko.sliderPosition()
+ params.cmd_last_time = self.ui.slider_cmd_lasttime.sliderPosition()
+ params.max_v_liner_x = self.ui.slider_vx_max.sliderPosition()
+ params.max_v_liner_y = self.ui.slider_vy_max.sliderPosition()
+ params.max_v_angular_z = self.ui.slider_va_max.sliderPosition()
+ params.motor_ratio = self.ui.slider_motor_ratio.sliderPosition()
+ params.imu_type = self.imu_index_list[self.ui.combox_imu_type.currentIndex(
+ )]
+
+ params.model_type = self.model_value_list[self.ui.combox_model.currentIndex()]
+
+ params.motor_nonexchange_flag = 0
+
+ if self.ui.checkBox_motor1.isChecked():
+ params.motor_nonexchange_flag = params.motor_nonexchange_flag | 0x1
+ else:
+ params.motor_nonexchange_flag = params.motor_nonexchange_flag & 0xfe
+
+ if self.ui.checkBox_motor2.isChecked():
+ params.motor_nonexchange_flag = params.motor_nonexchange_flag | 0x2
+ else:
+ params.motor_nonexchange_flag = params.motor_nonexchange_flag & 0xfd
+
+ if self.ui.checkBox_motor3.isChecked():
+ params.motor_nonexchange_flag = params.motor_nonexchange_flag | 0x4
+ else:
+ params.motor_nonexchange_flag = params.motor_nonexchange_flag & 0xfb
+
+ if self.ui.checkBox_motor4.isChecked():
+ params.motor_nonexchange_flag = params.motor_nonexchange_flag | 0x8
+ else:
+ params.motor_nonexchange_flag = params.motor_nonexchange_flag & 0xf7
+
+ params.encoder_nonexchange_flag = 0
+
+ if self.ui.checkBox_encoder1.isChecked():
+ params.encoder_nonexchange_flag = params.encoder_nonexchange_flag | 0x1
+ else:
+ params.encoder_nonexchange_flag = params.encoder_nonexchange_flag & 0xfe
+
+ if self.ui.checkBox_encoder2.isChecked():
+ params.encoder_nonexchange_flag = params.encoder_nonexchange_flag | 0x2
+ else:
+ params.encoder_nonexchange_flag = params.encoder_nonexchange_flag & 0xfd
+
+ if self.ui.checkBox_encoder3.isChecked():
+ params.encoder_nonexchange_flag = params.encoder_nonexchange_flag | 0x4
+ else:
+ params.encoder_nonexchange_flag = params.encoder_nonexchange_flag & 0xfb
+
+ if self.ui.checkBox_encoder4.isChecked():
+ params.encoder_nonexchange_flag = params.encoder_nonexchange_flag | 0x8
+ else:
+ params.encoder_nonexchange_flag = params.encoder_nonexchange_flag & 0xf7
+
+ return params
+
+ def write_params(self):
+ self.DataHolder[MessageID.ID_SET_ROBOT_PARAMETER].param = self.get_input_param()
+ p = self.mboard.request(MessageID.ID_SET_ROBOT_PARAMETER)
+ if p:
+ log.info('set parameter success')
+ else:
+ log.error('set parameter err')
+ quit(1)
+
+ def update_pid_debug(self, pid_data):
+ self.ui.label_input_1.setText(str(pid_data[0]))
+ self.ui.label_input_2.setText(str(pid_data[1]))
+ self.ui.label_input_3.setText(str(pid_data[2]))
+ self.ui.label_input_4.setText(str(pid_data[3]))
+ self.ui.label_output_1.setText(str(pid_data[4]))
+ self.ui.label_output_2.setText(str(pid_data[5]))
+ self.ui.label_output_3.setText(str(pid_data[6]))
+ self.ui.label_output_4.setText(str(pid_data[7]))
+
+ def update_imu(self, imu):
+ #log.info('imu: %s'%(('\t\t').join([str(x) for x in imu])))
+ self.ui.label_acc_x.setText(str(round(imu[0], 6)))
+ self.ui.label_acc_y.setText(str(round(imu[1], 6)))
+ self.ui.label_acc_z.setText(str(round(imu[2], 6)))
+ self.ui.label_gyro_x.setText(str(round(imu[3], 6)))
+ self.ui.label_gyro_y.setText(str(round(imu[4], 6)))
+ self.ui.label_gyro_z.setText(str(round(imu[5], 6)))
+ self.ui.label_magn_x.setText(str(round(imu[6], 6)))
+ self.ui.label_magn_y.setText(str(round(imu[7], 6)))
+ self.ui.label_magn_z.setText(str(round(imu[8], 6)))
+
+ def update_encoder(self, encoder):
+ log.debug('encoder count: %s'%(('\t\t').join([str(x) for x in encoder])))
+ self.ui.label_feedback1.setText(str(encoder[0]))
+ self.ui.label_feedback2.setText(str(encoder[1]))
+ self.ui.label_feedback3.setText(str(encoder[2]))
+ self.ui.label_feedback4.setText(str(encoder[3]))
+
+
+ def _read_encoder(self):
+ while self._KeepRunning:
+ robot_encoder = self.DataHolder[MessageID.ID_GET_ENCODER_COUNT].encoder
+ p = self.mboard.request(MessageID.ID_GET_ENCODER_COUNT)
+ if p:
+ # log.info('encoder count: %s'%(('\t\t').join([str(x) for x in robot_encoder])))
+ self.encoder_signal.emit([int(x) for x in robot_encoder])
+
+ robot_imu = self.DataHolder[MessageID.ID_GET_IMU].imu
+ p = self.mboard.request(MessageID.ID_GET_IMU)
+ if p:
+ # log.info('imu: %s'%(('\t\t').join([str(x) for x in robot_imu])))
+ self.imu_signal.emit([x for x in robot_imu])
+
+ pid_data = self.DataHolder[MessageID.ID_GET_PID_DEBUG].pid_data
+ p = self.mboard.request(MessageID.ID_GET_PID_DEBUG)
+ if p:
+ # log.info('imu: %s'%(('\t\t').join([str(x) for x in robot_imu])))
+ self.pid_debug_signal.emit([x for x in pid_data])
+ import time
+ time.sleep(0.1)
+
+ def start_motor(self):
+ self.DataHolder[MessageID.ID_SET_MOTOR_PWM].pwm = [self.ui.slider_set_pwm1.sliderPosition(),
+ self.ui.slider_set_pwm2.sliderPosition(),
+ self.ui.slider_set_pwm3.sliderPosition(),
+ self.ui.slider_set_pwm4.sliderPosition()]
+ p = self.mboard.request(MessageID.ID_SET_MOTOR_PWM)
+ if p:
+ log.info('set pwm success')
+ else:
+ log.error('set pwm err')
+
+ def stop_motor(self):
+ self.DataHolder[MessageID.ID_SET_MOTOR_PWM].pwm = [0]*4
+ p = self.mboard.request(MessageID.ID_SET_MOTOR_PWM)
+ if p:
+ log.info('set pwm success')
+ else:
+ log.error('set pwm err')
+
+ def start_control(self):
+ self.DataHolder[MessageID.ID_SET_VEL].v_liner_x = 200
+ self.DataHolder[MessageID.ID_SET_VEL].v_liner_y = 0
+ self.DataHolder[MessageID.ID_SET_VEL].v_angular_z = 10
+ p = self.mboard.request(MessageID.ID_SET_VEL)
+ if p:
+ log.info('set vel success')
+ else:
+ log.error('set vel err')
+
+ def stop_control(self):
+ self.DataHolder[MessageID.ID_SET_VEL].v_liner_x = 0
+ self.DataHolder[MessageID.ID_SET_VEL].v_liner_y = 0
+ self.DataHolder[MessageID.ID_SET_VEL].v_angular_z = 0
+ p = self.mboard.request(MessageID.ID_SET_VEL)
+ if p:
+ log.info('set vel success')
+ else:
+ log.error('set vel err')
+
+ def init_dev(self):
+ self.mboard = Transport(port, params.pibotBaud)
+ if not self.mboard.start():
+ log.error("can not open %s" % port)
+ return False
+
+ self.DataHolder = self.mboard.getDataHolder()
+
+ for num in range(0, 3):
+ log.info("****************get robot version*****************")
+ boardVersion = self.DataHolder[MessageID.ID_GET_VERSION]
+ p = self.mboard.request(MessageID.ID_GET_VERSION)
+ if p:
+ log.info("firmware version:%s buildtime:%s" % (
+ boardVersion.version.decode(), boardVersion.build_time.decode()))
+ break
+ else:
+ log.error('read firmware version err')
+ import time
+ time.sleep(1)
+ if num == 2:
+ log.error('please check connection or baudrate')
+ return False
+
+ return self.read_params()
+
+if __name__ == '__main__':
+ app = QApplication(sys.argv)
+
+ import qdarkstyle
+ app.setStyleSheet(qdarkstyle.load_stylesheet(qt_api='pyqt5'))
+
+ # from qt_material import apply_stylesheet
+ # apply_stylesheet(app, theme='light_teal.xml')
+ myDlg = MainDialog()
+ myDlg.show()
+ sys.exit(app.exec_())
diff --git a/Hardware/UPbot-Tools/dataholder.py b/Hardware/UPbot-Tools/dataholder.py
new file mode 100644
index 0000000..a9e80c5
--- /dev/null
+++ b/Hardware/UPbot-Tools/dataholder.py
@@ -0,0 +1,250 @@
+import struct
+
+params_size=29
+
+# main board
+class MessageID:
+ ID_GET_VERSION = 0
+ ID_SET_ROBOT_PARAMETER = 1
+ ID_GET_ROBOT_PARAMETER = 2
+ ID_INIT_ODOM = 3
+ ID_SET_VEL = 4
+ ID_GET_ODOM = 5
+ ID_GET_PID_DEBUG = 6
+ ID_GET_IMU = 7
+ ID_GET_ENCODER_COUNT = 8
+ ID_SET_MOTOR_PWM = 9
+
+class RobotMessage:
+ def pack(self):
+ return b''
+
+ def unpack(self):
+ return True
+
+class RobotFirmwareInfo(RobotMessage):
+ def __init__(self):
+ self.version = ''
+ self.build_time = ''
+
+ def unpack(self, data):
+ try:
+ upk = struct.unpack('16s16s', bytes(data))
+ except:
+ return False
+ [self.version, self.build_time] = upk
+ return True
+
+class RobotImuType:
+ IMU_TYPE_GY65 = 49
+ IMU_TYPE_GY85 = 69
+ IMU_TYPE_GY87 = 71
+
+class RobotModelType:
+ MODEL_TYPE_2WD_DIFF = 1
+ MODEL_TYPE_4WD_DIFF = 2
+ MODEL_TYPE_3WD_OMNI = 101
+ MODEL_TYPE_4WD_OMNI = 102
+ MODEL_TYPE_4WD_MECANUM = 201
+
+class RobotParameters():
+ def __init__(self, wheel_diameter=0, \
+ wheel_track=0, \
+ encoder_resolution=0, \
+ do_pid_interval=0, \
+ kp=0, \
+ ki=0, \
+ kd=0, \
+ ko=0, \
+ cmd_last_time=0, \
+ max_v_liner_x=0, \
+ max_v_liner_y=0, \
+ max_v_angular_z=0, \
+ imu_type=0, \
+ motor_ratio=0, \
+ model_type=0, \
+ motor_nonexchange_flag=255, \
+ encoder_nonexchange_flag=255, \
+ ):
+ self.wheel_diameter = wheel_diameter
+ self.wheel_track = wheel_track
+ self.encoder_resolution = encoder_resolution
+ self.do_pid_interval = do_pid_interval
+ self.kp = kp
+ self.ki = ki
+ self.kd = kd
+ self.ko = ko
+ self.cmd_last_time = cmd_last_time
+ self.max_v_liner_x = max_v_liner_x
+ self.max_v_liner_y = max_v_liner_y
+ self.max_v_angular_z = max_v_angular_z
+ self.imu_type = imu_type
+ self.motor_ratio = motor_ratio
+ self.model_type = model_type
+ self.motor_nonexchange_flag = motor_nonexchange_flag
+ self.encoder_nonexchange_flag = encoder_nonexchange_flag
+ reserve=b'\xff'
+ self.reserve=b''
+ for i in range(64-params_size):
+ self.reserve+=reserve
+robotParam = RobotParameters()
+
+class GetRobotParameters(RobotMessage):
+ def __init__(self):
+ self.param = robotParam
+
+ def unpack(self, data):
+ #print(bytes(data), len(bytes(data)))
+ upk = struct.unpack('<3H1B8H1B1H3B%ds'%(64-params_size), bytes(data))
+
+ [self.param.wheel_diameter,
+ self.param.wheel_track,
+ self.param.encoder_resolution,
+ self.param.do_pid_interval,
+ self.param.kp,
+ self.param.ki,
+ self.param.kd,
+ self.param.ko,
+ self.param.cmd_last_time,
+ self.param.max_v_liner_x,
+ self.param.max_v_liner_y,
+ self.param.max_v_angular_z,
+ self.param.imu_type,
+ self.param.motor_ratio,
+ self.param.model_type,
+ self.param.motor_nonexchange_flag,
+ self.param.encoder_nonexchange_flag,
+ self.param.reserve] = upk
+ return True
+
+class SetRobotParameters(RobotMessage):
+ def __init__(self):
+ self.param = robotParam
+
+ def pack(self):
+ data = [self.param.wheel_diameter,
+ self.param.wheel_track,
+ self.param.encoder_resolution,
+ self.param.do_pid_interval,
+ self.param.kp,
+ self.param.ki,
+ self.param.kd,
+ self.param.ko,
+ self.param.cmd_last_time,
+ self.param.max_v_liner_x,
+ self.param.max_v_liner_y,
+ self.param.max_v_angular_z,
+ self.param.imu_type,
+ self.param.motor_ratio,
+ self.param.model_type,
+ self.param.motor_nonexchange_flag,
+ self.param.encoder_nonexchange_flag,
+ self.param.reserve]
+
+ print(data)
+ pk = struct.pack('<3H1B8H1B1H3B%ds'%(64-(3*2+1+8*2+1+2+3)), *data)
+ return pk
+
+ def unpack(self, data):
+ return True
+
+class RobotVel(RobotMessage):
+ def __init__(self):
+ self.v_liner_x = 0
+ self.v_liner_y = 0
+ self.v_angular_z = 0
+
+ def pack(self):
+ data = [self.v_liner_x,
+ self.v_liner_y,
+ self.v_angular_z]
+ pk = struct.pack('3h', *data)
+ return pk
+
+ def unpack(self, data):
+ return True
+
+#todo the rest of the message classes
+class RobotOdom(RobotMessage):
+ def __init__(self):
+ self.v_liner_x = 0
+ self.v_liner_y = 0
+ self.v_angular_z = 0
+ self.x = 0
+ self.y = 0
+ self.yaw = 0
+
+ def unpack(self, data):
+ try:
+ upk = struct.unpack('<3H2l1H', bytes(data))
+ except:
+ return False
+ [self.v_liner_x,
+ self.v_liner_y,
+ self.v_angular_z,
+ self.x,
+ self.y,
+ self.yaw] = upk
+ return True
+
+class RobotPIDData(RobotMessage):
+ def __init__(self):
+ self.pid_data = [0]*8
+
+ def unpack(self, data):
+ try:
+ upk = struct.unpack('<8l', bytes(data))
+ except:
+ return False
+
+ self.pid_data = upk
+ return True
+
+class RobotIMU(RobotMessage):
+ def __init__(self):
+ self.imu = [0]*9
+
+ def unpack(self, data):
+ try:
+ upk = struct.unpack('<9f', bytes(data))
+ except:
+ return False
+
+ self.imu = upk
+ return True
+
+class RobotEncoderCount(RobotMessage):
+ def __init__(self):
+ self.encoder = [0]*4
+
+ def unpack(self, data):
+ try:
+ upk = struct.unpack('<4f', bytes(data))
+ except:
+ return False
+
+ self.encoder = upk
+ return True
+
+class RobotMotorPWM(RobotMessage):
+ def __init__(self):
+ self.pwm = [0]*4
+
+ def pack(self):
+ pk = struct.pack('4h', *self.pwm)
+ return pk
+
+ def unpack(self, data):
+ return True
+
+BoardDataDict = {MessageID.ID_GET_VERSION:RobotFirmwareInfo(),
+ MessageID.ID_GET_ROBOT_PARAMETER:GetRobotParameters(),
+ MessageID.ID_SET_ROBOT_PARAMETER:SetRobotParameters(),
+ MessageID.ID_SET_VEL:RobotVel(),
+ MessageID.ID_GET_ODOM:RobotOdom(),
+ MessageID.ID_GET_PID_DEBUG: RobotPIDData(),
+ MessageID.ID_GET_IMU: RobotIMU(),
+ MessageID.ID_GET_ENCODER_COUNT: RobotEncoderCount(),
+ MessageID.ID_SET_MOTOR_PWM: RobotMotorPWM(),
+ }
+
diff --git a/Hardware/UPbot-Tools/main.py b/Hardware/UPbot-Tools/main.py
new file mode 100644
index 0000000..5eaeb3a
--- /dev/null
+++ b/Hardware/UPbot-Tools/main.py
@@ -0,0 +1,115 @@
+import platform
+import sys
+sys.path.append("..")
+import pypibot
+from pypibot import log
+from transport import Transport
+from dataholder import MessageID
+import params
+import time
+import signal
+
+#for linux
+#port="/dev/pibot"
+
+#for windows
+port="COM7"
+
+pypibot.assistant.enableGlobalExcept()
+#log.enableFileLog(log_dir + "ros_$(Date8)_$(filenumber2).log")
+log.setLevel("i")
+
+run_flag = True
+
+def exit(signum, frame):
+ global run_flag
+ run_flag = False
+
+if __name__ == '__main__':
+ signal.signal(signal.SIGINT, exit)
+
+ mboard = Transport(port, params.pibotBaud)
+ if not mboard.start():
+ log.error("can not open %s"%port)
+ sys.exit()
+
+ DataHolder = mboard.getDataHolder()
+
+ for num in range(0,3):
+ log.info("****************get robot version*****************")
+ boardVersion = DataHolder[MessageID.ID_GET_VERSION]
+ p = mboard.request(MessageID.ID_GET_VERSION)
+ if p:
+ log.info("firmware version:%s buildtime:%s\r\n"%(boardVersion.version.decode(), boardVersion.build_time.decode()))
+ break
+ else:
+ log.error('read firmware version err\r\n')
+ import time
+ time.sleep(1)
+ if num == 2:
+ log.error('please check connection or baudrate\r\n')
+ sys.exit()
+
+ # get robot parameter
+ robotParam = DataHolder[MessageID.ID_GET_ROBOT_PARAMETER]
+ p = mboard.request(MessageID.ID_GET_ROBOT_PARAMETER)
+ if p:
+ log.info("model_type:%d wheel_diameter:%d wheel_track:%d encoder_resolution:%d" \
+ %(robotParam.param.model_type, \
+ robotParam.param.wheel_diameter, \
+ robotParam.param.wheel_track, \
+ robotParam.param.encoder_resolution
+ ))
+
+ log.info("do_pid_interval:%d kp:%d ki:%d kd:%d ko:%d" \
+ %(robotParam.param.do_pid_interval, \
+ robotParam.param.kp, \
+ robotParam.param.ki, \
+ robotParam.param.kd, \
+ robotParam.param.ko))
+
+ log.info("cmd_last_time:%d imu_type:%d" \
+ %(robotParam.param.cmd_last_time,\
+ robotParam.param.imu_type
+ ))
+
+ log.info("max_v:%d %d %d\r\n" \
+ %(robotParam.param.max_v_liner_x,\
+ robotParam.param.max_v_liner_y, \
+ robotParam.param.max_v_angular_z
+ ))
+
+ log.info("motor flag:%d encoder flag: %d\r\n" \
+ %(robotParam.param.motor_nonexchange_flag,\
+ robotParam.param.encoder_nonexchange_flag
+ ))
+ else:
+ log.error('get params err\r\n')
+ quit(1)
+
+ log.info("****************get odom&imu*****************")
+ while run_flag:
+ robotOdom = DataHolder[MessageID.ID_GET_ODOM]
+ p = mboard.request(MessageID.ID_GET_ODOM)
+ if p:
+ log.info('request get odom success, vx=%d vy=%d vangular=%d, x=%d y=%d yaw=%d'%(robotOdom.v_liner_x, \
+ robotOdom.v_liner_y, \
+ robotOdom.v_angular_z, \
+ robotOdom.x, \
+ robotOdom.y, \
+ robotOdom.yaw))
+ else:
+ log.error('get odom err')
+ quit(1)
+
+ robotIMU = DataHolder[MessageID.ID_GET_IMU].imu
+ p = mboard.request(MessageID.ID_GET_IMU)
+ if p:
+ log.info('get imu success, imu=[%f %f %f %f %f %f %f %f %f]'%(robotIMU[0], robotIMU[1], robotIMU[2], \
+ robotIMU[3], robotIMU[4], robotIMU[5], \
+ robotIMU[6], robotIMU[7], robotIMU[8]))
+ else:
+ log.error('get imu err')
+ quit(1)
+
+ time.sleep(0.1)
diff --git a/Hardware/UPbot-Tools/params.py b/Hardware/UPbot-Tools/params.py
new file mode 100644
index 0000000..086ab3a
--- /dev/null
+++ b/Hardware/UPbot-Tools/params.py
@@ -0,0 +1,82 @@
+import dataholder
+import os
+from dataholder import RobotImuType
+from dataholder import RobotModelType
+
+# for linux
+# pibotModel = os.environ['PIBOT_MODEL']
+# boardType = os.environ['PIBOT_BOARD']
+# pibotBaud = os.environ['PIBOT_DRIVER_BAUDRATE']
+# for windwos
+pibotModel = "apollo"
+boardType = "stm32f1"
+pibotBaud = 115200
+
+print(pibotModel)
+print(boardType)
+print(pibotBaud)
+
+
+
+pibotParam = dataholder.RobotParameters()
+
+if pibotModel == "apollo" and boardType == "arduino":
+ pibotParam = dataholder.RobotParameters(65, 175, 44, 10, \
+ 75, 2500, 0, 10, \
+ 250, 40, 0, 200, \
+ RobotImuType.IMU_TYPE_GY85, 90, \
+ RobotModelType.MODEL_TYPE_2WD_DIFF)
+elif pibotModel == "apollo" and boardType == "stm32f1":
+ pibotParam = dataholder.RobotParameters(65, 175, 44, 10, \
+ 320, 2700, 0, 10, \
+ 250, 50, 0, 200, \
+ RobotImuType.IMU_TYPE_GY87, 90, \
+ RobotModelType.MODEL_TYPE_2WD_DIFF)
+elif pibotModel == "apollo" and boardType == "stm32f4":
+ pibotParam = dataholder.RobotParameters(65, 175, 44, 10, \
+ 320, 2700, 0, 10, \
+ 250, 40, 0, 200, \
+ RobotImuType.IMU_TYPE_GY87, 90, \
+ RobotModelType.MODEL_TYPE_2WD_DIFF)
+elif pibotModel == "zeus" and boardType == "stm32f4":
+ pibotParam = dataholder.RobotParameters(58, 230, 44, 10, \
+ 320, 2700, 0, 10, \
+ 250, 50, 50, 250, \
+ RobotImuType.IMU_TYPE_GY87, 90, \
+ RobotModelType.MODEL_TYPE_3WD_OMNI)
+elif pibotModel == "hades" and boardType == "stm32f4":
+ pibotParam = dataholder.RobotParameters(76, 470, 44, 10, \
+ 320, 2700, 0, 10, \
+ 250, 50, 50, 250, \
+ RobotImuType.IMU_TYPE_GY87, 90, \
+ RobotModelType.MODEL_TYPE_4WD_MECANUM)
+elif pibotModel == "hadesX" and boardType == "stm32f4":
+ pibotParam = dataholder.RobotParameters(150, 565, 44, 10, \
+ 250, 2750, 0, 10, \
+ 250, 50, 50, 250, \
+ RobotImuType.IMU_TYPE_GY87, 72, \
+ RobotModelType.MODEL_TYPE_4WD_MECANUM)
+elif pibotModel == "hera" and boardType == "stm32f4":
+ pibotParam = dataholder.RobotParameters(82, 338, 44, 10, \
+ 320, 2700, 0, 10, \
+ 250, 50, 50, 250, \
+ RobotImuType.IMU_TYPE_GY87, 90, \
+ RobotModelType.MODEL_TYPE_4WD_DIFF)
+elif pibotModel == "apolloX" and boardType == "arduino":
+ pibotParam = dataholder.RobotParameters(96, 350, 68, 10, \
+ 75, 2500, 0, 10, \
+ 250, 40, 0, 200, \
+ RobotImuType.IMU_TYPE_GY85, 90, \
+ RobotModelType.MODEL_TYPE_2WD_DIFF)
+elif pibotModel == "apolloX" and boardType == "stm32f1":
+ pibotParam = dataholder.RobotParameters(96, 350, 68, 10, \
+ 250, 1200, 0, 10, \
+ 250, 50, 0, 200, \
+ RobotImuType.IMU_TYPE_GY87, 90, \
+ RobotModelType.MODEL_TYPE_2WD_DIFF)
+elif pibotModel == "apolloX" and boardType == "stm32f4":
+ pibotParam = dataholder.RobotParameters(96, 350, 68, 10, \
+ 250, 1200, 0, 10, \
+ 250, 50, 0, 200, \
+ RobotImuType.IMU_TYPE_GY87, 90, \
+ RobotModelType.MODEL_TYPE_2WD_DIFF)
\ No newline at end of file
diff --git a/Hardware/UPbot-Tools/pb.py b/Hardware/UPbot-Tools/pb.py
new file mode 100644
index 0000000..d989af2
--- /dev/null
+++ b/Hardware/UPbot-Tools/pb.py
@@ -0,0 +1,749 @@
+# -*- coding: utf-8 -*-
+
+# Form implementation generated from reading ui file 'pb.ui'
+#
+# Created by: PyQt5 UI code generator 5.15.9
+#
+# WARNING: Any manual changes made to this file will be lost when pyuic5 is
+# run again. Do not edit this file unless you know what you are doing.
+
+
+from PyQt5 import QtCore, QtGui, QtWidgets
+
+
+class Ui_pb(object):
+ def setupUi(self, pb):
+ pb.setObjectName("pb")
+ pb.resize(866, 542)
+ self.gridLayout_2 = QtWidgets.QGridLayout(pb)
+ self.gridLayout_2.setObjectName("gridLayout_2")
+ self.line_5 = QtWidgets.QFrame(pb)
+ self.line_5.setFrameShape(QtWidgets.QFrame.HLine)
+ self.line_5.setFrameShadow(QtWidgets.QFrame.Sunken)
+ self.line_5.setObjectName("line_5")
+ self.gridLayout_2.addWidget(self.line_5, 0, 0, 1, 1)
+ self.tabWidget = QtWidgets.QTabWidget(pb)
+ self.tabWidget.setObjectName("tabWidget")
+ self.tab_3 = QtWidgets.QWidget()
+ self.tab_3.setObjectName("tab_3")
+ self.verticalLayout_3 = QtWidgets.QVBoxLayout(self.tab_3)
+ self.verticalLayout_3.setObjectName("verticalLayout_3")
+ self.horizontalLayout_25 = QtWidgets.QHBoxLayout()
+ self.horizontalLayout_25.setObjectName("horizontalLayout_25")
+ self.horizontalLayout_5 = QtWidgets.QHBoxLayout()
+ self.horizontalLayout_5.setContentsMargins(10, -1, -1, -1)
+ self.horizontalLayout_5.setObjectName("horizontalLayout_5")
+ self.label_2 = QtWidgets.QLabel(self.tab_3)
+ self.label_2.setObjectName("label_2")
+ self.horizontalLayout_5.addWidget(self.label_2)
+ spacerItem = QtWidgets.QSpacerItem(40, 20, QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Minimum)
+ self.horizontalLayout_5.addItem(spacerItem)
+ self.combox_model = QtWidgets.QComboBox(self.tab_3)
+ self.combox_model.setObjectName("combox_model")
+ self.horizontalLayout_5.addWidget(self.combox_model)
+ spacerItem1 = QtWidgets.QSpacerItem(40, 20, QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Minimum)
+ self.horizontalLayout_5.addItem(spacerItem1)
+ self.horizontalLayout_5.setStretch(1, 1)
+ self.horizontalLayout_5.setStretch(3, 8)
+ self.horizontalLayout_25.addLayout(self.horizontalLayout_5)
+ self.horizontalLayout_6 = QtWidgets.QHBoxLayout()
+ self.horizontalLayout_6.setContentsMargins(10, -1, -1, -1)
+ self.horizontalLayout_6.setObjectName("horizontalLayout_6")
+ self.label_3 = QtWidgets.QLabel(self.tab_3)
+ self.label_3.setObjectName("label_3")
+ self.horizontalLayout_6.addWidget(self.label_3)
+ spacerItem2 = QtWidgets.QSpacerItem(40, 20, QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Minimum)
+ self.horizontalLayout_6.addItem(spacerItem2)
+ self.combox_imu_type = QtWidgets.QComboBox(self.tab_3)
+ self.combox_imu_type.setObjectName("combox_imu_type")
+ self.horizontalLayout_6.addWidget(self.combox_imu_type)
+ spacerItem3 = QtWidgets.QSpacerItem(40, 20, QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Minimum)
+ self.horizontalLayout_6.addItem(spacerItem3)
+ self.horizontalLayout_6.setStretch(1, 1)
+ self.horizontalLayout_6.setStretch(2, 8)
+ self.horizontalLayout_6.setStretch(3, 8)
+ self.horizontalLayout_25.addLayout(self.horizontalLayout_6)
+ self.verticalLayout_3.addLayout(self.horizontalLayout_25)
+ self.line_2 = QtWidgets.QFrame(self.tab_3)
+ self.line_2.setFrameShape(QtWidgets.QFrame.HLine)
+ self.line_2.setFrameShadow(QtWidgets.QFrame.Sunken)
+ self.line_2.setObjectName("line_2")
+ self.verticalLayout_3.addWidget(self.line_2)
+ self.verticalLayout_2 = QtWidgets.QVBoxLayout()
+ self.verticalLayout_2.setObjectName("verticalLayout_2")
+ self.gridLayout = QtWidgets.QGridLayout()
+ self.gridLayout.setObjectName("gridLayout")
+ self.horizontalLayout = QtWidgets.QHBoxLayout()
+ self.horizontalLayout.setContentsMargins(10, -1, 10, -1)
+ self.horizontalLayout.setObjectName("horizontalLayout")
+ self.label_6 = QtWidgets.QLabel(self.tab_3)
+ self.label_6.setObjectName("label_6")
+ self.horizontalLayout.addWidget(self.label_6)
+ self.slider_motor_ratio = QtWidgets.QSlider(self.tab_3)
+ self.slider_motor_ratio.setOrientation(QtCore.Qt.Horizontal)
+ self.slider_motor_ratio.setObjectName("slider_motor_ratio")
+ self.horizontalLayout.addWidget(self.slider_motor_ratio)
+ self.label_motor_ratio = QtWidgets.QLabel(self.tab_3)
+ self.label_motor_ratio.setObjectName("label_motor_ratio")
+ self.horizontalLayout.addWidget(self.label_motor_ratio)
+ self.gridLayout.addLayout(self.horizontalLayout, 1, 1, 1, 1)
+ self.horizontalLayout_3 = QtWidgets.QHBoxLayout()
+ self.horizontalLayout_3.setContentsMargins(10, -1, 10, -1)
+ self.horizontalLayout_3.setObjectName("horizontalLayout_3")
+ self.label = QtWidgets.QLabel(self.tab_3)
+ self.label.setObjectName("label")
+ self.horizontalLayout_3.addWidget(self.label)
+ self.slider_wheel_diameter = QtWidgets.QSlider(self.tab_3)
+ self.slider_wheel_diameter.setOrientation(QtCore.Qt.Horizontal)
+ self.slider_wheel_diameter.setObjectName("slider_wheel_diameter")
+ self.horizontalLayout_3.addWidget(self.slider_wheel_diameter)
+ self.label_wheel_diameter = QtWidgets.QLabel(self.tab_3)
+ self.label_wheel_diameter.setObjectName("label_wheel_diameter")
+ self.horizontalLayout_3.addWidget(self.label_wheel_diameter)
+ self.horizontalLayout_3.setStretch(1, 16)
+ self.gridLayout.addLayout(self.horizontalLayout_3, 0, 0, 1, 1)
+ self.horizontalLayout_4 = QtWidgets.QHBoxLayout()
+ self.horizontalLayout_4.setContentsMargins(10, -1, 10, -1)
+ self.horizontalLayout_4.setObjectName("horizontalLayout_4")
+ self.label_4 = QtWidgets.QLabel(self.tab_3)
+ self.label_4.setObjectName("label_4")
+ self.horizontalLayout_4.addWidget(self.label_4)
+ self.slider_encoder = QtWidgets.QSlider(self.tab_3)
+ self.slider_encoder.setOrientation(QtCore.Qt.Horizontal)
+ self.slider_encoder.setObjectName("slider_encoder")
+ self.horizontalLayout_4.addWidget(self.slider_encoder)
+ self.label_encoder_res = QtWidgets.QLabel(self.tab_3)
+ self.label_encoder_res.setObjectName("label_encoder_res")
+ self.horizontalLayout_4.addWidget(self.label_encoder_res)
+ self.horizontalLayout_4.setStretch(1, 16)
+ self.gridLayout.addLayout(self.horizontalLayout_4, 1, 0, 1, 1)
+ self.horizontalLayout_2 = QtWidgets.QHBoxLayout()
+ self.horizontalLayout_2.setContentsMargins(10, -1, 10, -1)
+ self.horizontalLayout_2.setObjectName("horizontalLayout_2")
+ self.label_5 = QtWidgets.QLabel(self.tab_3)
+ self.label_5.setObjectName("label_5")
+ self.horizontalLayout_2.addWidget(self.label_5)
+ self.slider_wheel_track = QtWidgets.QSlider(self.tab_3)
+ self.slider_wheel_track.setOrientation(QtCore.Qt.Horizontal)
+ self.slider_wheel_track.setObjectName("slider_wheel_track")
+ self.horizontalLayout_2.addWidget(self.slider_wheel_track)
+ self.label_wheel_track = QtWidgets.QLabel(self.tab_3)
+ self.label_wheel_track.setObjectName("label_wheel_track")
+ self.horizontalLayout_2.addWidget(self.label_wheel_track)
+ self.gridLayout.addLayout(self.horizontalLayout_2, 0, 1, 1, 1)
+ self.verticalLayout_2.addLayout(self.gridLayout)
+ self.verticalLayout_3.addLayout(self.verticalLayout_2)
+ self.line_3 = QtWidgets.QFrame(self.tab_3)
+ self.line_3.setFrameShape(QtWidgets.QFrame.HLine)
+ self.line_3.setFrameShadow(QtWidgets.QFrame.Sunken)
+ self.line_3.setObjectName("line_3")
+ self.verticalLayout_3.addWidget(self.line_3)
+ self.verticalLayout = QtWidgets.QVBoxLayout()
+ self.verticalLayout.setObjectName("verticalLayout")
+ self.groupBox = QtWidgets.QGroupBox(self.tab_3)
+ self.groupBox.setAutoFillBackground(False)
+ self.groupBox.setFlat(False)
+ self.groupBox.setObjectName("groupBox")
+ self.verticalLayout_4 = QtWidgets.QVBoxLayout(self.groupBox)
+ self.verticalLayout_4.setObjectName("verticalLayout_4")
+ self.horizontalLayout_26 = QtWidgets.QHBoxLayout()
+ self.horizontalLayout_26.setObjectName("horizontalLayout_26")
+ self.gridLayout_4 = QtWidgets.QGridLayout()
+ self.gridLayout_4.setContentsMargins(5, -1, -1, -1)
+ self.gridLayout_4.setObjectName("gridLayout_4")
+ self.checkBox_motor1 = QtWidgets.QCheckBox(self.groupBox)
+ self.checkBox_motor1.setObjectName("checkBox_motor1")
+ self.gridLayout_4.addWidget(self.checkBox_motor1, 0, 0, 1, 1)
+ self.checkBox_motor2 = QtWidgets.QCheckBox(self.groupBox)
+ self.checkBox_motor2.setObjectName("checkBox_motor2")
+ self.gridLayout_4.addWidget(self.checkBox_motor2, 0, 1, 1, 1)
+ self.checkBox_motor3 = QtWidgets.QCheckBox(self.groupBox)
+ self.checkBox_motor3.setObjectName("checkBox_motor3")
+ self.gridLayout_4.addWidget(self.checkBox_motor3, 0, 2, 1, 1)
+ self.checkBox_motor4 = QtWidgets.QCheckBox(self.groupBox)
+ self.checkBox_motor4.setObjectName("checkBox_motor4")
+ self.gridLayout_4.addWidget(self.checkBox_motor4, 0, 3, 1, 1)
+ self.checkBox_encoder1 = QtWidgets.QCheckBox(self.groupBox)
+ self.checkBox_encoder1.setObjectName("checkBox_encoder1")
+ self.gridLayout_4.addWidget(self.checkBox_encoder1, 0, 4, 1, 1)
+ self.checkBox_encoder2 = QtWidgets.QCheckBox(self.groupBox)
+ self.checkBox_encoder2.setObjectName("checkBox_encoder2")
+ self.gridLayout_4.addWidget(self.checkBox_encoder2, 0, 5, 1, 1)
+ self.checkBox_encoder3 = QtWidgets.QCheckBox(self.groupBox)
+ self.checkBox_encoder3.setObjectName("checkBox_encoder3")
+ self.gridLayout_4.addWidget(self.checkBox_encoder3, 0, 6, 1, 1)
+ self.checkBox_encoder4 = QtWidgets.QCheckBox(self.groupBox)
+ self.checkBox_encoder4.setObjectName("checkBox_encoder4")
+ self.gridLayout_4.addWidget(self.checkBox_encoder4, 0, 7, 1, 1)
+ self.horizontalLayout_26.addLayout(self.gridLayout_4)
+ self.verticalLayout_4.addLayout(self.horizontalLayout_26)
+ self.verticalLayout.addWidget(self.groupBox)
+ self.verticalLayout_3.addLayout(self.verticalLayout)
+ self.horizontalLayout_24 = QtWidgets.QHBoxLayout()
+ self.horizontalLayout_24.setObjectName("horizontalLayout_24")
+ self.groupBox_3 = QtWidgets.QGroupBox(self.tab_3)
+ self.groupBox_3.setObjectName("groupBox_3")
+ self.gridLayout_5 = QtWidgets.QGridLayout(self.groupBox_3)
+ self.gridLayout_5.setObjectName("gridLayout_5")
+ self.horizontalLayout_20 = QtWidgets.QHBoxLayout()
+ self.horizontalLayout_20.setContentsMargins(10, -1, -1, -1)
+ self.horizontalLayout_20.setObjectName("horizontalLayout_20")
+ self.label_16 = QtWidgets.QLabel(self.groupBox_3)
+ self.label_16.setObjectName("label_16")
+ self.horizontalLayout_20.addWidget(self.label_16)
+ self.slider_ki = QtWidgets.QSlider(self.groupBox_3)
+ self.slider_ki.setOrientation(QtCore.Qt.Horizontal)
+ self.slider_ki.setObjectName("slider_ki")
+ self.horizontalLayout_20.addWidget(self.slider_ki)
+ self.label_ki = QtWidgets.QLabel(self.groupBox_3)
+ self.label_ki.setObjectName("label_ki")
+ self.horizontalLayout_20.addWidget(self.label_ki)
+ self.gridLayout_5.addLayout(self.horizontalLayout_20, 2, 0, 1, 1)
+ self.horizontalLayout_21 = QtWidgets.QHBoxLayout()
+ self.horizontalLayout_21.setContentsMargins(10, -1, -1, -1)
+ self.horizontalLayout_21.setObjectName("horizontalLayout_21")
+ self.label_17 = QtWidgets.QLabel(self.groupBox_3)
+ self.label_17.setObjectName("label_17")
+ self.horizontalLayout_21.addWidget(self.label_17)
+ self.slider_kd = QtWidgets.QSlider(self.groupBox_3)
+ self.slider_kd.setOrientation(QtCore.Qt.Horizontal)
+ self.slider_kd.setObjectName("slider_kd")
+ self.horizontalLayout_21.addWidget(self.slider_kd)
+ self.label_kd = QtWidgets.QLabel(self.groupBox_3)
+ self.label_kd.setObjectName("label_kd")
+ self.horizontalLayout_21.addWidget(self.label_kd)
+ self.gridLayout_5.addLayout(self.horizontalLayout_21, 3, 0, 1, 1)
+ self.horizontalLayout_22 = QtWidgets.QHBoxLayout()
+ self.horizontalLayout_22.setContentsMargins(10, -1, -1, -1)
+ self.horizontalLayout_22.setObjectName("horizontalLayout_22")
+ self.label_15 = QtWidgets.QLabel(self.groupBox_3)
+ self.label_15.setObjectName("label_15")
+ self.horizontalLayout_22.addWidget(self.label_15)
+ self.slider_kp = QtWidgets.QSlider(self.groupBox_3)
+ self.slider_kp.setOrientation(QtCore.Qt.Horizontal)
+ self.slider_kp.setObjectName("slider_kp")
+ self.horizontalLayout_22.addWidget(self.slider_kp)
+ self.label_kp = QtWidgets.QLabel(self.groupBox_3)
+ self.label_kp.setObjectName("label_kp")
+ self.horizontalLayout_22.addWidget(self.label_kp)
+ self.gridLayout_5.addLayout(self.horizontalLayout_22, 1, 0, 1, 1)
+ self.horizontalLayout_23 = QtWidgets.QHBoxLayout()
+ self.horizontalLayout_23.setContentsMargins(10, -1, -1, -1)
+ self.horizontalLayout_23.setObjectName("horizontalLayout_23")
+ self.label_18 = QtWidgets.QLabel(self.groupBox_3)
+ self.label_18.setObjectName("label_18")
+ self.horizontalLayout_23.addWidget(self.label_18)
+ self.slider_ko = QtWidgets.QSlider(self.groupBox_3)
+ self.slider_ko.setOrientation(QtCore.Qt.Horizontal)
+ self.slider_ko.setObjectName("slider_ko")
+ self.horizontalLayout_23.addWidget(self.slider_ko)
+ self.label_ko = QtWidgets.QLabel(self.groupBox_3)
+ self.label_ko.setObjectName("label_ko")
+ self.horizontalLayout_23.addWidget(self.label_ko)
+ self.gridLayout_5.addLayout(self.horizontalLayout_23, 4, 0, 1, 1)
+ self.horizontalLayout_15 = QtWidgets.QHBoxLayout()
+ self.horizontalLayout_15.setContentsMargins(10, -1, -1, -1)
+ self.horizontalLayout_15.setObjectName("horizontalLayout_15")
+ self.label_19 = QtWidgets.QLabel(self.groupBox_3)
+ self.label_19.setObjectName("label_19")
+ self.horizontalLayout_15.addWidget(self.label_19)
+ self.slider_pid_interval = QtWidgets.QSlider(self.groupBox_3)
+ self.slider_pid_interval.setOrientation(QtCore.Qt.Horizontal)
+ self.slider_pid_interval.setObjectName("slider_pid_interval")
+ self.horizontalLayout_15.addWidget(self.slider_pid_interval)
+ self.label_pid_interval = QtWidgets.QLabel(self.groupBox_3)
+ self.label_pid_interval.setObjectName("label_pid_interval")
+ self.horizontalLayout_15.addWidget(self.label_pid_interval)
+ self.gridLayout_5.addLayout(self.horizontalLayout_15, 0, 0, 1, 1)
+ self.horizontalLayout_24.addWidget(self.groupBox_3)
+ self.groupBox_2 = QtWidgets.QGroupBox(self.tab_3)
+ self.groupBox_2.setObjectName("groupBox_2")
+ self.gridLayout_3 = QtWidgets.QGridLayout(self.groupBox_2)
+ self.gridLayout_3.setObjectName("gridLayout_3")
+ self.horizontalLayout_17 = QtWidgets.QHBoxLayout()
+ self.horizontalLayout_17.setContentsMargins(10, -1, -1, -1)
+ self.horizontalLayout_17.setObjectName("horizontalLayout_17")
+ self.label_22 = QtWidgets.QLabel(self.groupBox_2)
+ self.label_22.setObjectName("label_22")
+ self.horizontalLayout_17.addWidget(self.label_22)
+ self.slider_vy_max = QtWidgets.QSlider(self.groupBox_2)
+ self.slider_vy_max.setOrientation(QtCore.Qt.Horizontal)
+ self.slider_vy_max.setObjectName("slider_vy_max")
+ self.horizontalLayout_17.addWidget(self.slider_vy_max)
+ self.label_vy_max = QtWidgets.QLabel(self.groupBox_2)
+ self.label_vy_max.setObjectName("label_vy_max")
+ self.horizontalLayout_17.addWidget(self.label_vy_max)
+ self.gridLayout_3.addLayout(self.horizontalLayout_17, 3, 0, 1, 1)
+ self.horizontalLayout_18 = QtWidgets.QHBoxLayout()
+ self.horizontalLayout_18.setContentsMargins(10, -1, -1, -1)
+ self.horizontalLayout_18.setObjectName("horizontalLayout_18")
+ self.label_21 = QtWidgets.QLabel(self.groupBox_2)
+ self.label_21.setObjectName("label_21")
+ self.horizontalLayout_18.addWidget(self.label_21)
+ self.slider_vx_max = QtWidgets.QSlider(self.groupBox_2)
+ self.slider_vx_max.setOrientation(QtCore.Qt.Horizontal)
+ self.slider_vx_max.setObjectName("slider_vx_max")
+ self.horizontalLayout_18.addWidget(self.slider_vx_max)
+ self.label_vx_max = QtWidgets.QLabel(self.groupBox_2)
+ self.label_vx_max.setObjectName("label_vx_max")
+ self.horizontalLayout_18.addWidget(self.label_vx_max)
+ self.gridLayout_3.addLayout(self.horizontalLayout_18, 2, 0, 1, 1)
+ self.horizontalLayout_19 = QtWidgets.QHBoxLayout()
+ self.horizontalLayout_19.setContentsMargins(10, -1, -1, -1)
+ self.horizontalLayout_19.setObjectName("horizontalLayout_19")
+ self.label_23 = QtWidgets.QLabel(self.groupBox_2)
+ self.label_23.setObjectName("label_23")
+ self.horizontalLayout_19.addWidget(self.label_23)
+ self.slider_va_max = QtWidgets.QSlider(self.groupBox_2)
+ self.slider_va_max.setOrientation(QtCore.Qt.Horizontal)
+ self.slider_va_max.setObjectName("slider_va_max")
+ self.horizontalLayout_19.addWidget(self.slider_va_max)
+ self.label_va_max = QtWidgets.QLabel(self.groupBox_2)
+ self.label_va_max.setObjectName("label_va_max")
+ self.horizontalLayout_19.addWidget(self.label_va_max)
+ self.gridLayout_3.addLayout(self.horizontalLayout_19, 4, 0, 1, 1)
+ self.horizontalLayout_16 = QtWidgets.QHBoxLayout()
+ self.horizontalLayout_16.setContentsMargins(10, -1, -1, -1)
+ self.horizontalLayout_16.setObjectName("horizontalLayout_16")
+ self.label_20 = QtWidgets.QLabel(self.groupBox_2)
+ self.label_20.setObjectName("label_20")
+ self.horizontalLayout_16.addWidget(self.label_20)
+ self.slider_cmd_lasttime = QtWidgets.QSlider(self.groupBox_2)
+ self.slider_cmd_lasttime.setOrientation(QtCore.Qt.Horizontal)
+ self.slider_cmd_lasttime.setObjectName("slider_cmd_lasttime")
+ self.horizontalLayout_16.addWidget(self.slider_cmd_lasttime)
+ self.label_cmd_lasttime = QtWidgets.QLabel(self.groupBox_2)
+ self.label_cmd_lasttime.setObjectName("label_cmd_lasttime")
+ self.horizontalLayout_16.addWidget(self.label_cmd_lasttime)
+ self.gridLayout_3.addLayout(self.horizontalLayout_16, 1, 0, 1, 1)
+ self.horizontalLayout_24.addWidget(self.groupBox_2)
+ self.verticalLayout_3.addLayout(self.horizontalLayout_24)
+ self.line_4 = QtWidgets.QFrame(self.tab_3)
+ self.line_4.setFrameShape(QtWidgets.QFrame.HLine)
+ self.line_4.setFrameShadow(QtWidgets.QFrame.Sunken)
+ self.line_4.setObjectName("line_4")
+ self.verticalLayout_3.addWidget(self.line_4)
+ self.horizontalLayout_29 = QtWidgets.QHBoxLayout()
+ self.horizontalLayout_29.setObjectName("horizontalLayout_29")
+ spacerItem4 = QtWidgets.QSpacerItem(40, 20, QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Minimum)
+ self.horizontalLayout_29.addItem(spacerItem4)
+ self.comboBox_support_model = QtWidgets.QComboBox(self.tab_3)
+ self.comboBox_support_model.setObjectName("comboBox_support_model")
+ self.horizontalLayout_29.addWidget(self.comboBox_support_model)
+ spacerItem5 = QtWidgets.QSpacerItem(40, 20, QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Minimum)
+ self.horizontalLayout_29.addItem(spacerItem5)
+ self.pushButton_load = QtWidgets.QPushButton(self.tab_3)
+ self.pushButton_load.setObjectName("pushButton_load")
+ self.horizontalLayout_29.addWidget(self.pushButton_load)
+ spacerItem6 = QtWidgets.QSpacerItem(40, 20, QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Minimum)
+ self.horizontalLayout_29.addItem(spacerItem6)
+ self.pushButton_set = QtWidgets.QPushButton(self.tab_3)
+ self.pushButton_set.setObjectName("pushButton_set")
+ self.horizontalLayout_29.addWidget(self.pushButton_set)
+ spacerItem7 = QtWidgets.QSpacerItem(40, 20, QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Minimum)
+ self.horizontalLayout_29.addItem(spacerItem7)
+ self.pushButton_read = QtWidgets.QPushButton(self.tab_3)
+ self.pushButton_read.setObjectName("pushButton_read")
+ self.horizontalLayout_29.addWidget(self.pushButton_read)
+ spacerItem8 = QtWidgets.QSpacerItem(40, 20, QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Minimum)
+ self.horizontalLayout_29.addItem(spacerItem8)
+ self.horizontalLayout_29.setStretch(0, 20)
+ self.horizontalLayout_29.setStretch(1, 3)
+ self.horizontalLayout_29.setStretch(2, 1)
+ self.horizontalLayout_29.setStretch(3, 3)
+ self.horizontalLayout_29.setStretch(4, 1)
+ self.horizontalLayout_29.setStretch(5, 3)
+ self.horizontalLayout_29.setStretch(6, 1)
+ self.horizontalLayout_29.setStretch(7, 3)
+ self.horizontalLayout_29.setStretch(8, 1)
+ self.verticalLayout_3.addLayout(self.horizontalLayout_29)
+ self.tabWidget.addTab(self.tab_3, "")
+ self.tab_4 = QtWidgets.QWidget()
+ self.tab_4.setObjectName("tab_4")
+ self.verticalLayout_6 = QtWidgets.QVBoxLayout(self.tab_4)
+ self.verticalLayout_6.setObjectName("verticalLayout_6")
+ self.groupBox_4 = QtWidgets.QGroupBox(self.tab_4)
+ self.groupBox_4.setObjectName("groupBox_4")
+ self.verticalLayout_5 = QtWidgets.QVBoxLayout(self.groupBox_4)
+ self.verticalLayout_5.setObjectName("verticalLayout_5")
+ self.horizontalLayout_7 = QtWidgets.QHBoxLayout()
+ self.horizontalLayout_7.setObjectName("horizontalLayout_7")
+ self.label_7 = QtWidgets.QLabel(self.groupBox_4)
+ self.label_7.setAlignment(QtCore.Qt.AlignCenter)
+ self.label_7.setObjectName("label_7")
+ self.horizontalLayout_7.addWidget(self.label_7)
+ self.slider_set_pwm1 = QtWidgets.QSlider(self.groupBox_4)
+ self.slider_set_pwm1.setOrientation(QtCore.Qt.Horizontal)
+ self.slider_set_pwm1.setObjectName("slider_set_pwm1")
+ self.horizontalLayout_7.addWidget(self.slider_set_pwm1)
+ self.label_set_pwm1 = QtWidgets.QLabel(self.groupBox_4)
+ self.label_set_pwm1.setAlignment(QtCore.Qt.AlignCenter)
+ self.label_set_pwm1.setObjectName("label_set_pwm1")
+ self.horizontalLayout_7.addWidget(self.label_set_pwm1)
+ spacerItem9 = QtWidgets.QSpacerItem(40, 20, QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Minimum)
+ self.horizontalLayout_7.addItem(spacerItem9)
+ self.label_10 = QtWidgets.QLabel(self.groupBox_4)
+ self.label_10.setObjectName("label_10")
+ self.horizontalLayout_7.addWidget(self.label_10)
+ self.label_feedback1 = QtWidgets.QLabel(self.groupBox_4)
+ self.label_feedback1.setAlignment(QtCore.Qt.AlignCenter)
+ self.label_feedback1.setObjectName("label_feedback1")
+ self.horizontalLayout_7.addWidget(self.label_feedback1)
+ self.horizontalLayout_7.setStretch(0, 1)
+ self.horizontalLayout_7.setStretch(1, 10)
+ self.horizontalLayout_7.setStretch(2, 1)
+ self.horizontalLayout_7.setStretch(3, 2)
+ self.horizontalLayout_7.setStretch(4, 1)
+ self.horizontalLayout_7.setStretch(5, 1)
+ self.verticalLayout_5.addLayout(self.horizontalLayout_7)
+ self.horizontalLayout_8 = QtWidgets.QHBoxLayout()
+ self.horizontalLayout_8.setObjectName("horizontalLayout_8")
+ self.label_8 = QtWidgets.QLabel(self.groupBox_4)
+ self.label_8.setAlignment(QtCore.Qt.AlignCenter)
+ self.label_8.setObjectName("label_8")
+ self.horizontalLayout_8.addWidget(self.label_8)
+ self.slider_set_pwm2 = QtWidgets.QSlider(self.groupBox_4)
+ self.slider_set_pwm2.setOrientation(QtCore.Qt.Horizontal)
+ self.slider_set_pwm2.setObjectName("slider_set_pwm2")
+ self.horizontalLayout_8.addWidget(self.slider_set_pwm2)
+ self.label_set_pwm2 = QtWidgets.QLabel(self.groupBox_4)
+ self.label_set_pwm2.setAlignment(QtCore.Qt.AlignCenter)
+ self.label_set_pwm2.setObjectName("label_set_pwm2")
+ self.horizontalLayout_8.addWidget(self.label_set_pwm2)
+ spacerItem10 = QtWidgets.QSpacerItem(40, 20, QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Minimum)
+ self.horizontalLayout_8.addItem(spacerItem10)
+ self.label_11 = QtWidgets.QLabel(self.groupBox_4)
+ self.label_11.setObjectName("label_11")
+ self.horizontalLayout_8.addWidget(self.label_11)
+ self.label_feedback2 = QtWidgets.QLabel(self.groupBox_4)
+ self.label_feedback2.setAlignment(QtCore.Qt.AlignCenter)
+ self.label_feedback2.setObjectName("label_feedback2")
+ self.horizontalLayout_8.addWidget(self.label_feedback2)
+ self.horizontalLayout_8.setStretch(0, 1)
+ self.horizontalLayout_8.setStretch(1, 10)
+ self.horizontalLayout_8.setStretch(2, 1)
+ self.horizontalLayout_8.setStretch(3, 2)
+ self.horizontalLayout_8.setStretch(4, 1)
+ self.horizontalLayout_8.setStretch(5, 1)
+ self.verticalLayout_5.addLayout(self.horizontalLayout_8)
+ self.horizontalLayout_9 = QtWidgets.QHBoxLayout()
+ self.horizontalLayout_9.setObjectName("horizontalLayout_9")
+ self.label_9 = QtWidgets.QLabel(self.groupBox_4)
+ self.label_9.setAlignment(QtCore.Qt.AlignCenter)
+ self.label_9.setObjectName("label_9")
+ self.horizontalLayout_9.addWidget(self.label_9)
+ self.slider_set_pwm3 = QtWidgets.QSlider(self.groupBox_4)
+ self.slider_set_pwm3.setOrientation(QtCore.Qt.Horizontal)
+ self.slider_set_pwm3.setObjectName("slider_set_pwm3")
+ self.horizontalLayout_9.addWidget(self.slider_set_pwm3)
+ self.label_set_pwm3 = QtWidgets.QLabel(self.groupBox_4)
+ self.label_set_pwm3.setAlignment(QtCore.Qt.AlignCenter)
+ self.label_set_pwm3.setObjectName("label_set_pwm3")
+ self.horizontalLayout_9.addWidget(self.label_set_pwm3)
+ spacerItem11 = QtWidgets.QSpacerItem(40, 20, QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Minimum)
+ self.horizontalLayout_9.addItem(spacerItem11)
+ self.label_12 = QtWidgets.QLabel(self.groupBox_4)
+ self.label_12.setObjectName("label_12")
+ self.horizontalLayout_9.addWidget(self.label_12)
+ self.label_feedback3 = QtWidgets.QLabel(self.groupBox_4)
+ self.label_feedback3.setAlignment(QtCore.Qt.AlignCenter)
+ self.label_feedback3.setObjectName("label_feedback3")
+ self.horizontalLayout_9.addWidget(self.label_feedback3)
+ self.horizontalLayout_9.setStretch(0, 1)
+ self.horizontalLayout_9.setStretch(1, 10)
+ self.horizontalLayout_9.setStretch(2, 1)
+ self.horizontalLayout_9.setStretch(3, 2)
+ self.horizontalLayout_9.setStretch(4, 1)
+ self.horizontalLayout_9.setStretch(5, 1)
+ self.verticalLayout_5.addLayout(self.horizontalLayout_9)
+ self.horizontalLayout_10 = QtWidgets.QHBoxLayout()
+ self.horizontalLayout_10.setObjectName("horizontalLayout_10")
+ self.label_13 = QtWidgets.QLabel(self.groupBox_4)
+ self.label_13.setAlignment(QtCore.Qt.AlignCenter)
+ self.label_13.setObjectName("label_13")
+ self.horizontalLayout_10.addWidget(self.label_13)
+ self.slider_set_pwm4 = QtWidgets.QSlider(self.groupBox_4)
+ self.slider_set_pwm4.setOrientation(QtCore.Qt.Horizontal)
+ self.slider_set_pwm4.setObjectName("slider_set_pwm4")
+ self.horizontalLayout_10.addWidget(self.slider_set_pwm4)
+ self.label_set_pwm4 = QtWidgets.QLabel(self.groupBox_4)
+ self.label_set_pwm4.setAlignment(QtCore.Qt.AlignCenter)
+ self.label_set_pwm4.setObjectName("label_set_pwm4")
+ self.horizontalLayout_10.addWidget(self.label_set_pwm4)
+ spacerItem12 = QtWidgets.QSpacerItem(40, 20, QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Minimum)
+ self.horizontalLayout_10.addItem(spacerItem12)
+ self.label_14 = QtWidgets.QLabel(self.groupBox_4)
+ self.label_14.setObjectName("label_14")
+ self.horizontalLayout_10.addWidget(self.label_14)
+ self.label_feedback4 = QtWidgets.QLabel(self.groupBox_4)
+ self.label_feedback4.setAlignment(QtCore.Qt.AlignCenter)
+ self.label_feedback4.setObjectName("label_feedback4")
+ self.horizontalLayout_10.addWidget(self.label_feedback4)
+ self.horizontalLayout_10.setStretch(1, 10)
+ self.horizontalLayout_10.setStretch(2, 1)
+ self.horizontalLayout_10.setStretch(3, 2)
+ self.horizontalLayout_10.setStretch(4, 1)
+ self.horizontalLayout_10.setStretch(5, 1)
+ self.verticalLayout_5.addLayout(self.horizontalLayout_10)
+ self.horizontalLayout_11 = QtWidgets.QHBoxLayout()
+ self.horizontalLayout_11.setObjectName("horizontalLayout_11")
+ spacerItem13 = QtWidgets.QSpacerItem(40, 20, QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Minimum)
+ self.horizontalLayout_11.addItem(spacerItem13)
+ self.pushButton_start = QtWidgets.QPushButton(self.groupBox_4)
+ self.pushButton_start.setObjectName("pushButton_start")
+ self.horizontalLayout_11.addWidget(self.pushButton_start)
+ self.pushButton_stop = QtWidgets.QPushButton(self.groupBox_4)
+ self.pushButton_stop.setObjectName("pushButton_stop")
+ self.horizontalLayout_11.addWidget(self.pushButton_stop)
+ self.verticalLayout_5.addLayout(self.horizontalLayout_11)
+ self.verticalLayout_6.addWidget(self.groupBox_4)
+ self.groupBox_6 = QtWidgets.QGroupBox(self.tab_4)
+ self.groupBox_6.setObjectName("groupBox_6")
+ self.verticalLayout_7 = QtWidgets.QVBoxLayout(self.groupBox_6)
+ self.verticalLayout_7.setObjectName("verticalLayout_7")
+ self.horizontalLayout_13 = QtWidgets.QHBoxLayout()
+ self.horizontalLayout_13.setObjectName("horizontalLayout_13")
+ self.label_25 = QtWidgets.QLabel(self.groupBox_6)
+ self.label_25.setAlignment(QtCore.Qt.AlignCenter)
+ self.label_25.setObjectName("label_25")
+ self.horizontalLayout_13.addWidget(self.label_25)
+ self.label_input_1 = QtWidgets.QLabel(self.groupBox_6)
+ self.label_input_1.setAlignment(QtCore.Qt.AlignCenter)
+ self.label_input_1.setObjectName("label_input_1")
+ self.horizontalLayout_13.addWidget(self.label_input_1)
+ self.label_input_2 = QtWidgets.QLabel(self.groupBox_6)
+ self.label_input_2.setAlignment(QtCore.Qt.AlignCenter)
+ self.label_input_2.setObjectName("label_input_2")
+ self.horizontalLayout_13.addWidget(self.label_input_2)
+ self.label_input_3 = QtWidgets.QLabel(self.groupBox_6)
+ self.label_input_3.setAlignment(QtCore.Qt.AlignCenter)
+ self.label_input_3.setObjectName("label_input_3")
+ self.horizontalLayout_13.addWidget(self.label_input_3)
+ self.label_input_4 = QtWidgets.QLabel(self.groupBox_6)
+ self.label_input_4.setAlignment(QtCore.Qt.AlignCenter)
+ self.label_input_4.setObjectName("label_input_4")
+ self.horizontalLayout_13.addWidget(self.label_input_4)
+ self.verticalLayout_7.addLayout(self.horizontalLayout_13)
+ self.horizontalLayout_14 = QtWidgets.QHBoxLayout()
+ self.horizontalLayout_14.setObjectName("horizontalLayout_14")
+ self.label_27 = QtWidgets.QLabel(self.groupBox_6)
+ self.label_27.setAlignment(QtCore.Qt.AlignCenter)
+ self.label_27.setObjectName("label_27")
+ self.horizontalLayout_14.addWidget(self.label_27)
+ self.label_output_1 = QtWidgets.QLabel(self.groupBox_6)
+ self.label_output_1.setAlignment(QtCore.Qt.AlignCenter)
+ self.label_output_1.setObjectName("label_output_1")
+ self.horizontalLayout_14.addWidget(self.label_output_1)
+ self.label_output_2 = QtWidgets.QLabel(self.groupBox_6)
+ self.label_output_2.setAlignment(QtCore.Qt.AlignCenter)
+ self.label_output_2.setObjectName("label_output_2")
+ self.horizontalLayout_14.addWidget(self.label_output_2)
+ self.label_output_3 = QtWidgets.QLabel(self.groupBox_6)
+ self.label_output_3.setAlignment(QtCore.Qt.AlignCenter)
+ self.label_output_3.setObjectName("label_output_3")
+ self.horizontalLayout_14.addWidget(self.label_output_3)
+ self.label_output_4 = QtWidgets.QLabel(self.groupBox_6)
+ self.label_output_4.setAlignment(QtCore.Qt.AlignCenter)
+ self.label_output_4.setObjectName("label_output_4")
+ self.horizontalLayout_14.addWidget(self.label_output_4)
+ self.verticalLayout_7.addLayout(self.horizontalLayout_14)
+ self.horizontalLayout_27 = QtWidgets.QHBoxLayout()
+ self.horizontalLayout_27.setObjectName("horizontalLayout_27")
+ self.label_29 = QtWidgets.QLabel(self.groupBox_6)
+ self.label_29.setAlignment(QtCore.Qt.AlignCenter)
+ self.label_29.setObjectName("label_29")
+ self.horizontalLayout_27.addWidget(self.label_29)
+ self.label_30 = QtWidgets.QLabel(self.groupBox_6)
+ self.label_30.setAlignment(QtCore.Qt.AlignCenter)
+ self.label_30.setObjectName("label_30")
+ self.horizontalLayout_27.addWidget(self.label_30)
+ self.label_31 = QtWidgets.QLabel(self.groupBox_6)
+ self.label_31.setAlignment(QtCore.Qt.AlignCenter)
+ self.label_31.setObjectName("label_31")
+ self.horizontalLayout_27.addWidget(self.label_31)
+ self.pushButton_start_2 = QtWidgets.QPushButton(self.groupBox_6)
+ self.pushButton_start_2.setObjectName("pushButton_start_2")
+ self.horizontalLayout_27.addWidget(self.pushButton_start_2)
+ self.pushButton_stop_2 = QtWidgets.QPushButton(self.groupBox_6)
+ self.pushButton_stop_2.setObjectName("pushButton_stop_2")
+ self.horizontalLayout_27.addWidget(self.pushButton_stop_2)
+ self.verticalLayout_7.addLayout(self.horizontalLayout_27)
+ self.verticalLayout_6.addWidget(self.groupBox_6)
+ self.groupBox_5 = QtWidgets.QGroupBox(self.tab_4)
+ self.groupBox_5.setObjectName("groupBox_5")
+ self.horizontalLayout_12 = QtWidgets.QHBoxLayout(self.groupBox_5)
+ self.horizontalLayout_12.setObjectName("horizontalLayout_12")
+ self.gridLayout_6 = QtWidgets.QGridLayout()
+ self.gridLayout_6.setObjectName("gridLayout_6")
+ self.label_28 = QtWidgets.QLabel(self.groupBox_5)
+ self.label_28.setAlignment(QtCore.Qt.AlignCenter)
+ self.label_28.setObjectName("label_28")
+ self.gridLayout_6.addWidget(self.label_28, 2, 0, 1, 1)
+ self.label_magn_y = QtWidgets.QLabel(self.groupBox_5)
+ self.label_magn_y.setAlignment(QtCore.Qt.AlignCenter)
+ self.label_magn_y.setObjectName("label_magn_y")
+ self.gridLayout_6.addWidget(self.label_magn_y, 2, 2, 1, 1)
+ self.label_26 = QtWidgets.QLabel(self.groupBox_5)
+ self.label_26.setAlignment(QtCore.Qt.AlignCenter)
+ self.label_26.setObjectName("label_26")
+ self.gridLayout_6.addWidget(self.label_26, 1, 0, 1, 1)
+ self.label_24 = QtWidgets.QLabel(self.groupBox_5)
+ self.label_24.setAlignment(QtCore.Qt.AlignCenter)
+ self.label_24.setObjectName("label_24")
+ self.gridLayout_6.addWidget(self.label_24, 0, 0, 1, 1)
+ self.label_acc_z = QtWidgets.QLabel(self.groupBox_5)
+ self.label_acc_z.setAlignment(QtCore.Qt.AlignCenter)
+ self.label_acc_z.setObjectName("label_acc_z")
+ self.gridLayout_6.addWidget(self.label_acc_z, 0, 3, 1, 1)
+ self.label_acc_y = QtWidgets.QLabel(self.groupBox_5)
+ self.label_acc_y.setAlignment(QtCore.Qt.AlignCenter)
+ self.label_acc_y.setObjectName("label_acc_y")
+ self.gridLayout_6.addWidget(self.label_acc_y, 0, 2, 1, 1)
+ self.label_gyro_x = QtWidgets.QLabel(self.groupBox_5)
+ self.label_gyro_x.setAlignment(QtCore.Qt.AlignCenter)
+ self.label_gyro_x.setObjectName("label_gyro_x")
+ self.gridLayout_6.addWidget(self.label_gyro_x, 1, 1, 1, 1)
+ self.label_gyro_z = QtWidgets.QLabel(self.groupBox_5)
+ self.label_gyro_z.setAlignment(QtCore.Qt.AlignCenter)
+ self.label_gyro_z.setObjectName("label_gyro_z")
+ self.gridLayout_6.addWidget(self.label_gyro_z, 1, 3, 1, 1)
+ self.label_gyro_y = QtWidgets.QLabel(self.groupBox_5)
+ self.label_gyro_y.setAlignment(QtCore.Qt.AlignCenter)
+ self.label_gyro_y.setObjectName("label_gyro_y")
+ self.gridLayout_6.addWidget(self.label_gyro_y, 1, 2, 1, 1)
+ self.label_magn_z = QtWidgets.QLabel(self.groupBox_5)
+ self.label_magn_z.setAlignment(QtCore.Qt.AlignCenter)
+ self.label_magn_z.setObjectName("label_magn_z")
+ self.gridLayout_6.addWidget(self.label_magn_z, 2, 3, 1, 1)
+ self.label_acc_x = QtWidgets.QLabel(self.groupBox_5)
+ self.label_acc_x.setAlignment(QtCore.Qt.AlignCenter)
+ self.label_acc_x.setObjectName("label_acc_x")
+ self.gridLayout_6.addWidget(self.label_acc_x, 0, 1, 1, 1)
+ self.label_magn_x = QtWidgets.QLabel(self.groupBox_5)
+ self.label_magn_x.setAlignment(QtCore.Qt.AlignCenter)
+ self.label_magn_x.setObjectName("label_magn_x")
+ self.gridLayout_6.addWidget(self.label_magn_x, 2, 1, 1, 1)
+ self.horizontalLayout_12.addLayout(self.gridLayout_6)
+ spacerItem14 = QtWidgets.QSpacerItem(615, 20, QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Minimum)
+ self.horizontalLayout_12.addItem(spacerItem14)
+ self.verticalLayout_6.addWidget(self.groupBox_5)
+ self.tabWidget.addTab(self.tab_4, "")
+ self.gridLayout_2.addWidget(self.tabWidget, 1, 0, 1, 1)
+ self.gridLayout_2.setRowStretch(0, 1)
+
+ self.retranslateUi(pb)
+ self.tabWidget.setCurrentIndex(1)
+ self.slider_wheel_diameter.valueChanged['int'].connect(self.label_wheel_diameter.setNum) # type: ignore
+ self.slider_wheel_track.valueChanged['int'].connect(self.label_wheel_track.setNum) # type: ignore
+ self.slider_encoder.valueChanged['int'].connect(self.label_encoder_res.setNum) # type: ignore
+ self.slider_motor_ratio.valueChanged['int'].connect(self.label_motor_ratio.setNum) # type: ignore
+ self.slider_pid_interval.valueChanged['int'].connect(self.label_pid_interval.setNum) # type: ignore
+ self.slider_kd.valueChanged['int'].connect(self.label_kd.setNum) # type: ignore
+ self.slider_kp.valueChanged['int'].connect(self.label_kp.setNum) # type: ignore
+ self.slider_ko.valueChanged['int'].connect(self.label_ko.setNum) # type: ignore
+ self.slider_ki.valueChanged['int'].connect(self.label_ki.setNum) # type: ignore
+ self.slider_cmd_lasttime.valueChanged['int'].connect(self.label_cmd_lasttime.setNum) # type: ignore
+ self.slider_va_max.valueChanged['int'].connect(self.label_va_max.setNum) # type: ignore
+ self.slider_vy_max.valueChanged['int'].connect(self.label_vy_max.setNum) # type: ignore
+ self.slider_vx_max.valueChanged['int'].connect(self.label_vx_max.setNum) # type: ignore
+ self.slider_set_pwm1.valueChanged['int'].connect(self.label_set_pwm1.setNum) # type: ignore
+ self.slider_set_pwm2.valueChanged['int'].connect(self.label_set_pwm2.setNum) # type: ignore
+ self.slider_set_pwm3.valueChanged['int'].connect(self.label_set_pwm3.setNum) # type: ignore
+ self.slider_set_pwm4.valueChanged['int'].connect(self.label_set_pwm4.setNum) # type: ignore
+ QtCore.QMetaObject.connectSlotsByName(pb)
+
+ def retranslateUi(self, pb):
+ _translate = QtCore.QCoreApplication.translate
+ pb.setWindowTitle(_translate("pb", "PIBOT Test Tool"))
+ self.label_2.setText(_translate("pb", "Model Name"))
+ self.label_3.setText(_translate("pb", "IMU Type"))
+ self.label_6.setText(_translate("pb", "MotorRatio"))
+ self.label_motor_ratio.setText(_translate("pb", "0"))
+ self.label.setText(_translate("pb", "Diameter"))
+ self.label_wheel_diameter.setText(_translate("pb", "0"))
+ self.label_4.setText(_translate("pb", "Encoder"))
+ self.label_encoder_res.setText(_translate("pb", "0"))
+ self.label_5.setText(_translate("pb", "WheelTrack"))
+ self.label_wheel_track.setText(_translate("pb", "0"))
+ self.groupBox.setTitle(_translate("pb", "Reverse Direction Flag"))
+ self.checkBox_motor1.setText(_translate("pb", "Motor1 "))
+ self.checkBox_motor2.setText(_translate("pb", "Motor2"))
+ self.checkBox_motor3.setText(_translate("pb", "Motor3"))
+ self.checkBox_motor4.setText(_translate("pb", "Motor4"))
+ self.checkBox_encoder1.setText(_translate("pb", "Encoder1"))
+ self.checkBox_encoder2.setText(_translate("pb", "Encoder2"))
+ self.checkBox_encoder3.setText(_translate("pb", "Encoder3"))
+ self.checkBox_encoder4.setText(_translate("pb", "Encoder4"))
+ self.groupBox_3.setTitle(_translate("pb", "PID"))
+ self.label_16.setText(_translate("pb", "KI"))
+ self.label_ki.setText(_translate("pb", "0"))
+ self.label_17.setText(_translate("pb", "KD"))
+ self.label_kd.setText(_translate("pb", "0"))
+ self.label_15.setText(_translate("pb", "KP"))
+ self.label_kp.setText(_translate("pb", "0"))
+ self.label_18.setText(_translate("pb", "KO"))
+ self.label_ko.setText(_translate("pb", "0"))
+ self.label_19.setText(_translate("pb", "Interval"))
+ self.label_pid_interval.setText(_translate("pb", "0"))
+ self.groupBox_2.setTitle(_translate("pb", "Speed Limit"))
+ self.label_22.setText(_translate("pb", "VY"))
+ self.label_vy_max.setText(_translate("pb", "0"))
+ self.label_21.setText(_translate("pb", "VX"))
+ self.label_vx_max.setText(_translate("pb", "0"))
+ self.label_23.setText(_translate("pb", "VA"))
+ self.label_va_max.setText(_translate("pb", "0"))
+ self.label_20.setText(_translate("pb", "CMD Time"))
+ self.label_cmd_lasttime.setText(_translate("pb", "0"))
+ self.pushButton_load.setText(_translate("pb", "Load"))
+ self.pushButton_set.setText(_translate("pb", "Set"))
+ self.pushButton_read.setText(_translate("pb", "Read"))
+ self.tabWidget.setTabText(self.tabWidget.indexOf(self.tab_3), _translate("pb", "Tab 1"))
+ self.groupBox_4.setTitle(_translate("pb", "Motor"))
+ self.label_7.setText(_translate("pb", "Motor1"))
+ self.label_set_pwm1.setText(_translate("pb", "0"))
+ self.label_10.setText(_translate("pb", "Encoder Feedback"))
+ self.label_feedback1.setText(_translate("pb", "0"))
+ self.label_8.setText(_translate("pb", "Motor2"))
+ self.label_set_pwm2.setText(_translate("pb", "0"))
+ self.label_11.setText(_translate("pb", "Encoder Feedback"))
+ self.label_feedback2.setText(_translate("pb", "0"))
+ self.label_9.setText(_translate("pb", "Motor3"))
+ self.label_set_pwm3.setText(_translate("pb", "0"))
+ self.label_12.setText(_translate("pb", "Encoder Feedback"))
+ self.label_feedback3.setText(_translate("pb", "0"))
+ self.label_13.setText(_translate("pb", "Motor4"))
+ self.label_set_pwm4.setText(_translate("pb", "0"))
+ self.label_14.setText(_translate("pb", "Encoder Feedback"))
+ self.label_feedback4.setText(_translate("pb", "0"))
+ self.pushButton_start.setText(_translate("pb", "start"))
+ self.pushButton_stop.setText(_translate("pb", "stop"))
+ self.groupBox_6.setTitle(_translate("pb", "PID Debug"))
+ self.label_25.setText(_translate("pb", "Input"))
+ self.label_input_1.setText(_translate("pb", "0"))
+ self.label_input_2.setText(_translate("pb", "0"))
+ self.label_input_3.setText(_translate("pb", "0"))
+ self.label_input_4.setText(_translate("pb", "0"))
+ self.label_27.setText(_translate("pb", "Feedback"))
+ self.label_output_1.setText(_translate("pb", "0"))
+ self.label_output_2.setText(_translate("pb", "0"))
+ self.label_output_3.setText(_translate("pb", "0"))
+ self.label_output_4.setText(_translate("pb", "0"))
+ self.label_29.setText(_translate("pb", "VY"))
+ self.label_30.setText(_translate("pb", "VY"))
+ self.label_31.setText(_translate("pb", "VA"))
+ self.pushButton_start_2.setText(_translate("pb", "start"))
+ self.pushButton_stop_2.setText(_translate("pb", "stop"))
+ self.groupBox_5.setTitle(_translate("pb", "IMU"))
+ self.label_28.setText(_translate("pb", "MAGN"))
+ self.label_magn_y.setText(_translate("pb", "0.000"))
+ self.label_26.setText(_translate("pb", "GYRO"))
+ self.label_24.setText(_translate("pb", "ACC"))
+ self.label_acc_z.setText(_translate("pb", "0.000"))
+ self.label_acc_y.setText(_translate("pb", "0.000"))
+ self.label_gyro_x.setText(_translate("pb", "0.000"))
+ self.label_gyro_z.setText(_translate("pb", "0.000"))
+ self.label_gyro_y.setText(_translate("pb", "0.000"))
+ self.label_magn_z.setText(_translate("pb", "0.000"))
+ self.label_acc_x.setText(_translate("pb", "0.000"))
+ self.label_magn_x.setText(_translate("pb", "0.000"))
+ self.tabWidget.setTabText(self.tabWidget.indexOf(self.tab_4), _translate("pb", "Tab 2"))
diff --git a/Hardware/UPbot-Tools/pb.ui b/Hardware/UPbot-Tools/pb.ui
new file mode 100644
index 0000000..cbca814
--- /dev/null
+++ b/Hardware/UPbot-Tools/pb.ui
@@ -0,0 +1,1613 @@
+
+
+ pb
+
+
+
+ 0
+ 0
+ 866
+ 542
+
+
+
+ UPBot 图形化配置工具
+
+
+ -
+
+
+ Qt::Horizontal
+
+
+
+ -
+
+
+ 1
+
+
+
+ Tab 1
+
+
+
-
+
+
-
+
+
+ 10
+
+
-
+
+
+ Model Name
+
+
+
+ -
+
+
+ Qt::Horizontal
+
+
+
+ 40
+ 20
+
+
+
+
+ -
+
+
+ -
+
+
+ Qt::Horizontal
+
+
+
+ 40
+ 20
+
+
+
+
+
+
+ -
+
+
+ 10
+
+
-
+
+
+ IMU Type
+
+
+
+ -
+
+
+ Qt::Horizontal
+
+
+
+ 40
+ 20
+
+
+
+
+ -
+
+
+ -
+
+
+ Qt::Horizontal
+
+
+
+ 40
+ 20
+
+
+
+
+
+
+
+
+ -
+
+
+ Qt::Horizontal
+
+
+
+ -
+
+
-
+
+
-
+
+
+ 10
+
+
+ 10
+
+
-
+
+
+ MotorRatio
+
+
+
+ -
+
+
+ Qt::Horizontal
+
+
+
+ -
+
+
+ 0
+
+
+
+
+
+ -
+
+
+ 10
+
+
+ 10
+
+
-
+
+
+ Diameter
+
+
+
+ -
+
+
+ Qt::Horizontal
+
+
+
+ -
+
+
+ 0
+
+
+
+
+
+ -
+
+
+ 10
+
+
+ 10
+
+
-
+
+
+ Encoder
+
+
+
+ -
+
+
+ Qt::Horizontal
+
+
+
+ -
+
+
+ 0
+
+
+
+
+
+ -
+
+
+ 10
+
+
+ 10
+
+
-
+
+
+ WheelTrack
+
+
+
+ -
+
+
+ Qt::Horizontal
+
+
+
+ -
+
+
+ 0
+
+
+
+
+
+
+
+
+
+ -
+
+
+ Qt::Horizontal
+
+
+
+ -
+
+
-
+
+
+ false
+
+
+ Reverse Direction Flag
+
+
+ false
+
+
+
-
+
+
-
+
+
+ 5
+
+
-
+
+
+ Motor1
+
+
+
+ -
+
+
+ Motor2
+
+
+
+ -
+
+
+ Motor3
+
+
+
+ -
+
+
+ Motor4
+
+
+
+ -
+
+
+ Encoder1
+
+
+
+ -
+
+
+ Encoder2
+
+
+
+ -
+
+
+ Encoder3
+
+
+
+ -
+
+
+ Encoder4
+
+
+
+
+
+
+
+
+
+
+
+
+ -
+
+
-
+
+
+ PID
+
+
+
-
+
+
+ 10
+
+
-
+
+
+ KI
+
+
+
+ -
+
+
+ Qt::Horizontal
+
+
+
+ -
+
+
+ 0
+
+
+
+
+
+ -
+
+
+ 10
+
+
-
+
+
+ KD
+
+
+
+ -
+
+
+ Qt::Horizontal
+
+
+
+ -
+
+
+ 0
+
+
+
+
+
+ -
+
+
+ 10
+
+
-
+
+
+ KP
+
+
+
+ -
+
+
+ Qt::Horizontal
+
+
+
+ -
+
+
+ 0
+
+
+
+
+
+ -
+
+
+ 10
+
+
-
+
+
+ KO
+
+
+
+ -
+
+
+ Qt::Horizontal
+
+
+
+ -
+
+
+ 0
+
+
+
+
+
+ -
+
+
+ 10
+
+
-
+
+
+ Interval
+
+
+
+ -
+
+
+ Qt::Horizontal
+
+
+
+ -
+
+
+ 0
+
+
+
+
+
+
+
+
+ -
+
+
+ Speed Limit
+
+
+
-
+
+
+ 10
+
+
-
+
+
+ VY
+
+
+
+ -
+
+
+ Qt::Horizontal
+
+
+
+ -
+
+
+ 0
+
+
+
+
+
+ -
+
+
+ 10
+
+
-
+
+
+ VX
+
+
+
+ -
+
+
+ Qt::Horizontal
+
+
+
+ -
+
+
+ 0
+
+
+
+
+
+ -
+
+
+ 10
+
+
-
+
+
+ VA
+
+
+
+ -
+
+
+ Qt::Horizontal
+
+
+
+ -
+
+
+ 0
+
+
+
+
+
+ -
+
+
+ 10
+
+
-
+
+
+ CMD Time
+
+
+
+ -
+
+
+ Qt::Horizontal
+
+
+
+ -
+
+
+ 0
+
+
+
+
+
+
+
+
+
+
+ -
+
+
+ Qt::Horizontal
+
+
+
+ -
+
+
-
+
+
+ Qt::Horizontal
+
+
+
+ 40
+ 20
+
+
+
+
+ -
+
+
+ -
+
+
+ Qt::Horizontal
+
+
+
+ 40
+ 20
+
+
+
+
+ -
+
+
+ Load
+
+
+
+ -
+
+
+ Qt::Horizontal
+
+
+
+ 40
+ 20
+
+
+
+
+ -
+
+
+ Set
+
+
+
+ -
+
+
+ Qt::Horizontal
+
+
+
+ 40
+ 20
+
+
+
+
+ -
+
+
+ Read
+
+
+
+ -
+
+
+ Qt::Horizontal
+
+
+
+ 40
+ 20
+
+
+
+
+
+
+
+
+
+
+ Tab 2
+
+
+ -
+
+
+ Motor
+
+
+
-
+
+
-
+
+
+ Motor1
+
+
+ Qt::AlignCenter
+
+
+
+ -
+
+
+ Qt::Horizontal
+
+
+
+ -
+
+
+ 0
+
+
+ Qt::AlignCenter
+
+
+
+ -
+
+
+ Qt::Horizontal
+
+
+
+ 40
+ 20
+
+
+
+
+ -
+
+
+ Feedback
+
+
+
+ -
+
+
+ 0
+
+
+ Qt::AlignCenter
+
+
+
+
+
+ -
+
+
-
+
+
+ Motor2
+
+
+ Qt::AlignCenter
+
+
+
+ -
+
+
+ Qt::Horizontal
+
+
+
+ -
+
+
+ 0
+
+
+ Qt::AlignCenter
+
+
+
+ -
+
+
+ Qt::Horizontal
+
+
+
+ 40
+ 20
+
+
+
+
+ -
+
+
+ Feedback
+
+
+
+ -
+
+
+ 0
+
+
+ Qt::AlignCenter
+
+
+
+
+
+ -
+
+
-
+
+
+ Motor3
+
+
+ Qt::AlignCenter
+
+
+
+ -
+
+
+ Qt::Horizontal
+
+
+
+ -
+
+
+ 0
+
+
+ Qt::AlignCenter
+
+
+
+ -
+
+
+ Qt::Horizontal
+
+
+
+ 40
+ 20
+
+
+
+
+ -
+
+
+ Feedback
+
+
+
+ -
+
+
+ 0
+
+
+ Qt::AlignCenter
+
+
+
+
+
+ -
+
+
-
+
+
+ Motor4
+
+
+ Qt::AlignCenter
+
+
+
+ -
+
+
+ Qt::Horizontal
+
+
+
+ -
+
+
+ 0
+
+
+ Qt::AlignCenter
+
+
+
+ -
+
+
+ Qt::Horizontal
+
+
+
+ 40
+ 20
+
+
+
+
+ -
+
+
+ Feedback
+
+
+
+ -
+
+
+ 0
+
+
+ Qt::AlignCenter
+
+
+
+
+
+ -
+
+
-
+
+
+ Qt::Horizontal
+
+
+
+ 40
+ 20
+
+
+
+
+ -
+
+
+ start
+
+
+
+ -
+
+
+ stop
+
+
+
+
+
+
+
+
+ -
+
+
+ PID Debug
+
+
+
-
+
+
-
+
+
+ Input
+
+
+ Qt::AlignCenter
+
+
+
+ -
+
+
+ 0
+
+
+ Qt::AlignCenter
+
+
+
+ -
+
+
+ 0
+
+
+ Qt::AlignCenter
+
+
+
+ -
+
+
+ 0
+
+
+ Qt::AlignCenter
+
+
+
+ -
+
+
+ 0
+
+
+ Qt::AlignCenter
+
+
+
+
+
+ -
+
+
-
+
+
+ Feedback
+
+
+ Qt::AlignCenter
+
+
+
+ -
+
+
+ 0
+
+
+ Qt::AlignCenter
+
+
+
+ -
+
+
+ 0
+
+
+ Qt::AlignCenter
+
+
+
+ -
+
+
+ 0
+
+
+ Qt::AlignCenter
+
+
+
+ -
+
+
+ 0
+
+
+ Qt::AlignCenter
+
+
+
+
+
+ -
+
+
-
+
+
+ VY
+
+
+ Qt::AlignCenter
+
+
+
+ -
+
+
+ VY
+
+
+ Qt::AlignCenter
+
+
+
+ -
+
+
+ VA
+
+
+ Qt::AlignCenter
+
+
+
+ -
+
+
+ start
+
+
+
+ -
+
+
+ stop
+
+
+
+
+
+
+
+
+ -
+
+
+ IMU
+
+
+
-
+
+
-
+
+
+ MAGN
+
+
+ Qt::AlignCenter
+
+
+
+ -
+
+
+ 0.000
+
+
+ Qt::AlignCenter
+
+
+
+ -
+
+
+ GYRO
+
+
+ Qt::AlignCenter
+
+
+
+ -
+
+
+ ACC
+
+
+ Qt::AlignCenter
+
+
+
+ -
+
+
+ 0.000
+
+
+ Qt::AlignCenter
+
+
+
+ -
+
+
+ 0.000
+
+
+ Qt::AlignCenter
+
+
+
+ -
+
+
+ 0.000
+
+
+ Qt::AlignCenter
+
+
+
+ -
+
+
+ 0.000
+
+
+ Qt::AlignCenter
+
+
+
+ -
+
+
+ 0.000
+
+
+ Qt::AlignCenter
+
+
+
+ -
+
+
+ 0.000
+
+
+ Qt::AlignCenter
+
+
+
+ -
+
+
+ 0.000
+
+
+ Qt::AlignCenter
+
+
+
+ -
+
+
+ 0.000
+
+
+ Qt::AlignCenter
+
+
+
+
+
+ -
+
+
+ Qt::Horizontal
+
+
+
+ 615
+ 20
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ slider_wheel_diameter
+ valueChanged(int)
+ label_wheel_diameter
+ setNum(int)
+
+
+ 218
+ 98
+
+
+ 395
+ 98
+
+
+
+
+ slider_wheel_track
+ valueChanged(int)
+ label_wheel_track
+ setNum(int)
+
+
+ 651
+ 98
+
+
+ 820
+ 98
+
+
+
+
+ slider_encoder
+ valueChanged(int)
+ label_encoder_res
+ setNum(int)
+
+
+ 214
+ 142
+
+
+ 395
+ 142
+
+
+
+
+ slider_motor_ratio
+ valueChanged(int)
+ label_motor_ratio
+ setNum(int)
+
+
+ 651
+ 142
+
+
+ 820
+ 142
+
+
+
+
+ slider_pid_interval
+ valueChanged(int)
+ label_pid_interval
+ setNum(int)
+
+
+ 246
+ 330
+
+
+ 412
+ 330
+
+
+
+
+ slider_kd
+ valueChanged(int)
+ label_kd
+ setNum(int)
+
+
+ 230
+ 418
+
+
+ 412
+ 418
+
+
+
+
+ slider_kp
+ valueChanged(int)
+ label_kp
+ setNum(int)
+
+
+ 229
+ 359
+
+
+ 412
+ 359
+
+
+
+
+ slider_ko
+ valueChanged(int)
+ label_ko
+ setNum(int)
+
+
+ 230
+ 447
+
+
+ 412
+ 447
+
+
+
+
+ slider_ki
+ valueChanged(int)
+ label_ki
+ setNum(int)
+
+
+ 226
+ 388
+
+
+ 412
+ 388
+
+
+
+
+ slider_cmd_lasttime
+ valueChanged(int)
+ label_cmd_lasttime
+ setNum(int)
+
+
+ 681
+ 334
+
+
+ 838
+ 334
+
+
+
+
+ slider_va_max
+ valueChanged(int)
+ label_va_max
+ setNum(int)
+
+
+ 655
+ 443
+
+
+ 838
+ 443
+
+
+
+
+ slider_vy_max
+ valueChanged(int)
+ label_vy_max
+ setNum(int)
+
+
+ 655
+ 407
+
+
+ 838
+ 407
+
+
+
+
+ slider_vx_max
+ valueChanged(int)
+ label_vx_max
+ setNum(int)
+
+
+ 656
+ 370
+
+
+ 838
+ 370
+
+
+
+
+ slider_set_pwm1
+ valueChanged(int)
+ label_set_pwm1
+ setNum(int)
+
+
+ 313
+ 142
+
+
+ 525
+ 142
+
+
+
+
+ slider_set_pwm2
+ valueChanged(int)
+ label_set_pwm2
+ setNum(int)
+
+
+ 322
+ 165
+
+
+ 528
+ 165
+
+
+
+
+ slider_set_pwm3
+ valueChanged(int)
+ label_set_pwm3
+ setNum(int)
+
+
+ 322
+ 199
+
+
+ 528
+ 199
+
+
+
+
+ slider_set_pwm4
+ valueChanged(int)
+ label_set_pwm4
+ setNum(int)
+
+
+ 322
+ 232
+
+
+ 528
+ 232
+
+
+
+
+
diff --git a/Hardware/UPbot-Tools/pypibot/__init__.py b/Hardware/UPbot-Tools/pypibot/__init__.py
new file mode 100644
index 0000000..aa21836
--- /dev/null
+++ b/Hardware/UPbot-Tools/pypibot/__init__.py
@@ -0,0 +1,17 @@
+#!/usr/bin/python
+# -*- coding: utf-8 -*-
+import pypibot.assistant
+import pypibot.log as Logger
+import pypibot.err
+log=Logger.log
+import sys
+def createNamedLog(name):
+ return Logger.NamedLog(name)
+class Object():
+ pass
+isDebug="-d" in sys.argv
+
+import platform
+isWindows=False
+if platform.system()=='Windows':
+ isWindows=True
diff --git a/Hardware/UPbot-Tools/pypibot/__pycache__/__init__.cpython-37.pyc b/Hardware/UPbot-Tools/pypibot/__pycache__/__init__.cpython-37.pyc
new file mode 100644
index 0000000..e76284f
Binary files /dev/null and b/Hardware/UPbot-Tools/pypibot/__pycache__/__init__.cpython-37.pyc differ
diff --git a/Hardware/UPbot-Tools/pypibot/__pycache__/assistant.cpython-37.pyc b/Hardware/UPbot-Tools/pypibot/__pycache__/assistant.cpython-37.pyc
new file mode 100644
index 0000000..c2b3710
Binary files /dev/null and b/Hardware/UPbot-Tools/pypibot/__pycache__/assistant.cpython-37.pyc differ
diff --git a/Hardware/UPbot-Tools/pypibot/__pycache__/err.cpython-37.pyc b/Hardware/UPbot-Tools/pypibot/__pycache__/err.cpython-37.pyc
new file mode 100644
index 0000000..5eff6b8
Binary files /dev/null and b/Hardware/UPbot-Tools/pypibot/__pycache__/err.cpython-37.pyc differ
diff --git a/Hardware/UPbot-Tools/pypibot/__pycache__/log.cpython-37.pyc b/Hardware/UPbot-Tools/pypibot/__pycache__/log.cpython-37.pyc
new file mode 100644
index 0000000..05b8abd
Binary files /dev/null and b/Hardware/UPbot-Tools/pypibot/__pycache__/log.cpython-37.pyc differ
diff --git a/Hardware/UPbot-Tools/pypibot/assistant.py b/Hardware/UPbot-Tools/pypibot/assistant.py
new file mode 100644
index 0000000..94683b0
--- /dev/null
+++ b/Hardware/UPbot-Tools/pypibot/assistant.py
@@ -0,0 +1,234 @@
+#!/usr/bin/python
+# -*- coding: utf-8 -*-
+import os, sys, inspect
+import datetime
+import signal
+import threading
+import time
+# function: get directory of current script, if script is built
+# into an executable file, get directory of the excutable file
+def current_file_directory():
+ path = os.path.realpath(sys.path[0]) # interpreter starter's path
+ if os.path.isfile(path): # starter is excutable file
+ path = os.path.dirname(path)
+ path = os.path.abspath(path) # return excutable file's directory
+ else: # starter is python script
+ caller_file = inspect.stack()[0][1] # function caller's filename
+ path = os.path.abspath(os.path.dirname(caller_file))# return function caller's file's directory
+ if path[-1]!=os.path.sep:path+=os.path.sep
+ return path
+
+"""格式化字符串"""
+def formatString(string,*argv):
+ string=string%argv
+ if string.find('$(scriptpath)')>=0:
+ string=string.replace('$(scriptpath)',current_file_directory())
+ if string.find('$(filenumber2)')>=0:
+ i=0
+ path=""
+ while True:
+ path=string.replace('$(scriptpath)',"%02d"%i)
+ if not os.path.lexists(path):break
+ i+=1
+ string=path
+ #8位日期(20140404)
+ if string.find('$(Date8)')>=0:
+ now=datetime.datetime.now()
+ string=string.replace('$(Date8)', now.strftime("%Y%m%d"))
+ #6位日期(140404)
+ if string.find('$(Date6)')>=0:
+ now=datetime.datetime.now()
+ string=string.replace('$(Date6)', now.strftime("%y%m%d"))
+ #6位时间(121212)
+ if string.find('$(Time6)')>=0:
+ now=datetime.datetime.now()
+ string=string.replace('$(Time6)', now.strftime("%H%M%S"))
+ #4位时间(1212)
+ if string.find('$(Time4)')>=0:
+ now=datetime.datetime.now()
+ string=string.replace('$(Time4)', now.strftime("%H%M"))
+ #文件编号2位(必须在最后)
+ if string.find('$(filenumber2)')>=0:
+ i=0
+ path=""
+ while True:
+ path=string.replace('$(filenumber2)',"%02d"%i)
+ if not os.path.lexists(path):break
+ i+=1
+ string=path
+ #文件编号3位(必须在最后)
+ if string.find('$(filenumber3)')>=0:
+ i=0
+ path=""
+ while True:
+ path=string.replace('$(filenumber3)',"%03d"%i)
+ if not os.path.lexists(path):break
+ i+=1
+ string=path
+ return string
+
+"""
+ 取得进程列表
+ 格式:(PID,cmd)
+"""
+def getProcessList():
+ processList = []
+ try:
+ for line in os.popen("ps xa"):
+ fields = line.split()
+ # spid = fields[0]
+ pid = 0
+ try:pid = int(fields[0])
+ except:None
+ cmd = line[27:-1]
+ # print "PS:%d,%s"%(npid,process)
+ if pid != 0 and len(cmd) > 0:
+ processList.append((pid, cmd))
+ except Exception as e:
+ print("getProcessList except:%s" % (e))
+ return processList
+def killCommand(cmd):
+ try:
+ processList = getProcessList()
+ for p in processList:
+ if p[1].find(cmd) != -1:
+ pid = p[0]
+ os.kill(pid, signal.SIGKILL)
+ except Exception as e:
+ print("killCommand ‘%s’ except:%s" % (cmd,e))
+
+def check_pid(pid):
+ """ Check For the existence of a unix pid. """
+ if pid == 0:return False
+ try:
+ os.kill(pid, 0)
+ except OSError:
+ return False
+ else:
+ return True
+
+SF=formatString
+
+#全局异常捕获
+def excepthook(excType, excValue, tb):
+ '''''write the unhandle exception to log'''
+ from log import log
+ import traceback
+ log.e('Unhandled Error: %s',''.join(traceback.format_exception(excType, excValue, tb)))
+ sys.exit(-1)
+ #sys.__excepthook__(type, value, trace)
+ #sys.__excepthook__(excType, excValue, tb)
+
+_defaultGlobalExcept=sys.excepthook
+
+def enableGlobalExcept(enable=True):
+ if enable:
+ sys.excepthook = excepthook
+ else:
+ sys.excepthook=_defaultGlobalExcept
+# 默认启动全局异常处理
+enableGlobalExcept()
+#创建线程
+def createThread(name,target,args=(),autoRun=True,daemon=True):
+ from log import log
+ def threadProc():
+ log.i("thread %s started!",name)
+ try:
+ target(*args)
+ log.i("thread %s ended!",name)
+ except Exception as e:
+ log.e("thread %s crash!err=%s",name,e)
+ thd=threading.Thread(name=name,target=threadProc)
+ thd.setDaemon(daemon)
+ if autoRun:thd.start()
+ return thd
+
+
+#定时器
+class Timer():
+ def __init__(self, timer_proc, args=(),first=0,period=0,name="Timer"):
+ self.name=name
+ self.first=first
+ self.period=period
+ self.args=args
+ self.timer_proc=timer_proc
+ self.thdWork=None
+ self.stopFlag=False
+ from log import NamedLog
+ self.log=NamedLog(name)
+ def run(self):
+ if self.first>0:
+ time.sleep(self.first)
+ try:
+ self.timer_proc(*self.args)
+ except Exception as e:
+ self.log.error("timer proc crash!err=%s",e)
+ while self.period>0 and not self.stopFlag:
+ time.sleep(self.period)
+ try:
+ self.timer_proc(*self.args)
+ except Exception as e:
+ self.log.error("timer proc crash!err=%s",e)
+ def start(self):
+ if self.isAlive():
+ self.log.d("already running!")
+ return True
+ self.stopFlag=False
+ self.thdWork=threading.Thread(name=self.name,target=self.run)
+ self.thdWork.setDaemon(True)
+ self.thdWork.start()
+ def stop(self,timeout=3):
+ if self.isAlive():
+ self.stopFlag=True
+ try:
+ self.thdWork.join(timeout)
+ except Exception as e:
+ self.log.e("stop timeout!")
+
+ def isAlive(self):
+ return self.thdWork and self.thdWork.isAlive()
+#计时器
+class Ticker():
+ def __init__(self):
+ self.reset()
+ # 片段,可以判断时长是否在一个特定毫秒段内
+ self.section=[]
+ def reset(self):
+ self.tick=time.time()
+ self.end=0
+ def stop(self):
+ self.end=time.time()
+ @property
+ def ticker(self):
+ if self.end==0:
+ return int((time.time()-self.tick)*1000)
+ else:
+ return int((self.end-self.tick)*1000)
+ def addSection(self,a,b):
+ a,b=int(a),int(b)
+ assert a=a and tick<=b:
+ return True
+ return False
+ def __call__(self):
+ return self.ticker
+def waitExit():
+ import log
+ log.log.i("start waiting to exit...")
+ try:
+ while(True):
+ time.sleep(1)
+ except Exception as e:
+ log.log.w("recv exit sign!")
+
+def is_python3():
+ return sys.hexversion > 0x03000000
diff --git a/Hardware/UPbot-Tools/pypibot/configer.py b/Hardware/UPbot-Tools/pypibot/configer.py
new file mode 100644
index 0000000..7bb3b9f
--- /dev/null
+++ b/Hardware/UPbot-Tools/pypibot/configer.py
@@ -0,0 +1,56 @@
+#!/usr/bin/python
+# -*- coding: utf-8 -*-
+
+import ConfigParser
+from log import PLOG
+import os
+def getdefaultfilename():
+ pass
+def openconfiger(filename):
+ return configer(filename)
+class configer:
+ def __init__(self,fullfilepath):
+ self._filepath=fullfilepath
+ if not os.path.isdir(os.path.dirname(fullfilepath)):
+ os.makedirs(os.path.dirname(fullfilepath))
+ self._conf=ConfigParser.ConfigParser()
+ if os.path.isfile(fullfilepath):
+ try:
+ self._conf.readfp(open(fullfilepath,"r"))
+ except Exception,e:
+ PLOG.error("配置文件'%s'打开失败,err=%s"%(self._filepath,e))
+ def save(self):
+ try:
+ self._conf.write(open(self._filepath,"w"))
+ except Exception,e:
+ PLOG.error("配置文件'%s'保存失败,err=%s"%(self._filepath,e))
+
+ def changeConfValue(self,section,option,value):
+ if self._conf.has_section(section):
+ self._conf.set(section,option,value)
+ else:
+ self._conf.add_section(section)
+ self._conf.set(section,option,value)
+
+ def _readvalue(self,fn,section,option,default):
+ result=default
+ if self._conf.has_section(section):
+ if self._conf.has_option(section,option):
+ result=fn(section,option)
+ PLOG.debug("Option[%s][%s]=%s"%(section,option,str(result)))
+ else:
+ self._conf.set(section,option,str(default))
+ result=default
+ else:
+ self._conf.add_section(section)
+ self._conf.set(section,option,str(default))
+ result=default
+ return result
+ def getstr(self,section,option,default=""):
+ return self._readvalue(self._conf.get, section, option, default)
+ def getint(self,section,option,default=0):
+ return self._readvalue(self._conf.getint, section, option, default)
+ def getfloat(self,section,option,default=0.0):
+ return self._readvalue(self._conf.getfloat, section, option, default)
+ def getboolean(self,section,option,default=False):
+ return self._readvalue(self._conf.getboolean, section, option, default)
diff --git a/Hardware/UPbot-Tools/pypibot/daemon.py b/Hardware/UPbot-Tools/pypibot/daemon.py
new file mode 100644
index 0000000..1ff78dc
--- /dev/null
+++ b/Hardware/UPbot-Tools/pypibot/daemon.py
@@ -0,0 +1,140 @@
+#!/usr/bin/env python
+# -*- coding: utf-8 -*-
+
+import sys, os, time, atexit
+from signal import SIGTERM
+
+def check_pid(pid):
+ """ Check For the existence of a unix pid. """
+ if pid == 0:return False
+ try:
+ os.kill(pid, 0)
+ except OSError:
+ return False
+ else:
+ return True
+
+class daemon:
+ """
+ A generic daemon class.
+
+ Usage: subclass the Daemon class and override the run() method
+ """
+ def __init__(self, pidfile, stdin='/dev/null', stdout='/dev/null', stderr='/dev/null'):
+ self.stdin = stdin
+ self.stdout = stdout
+ self.stderr = stderr
+ self.pidfile = pidfile
+
+ def daemonize(self):
+ """
+ do the UNIX double-fork magic, see Stevens' "Advanced
+ Programming in the UNIX Environment" for details (ISBN 0201563177)
+ http://www.erlenstar.demon.co.uk/unix/faq_2.html#SEC16
+ """
+ try:
+ pid = os.fork()
+ if pid > 0:
+ # exit first parent
+ sys.exit(0)
+ except OSError, e:
+ sys.stderr.write("fork #1 failed: %d (%s)\n" % (e.errno, e.strerror))
+ sys.exit(1)
+
+ # decouple from parent environment
+ os.chdir("/")
+ os.setsid()
+ os.umask(0)
+
+ # do second fork
+ try:
+ pid = os.fork()
+ if pid > 0:
+ # exit from second parent
+ sys.exit(0)
+ except OSError, e:
+ sys.stderr.write("fork #2 failed: %d (%s)\n" % (e.errno, e.strerror))
+ sys.exit(1)
+
+ # redirect standard file descriptors
+ sys.stdout.flush()
+ sys.stderr.flush()
+ si = file(self.stdin, 'r')
+ so = file(self.stdout, 'a+')
+ se = file(self.stderr, 'a+', 0)
+ os.dup2(si.fileno(), sys.stdin.fileno())
+ os.dup2(so.fileno(), sys.stdout.fileno())
+ os.dup2(se.fileno(), sys.stderr.fileno())
+
+ # write pidfile
+ atexit.register(self.delpid)
+ pid = str(os.getpid())
+ file(self.pidfile, 'w+').write("%s\n" % pid)
+
+ def delpid(self):
+ os.remove(self.pidfile)
+
+ def start(self):
+ """
+ Start the daemon
+ """
+ # Check for a pidfile to see if the daemon already runs
+ try:
+ pf = file(self.pidfile, 'r')
+ pid = int(pf.read().strip())
+ pf.close()
+ except IOError:
+ pid = None
+
+ if pid and check_pid(pid):
+ message = "pidfile %s already exist. Daemon already running?\n"
+ sys.stderr.write(message % self.pidfile)
+ sys.exit(1)
+ print("daemon start...")
+ # Start the daemon
+ self.daemonize()
+ self.run()
+
+ def stop(self):
+ """
+ Stop the daemon
+ """
+ # Get the pid from the pidfile
+ try:
+ pf = file(self.pidfile, 'r')
+ pid = int(pf.read().strip())
+ pf.close()
+ except IOError:
+ pid = None
+
+ if not pid:
+ message = "pidfile %s does not exist. Daemon not running?\n"
+ sys.stderr.write(message % self.pidfile)
+ return # not an error in a restart
+
+ # Try killing the daemon process
+ try:
+ while 1:
+ os.kill(pid, SIGTERM)
+ time.sleep(0.1)
+ except OSError, err:
+ err = str(err)
+ if err.find("No such process") > 0:
+ if os.path.exists(self.pidfile):
+ os.remove(self.pidfile)
+ else:
+ print(str(err))
+ sys.exit(1)
+
+ def restart(self):
+ """
+ Restart the daemon
+ """
+ self.stop()
+ self.start()
+
+ def run(self):
+ """
+ You should override this method when you subclass Daemon. It will be called after the process has been
+ daemonized by start() or restart().
+ """
diff --git a/Hardware/UPbot-Tools/pypibot/err.py b/Hardware/UPbot-Tools/pypibot/err.py
new file mode 100644
index 0000000..d812de9
--- /dev/null
+++ b/Hardware/UPbot-Tools/pypibot/err.py
@@ -0,0 +1,58 @@
+#!/usr/bin/python
+# -*- coding: utf-8 -*-
+
+# 异常类
+class PibotError(Exception):
+ def __init__(self, errcode, errmsg):
+ self.errcode = errcode
+ self.errmsg = errmsg
+ #Exception.__init__(self,self.__str__())
+
+ def msg(self, msg):
+ if not msg is None:return PibotError(self.errcode, msg)
+ return PibotError(8,"unknow error")
+ def __str__(self):
+ return "PibotError:%s(%d)"%(self.errmsg,self.errcode)
+ @property
+ def message(self):
+ return str(self)
+# 声明
+# 成功
+success=PibotError(0,"null")
+# 通用失败
+fail=PibotError(1,"fail")
+# 参数无效
+invalidParameter=PibotError(2,"invalid parameter")
+# 不支持
+noSupport=PibotError(3,"no support")
+# 不存在
+noExist=PibotError(4,"no exist")
+# 超时
+timeout=PibotError(5,"timeout")
+# 繁忙
+busy=PibotError(6,"busy")
+# 缺少参数
+missParameter=PibotError(7,"miss parameter")
+# 系统错误(通用错误)
+systemError=PibotError(8,"system error")
+# 密码错误
+invalidPassword=PibotError(9,"invalid password")
+# 编码失败
+encodeFailed=PibotError(10,"encode failed")
+# 数据库操作失败
+dbOpertationFailed=PibotError(11,"db error")
+# 已占用
+occupied=PibotError(12,"occupied")
+# session不存在
+noSession = PibotError(13,'cannot find session')
+#没有找到
+noFound = PibotError(14, "no found")
+#已经存在
+existed = PibotError(15, "existed")
+#已经锁定
+locked = PibotError(16, "locked")
+#已经过期
+expired = PibotError(17, "is expired")
+#无效的参数
+invalidParameter = PibotError(18, "invalid parameter")
+
diff --git a/Hardware/UPbot-Tools/pypibot/log.py b/Hardware/UPbot-Tools/pypibot/log.py
new file mode 100644
index 0000000..c031d4a
--- /dev/null
+++ b/Hardware/UPbot-Tools/pypibot/log.py
@@ -0,0 +1,259 @@
+#!/usr/bin/python
+# -*- coding: utf-8 -*-
+import sys,os
+import datetime
+import threading
+import pypibot.assistant as assistant
+import platform
+if assistant.is_python3():
+ import _thread
+else:
+ import thread
+import traceback
+"""
+%a Locale’s abbreviated weekday name.
+%A Locale’s full weekday name.
+%b Locale’s abbreviated month name.
+%B Locale’s full month name.
+%c Locale’s appropriate date and time representation.
+%d Day of the month as a decimal number [01,31].
+%H Hour (24-hour clock) as a decimal number [00,23].
+%I Hour (12-hour clock) as a decimal number [01,12].
+%j Day of the year as a decimal number [001,366].
+%m Month as a decimal number [01,12].
+%M Minute as a decimal number [00,59].
+%p Locale’s equivalent of either AM or PM. (1)
+%S Second as a decimal number [00,61]. (2)
+%U Week number of the year (Sunday as the first day of the week) as a decimal number [00,53]. All days in a new year preceding the first Sunday are considered to be in week 0. (3)
+%w Weekday as a decimal number [0(Sunday),6].
+%W Week number of the year (Monday as the first day of the week) as a decimal number [00,53]. All days in a new year preceding the first Monday are considered to be in week 0. (3)
+%x Locale’s appropriate date representation.
+%X Locale’s appropriate time representation.
+%y Year without century as a decimal number [00,99].
+%Y Year with century as a decimal number.
+%Z Time zone name (no characters if no time zone exists).
+%% A literal '%' character.
+
+"""
+isWindows=False
+if platform.system()=='Windows':
+ isWindows=True
+defaultEncodeing="utf8"
+if "-utf8" in sys.argv:
+ defaultEncodeing="utf-8"
+if "-gbk" in sys.argv:
+ defaultEncodeing="gbk"
+
+TRACE=5
+DEBUG=4
+INFORMATION=3
+WARNING=2
+ERROR=1
+NONE=0
+
+MAX_MSG_SIZE = 4096
+
+def getLevelFromString(level):
+ level=level.lower()
+ if level=='t' or level=='trace':return 5
+ elif level=='d' or level=='debug':return 4
+ elif level=='i' or level=='info':return 3
+ elif level=='w' or level=='wran':return 2
+ elif level=='e' or level=='error':return 1
+ else :return 0
+def getLevelString(level):
+ if level==TRACE:return "T"
+ elif level==DEBUG:return "D"
+ elif level==INFORMATION:return "I"
+ elif level==WARNING:return "W"
+ elif level==ERROR:return "E"
+ else:return "N"
+class PibotLog:
+ def __init__(self):
+ self.isEnableControlLog=True
+ self.fileTemple=None
+ self.filePath=""
+ self.level=5
+ self._lock=threading.RLock()
+ self.fd=None
+ self.fd_day=-1
+ def setLevel(self,level):
+ self.level=getLevelFromString(level)
+ def enableControllog(self,enable):
+ self.isEnableControlLog=enable
+ def enableFileLog(self,fileName):
+ self.fileTemple=fileName
+ self.updateFilelog()
+ def updateFilelog(self):
+ fn=assistant.SF(self.fileTemple)
+ if fn!=self.filePath:
+ self.i("new log file:%s",fn)
+ if self.fd:
+ self.fd.close()
+ self.fd=None
+ self.fd_day=-1
+ self.filePath=""
+ try:
+ path=os.path.dirname(fn)
+ if path!="" and not os.path.isdir(path):os.makedirs(path)
+ self.fd=open(fn,mode="w")
+ try:
+ linkfn = fn.split(".log.", 1)[0] + ".INFO"
+ if os.path.exists(linkfn):
+ os.remove(linkfn)
+ (filepath, tempfilename) = os.path.split(fn)
+ os.symlink(tempfilename, linkfn)
+ except:
+ pass
+ self.fd_day=datetime.datetime.now().day
+ self.filePath=fn
+ except Exception as e:
+ print("open file fail!file=%s,err=%s"%(fn,e))
+ def _output(self,level,msg,args):
+ if self.level0:
+ t=[]
+ for arg in args:
+ if isinstance(arg,Exception):
+ t.append(traceback.format_exc(arg).decode('utf-8'))
+ elif isinstance(arg,bytes) :
+ t.append(arg.decode('utf-8'))
+ else:
+ t.append(arg)
+ args=tuple(t)
+ try:
+ msg=msg%args
+ except:
+ try:
+ for arg in args:
+ msg=msg+str(arg)+" "
+ except Exception as e:
+ msg=msg+"==LOG ERROR==>%s"%(e)
+ if len(msg)>MAX_MSG_SIZE:msg=msg[0:MAX_MSG_SIZE]
+ now=datetime.datetime.now()
+ msg=msg+"\r\n"
+ if assistant.is_python3():
+ id = _thread.get_ident()
+ else:
+ id = thread.get_ident()
+ s="[%s] %04d-%02d-%02d %02d:%02d:%02d.%03d (0x%04X):%s"%(getLevelString(level),now.year,now.month,now.day,now.hour,now.minute,now.second,now.microsecond/1000,(id>>8)&0xffff,msg)
+ prefix=''
+ suffix=''
+ if not isWindows:
+ suffix='\033[0m'
+ if level==TRACE:
+ prefix='\033[0;37m'
+ elif level==DEBUG:
+ prefix='\033[1m'
+ elif level==INFORMATION:
+ prefix='\033[0;32m'
+ elif level==WARNING:
+ prefix='\033[0;33m'
+ elif level==ERROR:
+ prefix='\033[0;31m'
+ else:
+ pass
+ self._lock.acquire()
+ try:
+ if self.isEnableControlLog:
+ sys.stdout.write((prefix+s+suffix))
+ if self.fd:
+ if self.fd_day!=now.day:
+ self.updateFilelog()
+ if assistant.is_python3():
+ self.fd.write(s)
+ else:
+ self.fd.write(s.encode('utf-8'))
+ self.fd.flush()
+ finally:
+ self._lock.release()
+ except Exception as e:
+ if assistant.is_python3():
+ print(e)
+ else:
+ print("PibotLog._output crash!err=%s"%traceback.format_exc(e))
+
+ def trace(self,msg,*args):
+ self._output(TRACE,msg,args)
+ def t(self,msg,*args):
+ self._output(TRACE,msg,args)
+ def debug(self,msg,*args):
+ self._output(DEBUG, msg,args)
+ def d(self,msg,*args):
+ self._output(DEBUG, msg,args)
+ def info(self,msg,*args):
+ self._output(INFORMATION, msg,args)
+ def i(self,msg,*args):
+ self._output(INFORMATION, msg,args)
+ def warn(self,msg,*args):
+ self._output(WARNING, msg,args)
+ def w(self,msg,*args):
+ self._output(WARNING, msg,args)
+ def error(self,msg,*args):
+ self._output(ERROR, msg,args)
+ def e(self,msg,*args):
+ self._output(ERROR, msg,args)
+ def _log(self,level,msg,args):
+ self._output(level, msg,args)
+ def createNamedLog(self,name):
+ return NamedLog(name)
+log=PibotLog()
+class NamedLog:
+ def __init__(self,name=None):
+ global log
+ self.name=''
+ if name:
+ self.name='['+name+']'
+ self.log=log
+ def trace(self,msg,*args):
+ msg=self.name+msg
+ self.log._log(TRACE,msg,args)
+ def t(self,msg,*args):
+ msg=self.name+msg
+ self.log._log(TRACE,msg,args)
+ def debug(self,msg,*args):
+ msg=self.name+msg
+ self.log._log(DEBUG, msg,args)
+ def d(self,msg,*args):
+ msg=self.name+msg
+ self.log._log(DEBUG, msg,args)
+ def info(self,msg,*args):
+ msg=self.name+msg
+ self.log._log(INFORMATION, msg,args)
+ def i(self,msg,*args):
+ msg=self.name+msg
+ self.log._log(INFORMATION, msg,args)
+ def warn(self,msg,*args):
+ msg=self.name+msg
+ self.log._log(WARNING, msg,args)
+ def w(self,msg,*args):
+ msg=self.name+msg
+ self.log._log(WARNING, msg,args)
+ def error(self,msg,*args):
+ msg=self.name+msg
+ self.log._log(ERROR, msg,args)
+ def e(self,msg,*args):
+ msg=self.name+msg
+ self.log._log(ERROR, msg,args)
+
+if __name__ == "__main__":
+ log.trace("1%s","hello")
+ log.debug("2%d",12)
+ try:
+ raise Exception("EXC")
+ except Exception as e:
+ log.info("3%s",e)
+ log.warn("1")
+ log.error("1")
+ #log.enableFileLog("$(scriptpath)test_$(Date8)_$(filenumber2).log")
+ log.trace("1")
+ log.debug("1")
+ log.info("1")
+ log.warn("1")
+ log.error("1")
+ log=NamedLog("test")
+ log.d("1")
+ log.i("1")
+ log.warn("1")
+ log.error("1=%d,%s",100,e)
diff --git a/Hardware/UPbot-Tools/pypibot/mapconvert.py b/Hardware/UPbot-Tools/pypibot/mapconvert.py
new file mode 100644
index 0000000..0d27ec4
--- /dev/null
+++ b/Hardware/UPbot-Tools/pypibot/mapconvert.py
@@ -0,0 +1,35 @@
+import cv2
+import numpy as np
+
+def map_server_to_cv2(data):
+ # print(data.info.height, data.info.width)
+ data = np.reshape(data.data, (data.info.height, data.info.width))
+ data = np.flipud(data)
+
+ # -1 --> 205
+ # 0 --> 255
+ # 100--> 0
+ image = np.where(data == -1, 205, 255 - (255.0 * data / 100)).astype(np.uint8)
+
+ #cv2.imshow("cv2_map", data)
+ return image
+
+
+def cv2_to_map_server(image):
+ image = np.flipud(image)
+
+ # 205 --> -1
+ # 255 --> 0
+ # 0 --> 100
+ data = np.where(image == 205, -1, (255 - image) * 100.0 / 255).astype(np.int8).flatten()
+
+ return list(data)
+ # pub_data = OccupancyGrid()
+ # pub_data.header.frame_id = "map"
+ # pub_data.header.stamp = rospy.Time.now()
+ # pub_data.info = map_data.info
+ # pub_data.data = list(data)
+
+ # print(len(pub_data.data), pub_data.info.height * pub_data.info.width)
+
+ # map_publisher.publish(pub_data)
\ No newline at end of file
diff --git a/Hardware/UPbot-Tools/pypibot/proxy.py b/Hardware/UPbot-Tools/pypibot/proxy.py
new file mode 100644
index 0000000..5187c22
--- /dev/null
+++ b/Hardware/UPbot-Tools/pypibot/proxy.py
@@ -0,0 +1,38 @@
+from pypibot import log
+
+import threading
+import zmq
+
+class MqProxy:
+ def __init__(self, sub_addr, pub_addr):
+ self.thd = None
+ self.sub_addr = sub_addr
+ self.pub_addr = pub_addr
+
+ def _run(self):
+ context = zmq.Context()
+
+ frontend = context.socket(zmq.XSUB)
+ frontend.bind(self.sub_addr)
+ # frontend.bind("tcp://*:5556")
+ backend = context.socket(zmq.XPUB)
+ backend.bind(self.pub_addr)
+ # backend.bind("tcp://*:5557")
+ try:
+ zmq.proxy(frontend, backend)
+ except KeyboardInterrupt:
+ pass
+
+ frontend.close()
+ backend.close()
+ context.term()
+
+ def start(self):
+ if self.thd is None:
+ log.i("mq proxy starting...")
+ self.thd=threading.Thread(target=self._run, name="proxy")
+ self.thd.setDaemon(True)
+ self.thd.start()
+
+ def stop(self):
+ pass
diff --git a/Hardware/UPbot-Tools/set_default_params.py b/Hardware/UPbot-Tools/set_default_params.py
new file mode 100644
index 0000000..096b17c
--- /dev/null
+++ b/Hardware/UPbot-Tools/set_default_params.py
@@ -0,0 +1,90 @@
+import platform
+import sys
+sys.path.append("..")
+import pypibot
+from pypibot import log
+from transport import Transport
+from dataholder import MessageID
+import params
+
+#for linux
+port="/dev/pibot"
+
+#for windows
+#port="com3"
+
+pypibot.assistant.enableGlobalExcept()
+#log.enableFileLog(log_dir + "ros_$(Date8)_$(filenumber2).log")
+log.setLevel("i")
+
+if __name__ == '__main__':
+ mboard = Transport(port, params.pibotBaud)
+ if not mboard.start():
+ log.error("can not open %s"%port)
+ sys.exit()
+
+ DataHolder = mboard.getDataHolder()
+
+ for num in range(0,3):
+ log.info("****************get robot version*****************")
+ boardVersion = DataHolder[MessageID.ID_GET_VERSION]
+ p = mboard.request(MessageID.ID_GET_VERSION)
+ if p:
+ log.info("firmware version:%s buildtime:%s\r\n"%(boardVersion.version.decode(), boardVersion.build_time.decode()))
+ break
+ else:
+ log.error('read firmware version err\r\n')
+ import time
+ time.sleep(1)
+ if num == 2:
+ log.error('please check connection or baudrate\r\n')
+ sys.exit()
+
+ # set robot parameter
+ log.info("****************set robot parameter*****************")
+
+ DataHolder[MessageID.ID_SET_ROBOT_PARAMETER].param = params.pibotParam
+
+ p = mboard.request(MessageID.ID_SET_ROBOT_PARAMETER)
+ if p:
+ log.info('set parameter success')
+ else:
+ log.error('set parameter err')
+ quit(1)
+
+ # get robot parameter
+ robotParam = DataHolder[MessageID.ID_GET_ROBOT_PARAMETER]
+ p = mboard.request(MessageID.ID_GET_ROBOT_PARAMETER)
+ if p:
+ log.info("model_type:%d wheel_diameter:%d wheel_track:%d encoder_resolution:%d" \
+ %(robotParam.param.model_type, \
+ robotParam.param.wheel_diameter, \
+ robotParam.param.wheel_track, \
+ robotParam.param.encoder_resolution
+ ))
+
+ log.info("do_pid_interval:%d kp:%d ki:%d kd:%d ko:%d" \
+ %(robotParam.param.do_pid_interval, \
+ robotParam.param.kp, \
+ robotParam.param.ki, \
+ robotParam.param.kd, \
+ robotParam.param.ko))
+
+ log.info("cmd_last_time:%d imu_type:%d" \
+ %(robotParam.param.cmd_last_time,\
+ robotParam.param.imu_type
+ ))
+
+ log.info("max_v:%d %d %d\r\n" \
+ %(robotParam.param.max_v_liner_x,\
+ robotParam.param.max_v_liner_y, \
+ robotParam.param.max_v_angular_z
+ ))
+
+ log.info("motor flag:%d encoder flag: %d\r\n" \
+ %(robotParam.param.motor_nonexchange_flag,\
+ robotParam.param.encoder_nonexchange_flag
+ ))
+ else:
+ log.error('get param err\r\n')
+ quit(1)
\ No newline at end of file
diff --git a/Hardware/UPbot-Tools/test_motors.py b/Hardware/UPbot-Tools/test_motors.py
new file mode 100644
index 0000000..d5e0daa
--- /dev/null
+++ b/Hardware/UPbot-Tools/test_motors.py
@@ -0,0 +1,122 @@
+import platform
+import sys
+sys.path.append("..")
+import pypibot
+from pypibot import log
+from transport import Transport
+from dataholder import MessageID
+import params
+import signal
+
+#for linux
+port="/dev/pibot"
+
+#for windows
+#port="com3"
+
+pypibot.assistant.enableGlobalExcept()
+#log.enableFileLog(log_dir + "ros_$(Date8)_$(filenumber2).log")
+log.setLevel("i")
+
+run_flag = True
+
+def exit(signum, frame):
+ global run_flag
+ run_flag = False
+
+if __name__ == '__main__':
+ signal.signal(signal.SIGINT, exit)
+
+ mboard = Transport(port, params.pibotBaud)
+ if not mboard.start():
+ log.error("can not open %s"%port)
+ sys.exit()
+
+ pwm=[0]*4
+ for i in range(len(sys.argv)-1):
+ pwm[i] = int(sys.argv[i+1])
+
+ DataHolder = mboard.getDataHolder()
+
+ for num in range(0,3):
+ log.info("****************get robot version*****************")
+ boardVersion = DataHolder[MessageID.ID_GET_VERSION]
+ p = mboard.request(MessageID.ID_GET_VERSION)
+ if p:
+ log.info("firmware version:%s buildtime:%s\r\n"%(boardVersion.version.decode(), boardVersion.build_time.decode()))
+ break
+ else:
+ log.error('read firmware version err\r\n')
+ import time
+ time.sleep(1)
+ if num == 2:
+ log.error('please check connection or baudrate\r\n')
+ sys.exit()
+
+ # get robot parameter
+ robotParam = DataHolder[MessageID.ID_GET_ROBOT_PARAMETER]
+ p = mboard.request(MessageID.ID_GET_ROBOT_PARAMETER)
+ if p:
+ log.info("model_type:%d wheel_diameter:%d wheel_track:%d encoder_resolution:%d" \
+ %(robotParam.param.model_type, \
+ robotParam.param.wheel_diameter, \
+ robotParam.param.wheel_track, \
+ robotParam.param.encoder_resolution
+ ))
+
+ log.info("do_pid_interval:%d kp:%d ki:%d kd:%d ko:%d" \
+ %(robotParam.param.do_pid_interval, \
+ robotParam.param.kp, \
+ robotParam.param.ki, \
+ robotParam.param.kd, \
+ robotParam.param.ko))
+
+ log.info("cmd_last_time:%d imu_type:%d" \
+ %(robotParam.param.cmd_last_time,\
+ robotParam.param.imu_type
+ ))
+
+ log.info("max_v:%d %d %d\r\n" \
+ %(robotParam.param.max_v_liner_x,\
+ robotParam.param.max_v_liner_y, \
+ robotParam.param.max_v_angular_z
+ ))
+
+ log.info("motor flag:%d encoder flag: %d\r\n" \
+ %(robotParam.param.motor_nonexchange_flag,\
+ robotParam.param.encoder_nonexchange_flag
+ ))
+ else:
+ log.error('get params err\r\n')
+ quit(1)
+
+ DataHolder[MessageID.ID_SET_MOTOR_PWM].pwm = pwm
+
+ p = mboard.request(MessageID.ID_SET_MOTOR_PWM)
+ if p:
+ log.info('set pwm success')
+ else:
+ log.error('set pwm err')
+ quit(1)
+
+ log.info("****************get encoder count*****************")
+ while run_flag:
+ robotEncoder = DataHolder[MessageID.ID_GET_ENCODER_COUNT].encoder
+ p = mboard.request(MessageID.ID_GET_ENCODER_COUNT)
+ if p:
+ log.info('encoder count: %s'%(('\t\t').join([str(x) for x in robotEncoder])))
+ else:
+ log.error('get encoder count err')
+ quit(1)
+
+ import time
+ time.sleep(0.5)
+
+ DataHolder[MessageID.ID_SET_MOTOR_PWM].pwm = [0]*4
+
+ p = mboard.request(MessageID.ID_SET_MOTOR_PWM)
+ if p:
+ log.info('set pwm success')
+ else:
+ log.error('set pwm err')
+ quit(1)
\ No newline at end of file
diff --git a/Hardware/UPbot-Tools/transport.py b/Hardware/UPbot-Tools/transport.py
new file mode 100644
index 0000000..d3c63db
--- /dev/null
+++ b/Hardware/UPbot-Tools/transport.py
@@ -0,0 +1,203 @@
+import sys
+sys.path.append("..")
+import pypibot
+from pypibot import log
+from pypibot import assistant
+
+import serial
+import threading
+import struct
+import time
+from dataholder import MessageID, BoardDataDict
+FIX_HEAD = 0x5a
+
+class Recstate():
+ WAITING_HD = 0
+ WAITING_MSG_ID = 1
+ RECEIVE_LEN = 2
+ RECEIVE_PACKAGE = 3
+ RECEIVE_CHECK = 4
+
+def checksum(d):
+ sum = 0
+ if assistant.is_python3():
+ for i in d:
+ sum += i
+ sum = sum&0xff
+ else:
+ for i in d:
+ sum += ord(i)
+ sum = sum&0xff
+ return sum
+
+
+class Transport:
+ def __init__(self, port, baudrate=921600):
+ self._Port = port
+ self._Baudrate = baudrate
+ self._KeepRunning = False
+ self.receive_state = Recstate.WAITING_HD
+ self.rev_msg = []
+ self.rev_data = []
+ self.req_lock = threading.Lock()
+ self.wait_event = threading.Event()
+
+ def getDataHolder(self):
+ return BoardDataDict
+
+ def start(self):
+ try:
+ self._Serial = serial.Serial(port=self._Port, baudrate=self._Baudrate, timeout=0.2)
+ self._KeepRunning = True
+ self._ReceiverThread = threading.Thread(target=self._Listen)
+ self._ReceiverThread.setDaemon(True)
+ self._ReceiverThread.start()
+ return True
+ except:
+ print("Open Serial Error")
+ return False
+
+ def Stop(self):
+ self._KeepRunning = False
+ time.sleep(0.1)
+ self._Serial.close()
+
+ def _Listen(self):
+ while self._KeepRunning:
+ if self.receiveFiniteStates(self._Serial.read()):
+ self.packageAnalysis()
+
+ def receiveFiniteStates(self, s):
+ if len(s) == 0:
+ return False
+ val = s[0]
+ val_int = val
+ if not assistant.is_python3():
+ val_int = ord(val)
+
+ if self.receive_state == Recstate.WAITING_HD:
+ if val_int == FIX_HEAD:
+ log.trace('got head')
+ self.rev_msg = []
+ self.rev_data =[]
+ self.rev_msg.append(val)
+ self.receive_state = Recstate.WAITING_MSG_ID
+ elif self.receive_state == Recstate.WAITING_MSG_ID:
+ log.trace('got msg id')
+ self.rev_msg.append(val)
+ self.receive_state = Recstate.RECEIVE_LEN
+ elif self.receive_state == Recstate.RECEIVE_LEN:
+ log.trace('got len:%d', val_int)
+ self.rev_msg.append(val)
+ if val_int == 0:
+ self.receive_state = Recstate.RECEIVE_CHECK
+ else:
+ self.receive_state = Recstate.RECEIVE_PACKAGE
+ elif self.receive_state == Recstate.RECEIVE_PACKAGE:
+ # if assistant.is_python3():
+ # self.rev_data.append((chr(val)).encode('latin1'))
+ # else:
+ self.rev_data.append(val)
+ r = False
+ if assistant.is_python3():
+ r = len(self.rev_data) == int(self.rev_msg[-1])
+ else:
+ r = len(self.rev_data) == ord(self.rev_msg[-1])
+
+ if r:
+ self.rev_msg.extend(self.rev_data)
+ self.receive_state = Recstate.RECEIVE_CHECK
+ elif self.receive_state == Recstate.RECEIVE_CHECK:
+ log.trace('got check')
+ self.receive_state = Recstate.WAITING_HD
+ if val_int == checksum(self.rev_msg):
+ log.trace('got a complete message')
+ return True
+ else:
+ self.receive_state = Recstate.WAITING_HD
+
+ # continue receiving
+ return False
+
+ def packageAnalysis(self):
+ if assistant.is_python3():
+ in_msg_id = int(self.rev_msg[1])
+ else:
+ in_msg_id = ord(self.rev_msg[1])
+ if assistant.is_python3():
+ log.debug("recv body:" + " ".join("{:02x}".format(c) for c in self.rev_data))
+ r = BoardDataDict[in_msg_id].unpack(bytes(self.rev_data))
+ else:
+ log.debug("recv body:" + " ".join("{:02x}".format(ord(c)) for c in self.rev_data))
+ r = BoardDataDict[in_msg_id].unpack(''.join(self.rev_data))
+ if r:
+ self.res_id = in_msg_id
+ if in_msg_id<100:
+ self.set_response()
+ else:#notify
+ log.debug('msg %d'%self.rev_msg[4],'data incoming')
+ pass
+ else:
+ log.debug ('error unpacking pkg')
+
+ def request(self, id, timeout=0.5):
+ self.req_lock.acquire()
+ if not self.write(id):
+ log.debug ('Serial send error!')
+ self.req_lock.release()
+ return False
+ if self.wait_for_response(timeout):
+ if id == self.res_id:
+ log.trace ('OK')
+ else:
+ log.error ('Got unmatched response!')
+ else:
+ log.error ('Request got no response!')
+ self.req_lock.release()
+ return False
+ # clear response
+ self.req_lock.release()
+ self.res_id = None
+ return True
+
+ def write(self, id):
+ cmd = self.make_command(id)
+ if assistant.is_python3():
+ log.d("write:" + " ".join("{:02x}".format(c) for c in cmd))
+ else:
+ log.d("write:" + " ".join("{:02x}".format(ord(c)) for c in cmd))
+ self._Serial.write(cmd)
+ return True
+
+ def wait_for_response(self, timeout):
+ self.wait_event.clear()
+ return self.wait_event.wait(timeout)
+
+ def set_response(self):
+ self.wait_event.set()
+
+ def make_command(self, id):
+ #print(DataDict[id])
+ data = BoardDataDict[id].pack()
+ l = [FIX_HEAD, id, len(data)]
+ head = struct.pack("3B", *l)
+ body = head + data
+
+ if assistant.is_python3():
+ return body + chr(checksum(body)).encode('latin1')
+ else:
+ return body + chr(checksum(body))
+
+
+if __name__ == '__main__':
+
+ mboard = Transport('com10')
+ if not mboard.start():
+ import sys
+ sys.exit()
+
+ p = mboard.request(MessageID.ID_GET_VERSION)
+ log.i("result=%s"%p)
+ print('Version =[',mboard.getDataHolder()[MessageID.ID_GET_VERSION].version.decode(), mboard.getDataHolder()[MessageID.ID_GET_VERSION].build_time.decode(),"]\r\n")
+
+