目 录CONTENT

文章目录

基于AP的网络延迟计算

Rho
Rho
2023-10-25 / 0 评论 / 0 点赞 / 30 阅读 / 4106 字

计算网络延迟,而不使用Ping/ICMP回显请求。它使用ROS动作调用来测量应用层(带TCP连接)的往返时间(2倍延迟)。每行代码增加中文注释,如下:

// 描述:这个ROS节点计算网络延迟,而不使用Ping/ICMP回显请求。它使用ROS动作调用来测量应用层(带TCP连接)的往返时间(2倍延迟)。


// 引入ROS头文件
#include <ros/ros.h>
// 引入PingAction的头文件,这是一个自定义的动作类型
#include <network_analysis/PingAction.h>
// 引入NetworkDelay的头文件,这是一个自定义的消息类型
#include <network_analysis/NetworkDelay.h>
// 引入actionlib客户端的头文件,用于与动作服务器通信
#include <actionlib/client/simple_action_client.h>
#include <actionlib/client/terminal_state.h>
// 引入sys/time.h头文件,用于获取系统时间
#include <sys/time.h>
// 引入iostream头文件,用于输入输出流
#include <iostream>

// 定义主函数,接收命令行参数
int main(int argc, char* argv[])
{
try // 使用try-catch语句处理异常
{
ros::init(argc, argv, "network_delay"); // 初始化ROS节点,命名为network_delay

ros::NodeHandle n; // 创建节点句柄,用于与ROS系统交互

struct timeval start, end; // 定义两个timeval结构体变量,用于存储开始和结束时间
double mtime, seconds, useconds; // 定义三个double类型变量,用于存储毫秒、秒和微秒
double timeout=2.0; // 定义一个double类型变量,用于存储动作超时时间,默认为2.0秒
int updaterate=1; // 定义一个int类型变量,用于存储主题更新频率,默认为1Hz
n.param("timeout_network_delay", timeout, 2.0); // 从参数服务器获取timeout_network_delay参数的值,如果没有则使用默认值2.0
n.param("update_rate_network_delay", updaterate, 1); // 从参数服务器获取update_rate_network_delay参数的值,如果没有则使用默认值1

// 在/network_analysis/network_delay主题上发布延迟值,消息类型为NetworkDelay,队列长度为10
ros::Publisher pub = n.advertise<network_analysis::NetworkDelay>("network_analysis/network_delay", 10);
network_analysis::NetworkDelay msg; // 定义一个NetworkDelay类型的变量,用于存储和发送消息

// 使用ROS动作调用来计算延迟
actionlib::SimpleActionClient<network_analysis::PingAction> ac("Ping", true); // 创建一个SimpleActionClient对象,指定动作类型为PingAction,动作名称为Ping,并自动启动动作服务器
ac.waitForServer(); // 等待无限时间直到动作服务器启动
network_analysis::PingGoal goal; // 定义一个PingGoal类型的变量,用于存储和发送目标
goal.inp = true; // 设置目标的inp属性为true

ros::Rate loop_rate(updaterate); // 创建一个Rate对象,指定循环频率为updaterate

msg.header.stamp = ros::Time::now(); // 设置消息的头部时间戳为当前时间
msg.iface = "default"; // 设置消息的iface属性为"default"
msg.delay = -1; // 设置消息的delay属性为-1,默认值
msg.alive = 0; // 设置消息的alive属性为0,默认值

while (ros::ok()) // 当ROS节点正常运行时
{
gettimeofday(&start, NULL); // 获取当前时间,存储在start变量中
ac.sendGoal(goal); // 向动作服务器发送目标
// 等待动作返回结果,超时时间为timeout秒
bool finished_before_timeout = ac.waitForResult(ros::Duration(timeout));
if (finished_before_timeout) // 如果在超时时间内完成动作
{
actionlib::SimpleClientGoalState state = ac.getState(); // 获取动作的状态
ROS_INFO("ROS Ping Action finished: %s",state.toString().c_str()); // 打印动作的状态信息
gettimeofday(&end, NULL); // 获取当前时间,存储在end变量中
seconds  = end.tv_sec  - start.tv_sec; // 计算秒数差值
useconds = end.tv_usec - start.tv_usec; // 计算微秒数差值
mtime = ((seconds) * 1000 + useconds/1000.0) + 0.5; // 计算毫秒数差值,四舍五入
msg.delay = (float) mtime; // 设置消息的delay属性为毫秒数差值,转换为float类型
msg.alive = 1; // 设置消息的alive属性为1,表示网络正常
}
else // 如果超时未完成动作
{
ROS_ERROR("Action did not finish before the timeout. May be a network problem or may be the ping action server node stopped. See network_delay.alive history for more diagnosis"); // 打印错误信息,提示可能是网络问题或动作服务器节点停止了
msg.delay=-1; // 设置消息的delay属性为-1,表示错误值
msg.alive=0; // 设置消息的alive属性为0,表示网络异常
}
pub.publish(msg); // 发布消息到主题上
ros::spinOnce(); // 处理一次回调函数
loop_rate.sleep(); // 按照循环频率休眠一段时间
}
}
catch (std::exception& e) // 捕获异常
{
std::cerr << "Exception: " << e.what() << std::endl; // 打印异常信息到标准错误流
}

return 0; // 返回0,表示程序正常退出
}
0

评论区