Ros实时监控各小车硬件信息
在小车移动过程中如何实现对小车硬件信息的硬件信息,首先我们能想到的是通过使用Prometheus(普罗米修斯)对小车硬件信息进行监控与展示,但这里我们想通过编写python脚本实现同样的功能。
定义小车硬件信息服务
简单的自定义一个硬件信息服务类型InformationSystem.srv
bool state
---
string information
小车硬件信息服务端,当有client客服端发送请求时,服务端通过python的psutil库对小车硬件信息进行获取,转化为json格式字符串反馈给客户端
#!/usr/bin/env python
import psutil
import rospy
from information_system.srv import InformationSystem
import json
class Information_server:
def __init__(self,robot_name="robot1"):
self.robot_name=robot_name
def InformationCallback(self,req):
try:
if req.state:
memory = psutil.virtual_memory()
cpu_percent = psutil.cpu_percent()
return json.dumps({"memory":{"total":memory.total,"available":memory.available,"percent":memory.percent,"used":memory.used,"free":memory.free},"cpu":{"percent":cpu_percent}}).replace(" ","")
else:
return None
except:
return None
def server(self):
s = rospy.Service(str(self.robot_name)+"/information", InformationSystem, self.InformationCallback)
rospy.spin()
if __name__=="__main__":
rospy.init_node("information")
robot_name = rospy.get_param('~robot_name','robot1')
information_server = Information_server(robot_name=robot_name)
information_server.server()
客户端各小车硬件信息获取汇总并可视化
import rospy
import math
import numpy as np
import matplotlib.pyplot as plt
import time
import psutil
from information_system.srv import InformationSystem
import json
import threading
# 创建一个客户端类用于获取各小车硬件信息
class Get_Information:
def __init__(self, robot_name):
self.robot_name = robot_name
def information_client(self):
rospy.wait_for_service(str(self.robot_name)+"/information")
try:
information_client = rospy.ServiceProxy(self.robot_name+"/information", InformationSystem)
response = information_client(True)
return response.information
except:
return None
# 画图的类用于cpu信息展示
class Cpu_Figure:
def __init__(self,robot_names=[],x_len=10,colors=["r","g","b"]):
self.robot_names = robot_names
self.x_len = x_len
self.x_index = np.array(range(1,x_len+1))
self.x_label = np.zeros(x_len)
self.data_init()
self.colors = colors
# 初始化数据,构建一个用于存放数据的字典
def data_init(self):
self.data_dict = {}
for robot_name in self.robot_names:
self.data_dict[robot_name] = np.zeros(self.x_len)
# 通过客户端类,json获取数据
def get_data(self,robot_name):
information = Get_Information(robot_name).information_client()
if information != None:
information = json.loads(information)
new_data = float(information["cpu"]["percent"])
self.data_dict[robot_name] = np.append(np.delete(self.data_dict[robot_name],0),new_data)
print("new_data: ",self.data_dict[robot_name])
# 多线程获取更好的实现时间轴上的同步可取消注释替换下面的update_data()
#def update_data(self):
# threads = [threading.Thread(target=self.get_data,args=(robot_name,)) for robot_name in self.robot_names]
# for t in threads:
# t.setDaemon(True)
# t.start()
#for t in threads:
# t.join()
# 简单的循环更新没有较好的实时性
def update_data(self):
for robot_name in self.robot_names:
self.get_data(robot_name)
# 时间轴标签更新
def update_label(self):
self.x_label = np.append(np.delete(self.x_label,0),time.strftime("%H:%M:%S", time.localtime()))
# 绘图的方法
def plt_show(self):
#
figID = 1
fig = plt.figure(num=figID, figsize=(10,5))
ax = fig.add_subplot(1,1,1)
#ax1 ,ax2 ,ax3 = [fig.add_subplot(1,len(self.robot_names),i)for i in range(len(self.robot_names))]+[None for i in range(3-len(self.cup_num))]
while plt.fignum_exists(figID): # 通过判断创建的窗口是否存在作为循环条件,防止关闭当前窗口后,产生新的窗口导致无法退出程序
ax.set_xlim([1,10])
ax.set_ylim([0,100])
fontdict = {'fontsize': 10}
ax.set_xlabel('time')
ax.set_ylabel('use')
ax.set_title('cup')
self.update_label()
start_time = time.time()
self.update_data()
ax.set_xticklabels(self.x_label, fontdict=fontdict)
for i,robot_name in enumerate(self.robot_names):
line = ax.plot([0,0],[10,100],self.colors[i],marker='*',label=robot_name)[0]
line.set_xdata(self.x_index)
line.set_ydata(self.data_dict[robot_name])
for i in range(self.x_len):
ax.text(self.x_index[i], self.data_dict[robot_name][i]+0.05, '%.2f'% self.data_dict[robot_name][i]+"%" , ha='center', va= 'bottom',fontsize=7)
plt.legend(loc=1)
# 暂停
plt.pause(0.5)
if time.time() - start_time <= 20:
time.sleep(time.time() - start_time)
ax.cla()
if __name__=="__main__":
rospy.init_node("information_show")
fig = Cpu_Figure(robot_names = ["robot2","robot3"])
fig.plt_show()
结论
由于每次请求数据到绘图需要一定时间会有十几秒的延迟,待继续优化。目前效果图为两条折线,后续可考虑加入内存等硬件信息。