我想将来自 ROS 主题的消息存储在数组中以供进一步阐述
I want to store in an array messages from a ROS topic for further elaboration
如果这个问题对你来说太简单了,我很抱歉,但我没有良好的编程技能和 ROS 知识。我有一个 ROS 主题,其中发布了一些以秒为单位的心跳间隔数字。我需要订阅那个主题并做这样的阐述:我的想法是有一个由十个数字组成的小数组,我可以在其中连续存储十个心跳。然后我有一个更大的 60 个数字数组,必须上升十个位置才能在底部有小数组的最新十个值,它必须 "throw away" 十个最旧的值(我做了一点研究,也许我必须使用向量而不是数组,因为在 C++ 中,数组在我阅读时是固定的)。然后我必须每次在文本文件中打印这 60 个值(我的意思是在一个循环中,所以文本文件将被连续覆盖)。此外,我看到 ROS 以这种方式从主题输出数据:data: 0.987
,每个数据在一列中被 ---
与其他数据分开。我真正想要的是一个文本文件,因为我需要一个以这种方式读取文本文件的脚本,其中的值位于一列中,没有空格和其他符号或单词,如下所示:
0.404
0.952
0.956
0.940
0.960
我在下面提供了我的节点的代码,其中,目前我只做了订阅部分,因为我不知道如何做我以后必须做的事情。预先感谢您的帮助!!!
代码:
#include "ros/ros.h"
#include "std_msgs/String.h"
#include "../include/heart_rate_monitor/wfdb.h"
#include <stdio.h>
#include <sstream>
#include <iostream>
#include <fstream>
#include <iomanip>
#include <algorithm>
#include <vector>
int main(int argc, char **argv)
{
ros::init(argc, argv, "writer");
ros::NodeHandle n;
ros::Subscriber sub = n.subscribe("/HeartRateInterval", 1000);
ros::spin();
return 0;
}
注意:我没有包含 Float32/64 header 因为我将心跳作为字符串发布。不知道大家有没有兴趣
编辑:我将在下面包含在 ROS 主题上发布数据的发布者节点的代码。
#include "ros/ros.h"
#include "std_msgs/String.h"
#include "../include/heart_rate_monitor/wfdb.h"
#include <stdio.h>
#include <sstream>
#include <iostream>
#include <fstream>
#include <iomanip>
using namespace std;
int main(int argc, char **argv)
{
ros::init(argc, argv, "heart_rate_monitor");
ros::NodeHandle n;
ros::Publisher pub = n.advertise<std_msgs::String>("/HeartRateInterval", 1000);
ros::Rate loop_rate(1);
while (ros::ok())
{
ifstream inputFile("/home/marco/Scrivania/marks.txt");
string line;
while (getline(inputFile, line)) {
istringstream ss(line);
string heart;
ss >> heart;
std_msgs::String msg;
msg.data = ss.str();
pub.publish(msg);
ros::spinOnce();
loop_rate.sleep();
}
}
return 0;
}
由于发布的是 "variable" msg
,我试图在作为答案给出的代码中将变量 string_msg
替换为 msg
,但没有任何结果变了。谢谢!
我不确定我是否完全理解您想要什么,但这里有一个可能满足您需要的简短示例。
我在这里使用 std::deque
来获得一个包含 60 个值的循环缓冲区。您的代码中缺少的是一个回调函数 process_message
,每次收到新消息时都会为订阅者调用该函数。
我没有编译这段代码,所以它可能不会马上编译,但基础知识已经有了。
#include <ros/ros.h>
#include <std_msgs/String.h>
#include "../include/heart_rate_monitor/wfdb.h"
#include <stdio.h>
#include <sstream>
#include <iostream>
#include <fstream>
#include <iomanip>
#include <algorithm>
#include <deque>
static std::deque<std::string> queue_buffer;
static int entries_added_since_last_write = 0;
void write_data_to_file()
{
// open file
std::ofstream data_file("my_data_file.txt");
if (data_file.is_open())
{
for (int i = 0; i < queue_buffer.size(); ++i)
{
data_file << queue_buffer[i] << std::end;
}
}
else
{
std::cout << "Error - Cannot open file." << std::endl;
exit(1);
}
data_file.close();
}
void process_message(const std_msgs::String::ConstPtr& string_msg)
{
// if buffer has already 60 entries, throw away the oldest one
if (queue_buffer.size() == 60)
{
queue_buffer.pop_front();
}
// add the new data at the end
queue_buffer.push_back(string_msg.data);
// check if 10 elements have been added and write to file if so
entries_added_since_last_write++;
if (entries_added_since_last_write == 10
&& queue_buffer.size() == 60)
{
// write data to file and reset counter
write_data_to_file();
entries_added_since_last_write = 0;
}
}
int main(int argc, char **argv)
{
ros::init(argc, argv, "writer");
ros::NodeHandle n;
ros::Subscriber sub = n.subscribe("/HeartRateInterval", 1000, process_message);
ros::spin();
return 0;
}
如果这个问题对你来说太简单了,我很抱歉,但我没有良好的编程技能和 ROS 知识。我有一个 ROS 主题,其中发布了一些以秒为单位的心跳间隔数字。我需要订阅那个主题并做这样的阐述:我的想法是有一个由十个数字组成的小数组,我可以在其中连续存储十个心跳。然后我有一个更大的 60 个数字数组,必须上升十个位置才能在底部有小数组的最新十个值,它必须 "throw away" 十个最旧的值(我做了一点研究,也许我必须使用向量而不是数组,因为在 C++ 中,数组在我阅读时是固定的)。然后我必须每次在文本文件中打印这 60 个值(我的意思是在一个循环中,所以文本文件将被连续覆盖)。此外,我看到 ROS 以这种方式从主题输出数据:data: 0.987
,每个数据在一列中被 ---
与其他数据分开。我真正想要的是一个文本文件,因为我需要一个以这种方式读取文本文件的脚本,其中的值位于一列中,没有空格和其他符号或单词,如下所示:
0.404
0.952
0.956
0.940
0.960
我在下面提供了我的节点的代码,其中,目前我只做了订阅部分,因为我不知道如何做我以后必须做的事情。预先感谢您的帮助!!!
代码:
#include "ros/ros.h"
#include "std_msgs/String.h"
#include "../include/heart_rate_monitor/wfdb.h"
#include <stdio.h>
#include <sstream>
#include <iostream>
#include <fstream>
#include <iomanip>
#include <algorithm>
#include <vector>
int main(int argc, char **argv)
{
ros::init(argc, argv, "writer");
ros::NodeHandle n;
ros::Subscriber sub = n.subscribe("/HeartRateInterval", 1000);
ros::spin();
return 0;
}
注意:我没有包含 Float32/64 header 因为我将心跳作为字符串发布。不知道大家有没有兴趣
编辑:我将在下面包含在 ROS 主题上发布数据的发布者节点的代码。
#include "ros/ros.h"
#include "std_msgs/String.h"
#include "../include/heart_rate_monitor/wfdb.h"
#include <stdio.h>
#include <sstream>
#include <iostream>
#include <fstream>
#include <iomanip>
using namespace std;
int main(int argc, char **argv)
{
ros::init(argc, argv, "heart_rate_monitor");
ros::NodeHandle n;
ros::Publisher pub = n.advertise<std_msgs::String>("/HeartRateInterval", 1000);
ros::Rate loop_rate(1);
while (ros::ok())
{
ifstream inputFile("/home/marco/Scrivania/marks.txt");
string line;
while (getline(inputFile, line)) {
istringstream ss(line);
string heart;
ss >> heart;
std_msgs::String msg;
msg.data = ss.str();
pub.publish(msg);
ros::spinOnce();
loop_rate.sleep();
}
}
return 0;
}
由于发布的是 "variable" msg
,我试图在作为答案给出的代码中将变量 string_msg
替换为 msg
,但没有任何结果变了。谢谢!
我不确定我是否完全理解您想要什么,但这里有一个可能满足您需要的简短示例。
我在这里使用 std::deque
来获得一个包含 60 个值的循环缓冲区。您的代码中缺少的是一个回调函数 process_message
,每次收到新消息时都会为订阅者调用该函数。
我没有编译这段代码,所以它可能不会马上编译,但基础知识已经有了。
#include <ros/ros.h>
#include <std_msgs/String.h>
#include "../include/heart_rate_monitor/wfdb.h"
#include <stdio.h>
#include <sstream>
#include <iostream>
#include <fstream>
#include <iomanip>
#include <algorithm>
#include <deque>
static std::deque<std::string> queue_buffer;
static int entries_added_since_last_write = 0;
void write_data_to_file()
{
// open file
std::ofstream data_file("my_data_file.txt");
if (data_file.is_open())
{
for (int i = 0; i < queue_buffer.size(); ++i)
{
data_file << queue_buffer[i] << std::end;
}
}
else
{
std::cout << "Error - Cannot open file." << std::endl;
exit(1);
}
data_file.close();
}
void process_message(const std_msgs::String::ConstPtr& string_msg)
{
// if buffer has already 60 entries, throw away the oldest one
if (queue_buffer.size() == 60)
{
queue_buffer.pop_front();
}
// add the new data at the end
queue_buffer.push_back(string_msg.data);
// check if 10 elements have been added and write to file if so
entries_added_since_last_write++;
if (entries_added_since_last_write == 10
&& queue_buffer.size() == 60)
{
// write data to file and reset counter
write_data_to_file();
entries_added_since_last_write = 0;
}
}
int main(int argc, char **argv)
{
ros::init(argc, argv, "writer");
ros::NodeHandle n;
ros::Subscriber sub = n.subscribe("/HeartRateInterval", 1000, process_message);
ros::spin();
return 0;
}