File size: 6,136 Bytes
f52a1d4 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 | #!/usr/bin/env python3
"""
Kuavo机器人控制指令发送器
用于向正在运行的script.py进程发送控制指令
使用示例:
python controller.py pause # 暂停机械臂运动
python controller.py resume # 恢复机械臂运动
python controller.py stop # 停止机械臂运动
python controller.py status # 查看进程状态
"""
import os
import sys
import signal
import psutil
import argparse
from pathlib import Path
def find_example_process():
"""
查找正在运行的script.py进程
Returns:
psutil.Process: 找到的进程对象,如果没找到返回None
"""
target_processes = []
for proc in psutil.process_iter(['pid', 'name', 'cmdline']):
try:
# 检查进程名或命令行参数
if (proc.info['name'] == 'python' or proc.info['name'] == 'python3') and proc.info['cmdline']:
cmdline = ' '.join(proc.info['cmdline'])
# 精确匹配 kuavo_deploy/src/scripts/script.py 路径
if 'kuavo_deploy/src/scripts/script.py' in cmdline:
target_processes.append((proc, 'exact'))
except (psutil.NoSuchProcess, psutil.AccessDenied, psutil.ZombieProcess):
continue
if len(target_processes) != 1:
print(f"❌ 找到 {len(target_processes)} 个匹配的进程,请使用 --pid 参数指定进程ID")
sys.exit(1)
else:
return target_processes[0][0]
def send_signal_to_process(proc, signal_type):
"""
向指定进程发送信号
Args:
proc: psutil.Process对象
signal_type: 信号类型 ('pause', 'resume', 'stop')
"""
try:
if signal_type == 'pause':
proc.send_signal(signal.SIGUSR1)
print(f"✅ 已发送暂停信号到进程 {proc.pid}")
elif signal_type == 'resume':
proc.send_signal(signal.SIGUSR1)
print(f"✅ 已发送恢复信号到进程 {proc.pid}")
elif signal_type == 'stop':
proc.send_signal(signal.SIGUSR2)
print(f"✅ 已发送停止信号到进程 {proc.pid}")
else:
print(f"❌ 未知的信号类型: {signal_type}")
return False
return True
except psutil.NoSuchProcess:
print(f"❌ 进程 {proc.pid} 不存在")
return False
except psutil.AccessDenied:
print(f"❌ 没有权限向进程 {proc.pid} 发送信号")
return False
except Exception as e:
print(f"❌ 发送信号时发生错误: {e}")
return False
def show_process_status(proc):
"""
显示进程状态信息
Args:
proc: psutil.Process对象
"""
try:
print(f"📊 进程信息:")
print(f" PID: {proc.pid}")
print(f" 状态: {proc.status()}")
print(f" 创建时间: {proc.create_time()}")
print(f" CPU使用率: {proc.cpu_percent()}%")
print(f" 内存使用: {proc.memory_info().rss / 1024 / 1024:.1f} MB")
print(f" 命令行: {' '.join(proc.cmdline())}")
except (psutil.NoSuchProcess, psutil.AccessDenied) as e:
print(f"❌ 无法获取进程信息: {e}")
def main():
"""主函数"""
parser = argparse.ArgumentParser(
description="Kuavo机器人控制指令发送器",
formatter_class=argparse.RawDescriptionHelpFormatter,
epilog="""
使用示例:
python controller.py pause # 暂停机械臂运动
python controller.py resume # 恢复机械臂运动
python controller.py stop # 停止机械臂运动
python controller.py status # 查看进程状态
控制指令说明:
pause - 暂停机械臂运动 (发送SIGUSR1信号)
resume - 恢复机械臂运动 (发送SIGUSR1信号)
stop - 停止机械臂运动 (发送SIGUSR2信号)
status - 显示当前运行的script.py进程状态
"""
)
parser.add_argument(
"command",
type=str,
choices=["pause", "resume", "stop", "status"],
help="控制指令"
)
parser.add_argument(
"--pid",
type=int,
help="指定进程PID (如果不指定,将自动查找script.py进程)"
)
args = parser.parse_args()
# 查找目标进程
target_proc = None
if args.pid:
# 使用指定的PID
try:
target_proc = psutil.Process(args.pid)
# 验证进程是否运行script.py
cmdline = ' '.join(target_proc.cmdline())
if 'script.py' not in cmdline:
print(f"❌ 进程 {args.pid} 不是script.py进程")
print(f" 命令行: {cmdline}")
sys.exit(1)
except psutil.NoSuchProcess:
print(f"❌ 进程 {args.pid} 不存在")
sys.exit(1)
except psutil.AccessDenied:
print(f"❌ 没有权限访问进程 {args.pid}")
sys.exit(1)
else:
# 自动查找script.py进程
print("🔍 正在查找运行中的script.py进程...")
target_proc = find_example_process()
if not target_proc:
print("❌ 未找到运行中的script.py进程")
print("💡 请确保script.py正在运行,或使用 --pid 参数指定进程ID")
print("💡 预期的进程路径: kuavo_deploy/src/scripts/script.py")
sys.exit(1)
# 显示找到的进程信息
cmdline = ' '.join(target_proc.cmdline())
if 'kuavo_deploy/src/scripts/script.py' in cmdline:
print(f"✅ 找到精确匹配的进程: {target_proc.pid}")
else:
print(f"⚠️ 找到部分匹配的进程: {target_proc.pid}")
print(f" 命令行: {cmdline}")
# 执行命令
if args.command == "status":
show_process_status(target_proc)
else:
print(f"🎯 目标进程: {target_proc.pid}")
success = send_signal_to_process(target_proc, args.command)
if not success:
sys.exit(1)
if __name__ == "__main__":
main()
|