Compare commits

..

28 Commits

Author SHA1 Message Date
bmy
34504d9ff9 区域赛版本 2024-07-25 23:17:27 +08:00
bmy
211b4767c1 feat: 添加新遠程頁面 2024-07-16 17:36:48 +08:00
bmy
de8012a590 feat: 增加最後對準基地運行
feat: 增加原始模型參數和任務版本
2024-07-15 23:25:40 +08:00
bmy
6205fabf34 備份 6_9 subtask 參數 2024-07-15 17:04:28 +08:00
bmy
527fa4b04b fix: 修復hanoi2右側圖像上下翻轉時過濾條件錯誤的情況
pref: 6_9較好參數
pref: 關閉hanoi2循跡模型切換
2024-07-15 16:55:03 +08:00
bmy
1edd292ac6 feat: 增加 hanoi 跳过过滤条件(存在问题) 2024-07-14 13:34:18 +08:00
bmy
b1300fc8f1 feat: 添加hanoi2物块掉落处理,添加hanoi2 停车延时,修改蓝球计数 2024-07-13 17:31:44 +08:00
bmy
5b6ca482e5 feat: 增加雙lane服務端,修改hanoi動作以應對放置在圍擋上的問題 2024-07-13 15:21:21 +08:00
bmy
ac6e055c42 暫存版本(物資盤點切換模型完成,需要重調偏移值) 2024-07-13 00:06:37 +08:00
bmy
6d9fb5b42a 提交 6_9 巡线模型参数和子任务 2024-07-12 20:31:12 +08:00
bmy
326bfb4d9a 暂存版本 2024-07-10 18:42:21 +08:00
bmy
da67c9a62b 暫存版本 2024-07-09 00:28:41 +08:00
bmy
8acecadd2a 版本暂存 2024-07-05 18:29:22 +08:00
bmy
f3e6bcc01f update: 抓蓝块、转塔、应急避险和扫黑除恶动作修改 2024-07-04 17:47:12 +08:00
bmy
c968e28b1f fix: 补全上次提交未完全的內容 2024-07-02 10:53:54 +08:00
bmy
605d218b15 pref: 新建线程初始化LLM接口 2024-06-30 21:57:01 +08:00
bmy
968f225526 pref: 在move_area离开任务区后下发零速度,避免位移指令未执行完时发送速度指令,导致侧向速度未清空的问题 2024-06-30 21:53:58 +08:00
bmy
e82c254dc4 feat: 新增文心一言接口 2024-06-28 21:34:49 +08:00
bmy
066ef112ad pref: 部分动作优化 2024-06-24 22:05:11 +08:00
bmy
90b888eac7 feat: 增加hanoi右侧动作 2024-06-22 20:47:00 +08:00
bmy
e72f1e5c24 fix: 修复 calibrate_new 方法中超过20次未找到处理的问题 2024-06-17 17:21:36 +08:00
bmy
1ac91b678b feat: 增加动作类方法 2024-06-17 17:19:18 +08:00
bmy
d340ad044d fix: 修复动作队列线程安全问题 2024-06-16 17:52:24 +08:00
bmy
0a0e597fe9 feat: 增加动作队列 2024-06-16 17:28:00 +08:00
bmy
f5be160fd9 feat: 增加任务后处理方法 2024-06-16 14:41:20 +08:00
bmy
ac72d1e3e6 feat: 增加任务段pid参数设置 2024-06-15 22:04:11 +08:00
bmy
db6ec06441 fix: 修复跳过任务时等待所有nexec执行完毕后才开始巡线的问题 2024-06-15 11:04:39 +08:00
bmy
d9a68d408d feat: 增加转塔动作 2024-06-15 10:42:41 +08:00
39 changed files with 28222 additions and 538 deletions

2
.gitignore vendored
View File

@@ -196,3 +196,5 @@ pyrightconfig.json
# log path
log/*
temp/*

169
action.py
View File

@@ -1,6 +1,8 @@
import threading
import time
import zmq
import queue
import toml
import numpy as np
from loguru import logger
from simple_pid import PID
@@ -8,13 +10,21 @@ from utils import PidWrap
bycmd = None
move = None
axis = None
cmd = None
cfg = toml.load('/home/evan/Workplace/project_main/cfg_action.toml')
def import_obj(_bycmd):
global bycmd
global move
global axis
global cmd
bycmd = _bycmd
move = move_cls()
axis = axis_cls()
cmd = cmd_cls()
class lane_cls:
def __init__(self, _speed, _time, _pid_argv = {"kp" : 1.2, "ki" : 0, "kd" : 0}) -> None:
@@ -88,12 +98,163 @@ class move_cls:
# TODO 新运动指令类,指令的发送和完成查询功能,发送时开启新线程
# TODO 轴控制指令类,增加指令后加入动作队列,非阻塞
class cmd_cls():
# FIXME 延时计算时没有关联轴速度
def __init__(self) -> None:
# 根据设备上电复位后实际位置设置
self.__axis_x_pos = 160
self.__axis_z_pos = 100
# self.__axis_claw_pos = 0
# self.__axis_claw_arm_pos = 0
# self.__axis_storage_pos = 0
pass
def z(self, _speed, _dis, _time_via = -1):
# 设置绝对位置
self.__axis_z_pos += _dis
# 如果未指定延时时间,则按照相对位移计算延时时间
if _time_via == -1:
time_via = abs(_dis) * cfg["axis"]["axis_z_time_via_alpha"]
else:
time_via = _time_via
logger.info(f"z[{self.__axis_z_pos}] speed:{_speed:.2f}, dis:{_dis:.2f}, time_via:{time_via:.2f}")
while bycmd.send_position_axis_z(_speed, self.__axis_z_pos) == -1:
pass
time.sleep(time_via)
def z2(self, _speed, _pos, _time_via = -1):
# 计算绝对位置
_dis = self.__axis_z_pos - _pos
self.__axis_z_pos = _pos
# 如果未指定延时时间,则按照相对位移计算延时时间
if _time_via == -1:
time_via = abs(_dis) * cfg["axis"]["axis_z_time_via_alpha"]
else:
time_via = _time_via
logger.info(f"z[{self.__axis_z_pos}] speed:{_speed:.2f}, pos:{_pos:.2f}, time_via:{time_via:.2f}")
while bycmd.send_position_axis_z(_speed, self.__axis_z_pos) == -1:
pass
time.sleep(time_via)
def x(self, _speed, _dis, _time_via = -1):
# 设置绝对位置
self.__axis_x_pos += _dis
# 如果未指定延时时间,则按照相对位移计算延时时间
if _time_via == -1:
time_via = abs(_dis) * cfg["axis"]["axis_z_time_via_alpha"]
else:
time_via = _time_via
logger.info(f"x[{self.__axis_x_pos}] speed:{_speed:.2f}, dis:{_dis:.2f}, time_via:{time_via:.2f}")
while bycmd.send_position_axis_x(_speed, self.__axis_x_pos) == -1:
pass
time.sleep(time_via)
def x2(self, _speed, _pos, _time_via = -1):
# 计算绝对位置
_dis = self.__axis_x_pos - _pos
self.__axis_x_pos = _pos
# 如果未指定延时时间,则按照相对位移计算延时时间
if _time_via == -1:
time_via = abs(_dis) * cfg["axis"]["axis_x_time_via_alpha"]
else:
time_via = _time_via
logger.info(f"x[{self.__axis_x_pos}] speed:{_speed:.2f}, pos:{_pos:.2f}, time_via:{time_via:.2f}")
while bycmd.send_position_axis_x(_speed, self.__axis_x_pos) == -1:
pass
time.sleep(time_via)
def camera(self, angle):
while bycmd.send_angle_camera(angle) == -1:
pass
def claw(self, angle):
while bycmd.send_angle_claw(angle) == -1:
pass
time.sleep(0.5)
def claw_arm(self, angle):
while bycmd.send_angle_claw_arm(angle) == -1:
pass
time.sleep(1)
def scoop(self, angle):
while bycmd.send_angle_scoop(angle) == -1:
pass
time.sleep(0.5)
def storage(self, angle):
while bycmd.send_angle_storage(angle) == -1:
pass
time.sleep(0.5)
def zhuan(self, angle):
while bycmd.send_angle_zhuan(angle) == -1:
pass
time.sleep(0.5)
def wait(self, _time):
time.sleep(_time)
# TODO 增加任务队列中非阻塞控制
class axis_cls():
def axis_z(self, _distance):
def __init__(self) -> None:
self.axis_queue = queue.Queue()
self.busy = False
pass
def axis_z2(self, _position):
def z(self, _distance, _time_via = -1):
while self.busy is True:
pass
def exec(self):
self.axis_queue.put(lambda: cmd.z(20, _distance, _time_via))
pass
def z2(self, _position, _time_via = -1):
while self.busy is True:
pass
self.axis_queue.put(lambda: cmd.z2(20, _position, _time_via))
pass
def x(self, _distance, _time_via = -1):
while self.busy is True:
pass
self.axis_queue.put(lambda: cmd.x(1, _distance, _time_via))
pass
def x2(self, _position, _time_via = -1):
while self.busy is True:
pass
self.axis_queue.put(lambda: cmd.x2(1, _position, _time_via))
pass
def camera(self, _angle):
while self.busy is True:
pass
self.axis_queue.put(lambda: cmd.camera(_angle))
pass
def claw(self, _angle):
while self.busy is True:
pass
self.axis_queue.put(lambda: cmd.claw(_angle))
pass
def claw_arm(self, _angle):
while self.busy is True:
pass
self.axis_queue.put(lambda: cmd.claw_arm(_angle))
pass
def scoop(self, _angle):
while self.busy is True:
pass
self.axis_queue.put(lambda: cmd.scoop(_angle))
pass
def storage(self, _angle):
while self.busy is True:
pass
self.axis_queue.put(lambda: cmd.storage(_angle))
pass
def wait(self, _time):
while self.busy is True:
pass
self.axis_queue.put(lambda: cmd.wait(_time))
def pop(self):
self.busy = True
while self.axis_queue.qsize() > 0:
logger.info(f"axis cmd {self.axis_queue.qsize()}")
self.axis_queue.get()()
self.axis_queue.task_done()
time.sleep(0.005)
self.busy = False
pass
def exec(self, _block:bool = True):
while self.busy is True:
pass
if _block is True:
self.pop()
else:
thread = threading.Thread(target=self.pop)
thread.start()
pass

203
app.py Normal file
View File

@@ -0,0 +1,203 @@
from flask import Flask, render_template, request
from flask_socketio import SocketIO
import toml
from loguru import logger
import logging
from multiprocessing import Process, Queue
import threading
import multiprocessing
import os
import time
import subprocess
import signal
import importlib
from main_upper import main_func
server_command = [
{"path": "/home/evan/Workplace/project_capture/build/", "script": "./capture"},
{"path": "/home/evan/Workplace/project_infer/lane_server/", "script": "lane_infer_server.py"},
# {"path": "/home/evan/Workplace/project_infer/lane_server/", "script": "lane_infer_server1.py"},
{"path": "/home/evan/Workplace/project_infer/yolo_server/", "script": "yolo_infer_server.py"},
]
processes = []
time_record = None
task_run_flag = False
# 日志队列
queue = Queue()
# 跳过任务 干预任务调度
skip_task_queue = Queue()
app = Flask(__name__)
app.jinja_env.variable_start_string = '[('
app.jinja_env.variable_end_string = ')]'
app.config['SECRET_KEY'] = 'secret!'
socketio = SocketIO(app, allow_unsafe_werkzeug=True)
server_process = None
task_process = None
class WebSocketHandler(logging.Handler):
def emit(self, record):
log_entry = self.format(record)
socketio.emit('log', {'level': record.levelname.lower(), 'content': log_entry})
# 设置日志
logger.remove()
handler = WebSocketHandler()
logger.add(handler, format="{time:MM-DD HH:mm:ss} {message}", level="DEBUG")
fileOptions_path = '/home/evan/Workplace/project_main'
fileOptions_list = ['cfg_args.toml','cfg_main.toml', 'cfg_subtask.toml']
cfg_args_path = os.path.join(fileOptions_path, 'cfg_args.toml')
@app.route('/')
def index():
return render_template('index.html')
@app.route('/run')
def run():
mode_index = request.args.get('mode')
config_args = toml.load(cfg_args_path)
config_args['lane_mode']['mode_index'] = int(mode_index)
with open(cfg_args_path, 'w') as config_file:
toml.dump(config_args, config_file)
return render_template('index2.html')
# @app.route('/csdn')
# def csdn():
# return render_template('csdn.html')
@socketio.on('operate')
def operate_handle(data):
global server_process
global task_process
global processes
global time_record
global task_run_flag
if data['type'] == 'save_config':
f = open(os.path.join(fileOptions_path,data['file_name']), 'w')
ret = toml.dump(data['content'], f)
logger.info(f"保存成功 {data['file_name']}")
f.close()
elif data['type'] == 'operate_server':
logger.info(data)
if data['content'] == 'run':
log_file = "server_processes.log"
log = open(log_file, "w")
time.sleep(2)
# 启动所有脚本
for i, env_info in enumerate(server_command):
env_path = env_info["path"]
script = env_info["script"]
env = os.environ.copy()
if i == 0:
process = subprocess.Popen([script], cwd=env_path, env=env, stdout=log, stderr=subprocess.STDOUT)
processes.append(process)
time.sleep(2)
process = subprocess.Popen(['python', script], cwd=env_path, env=env, stdout=log, stderr=subprocess.STDOUT)
processes.append(process)
logger.info("开启 server")
elif data['content'] == 'stop':
for process in processes:
logger.error(process.pid)
os.kill(process.pid, signal.SIGINT)
logger.info("关闭 server")
elif data['content'] == 'restart':
logger.info("重启 server")
elif data['type'] == 'operate_task':
# 任务函数
if data['content'] == 'run':
task_run_flag = True
if task_process != None:
task_process.terminate()
time_record = time.perf_counter()
task_process = Process(target=main_func, args=(queue,skip_task_queue))
task_process.start()
logger.info("开启 task")
elif data['content'] == 'stop':
task_run_flag = False
task_process.terminate()
logger.info(f"任务结束 用时{time.perf_counter() - time_record}s")
logger.info("关闭 task")
elif data['content'] == 'restart':
if task_process != None:
task_process.terminate()
task_process = Process(target=main_func, args=(queue,skip_task_queue))
task_process.start()
elif data['type'] == 'show_server_log':
content = ''
try:
with open("server_processes.log", 'r') as file:
content = file.read()
except:
pass
socketio.emit('server_log', {'type': 'server_log', 'content': content})
elif data['type'] == 'skip_task':
logger.info(data)
skip_task_queue.put(1)
# elif data['type'] == 'save_target_person':
# config_path = os.path.join(fileOptions_path, 'cfg_args.toml')
# config_args = toml.load(config_path)
# config_args['lane_mode']['mode_index'] = int(data['content'])
# with open(config_path, 'w') as config_file:
# toml.dump(config_args, config_file)
@socketio.on('connect')
def test_connect():
logger.info('Client connected')
socketio.emit('config_data', {'type': 'fileOptions', 'content': fileOptions_list})
config_data = {}
for item in fileOptions_list:
config_data[item] = toml.load(os.path.join(fileOptions_path,item))
socketio.emit('config_data', {'type': 'config_data', 'content': config_data})
socketio.emit('task_status', {'type': 'task_status', 'content': int(task_run_flag)})
def thread_function():
global queue
while True:
try:
log = queue.get()
socketio.emit('log', log)
except multiprocessing.Queue.Empty:
pass
if __name__ == '__main__':
config_path = os.path.join(fileOptions_path, 'cfg_args.toml')
config_args = toml.load(config_path)
config_args['lane_mode']['mode_index'] = 1
with open(config_path, 'w') as config_file:
toml.dump(config_args, config_file)
log_file = "server_processes.log"
log = open(log_file, "w")
time.sleep(2)
# 启动所有脚本
for i, env_info in enumerate(server_command):
env_path = env_info["path"]
script = env_info["script"]
env = os.environ.copy()
if i == 0:
process = subprocess.Popen([script], cwd=env_path, env=env, stdout=log, stderr=subprocess.STDOUT)
processes.append(process)
time.sleep(2)
process = subprocess.Popen(['python', script], cwd=env_path, env=env, stdout=log, stderr=subprocess.STDOUT)
processes.append(process)
thread1 = threading.Thread(target=thread_function, daemon = True)
thread1.start()
socketio.run(app, host='0.0.0.0', port=5001, allow_unsafe_werkzeug=True)
if server_process != None:
server_process.terminate()
if task_process != None:
task_process.terminate()
for process in processes:
logger.error(process.pid)
os.kill(process.pid, signal.SIGINT)

4
cfg_action.toml Normal file
View File

@@ -0,0 +1,4 @@
[axis]
# 轴运动延时系数
axis_z_time_via_alpha = 0.05
axis_x_time_via_alpha = 0.01

14
cfg_args.toml Normal file
View File

@@ -0,0 +1,14 @@
[lane_mode]
mode_index = 1
[task]
Subtask_enable = true
GetBlock_enable = true
PutBlock_enable = true
GetBBall_enable = true
UpTower_enable = true
GetRBall_enable = true
PutBBall_enable = true
PutHanoi_enable = true
MoveArea_enable = false
KickAss_enable = true

View File

@@ -2,29 +2,18 @@
logger_filename = "log/file_{time}.log"
logger_format = "{time} {level} {message}"
[task]
GetBlock_enable = true # 人员施救使能
PutBlock_enable = true # 紧急转移使能
GetBBall_enable = true # 整装上阵使能
UpTower_enable = true # 通信抢修使能
GetRBall_enable = true # 高空排险使能
PutBBall_enable = true # 派发物资使能
PutHanoi_enable = true # 物资盘点使能
MoveArea_enable = true # 应急避险使能
KickAss_enable = true # 扫黑除暴使能
[find_counts]
GetBlock_counts = 10 # 人员施救计数
PutBlock_counts = 5 # 紧急转移计数
GetBBall_counts = 1 # 整装上阵计数
UpTower_counts = 3 # 通信抢修计数
GetRBall_counts = 10 # 高空排险计数
PutBBall_counts = 5 # 派发物资计数
PutHanoi1_counts = 10 # 物资盘点计数
PutHanoi2_counts = 2 # 物资盘点计数
PutHanoi3_counts = 2 # 物资盘点计数
MoveArea1_counts = 6 # 应急避险计数
MoveArea2_counts = 1700 # 应急避险第二阶段计数
KickAss_counts = 10 # 扫黑除暴计数
GetBlock_counts = 5
PutBlock_counts = 12
GetBBall_counts = 5
UpTower_counts = 3
GetRBall_counts = 10
PutBBall_counts = 15
PutHanoi1_counts = 7
PutHanoi2_counts = 2
PutHanoi3_counts = 5
MoveArea1_counts = 6
MoveArea2_counts = 1700
KickAss_counts = 10

29
cfg_main.toml.bak Normal file
View File

@@ -0,0 +1,29 @@
[debug]
logger_filename = "log/file_{time}.log"
logger_format = "{time} {level} {message}"
[task]
Subtask_enable = false
GetBlock_enable = false
PutBlock_enable = false
GetBBall_enable = false
UpTower_enable = false
GetRBall_enable = false
PutBBall_enable = false
PutHanoi_enable = false
MoveArea_enable = true
KickAss_enable = true
[find_counts]
GetBlock_counts = 8
PutBlock_counts = 5
GetBBall_counts = 3
UpTower_counts = 3
GetRBall_counts = 10
PutBBall_counts = 10
PutHanoi1_counts = 10
PutHanoi2_counts = 2
PutHanoi3_counts = 2
MoveArea1_counts = 6
MoveArea2_counts = 1700
KickAss_counts = 10

View File

@@ -1,27 +1,61 @@
[get_block]
# first_block = "red"
pid_kp = 1.0
pid_ki = 0
pid_kd = 0
first_block = "blue"
[put_block]
pid_kp = 1.2
pid_ki = 0
pid_kd = 0
[get_bball]
pid_kp = 1.2
pid_ki = 0
pid_kd = 0
[up_tower]
pid_kp = 1.0
pid_ki = 0
pid_kd = 0
[get_rball]
pid_kp = 1.5
pid_ki = 0
pid_kd = 0
[put_bball]
pid_kp = 2.0
pid_ki = 0
pid_kd = 0
[put_hanoi1]
pid_kp = 0.7
pid_ki = 0
pid_kd = 0
[put_hanoi2]
pos_gap = 160 # 标定值,两个放置位置的标定距离
pos_lp = 2 # 1\2\3 数字越小越靠近红色置物区
pos_mp = 1
pid_kp = 1.0
pid_ki = 0
pid_kd = 0
pos_gap = 160
first_target = "mp"
[put_hanoi3]
pid_kp = 1.7
pid_ki = 0
pid_kd = 0
[move_area]
llm_enable = false # 大模型机器人
pid_kp = 1.2
pid_ki = 0
pid_kd = 0
llm_enable = false
[kick_ass]
pos_gap1 = 150 # 目标牌和第一个 person 之间的距离
pos_gap2 = 80 # person 之间的距离
pid_kp = 0.8
pid_ki = 0
pid_kd = 0
pos_gap1 = 150
pos_gap2 = 80
target_person = 1

61
cfg_subtask.toml.6_9.bak Normal file
View File

@@ -0,0 +1,61 @@
[get_block]
pid_kp = 1.2
pid_ki = 0
pid_kd = 0
first_block = "blue"
[put_block]
pid_kp = 1.2
pid_ki = 0
pid_kd = 0
[get_bball]
pid_kp = 1.2
pid_ki = 0
pid_kd = 0
[up_tower]
pid_kp = 1.1
pid_ki = 0
pid_kd = 0
[get_rball]
pid_kp = 0.8
pid_ki = 0
pid_kd = 0
[put_bball]
pid_kp = 1.6
pid_ki = 0
pid_kd = 0
[put_hanoi1]
pid_kp = 0.7
pid_ki = 0
pid_kd = 0
[put_hanoi2]
pid_kp = 2.0
pid_ki = 0
pid_kd = 0
pos_gap = 160
first_target = "mp"
[put_hanoi3]
pid_kp = 1.3
pid_ki = 0
pid_kd = 0
[move_area]
pid_kp = 1.2
pid_ki = 0
pid_kd = 0
llm_enable = false
[kick_ass]
pid_kp = 0.8
pid_ki = 0
pid_kd = 0
pos_gap1 = 150
pos_gap2 = 80
target_person = 1

61
cfg_subtask.toml.7126.bak Normal file
View File

@@ -0,0 +1,61 @@
[get_block]
pid_kp = 1.2
pid_ki = 0
pid_kd = 0
first_block = "blue"
[put_block]
pid_kp = 1.3
pid_ki = 0
pid_kd = 0
[get_bball]
pid_kp = 1.2
pid_ki = 0
pid_kd = 0
[up_tower]
pid_kp = 1.3
pid_ki = 0
pid_kd = 0
[get_rball]
pid_kp = 1.0
pid_ki = 0
pid_kd = 0
[put_bball]
pid_kp = 1.3
pid_ki = 0
pid_kd = 0
[put_hanoi1]
pid_kp = 1.3
pid_ki = 0
pid_kd = 0
[put_hanoi2]
pid_kp = 1.2
pid_ki = 0
pid_kd = 0
pos_gap = 160
first_target = "mp"
[put_hanoi3]
pid_kp = 1.2
pid_ki = 0
pid_kd = 0
[move_area]
pid_kp = 1.4
pid_ki = 0
pid_kd = 0
llm_enable = false
[kick_ass]
pid_kp = 1.2
pid_ki = 0
pid_kd = 0
pos_gap1 = 150
pos_gap2 = 80
target_person = 1

61
cfg_subtask.toml.7131.bak Normal file
View File

@@ -0,0 +1,61 @@
[get_block]
pid_kp = 1.2
pid_ki = 0
pid_kd = 0
first_block = "blue"
[put_block]
pid_kp = 1.2
pid_ki = 0
pid_kd = 0
[get_bball]
pid_kp = 1.2
pid_ki = 0
pid_kd = 0
[up_tower]
pid_kp = 1.3
pid_ki = 0
pid_kd = 0
[get_rball]
pid_kp = 0.8
pid_ki = 0
pid_kd = 0
[put_bball]
pid_kp = 1.6
pid_ki = 0
pid_kd = 0
[put_hanoi1]
pid_kp = 0.7
pid_ki = 0
pid_kd = 0
[put_hanoi2]
pid_kp = 2.5
pid_ki = 0
pid_kd = 0
pos_gap = 160
first_target = "mp"
[put_hanoi3]
pid_kp = 1.3
pid_ki = 0
pid_kd = 0
[move_area]
pid_kp = 1.2
pid_ki = 0
pid_kd = 0
llm_enable = false
[kick_ass]
pid_kp = 0.8
pid_ki = 0
pid_kd = 0
pos_gap1 = 150
pos_gap2 = 80
target_person = 1

61
cfg_subtask.toml.7154.bak Normal file
View File

@@ -0,0 +1,61 @@
[get_block]
pid_kp = 1.2
pid_ki = 0
pid_kd = 0
first_block = "blue"
[put_block]
pid_kp = 1.2
pid_ki = 0
pid_kd = 0
[get_bball]
pid_kp = 1.2
pid_ki = 0
pid_kd = 0
[up_tower]
pid_kp = 1
pid_ki = 0
pid_kd = 0
[get_rball]
pid_kp = 1.2
pid_ki = 0
pid_kd = 0
[put_bball]
pid_kp = 2
pid_ki = 0
pid_kd = 0
[put_hanoi1]
pid_kp = 0.7
pid_ki = 0
pid_kd = 0
[put_hanoi2]
pid_kp = 1
pid_ki = 0
pid_kd = 0
pos_gap = 160
first_target = "mp"
[put_hanoi3]
pid_kp = 2.5
pid_ki = 0
pid_kd = 0
[move_area]
pid_kp = 1.2
pid_ki = 0
pid_kd = 0
llm_enable = false
[kick_ass]
pid_kp = 0.8
pid_ki = 0
pid_kd = 0
pos_gap1 = 150
pos_gap2 = 80
target_person = 1

61
cfg_subtask.toml.bak.7102 Normal file
View File

@@ -0,0 +1,61 @@
[get_block]
pid_kp = 2.0
pid_ki = 0
pid_kd = 0
first_block = "blue"
[put_block]
pid_kp = 2.0
pid_ki = 0
pid_kd = 0.1
[get_bball]
pid_kp = 2.0
pid_ki = 0
pid_kd = 0
[up_tower]
pid_kp = 2.8
pid_ki = 0
pid_kd = 0
[get_rball]
pid_kp = 2.0
pid_ki = 0
pid_kd = 0
[put_bball]
pid_kp = 2.4
pid_ki = 0
pid_kd = 0
[put_hanoi1]
pid_kp =
pid_ki = 0
pid_kd = 0
[put_hanoi2]
pid_kp = 1.2
pid_ki = 0
pid_kd = 0
pos_gap = 160
first_target = "mp"
[put_hanoi3]
pid_kp = 2.5
pid_ki = 0
pid_kd = 0
[move_area]
pid_kp = 2.0
pid_ki = 0
pid_kd = 0
llm_enable = false
[kick_ass]
pid_kp = 0.8
pid_ki = 0
pid_kd = 0
pos_gap1 = 150
pos_gap2 = 80
target_person = 1

61
cfg_subtask.toml.raw.bak Normal file
View File

@@ -0,0 +1,61 @@
[get_block]
pid_kp = 1.2
pid_ki = 0
pid_kd = 0
first_block = "blue"
[put_block]
pid_kp = 1.2
pid_ki = 0
pid_kd = 0
[get_bball]
pid_kp = 1.2
pid_ki = 0
pid_kd = 0
[up_tower]
pid_kp = 1.0
pid_ki = 0
pid_kd = 0
[get_rball]
pid_kp = 1.2
pid_ki = 0
pid_kd = 0
[put_bball]
pid_kp = 1.8
pid_ki = 0
pid_kd = 0
[put_hanoi1]
pid_kp = 0.7
pid_ki = 0
pid_kd = 0
[put_hanoi2]
pid_kp = 1.0
pid_ki = 0
pid_kd = 0
pos_gap = 160
first_target = "mp"
[put_hanoi3]
pid_kp = 1.5
pid_ki = 0
pid_kd = 0
[move_area]
pid_kp = 1.2
pid_ki = 0
pid_kd = 0
llm_enable = false
[kick_ass]
pid_kp = 0.8
pid_ki = 0
pid_kd = 0
pos_gap1 = 150
pos_gap2 = 80
target_person = 1

67
main.py
View File

@@ -1,40 +1,47 @@
import toml
import queue
import threading
import queue
from loguru import logger
import subtask as sb
import majtask as mj
from by_cmd_py import by_cmd_py
import time
import action as act
# 读取配置
cfg_main = toml.load('cfg_main.toml')
cfg_subtask = toml.load('cfg_subtask.toml')
# logger.add(cfg_main['debug']['logger_filename'], format=cfg_main['debug']['logger_format'], retention = 5, level="INFO")
running = True
cmd_py_obj = by_cmd_py()
sb.import_obj(cmd_py_obj)
act.import_obj(cmd_py_obj)
# 读取配置
cfg_main = toml.load('cfg_main.toml')
# 配置日志输出
logger.add(cfg_main['debug']['logger_filename'], format=cfg_main['debug']['logger_format'], retention = 5, level="INFO")
act.axis.camera(0)
act.axis.x2(140)
act.axis.storage(20)
act.axis.scoop(25)
act.axis.exec()
# 向任务队列添加任务
task_queue = queue.Queue()
task_queue.put(sb.task(sb.get_block1, cfg_main['find_counts']['GetBlock_counts'], cfg_main['task']['GetBlock_enable']))
task_queue.put(sb.task(sb.get_block2, cfg_main['find_counts']['GetBlock_counts'], cfg_main['task']['GetBlock_enable']))
task_queue.put(sb.task(sb.put_block, cfg_main['find_counts']['PutBlock_counts'], cfg_main['task']['GetBlock_enable']))
task_queue.put(sb.task(sb.get_bball, cfg_main['find_counts']['GetBBall_counts'], cfg_main['task']['GetBBall_enable']))
# TODO 添加一个空任务用于提前降 z 轴
task_queue.put(sb.task(sb.up_tower, cfg_main['find_counts']['UpTower_counts'], cfg_main['task']['UpTower_enable']))
task_queue.put(sb.task(sb.get_rball, cfg_main['find_counts']['GetRBall_counts'], cfg_main['task']['GetRBall_enable']))
task_queue.put(sb.task(sb.put_bball, cfg_main['find_counts']['PutBBall_counts'], cfg_main['task']['GetBBall_enable'] and cfg_main['task']['PutBBall_enable']))
task_queue.put(sb.task(sb.put_hanoi1, cfg_main['find_counts']['PutHanoi1_counts'], True)) # 无论是否进行任务,检测标识并转向都是必须进行的
task_queue.put(sb.task(sb.put_hanoi2, cfg_main['find_counts']['PutHanoi2_counts'], cfg_main['task']['PutHanoi_enable']))
task_queue.put(sb.task(sb.put_hanoi3, cfg_main['find_counts']['PutHanoi2_counts'], cfg_main['task']['PutHanoi_enable']))
task_queue.put(sb.task(sb.move_area1, cfg_main['find_counts']['MoveArea1_counts'], cfg_main['task']['MoveArea_enable']))
task_queue.put(sb.task(sb.move_area2, cfg_main['find_counts']['MoveArea2_counts'], cfg_main['task']['MoveArea_enable']))
task_queue.put(sb.task(sb.kick_ass, cfg_main['find_counts']['KickAss_counts'], cfg_main['task']['KickAss_enable']))
# if cfg_main['task']['Subtask_enable'] is True:
# task_queue.put(sb.task("人员施救第一块", sb.get_block1, cfg_main['find_counts']['GetBlock_counts'], cfg_main['task']['GetBlock_enable']))
# task_queue.put(sb.task("人员施救第二块", sb.get_block2, cfg_main['find_counts']['GetBlock_counts'], cfg_main['task']['GetBlock_enable']))
# task_queue.put(sb.task("紧急转移", sb.put_block, cfg_main['find_counts']['PutBlock_counts'], cfg_main['task']['GetBlock_enable']))
# task_queue.put(sb.task("整装上阵", sb.get_bball, cfg_main['find_counts']['GetBBall_counts'], cfg_main['task']['GetBBall_enable']))
# # TODO 添加一个空任务用于提前降 z 轴
# task_queue.put(sb.task("通信抢修", sb.up_tower, cfg_main['find_counts']['UpTower_counts'], cfg_main['task']['UpTower_enable']))
# task_queue.put(sb.task("高控排险", sb.get_rball, cfg_main['find_counts']['GetRBall_counts'], cfg_main['task']['GetRBall_enable']))
# task_queue.put(sb.task("派发物资", sb.put_bball, cfg_main['find_counts']['PutBBall_counts'], cfg_main['task']['GetBBall_enable'] and cfg_main['task']['PutBBall_enable']))
# task_queue.put(sb.task("物资盘点一阶段", sb.put_hanoi1, cfg_main['find_counts']['PutHanoi1_counts'], enable = True)) # 无论是否进行任务,检测标识并转向都是必须进行的
# task_queue.put(sb.task("物资盘点二阶段", sb.put_hanoi2, cfg_main['find_counts']['PutHanoi2_counts'], cfg_main['task']['PutHanoi_enable']))
# task_queue.put(sb.task("物资盘点三阶段", sb.put_hanoi3, cfg_main['find_counts']['PutHanoi3_counts'], enable = True))
# task_queue.put(sb.task("应急避险一阶段", sb.move_area1, cfg_main['find_counts']['MoveArea1_counts'], cfg_main['task']['MoveArea_enable']))
# task_queue.put(sb.task("应急避险二阶段", sb.move_area2, cfg_main['find_counts']['MoveArea2_counts'], cfg_main['task']['MoveArea_enable']))
# task_queue.put(sb.task("扫黑除暴", sb.kick_ass, cfg_main['find_counts']['KickAss_counts'], cfg_main['task']['KickAss_enable']))
# 将任务队列传入调度模块中
task_queuem_t = sb.task_queuem(task_queue)
@@ -46,22 +53,12 @@ def worker_thread():
# 启动工作线程
worker = threading.Thread(target=worker_thread, daemon=True)
worker.start()
# if (cmd_py_obj.send_angle_camera(180) == -1):
# cmd_py_obj.send_angle_camera(180)
cmd_py_obj.send_position_axis_x(1, 140)
time.sleep(0.5)
cmd_py_obj.send_angle_storage(20)
time.sleep(0.5)
cmd_py_obj.send_angle_scoop(25)
time.sleep(2)
# 创建主任务
main_task_t = mj.main_task(cmd_py_obj) # 初始化时传入 zmq socket 对象
# 主线程仅在子线程搜索 (SEARCHING) 和 空闲 (IDLE) 状态下进行操作
# while task_queuem_t.busy is True:
try:
while True:
while running:
if task_queuem_t.status is sb.task_queuem_status.EXECUTING:
pass
else:
@@ -75,5 +72,9 @@ except KeyboardInterrupt:
time.sleep(0.1)
cmd_py_obj.send_speed_omega(0)
time.sleep(0.1)
for _ in range(3):
cmd_py_obj.send_speed_x(0)
time.sleep(0.1)
cmd_py_obj.send_speed_omega(0)
time.sleep(0.1)
logger.info("Main thread exit")

109
main_upper.py Normal file
View File

@@ -0,0 +1,109 @@
import toml
import threading
import queue
from loguru import logger
import subtask as sb
import majtask as mj
from by_cmd_py import by_cmd_py
import time
import action as act
import logging
import signal
running = True
def main_func(_queue, _skip_queue):
if _queue != None:
# 日志重定向
class Handler(logging.Handler):
def emit(self, record):
log_entry = self.format(record)
_queue.put({'level': record.levelname.lower(), 'content': log_entry})
logger.remove()
handler = Handler()
logger.add(handler, format="{time:MM-DD HH:mm:ss} {message}", level="DEBUG")
def signal_handler(sig, frame):
global running
running = False
signal.signal(signal.SIGTERM, signal_handler)
cmd_py_obj = by_cmd_py(_queue)
sb.import_obj(cmd_py_obj, _skip_queue)
act.import_obj(cmd_py_obj)
# 读取配置
cfg_main = toml.load('/home/evan/Workplace/project_main/cfg_main.toml')
cfg_args = toml.load('/home/evan/Workplace/project_main/cfg_args.toml')
# logger.info(cfg_main)
cfg_subtask = toml.load('/home/evan/Workplace/project_main/cfg_subtask.toml')
# 配置日志输出
logger.add(cfg_main['debug']['logger_filename'], format=cfg_main['debug']['logger_format'], retention = 5, level="INFO")
logger.info(cfg_args)
act.axis.camera(0)
act.axis.x2(140)
act.axis.storage(20)
act.axis.scoop(25)
act.axis.claw_arm(225)
act.axis.exec()
logger.info(cfg_main)
# 向任务队列添加任务
task_queue = queue.Queue()
if cfg_args['task']['Subtask_enable'] is True:
task_queue.put(sb.task("人员施救第一块", sb.get_block1, cfg_main['find_counts']['GetBlock_counts'], cfg_args['task']['GetBlock_enable']))
task_queue.put(sb.task("人员施救第二块", sb.get_block2, cfg_main['find_counts']['GetBlock_counts'], cfg_args['task']['GetBlock_enable']))
task_queue.put(sb.task("紧急转移", sb.put_block, cfg_main['find_counts']['PutBlock_counts'], cfg_args['task']['GetBlock_enable']))
task_queue.put(sb.task("整装上阵", sb.get_bball, cfg_main['find_counts']['GetBBall_counts'], cfg_args['task']['GetBBall_enable']))
# # TODO 添加一个空任务用于提前降 z 轴
task_queue.put(sb.task("通信抢修", sb.up_tower, cfg_main['find_counts']['UpTower_counts'], cfg_args['task']['UpTower_enable']))
task_queue.put(sb.task("高空排险", sb.get_rball, cfg_main['find_counts']['GetRBall_counts'], cfg_args['task']['GetRBall_enable']))
task_queue.put(sb.task("派发物资", sb.put_bball, cfg_main['find_counts']['PutBBall_counts'], cfg_args['task']['GetBBall_enable'] and cfg_args['task']['PutBBall_enable']))
task_queue.put(sb.task("物资盘点一阶段", sb.put_hanoi1, cfg_main['find_counts']['PutHanoi1_counts'], enable = True)) # 无论是否进行任务,检测标识并转向都是必须进行的
task_queue.put(sb.task("物资盘点二阶段", sb.put_hanoi2, cfg_main['find_counts']['PutHanoi2_counts'], cfg_args['task']['PutHanoi_enable']))
task_queue.put(sb.task("物资盘点三阶段", sb.put_hanoi3, cfg_main['find_counts']['PutHanoi3_counts'], enable = True))
task_queue.put(sb.task("应急避险一阶段", sb.move_area1, cfg_main['find_counts']['MoveArea1_counts'], cfg_args['task']['MoveArea_enable']))
task_queue.put(sb.task("应急避险二阶段", sb.move_area2, cfg_main['find_counts']['MoveArea2_counts'], cfg_args['task']['MoveArea_enable']))
task_queue.put(sb.task("扫黑除暴", sb.kick_ass, cfg_main['find_counts']['KickAss_counts'], cfg_args['task']['KickAss_enable']))
# 将任务队列传入调度模块中
task_queuem_t = sb.task_queuem(task_queue)
# 创建任务队列的工作线程
def worker_thread():
while task_queuem_t.exec(_skip_queue) is True:
pass
# 启动工作线程
worker = threading.Thread(target=worker_thread, daemon=True)
worker.start()
# 创建主任务
main_task_t = mj.main_task(cmd_py_obj) # 初始化时传入 zmq socket 对象
try:
while running:
if task_queuem_t.status is sb.task_queuem_status.EXECUTING:
pass
else:
main_task_t.run()
pass
except KeyboardInterrupt:
logger.info("Interrupt received, stopping...")
# 停车
for _ in range(3):
cmd_py_obj.send_speed_x(0)
time.sleep(0.1)
cmd_py_obj.send_speed_omega(0)
time.sleep(0.1)
for _ in range(3):
cmd_py_obj.send_speed_x(0)
time.sleep(0.1)
cmd_py_obj.send_speed_omega(0)
time.sleep(0.1)
logger.info("Main thread exit")
if __name__ == '__main__':
from multiprocessing import Queue
temp = Queue()
main_func(None, temp)

View File

@@ -4,13 +4,18 @@ import time
import numpy as np
from loguru import logger
import utils
from utils import PidWrap
import variable as var
class main_task():
def __init__(self,by_cmd):
# lane infer server
self.context = zmq.Context()
self.socket = self.context.socket(zmq.REQ)
self.socket.connect("tcp://localhost:6666")
# lane infer server1
# self.context1 = zmq.Context()
# self.socket1 = self.context.socket(zmq.REQ)
# self.socket1.connect("tcp://localhost:6669")
# 赛道回归相关
self.x = 0
@@ -22,9 +27,9 @@ class main_task():
self.by_cmd = by_cmd
# 转向 pid
# self.pid1 = PidWrap(0.5, 0, 0, output_limits=55) # 1.2
self.pid1 = PidWrap(1.2, 0, 0, output_limits=50) # 1.2
self.pid1.set_target(0)
# var.pid_turning = PidWrap(0.5, 0, 0, output_limits=55) # 1.2
# pid 参数在
var.pid_turning.set_target(0)
def parse_data(self,data):
if data.get('code') == 0:
@@ -55,24 +60,25 @@ class main_task():
self.x = self.x / 3
self.y = self.y / 3
self.lane_error = self.x - 160
utils.lane_error = self.lane_error # 赋全局变量
var.lane_error = self.lane_error # 赋全局变量
self.error_counts = 0
self.x = 0
self.y = 0
error_abs = abs(self.lane_error)
if error_abs > 50:
speed = 15
# speed = 11
speed = 13
elif error_abs > 45:
speed = 15
elif error_abs > 35:
speed = 15
speed = 17
elif error_abs > 25:
speed = 15
elif error_abs > 15:
speed = 15
else:
speed = 18
elif error_abs > 15:
speed = 19
else:
speed = 21
# lane_model initial
# if error_abs > 50:
@@ -88,16 +94,20 @@ class main_task():
# else:
# speed = 18
if utils.task_speed != 0:
speed = utils.task_speed
if var.task_speed != 0:
speed = var.task_speed
self.by_cmd.send_speed_x(speed)
# pid_out = self.pid1.get(self.lane_error*0.65)
pid_out = self.pid1.get(self.lane_error)
# pid_out = var.pid_turning.get(self.lane_error*0.65)
pid_out = var.pid_turning.get(self.lane_error)
# pid_out = -pid_out
logger.debug(f"err={self.lane_error}, pwm out={pid_out}")
# logger.debug(f"err={self.lane_error}, pwm out={pid_out}")
self.by_cmd.send_speed_omega(pid_out)
# if var.switch_lane_model:
# self.socket1.send_string("")
# resp = self.socket1.recv_pyobj()
# else:
# self.socket.send_string("")
# resp = self.socket.recv_pyobj()
self.socket.send_string("")
resp = self.socket.recv_pyobj()
# logger.info(resp)
self.parse_data(resp)

BIN
static/csdn.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 188 KiB

1
static/index.css Normal file

File diff suppressed because one or more lines are too long

1
static/index.js Normal file

File diff suppressed because one or more lines are too long

6046
static/socket.io.js Normal file

File diff suppressed because it is too large Load Diff

12014
static/vue.js Normal file

File diff suppressed because it is too large Load Diff

1272
subtask.py

File diff suppressed because it is too large Load Diff

1497
subtask_69.py Normal file

File diff suppressed because it is too large Load Diff

1412
subtask_7123.py Normal file

File diff suppressed because it is too large Load Diff

1406
subtask_7126.py Normal file

File diff suppressed because it is too large Load Diff

1487
subtask_7154.py Normal file

File diff suppressed because it is too large Load Diff

1497
subtask_raw.py Normal file

File diff suppressed because it is too large Load Diff

112
templates/csdn.html Normal file
View File

@@ -0,0 +1,112 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>第十九届全国大学生智能汽车竞赛 百度智慧交通创意组 “风雨同舟”比赛规则_全国大学生智能汽车竞赛 智慧交通创意-CSDN博客</title>
<script src="/static/vue.js"></script>
<script src="static/socket.io.js"></script>
<style>
body, html {
margin: 0;
padding: 0;
height: 100%;
overflow: hidden;
}
#app {
width: 100vw;
height: 100vh;
overflow: hidden;
position: relative;
}
.background-container {
width: 100%;
height: 100%;
background-size: cover;
background-position: center;
transition: background-position 0.1s ease-out;
}
.floating-buttons {
position: fixed;
bottom: 20px;
left: 0;
right: 0;
display: flex;
justify-content: center;
gap: 20px;
z-index: 10;
}
.floating-button {
width: 160px;
height: 40px;
border-radius: 20px;
background-color: #fc5531;
border: none;
color: white;
font-size: 16px;
cursor: pointer;
transition: background-color 0.3s;
}
.floating-button:hover {
background-color: #fc5531;
}
</style>
</head>
<body>
<div id="app">
<div class="background-container"
:style="backgroundStyle"
@mousemove="handleMouseMove"
ref="container">
</div>
<div class="floating-buttons">
<button class="floating-button" @click="handleButton1Click">打开 CSDN APP</button>
<button class="floating-button" @click="handleButton2Click">小程序看全文</button>
</div>
</div>
<script>
new Vue({
el: '#app',
data: {
imageSrc: '/static/csdn.png', // 使用大尺寸占位图片
backgroundPosition: '0%'
},
computed: {
backgroundStyle() {
return {
backgroundImage: `url(${this.imageSrc})`,
backgroundPosition: `center ${this.backgroundPosition}`
};
}
},
methods: {
handleMouseMove(event) {
const containerRect = this.$refs.container.getBoundingClientRect();
const mouseY = event.clientY - containerRect.top;
const scrollPercent = (mouseY / containerRect.height) * 100;
this.backgroundPosition = `${scrollPercent}%`;
},
handleButton1Click() {
// alert('按钮 1 被点击了');
},
handleButton2Click() {
this.socket.emit('operate', { type: 'skip_task', content: '' });
},
onImageLoad() {
console.log('背景图片加载完成');
// 这里可以添加图片加载完成后的额外操作
}
},
mounted() {
const img = new Image();
img.onload = this.onImageLoad;
img.src = this.imageSrc;
this.socket = io('http://' + document.domain + ':5001');
}
});
</script>
</body>
</html>

302
templates/index.html Normal file
View File

@@ -0,0 +1,302 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>btl143</title>
<!-- <link rel="stylesheet" href="https://unpkg.com/element-ui/lib/theme-chalk/index.css">
<script src="https://cdn.jsdelivr.net/npm/vue@2.6.14/dist/vue.js"></script>
<script src="https://unpkg.com/element-ui/lib/index.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/socket.io/4.0.1/socket.io.js"></script> -->
<link rel="stylesheet" href="static/index.css">
<script src="static/vue.js"></script>
<script src="static/index.js"></script>
<script src="static/socket.io.js"></script>
<style>
body {
font-family: Arial, sans-serif;
margin: 0;
padding: 0;
background-color: #f5f7fa;
}
.app-container {
padding: 20px;
max-width: 1200px;
margin: 0 auto;
}
.section-title {
margin-top: 30px;
margin-bottom: 20px;
color: #303133;
border-bottom: 1px solid #dcdfe6;
padding-bottom: 10px;
}
.button-group {
margin-bottom: 20px;
}
.config-form {
background-color: white;
padding: 20px;
border-radius: 4px;
box-shadow: 0 2px 12px 0 rgba(0,0,0,.1);
}
.log-container {
height: 400px;
overflow-y: auto;
background-color: white;
border-radius: 4px;
padding: 10px;
box-shadow: 0 2px 12px 0 rgba(0,0,0,.1);
}
.log-container1 {
height: 400px;
overflow-y: auto;
background-color: white;
border-radius: 4px;
padding: 10px;
box-shadow: 0 2px 12px 0 rgba(0,0,0,.1);
}
.log-entry {
margin-bottom: 5px;
font-family: monospace;
}
.log-info { color: #409EFF; }
.log-error { color: #F56C6C; }
.log-warning { color: #E6A23C; }
.log-debug { color: #909399; }
</style>
</head>
<body>
<div id="app">
<el-container class="app-container">
<el-main>
<h1 class="section-title">btl143 upper</h1>
<el-row :gutter="20" class="button-group">
<el-col :xs="24" :sm="8">
<el-button @click="startServer" type="success" style="width: 100%">开启 server</el-button>
</el-col>
<el-col :xs="24" :sm="8">
<el-button @click="stopServer" type="danger" style="width: 100%">关闭 server</el-button>
</el-col>
<el-col :xs="24" :sm="8">
<el-button @click="restartServer" type="warning" style="width: 100%">重启 server</el-button>
</el-col>
</el-row>
<el-row :gutter="20" class="button-group">
<el-col :xs="24" :sm="8">
<el-button @click="startTask" type="success" style="width: 100%">开启 task</el-button>
</el-col>
<el-col :xs="24" :sm="8">
<el-button @click="stopTask" type="danger" style="width: 100%">关闭 task</el-button>
</el-col>
<el-col :xs="24" :sm="8">
<el-button @click="restartTask" type="warning" style="width: 100%">重启 task</el-button>
</el-col>
</el-row>
<el-row :gutter="20" class="button-group">
<el-col :xs="24" :sm="8">
<el-button @click="showServerLog" type="success" style="width: 100%">
{{ showServerLogFlag ? '关闭' : '打开' }} server 日志
</el-button>
</el-col>
<el-col :xs="24" :sm="8">
</el-col>
<el-col :xs="24" :sm="8">
<el-button @click="skipTask" type="success" style="width: 100%">
关闭
</el-button>
</el-col>
</el-row>
<el-select v-model="selectedFile" placeholder="" @change="loadConfig" style="width: 100%; margin-bottom: 20px;">
<el-option
v-for="item in fileOptions"
:key="item"
:label="item"
:value="item">
</el-option>
</el-select>
<!-- <el-button v-if="showConfigForm" @click="toggleConfigForm" type="primary" style="margin-bottom: 20px;">
{{ showConfigForm ? '关闭' : '打开' }} 配置
</el-button> -->
<el-form v-if="showConfigForm && config" class="config-form">
<el-button @click="saveConfig" type="primary" style="margin-top: 20px;">保存配置</el-button>
<el-button v-if="showConfigForm" @click="toggleConfigForm" type="primary" style="margin-bottom: 20px;">
{{ showConfigForm ? '关闭' : '打开' }} 配置
</el-button>
<div v-for="(section, sectionName) in config" :key="sectionName">
<h3>{{ sectionName }}</h3>
<el-row :gutter="20">
<el-col v-for="(value, key) in section" :key="key" :xs="24" :sm="12" :md="8" :lg="6">
<el-form-item :label="key">
<el-select v-if="sectionName === 'lane_mode'" v-model="config[sectionName][key]">
<el-option
v-for="item in target_person_options"
:key="item.value"
:label="item.label"
:value="item.value">
</el-option>
</el-select>
<el-switch
v-if="typeof value === 'boolean'"
v-model="config[sectionName][key]">
</el-switch>
<el-input-number
v-else-if="typeof value === 'number'"
v-model="config[sectionName][key]"
:controls="true"
:min="Number.MIN_SAFE_INTEGER"
:max="Number.MAX_SAFE_INTEGER"
:step="1"
style="width: 100%;">
</el-input-number>
<el-input
v-else
v-model="config[sectionName][key]">
</el-input>
</el-form-item>
</el-col>
</el-row>
</div>
</el-form>
<h2 class="section-title">Log Display</h2>
<div v-if="showServerLogFlag" class="log-container1" v-html="formatServerLog(ServerLog)"></div>
<div class="log-container">
<div v-for="logEntry in logs" :key="logEntry.id" :class="['log-entry', `log-${logEntry.level}`]">
[{{ logEntry.level.toUpperCase() }}] {{ logEntry.content }}
</div>
</div>
</el-main>
</el-container>
</div>
<script>
new Vue({
el: '#app',
data: {
logs: [],
selectedFile: null,
showConfigForm: false,
fileOptions: [],
config: null,
files: {},
ServerLog: "",
showServerLogFlag: false,
timer: null,
target_person_options: [{
value: 1,
label: '6_9'
}, {
value: 2,
label: '7_10_2'
}, {
value: 3,
label: '7_14_2'
}, {
value: 4,
label: '7_15_4'
}],
},
methods: {
loadConfig() {
this.config = this.files[this.selectedFile];
this.showConfigForm = true;
},
toggleConfigForm() {
this.showConfigForm = !this.showConfigForm;
},
startServer() {
this.socket.emit('operate', {type: 'operate_server', content: 'run'});
},
stopServer() {
this.socket.emit('operate', {type: 'operate_server', content: 'stop'});
},
restartServer() {
this.socket.emit('operate', {type: 'operate_server', content: 'restart'});
},
startTask() {
this.socket.emit('operate', {type: 'operate_task', content: 'run'});
},
stopTask() {
this.socket.emit('operate', {type: 'operate_task', content: 'stop'});
},
restartTask() {
this.socket.emit('operate', {type: 'operate_task', content: 'restart'});
},
saveConfig() {
console.log(this.config);
this.socket.emit('operate', {type: 'save_config', file_name: this.selectedFile, content: this.config});
},
addLog(log) {
this.logs.push({
level: log.level,
content: log.content
});
this.$nextTick(() => {
const container = document.querySelector('.log-container');
container.scrollTop = container.scrollHeight;
if (this.logs.length > 100) {
this.logs = this.logs.slice(-100);
}
});
},
showServerLog() {
if (this.showServerLogFlag == false)
{
this.timer = setInterval(() => {
this.socket.emit('operate', { type: 'show_server_log', content: '' });
}, 2000);
}
else
{
clearInterval(this.timer);
this.timer = null;
}
this.showServerLogFlag = !this.showServerLogFlag;
},
formatServerLog(log) {
// 将换行符转换为 <br> 标签
return log.replace(/\n/g, '<br>');
},
skipTask() {
this.socket.emit('operate', { type: 'skip_task', content: '' });
}
},
mounted() {
this.socket = io('http://' + document.domain + ':5001');
this.socket.on('connect', () => {
console.log('Connected to server');
});
this.socket.on('log', (data) => {
this.addLog(data);
});
this.socket.on('config_data', (data) => {
if (data.type == 'config_data') {
this.files = data.content;
} else if (data.type == 'fileOptions') {
this.fileOptions = data.content;
}
});
this.socket.on('server_log', (data) => {
this.ServerLog = "";
this.ServerLog = data.content;
});
}
});
</script>
</body>
</html>

139
templates/index1.html Normal file
View File

@@ -0,0 +1,139 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>btl143</title>
<link rel="stylesheet" href="static/index.css">
<script src="static/vue.js"></script>
<script src="static/index.js"></script>
<script src="static/socket.io.js"></script>
<style>
body {
font-family: Arial, sans-serif;
margin: 0;
padding: 0;
background-color: #f5f7fa;
}
.app-container {
padding: 20px;
max-width: 1200px;
margin: 0 auto;
}
.button-group {
margin-bottom: 20px;
}
.full-screen-background {
background-color: #f0f0f0;
position: fixed;
top: 60px; /* Adjust based on button height and margin */
left: 0;
right: 0;
bottom: 0;
z-index: -1;
}
.counter-display {
padding: 20px;
text-align: center;
position: fixed;
top: 80px; /* Adjust based on your requirements */
left: 50%;
transform: translateX(-50%);
z-index: 1;
}
</style>
</head>
<body>
<div id="app">
<el-container class="app-container">
<el-main>
<h1 class="section-title">btl143 upper</h1>
<el-row :gutter="20" class="button-group">
<el-col :xs="24" :sm="8">
<el-button
@click="toggleTask"
:type="taskActive ? 'success' : 'danger'"
style="width: 100%">
{{ taskActive ? `开启 task ${counter}` : `关闭 task ${counter}` }}
</el-button>
</el-col>
</el-row>
<div class="full-screen-background" @click="incrementCounter">
<div class="counter-display">
</div>
</div>
</el-main>
</el-container>
</div>
<script>
new Vue({
el: '#app',
data: {
taskActive: true,
counter: 1
},
methods: {
toggleTask() {
if (this.taskActive) {
this.socket.emit('operate', {type: 'operate_task', content: 'run'});
}
else {
this.socket.emit('operate', {type: 'operate_task', content: 'stop'});
}
this.taskActive = !this.taskActive;
},
incrementCounter() {
this.counter += 1;
if (this.counter == 5) {
this.counter = 1;
}
this.socket.emit('operate', {type: 'save_target_person', content: this.counter});
},
startServer() {
this.socket.emit('operate', {type: 'operate_server', content: 'run'});
},
stopServer() {
this.socket.emit('operate', {type: 'operate_server', content: 'stop'});
},
restartServer() {
this.socket.emit('operate', {type: 'operate_server', content: 'restart'});
},
startTask() {
this.socket.emit('operate', {type: 'operate_task', content: 'run'});
},
stopTask() {
this.socket.emit('operate', {type: 'operate_task', content: 'stop'});
},
restartTask() {
this.socket.emit('operate', {type: 'operate_task', content: 'restart'});
},
skipTask() {
this.socket.emit('operate', { type: 'skip_task', content: '' });
}
},
mounted() {
this.socket = io('http://' + document.domain + ':5001');
this.socket.on('connect', () => {
console.log('Connected to server');
});
this.socket.on('task_status', (data) => {
if (data.content == 0) {
this.taskActive = true
} else {
this.taskActive = false
}
});
}
});
</script>
</body>
</html>

128
templates/index2.html Normal file
View File

@@ -0,0 +1,128 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>btl143</title>
<link rel="stylesheet" href="static/index.css">
<script src="static/vue.js"></script>
<script src="static/index.js"></script>
<script src="static/socket.io.js"></script>
<style>
body {
font-family: Arial, sans-serif;
margin: 0;
padding: 0;
background-color: #f5f7fa;
}
.app-container {
padding: 20px;
max-width: 1200px;
margin: 0 auto;
}
.button-group {
margin-bottom: 20px;
}
.full-screen-background {
background-color: #f0f0f0;
position: fixed;
top: 60px; /* Adjust based on button height and margin */
left: 0;
right: 0;
bottom: 0;
z-index: -1;
}
.counter-display {
padding: 20px;
text-align: center;
position: fixed;
top: 80px; /* Adjust based on your requirements */
left: 50%;
transform: translateX(-50%);
z-index: 1;
}
</style>
</head>
<body>
<div id="app">
<el-container class="app-container">
<el-main>
<h1 class="section-title">btl143 upper</h1>
<el-row :gutter="20" class="button-group">
<el-col :xs="24" :sm="8">
<el-button
@click="toggleTask"
:type="taskActive ? 'success' : 'danger'"
style="width: 100%">
{{ taskActive ? `开启 task` : `关闭 task` }}
</el-button>
</el-col>
</el-row>
</el-main>
</el-container>
</div>
<script>
new Vue({
el: '#app',
data: {
taskActive: true,
counter: 1
},
methods: {
toggleTask() {
if (this.taskActive) {
this.socket.emit('operate', {type: 'operate_task', content: 'run'});
}
else {
this.socket.emit('operate', {type: 'operate_task', content: 'stop'});
}
this.taskActive = !this.taskActive;
},
startServer() {
this.socket.emit('operate', {type: 'operate_server', content: 'run'});
},
stopServer() {
this.socket.emit('operate', {type: 'operate_server', content: 'stop'});
},
restartServer() {
this.socket.emit('operate', {type: 'operate_server', content: 'restart'});
},
startTask() {
this.socket.emit('operate', {type: 'operate_task', content: 'run'});
},
stopTask() {
this.socket.emit('operate', {type: 'operate_task', content: 'stop'});
},
restartTask() {
this.socket.emit('operate', {type: 'operate_task', content: 'restart'});
},
skipTask() {
this.socket.emit('operate', { type: 'skip_task', content: '' });
}
},
mounted() {
this.socket = io('http://' + document.domain + ':5001');
this.socket.on('connect', () => {
console.log('Connected to server');
});
this.socket.on('task_status', (data) => {
if (data.content == 0) {
this.taskActive = true
} else {
this.taskActive = false
}
});
}
});
</script>
</body>
</html>

49
test/test_cali.py Normal file
View File

@@ -0,0 +1,49 @@
import os
import sys
parent_dir = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
sys.path.append(parent_dir)
from utils import label_filter
from loguru import logger
from utils import tlabel
import zmq
import time
from by_cmd_py import by_cmd_py
import time
import signal
context = zmq.Context()
socket = context.socket(zmq.REQ)
socket.connect("tcp://localhost:6667")
logger.info("subtask yolo client init")
filter = label_filter(socket)
filter.switch_camera(2)
cmd_py_obj = by_cmd_py()
def car_stop():
for _ in range(3):
cmd_py_obj.send_speed_x(0)
time.sleep(0.2)
cmd_py_obj.send_speed_y(0)
time.sleep(0.2)
cmd_py_obj.send_speed_omega(0)
def signal_handler(sig, frame):
car_stop()
offset = 0
signal.signal(signal.SIGTERM, signal_handler)
cmd_py_obj.send_speed_x(15)
while True:
time.sleep(0.02)
ret, box = filter.get(tlabel.BASE)
# if ret:
# 宽度大于 41 停车
# print(f"width: {box[0][2] - box[0][0]} height: {box[0][3] - box[0][1]}")
if ret:
error = (box[0][2] + box[0][0] - 320) / 2 + offset
print(error)
cmd_py_obj.send_speed_omega(-error * 0.8)
car_stop()

14
test/test_capture.py Normal file
View File

@@ -0,0 +1,14 @@
import cv2
cap = cv2.VideoCapture(20)
cap.set(cv2.CAP_PROP_FOURCC, cv2.VideoWriter.fourcc('M','J','P','G'))
cap.set(cv2.CAP_PROP_FRAME_WIDTH, 960)
cap.set(cv2.CAP_PROP_FRAME_HEIGHT, 540)
while True:
ret, frame = cap.read()
if ret:
cv2.imshow("frame",frame)
cv2.waitKey(1)
cv2.destroyAllWindows()

View File

@@ -1,51 +1,40 @@
import sys
import os
import sys
parent_dir = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
sys.path.append(parent_dir)
from utils import label_filter
from loguru import logger
from utils import tlabel
import zmq
import time
context = zmq.Context()
socket = context.socket(zmq.REQ)
socket.connect("tcp://localhost:6667")
logger.info("subtask yolo client init")
filter = label_filter(socket)
filter.switch_camera(1)
offset = 12
filter.switch_camera(2)
# find_counts = 0
# offset = 19
# label = [tlabel.LPILLER, tlabel.MPILLER, tlabel.SPILLER]
# label = tlabel.TPLATFORM
while True:
time.sleep(0.2)
# ret1 = filter.get_mult(tlabel.RMARK)
# ret, label, error = filter.get_mult_box([tlabel.LMARK, tlabel.RMARK])
# if ret:
# # print(error)
# if abs(error) < 40:
# logger.info('yes')
label = tlabel.RBLOCK
ret, box = filter.get(label)
while not ret:
# 注意这里一定要保证摄像头内有该目标 否则会无限循环
ret, box = filter.get(label)
error = (box[0][2] + box[0][0] - 320) / 2 + offset
# ret, box = filter.get(tlabel.BBLOCK)
ret, box = filter.get(tlabel.BASE)
if ret:
print(error)
else:
pass
error = (box[0][2] + box[0][0] - 320) / 2
logger.error(error)
# label = tlabel.HOSPITAL
# ret, box = filter.get(label)
# while not ret:
# ret, box = filter.get(label)
# width = box[0][2] - box[0][0]
# logger.info(width)
# if ret1:
# print(error1)
# if abs(error1) < 30:
# print("you")
# elif ret2:
# print(error2)
# if abs(error2) < 30:
# print("zuo")

View File

@@ -14,7 +14,7 @@ class LLM:
self.model = 'ernie-3.5'
self.prompt = '''你是一个机器人动作规划者,需要把我的话翻译成机器人动作规划并生成对应的 json 结果,机器人工作空间参考右手坐标系。
严格按照下面的描述生成给定格式 json从现在开始你仅仅给我返回 json 数据'''
严格按照下面的描述生成给定格式 json从现在开始你仅仅给我返回 json 数据'''
self.prompt += '''正确的示例如下:
向左移 0.1m, 向左转弯 85 度 [{'func': 'move', 'x': 0, 'y': 0.1},{'func': 'turn','angle': -85}],
向右移 0.2m, 向前 0.1m [{'func': 'move', 'x': 0, 'y': -0.2},{'func': 'move', 'x': 0.1, 'y': 0}],
@@ -22,6 +22,8 @@ class LLM:
原地左转 38 度 [{'func': 'turn','angle': -38}],
蜂鸣器发声 5 秒 [{'func': 'beep', 'time': 5}]
发光或者照亮 5 秒 [{'func': 'light', 'time': 5}]
向右走 30cm照亮 2s [{'func': 'move', 'x': 0, 'y': -0.3}, {'func': 'light', 'time': 2}],
向左移 0.2m, 向后 0.1m [{'func': 'move', 'x': 0, 'y': 0.2},{'func': 'move', 'x': -0.1, 'y': 0}],
'''
self.messages = []
self.resp = None
@@ -47,6 +49,8 @@ if __name__ == "__main__":
lmm_bot = LLM()
while True:
chat = input("输入:")
print(lmm_bot.get_command_json(chat))
resp = lmm_bot.get_command_json(chat).replace(' ', '').replace('\n', '').replace('\t', '')
print(eval(resp[7:-3]))

32
test/test_ocr.py Normal file
View File

@@ -0,0 +1,32 @@
import zmq
context = zmq.Context()
socket = context.socket(zmq.REQ)
socket.connect("tcp://localhost:6668")
filter_w = (213, 540)
filter_h = (120, 360)
while True:
a = input("")
socket.send_string("")
resp = socket.recv_pyobj()
print(resp)
if resp.get('code') == 0:
text = ''
for item in resp.get('content'):
if item['probability']['average'] < 0.90:
continue
box = item['location']
center_x = box['left'] + box['width'] / 2
center_y = box['top'] + box['height'] / 2
if center_x < filter_w[0] or center_x > filter_w[1] \
or center_y < filter_h[0] or center_y > filter_h[1]:
continue
text += item['words']
print(text)

152
utils.py
View File

@@ -3,6 +3,8 @@ from enum import Enum
import numpy as np
import erniebot
from simple_pid import PID
from loguru import logger
import threading
# 巡线误差
lane_error = 0
@@ -104,6 +106,53 @@ class label_filter:
if len(results) > 0:
return True, np.array(results)
return False, None
# '''
# description: 对模型推理推理结果使用 threshold 和其他条件过滤 默认阈值为 0.5
# param {*} self
# param {*} data get_resp 返回的数据
# return {bool,array}
# '''
# def filter_box_custom(self, data, ymax_range):
# if len(data) > 0:
# expect_boxes = (data[:, 1] > self.threshold) & (data[:, 0] > -1)
# np_boxes = data[expect_boxes, :]
# results = [
# [
# item[0], # 'label':
# item[1], # 'score':
# item[2], # 'xmin':
# item[3], # 'ymin':
# item[4], # 'xmax':
# item[5], # 'ymax':
# not (ymax_range[0] < item[3] < ymax_range[1]), # 如果 ymin 处在范围内则返回 False认为该目标不符合要求
# not (ymax_range[0] < item[5] < ymax_range[1]) # 如果 ymax 处在范围内则返回 False认为该目标不符合要求
# ]
# for item in np_boxes
# ]
# if len(results) > 0:
# return True, np.array(results)
# return False, None
#原来的函数
def filter_box_custom(self,data):
if len(data) > 0:
expect_boxes = (data[:, 1] > self.threshold) & (data[:, 0] > -1)
np_boxes = data[expect_boxes, :]
results = [
[
item[0], # 'label':
item[1], # 'score':
item[2], # 'xmin':
item[3], # 'ymin':
item[4], # 'xmax':
item[5] # 'ymax':
]
for item in np_boxes
if item[5] < 180
]
if len(results) > 0:
return True, np.array(results)
return False, None
'''
description: 根据传入的标签过滤返回该标签的个数、box
param {*} self
@@ -188,6 +237,91 @@ class label_filter:
return True
return False
'''
description: 查询两个目标 只有 target_label 返回 box
param {*} self
param {*} tlabel
return {[bool]}
'''
def get_two(self, target_label, label):
response = self.get_resp()
if response['code'] == 0:
ret, results = self.filter_box_custom(response['data'])
if ret:
expect_boxes = (results[:, 0] == target_label.value)
boxes = results[expect_boxes, :]
if len(boxes) != 0:
target_bool = True
target_box = boxes[:, 2:]
else:
target_bool = False
target_box = None
expect_boxes = (results[:, 0] == label.value)
boxes = results[expect_boxes, :]
if len(boxes) != 0:
label_bool = True
else:
label_bool = False
return (target_bool, label_bool, target_box)
return (False, False, None)
'''
description: 查询两个目标 只有 target_label 返回 box
param {*} self
param {*} tlabel
return {[bool]}
'''
def get_two_hanoi(self, target_label, label, flipv):
response = self.get_resp()
if response['code'] == 0:
# FIXME 直接在外部过滤,不在 fliter 内过滤
ret, results = self.filter_box(response['data'])
if ret:
expect_boxes = (results[:, 0] == target_label.value)
boxes = results[expect_boxes, :]
if len(boxes) != 0:
target_bool = True
target_box = boxes[:, 2:]
else:
target_bool = False
target_box = None
expect_boxes = (results[:, 0] == label.value)
boxes = results[expect_boxes, :]
# 在此处过滤
if len(boxes) != 0:
# 如果垂直翻转 (走右侧) 且 *ymin* 小于 60走右侧
if flipv:
label_bool = all(box[3] > 60 for box in boxes)
# 如果不垂直翻转 (走左侧) 且 *ymax* 大于 180走左侧
else:
label_bool = all(box[5] < 180 for box in boxes)
# label_bool = True
else:
label_bool = False
return (target_bool, label_bool, target_box)
return (False, False, None)
'''
description: 判断传入的多目标标签是否存在,存在返回 True
param {*} self
param {*} tlabel
return {[bool]}
'''
def find_mult(self, tlabel):
response = self.get_resp()
find_result = []
if response['code'] == 0:
ret, results = self.filter_box(response['data'])
if ret:
for label in tlabel:
expect_boxes = (results[:, 0] == label.value)
boxes = results[expect_boxes, :]
if len(boxes) != 0:
find_result.append(True)
else:
find_result.append(False)
return find_result
return [False for _ in range(len(tlabel))]
'''
description: 根据传入的标签,寻找画面中最左侧的并返回 error
param {*} self
param {*} tlabel
@@ -242,6 +376,7 @@ class label_filter:
class LLM:
def __init__(self):
self.init_done_flag = False
erniebot.api_type = "qianfan"
erniebot.ak = "jReawMtWhPu0wrxN9Rp1MzZX"
erniebot.sk = "eowS1BqsNgD2i0C9xNnHUVOSNuAzVTh6"
@@ -255,11 +390,16 @@ class LLM:
原地左转 38 度 [{'func': 'turn','angle': -38}],
蜂鸣器发声 5 秒 [{'func': 'beep', 'time': 5}]
发光或者照亮 5 秒 [{'func': 'light', 'time': 5}]
向右走 30cm照亮 2s [{'func': 'move', 'x': 0, 'y': -0.3}, {'func': 'light', 'time': 2}],
向左移 0.2m, 向后 0.1m [{'func': 'move', 'x': 0, 'y': 0.2},{'func': 'move', 'x': -0.1, 'y': 0}],
鸣叫 3 声 [{'func': 'beep', 'time': 3}]
前行零点五米 [{'func': 'move', 'x': 0.5, 'y': 0}]
'''
self.prompt += '''无需回复我'''
self.prompt += '''只需要根据我的示例解析出指令即可,不要给我其他多余的回复;再次强调 你无需给我其他多余的回复 这对我很重要'''
self.messages = []
self.resp = None
self.reset()
worker = threading.Thread(target=self.reset, daemon=True)
worker.start()
def reset(self):
self.messages = [self.make_message(self.prompt)]
self.resp = erniebot.ChatCompletion.create(
@@ -267,16 +407,21 @@ class LLM:
messages=self.messages,
)
self.messages.append(self.resp.to_message())
self.init_done_flag = True
logger.info("LLM init done")
def make_message(self,content):
return {'role': 'user', 'content': content}
def get_command_json(self,chat):
while self.init_done_flag == False: # 等待初始化 (要是等到调用还没初始化,那就是真寄了)
pass
self.messages.append(self.make_message(chat))
self.resp = erniebot.ChatCompletion.create(
model=self.model,
messages=self.messages,
)
self.messages.append(self.resp.to_message())
return self.resp.get_result()
resp = self.resp.get_result().replace(' ', '').replace('\n', '').replace('\t', '')
return resp
class CountRecord:
def __init__(self, stop_count=2) -> None:
@@ -313,6 +458,7 @@ class PidWrap:
self.pid_t.Kp = kp
self.pid_t.Ki = ki
self.pid_t.Kd = kd
logger.info(f"[PID]# 更新 PID 参数Kp({kp:.2f}) Ki({ki:.2f}) Kd({kd:.2f})")
def get(self, val_in):
return self.pid_t(val_in)

22
variable.py Normal file
View File

@@ -0,0 +1,22 @@
from utils import PidWrap
# 巡线误差
lane_error = 0
# 进入任务时可以通过修改 task_speed 控制巡线速度
task_speed = 0
# pid 参数
pid_argv = {"kp" : 1.2, "ki" : 0, "kd" : 0} # 1.2
# 转向 pid 对象
# pid_turning = PidWrap(pid_argv["kp"], pid_argv["ki"], pid_argv["kd"], output_limits=70) # FIXME 6_9 模型为 60
pid_turning = PidWrap(pid_argv["kp"], pid_argv["ki"], pid_argv["kd"], output_limits=60) # FIXME 6_9 模型为 60
llm_text = ''
skip_llm_task_flag = False
first_block = None
second_block = None
switch_lane_model = False