Compare commits

...

15 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
37 changed files with 27715 additions and 657 deletions

2
.gitignore vendored
View File

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

View File

@@ -13,7 +13,7 @@ move = None
axis = None
cmd = None
cfg = toml.load('cfg_action.toml')
cfg = toml.load('/home/evan/Workplace/project_main/cfg_action.toml')
def import_obj(_bycmd):
global bycmd

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)

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,30 +2,18 @@
logger_filename = "log/file_{time}.log"
logger_format = "{time} {level} {message}"
[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 = true # 应急避险使能
KickAss_enable = true # 扫黑除暴使能
[find_counts]
GetBlock_counts = 5 # 人员施救计数
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,92 +1,61 @@
################################################
[get_block]
# pid 参数值
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
# *第一个抓取的方块
first_block = "red"
# first_block = "blue"
################################################
[put_block]
# pid 参数值
pid_kp = 1.2
pid_ki = 0
pid_kd = 0
################################################
[get_bball]
# pid 参数值
pid_kp = 1.2
pid_ki = 0
pid_kd = 0
################################################
[up_tower]
# pid 参数值
pid_kp = 1.2
pid_ki = 0
pid_kd = 0
################################################
[get_rball]
# pid 参数值
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]
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]
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
################################################
[put_bball]
# pid 参数值
pid_kp = 0.6
pid_ki = 0
pid_kd = 0
################################################
[put_hanoi1]
# pid 参数值
pid_kp = 1.0
pid_ki = 0
pid_kd = 0
################################################
[put_hanoi2]
# pid 参数值
pid_kp = 1.0
pid_ki = 0
pid_kd = 0
# 距离标定值
pos_gap = 160 # 标定值,两个放置位置的标定距离
# first_target = "lp"
first_target = "mp"
# first_target = "sp"
################################################
[put_hanoi3]
# pid 参数值
pid_kp = 1.2
pid_ki = 0
pid_kd = 0
################################################
[move_area]
# pid 参数值
pid_kp = 1.4
pid_ki = 0
pid_kd = 0
llm_enable = true # 大模型机器人
################################################
[kick_ass]
# pid 参数值
pid_kp = 1.2
pid_ki = 0
pid_kd = 0
pos_gap1 = 150 # 目标牌和第一个 person 之间的距离
pos_gap2 = 80 # person 之间的距离
target_person = 3 # 击打的人 - 最靠近标识牌的为 1
################################################
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

56
main.py
View File

@@ -1,23 +1,24 @@
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)
@@ -26,22 +27,21 @@ act.axis.exec()
# 向任务队列添加任务
task_queue = queue.Queue()
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'], 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)
@@ -54,13 +54,11 @@ def worker_thread():
worker = threading.Thread(target=worker_thread, daemon=True)
worker.start()
# 创建主任务
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:
@@ -74,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

@@ -8,9 +8,14 @@ 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
@@ -62,17 +67,18 @@ class main_task():
error_abs = abs(self.lane_error)
if error_abs > 50:
speed = 11
elif error_abs > 45:
# 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:
@@ -96,7 +102,12 @@ class main_task():
# pid_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()
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

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,18 +1,14 @@
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
from by_cmd_py import by_cmd_py
import time
from utils import CountRecord
by_cmd = by_cmd_py()
context = zmq.Context()
socket = context.socket(zmq.REQ)
@@ -20,211 +16,25 @@ socket.connect("tcp://localhost:6667")
logger.info("subtask yolo client init")
filter = label_filter(socket)
filter.switch_camera(1)
filter.switch_camera(2)
def car_stop():
for _ in range(3):
by_cmd.send_speed_x(0)
time.sleep(0.2)
by_cmd.send_speed_omega(0)
# 蓝色球使用
def calibrate_right_new(label, offset, run = True, run_speed = 3.5):
not_found_counts = 0
ret, error = filter.aim_right(label)
while not ret:
not_found_counts += 1
if not_found_counts >= 20:
not_found_counts = 0
error = -320 # error > 0 front run
logger.info("calibrate_right_new:找不到次数超过 20 帧 直接前进寻找")
break
ret, error = filter.aim_right(label)
error += offset
if abs(error) > 10 and run:
if error > 0:
by_cmd.send_speed_x(-run_speed)
else:
by_cmd.send_speed_x(run_speed)
pass
# 停的位置已经很接近目标,可以直接使用 distance 校准
else:
# logger.info("停车时误差就小于")
# error = error * 3
# if error > 0:
# by_cmd.send_distance_x(-10, int(error))
# else:
# by_cmd.send_distance_x(10, int(-error))
return
while True:
ret, error = filter.aim_right(label)
while not ret:
ret, error = filter.aim_right(label)
error += offset
if ret:
if abs(error) <= 8:
car_stop()
logger.info("calibrate_right_new:行进时 误差小于 8 直接停车")
ret, error = filter.aim_right(label)
while not ret:
ret, error = filter.aim_right(label)
error += offset
logger.info(f"calibrate_right_new:停车后的误差是{error}")
if abs(error) > 8:
logger.info(f"calibrate_right_new:停车后的误差大于 8 使用 distance 校准")
error = error * 3
if error > 0:
by_cmd.send_distance_x(-10, int(error))
else:
by_cmd.send_distance_x(10, int(-error))
break
'''
description: 校准新方法 找到后停止 然后根据 error 判断前后低速前进 error < 5 后直接停车
如果停车后 error > 8 则使用 distance 校准
这个方法仅用于在视野里能找到的情况下进行校准,并不能实现边走边寻找 然后再校准
param {*} label
param {*} offset
param {*} run
param {*} run_speed
return {*}
'''
def calibrate_new(label, offset, run = True, run_speed = 3.5):
not_found_counts = 0
ret, box = filter.get(label)
while not ret:
not_found_counts += 1
if not_found_counts >= 20:
not_found_counts = 0
error = -320 # error > 0 front run
logger.info("calibrate_new:找不到次数超过 20 帧 直接前进寻找")
ret, box = filter.get(label)
error = (box[0][2] + box[0][0] - 320) / 2 + offset
if abs(error) > 10 and run:
if error > 0:
by_cmd.send_speed_x(-run_speed)
else:
by_cmd.send_speed_x(run_speed)
# 停的位置已经很接近目标,可以直接使用 distance 校准
else:
if abs(error) > 8:
logger.info(f"calibrate_new:停车后误差{error}大于 8 使用 distance 校准")
# error = error # 3
if error > 0:
by_cmd.send_distance_x(-10, int(error))
else:
by_cmd.send_distance_x(10, int(-error))
return
logger.info(f"calibrate_new:停车后误差{error}小于 8 不校准")
return
while True:
ret, box = filter.get(label)
while not ret:
ret, box = filter.get(label)
error = (box[0][2] + box[0][0] - 320) / 2 + offset
if ret:
if abs(error) <= 10: # 5
car_stop()
logger.info("calibrate_new:行进时 误差小于 10 直接停车")
ret, box = filter.get(label)
while not ret:
ret, box = filter.get(label)
error = (box[0][2] + box[0][0] - 320) / 2 + offset
logger.info(f"calibrate_new:停车后的误差是{error}")
if abs(error) > 8:
logger.info(f"calibrate_new:停车后的误差大于 8 使用 distance 校准")
error = error * 3
logger.error(f"error * 3{error}")
if error > 0:
by_cmd.send_distance_x(-10, int(error))
else:
by_cmd.send_distance_x(10, int(-error))
break
def explore_calibrate_new(label, offset, run_direc ,run_speed = 3.5):
# run_direc == 1 向前
if run_direc == 1:
by_cmd.send_speed_x(run_speed)
else:
by_cmd.send_speed_x(-run_speed)
while True:
ret, box = filter.get(label)
while not ret:
ret, box = filter.get(label)
error = (box[0][2] + box[0][0] - 320) / 2 + offset
if ret:
logger.info(f"当前误差:{error}, box[{box[0][2]},{box[0][0]}]")
# 校准速度越大 停车的条件越宽泛
if abs(error) <= 20:
car_stop()
logger.info("explore_calibrate_new:行进时 误差小于 10 直接停车")
error_sum = 0
for _ in range(3):
ret, box = filter.get(label)
while not ret:
ret, box = filter.get(label)
error = (box[0][2] + box[0][0] - 320) / 2 + offset
error_sum += error
error_sum /= 3
# logger.info(f"停车后像素误差:{error}")
logger.info(f"停车后像素误差:{error_sum}")
# if abs(error) > 8:
logger.info(f"explore_calibrate_new:停车后的误差大于 8 使用 distance 校准")
error_sum = error_sum * 3
logger.error(f"error * 3 {error}")
if error > 0:
by_cmd.send_distance_x(-10, int(error))
else:
by_cmd.send_distance_x(10, int(-error))
break
offset = 10
# by_cmd.send_angle_claw_arm(217)
# while True:
# pass
# while (by_cmd.send_angle_camera(180) == -1):
# by_cmd.send_angle_camera(180)
while (by_cmd.send_angle_camera(180) == -1):
by_cmd.send_angle_camera(180)
# by_cmd.send_speed_x(15)
find_counts = 0
label = tlabel.HOSPITAL
record = CountRecord(5)
# find_counts = 0
# offset = 19
# label = [tlabel.LPILLER, tlabel.MPILLER, tlabel.SPILLER]
# label = tlabel.TPLATFORM
while True:
time.sleep(0.2)
ret, box = filter.get(tlabel.BASE)
if ret:
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)
# ret = filter.find(label)
# ret = filter.find(label)
# if ret > 0:
# find_counts += 1
# if record(label):
# car_stop()
# if find_counts >= 5:
# car_stop()
ret, box = filter.get(label)
while not ret:
ret, box = filter.get(label)
width = box[0][2] - box[0][0]
logger.info(width)
# error = (box[0][2] + box[0][0] - 320) / 2 + offset
# explore_calibrate_new(tlabel.LPILLER, offset = 10, run_direc = 1, run_speed = 5)
# calibrate_new(label, offset = 15, run = True)
# car_stop()
# time.sleep(0.5)
# for _ in range(3):
# calibrate_right_new(tlabel.BBALL, offset = 27, run = True, run_speed = 4)
# logger.info("抓蓝色球")
# time.sleep(5)
# logger.info("抓取块")
# time.sleep(0.1)

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)

143
utils.py
View File

@@ -106,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
@@ -190,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
@@ -260,11 +392,14 @@ class LLM:
发光或者照亮 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(
@@ -272,6 +407,8 @@ 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):
@@ -284,7 +421,7 @@ class LLM:
)
self.messages.append(self.resp.to_message())
resp = self.resp.get_result().replace(' ', '').replace('\n', '').replace('\t', '')
return resp[7:-3]
return resp
class CountRecord:
def __init__(self, stop_count=2) -> None:

View File

@@ -6,7 +6,17 @@ lane_error = 0
task_speed = 0
# pid 参数
pid_argv = {"kp" : 1.2, "ki" : 0, "kd" : 0}
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=50)
# 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