【问题标题】:I want to store in an array messages from a ROS topic for further elaboration我想将来自 ROS 主题的消息存储在数组中以供进一步阐述
【发布时间】:2016-11-18 16:18:29
【问题描述】:

如果这个问题对你来说太简单了,我很抱歉,但我没有良好的编程技能和 ROS 知识。我有一个 ROS 主题,其中发布了一些以秒为单位的心跳间隔数字。我需要订阅该主题并进行此类详细说明:想法是有一个十个数字的小数组,我可以在其中连续存储十个心跳。然后我有一个更大的 60 个数字数组,必须上升 10 个位置,以便在底部有小数组的最新十个值,它必须“丢弃”十个最旧的值(我做了一些研究也许我必须使用向量而不是数组,因为在 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 标头,因为我将心跳作为字符串发布。我不知道这是否有趣。

编辑:我将在发布者节点的代码下方包含在 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;

}

由于发布的是“变量”msg,我尝试在作为答案给出的代码中将变量string_msg 替换为msg,但没有任何改变。谢谢!

【问题讨论】:

  • 解决了在 process_message 函数的第二个 if 中将 ==10 更改为 &gt;=10。答案评论部分有详细解释。谢谢!

标签: c++ arrays text messages ros


【解决方案1】:

我不确定我是否完全理解您想要什么,但这里有一个简短的示例,它可能会满足您的需求。

我在这里使用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;
}

【讨论】:

  • 非常感谢@cassinaj 的回复和您的努力!对于迟到的答案,我很抱歉,但我有两天不在我的电脑上。我试图编译它,但我遇到了这个错误:/home/marco/catkin_ws/src/heart_rate_monitor/src/scrittore.c‌ ​pp: In function ‘void process_message(const ConstPtr&amp;)’: /home/marco/catkin_ws/src/heart_rate_monitor/src/scrittore.c‌​pp:46:37: error: ‘const ConstPtr’ has no member named ‘data’ queue_buffer.push_back(string_msg.data); 你知道为什么吗?反正我是自己找找的
  • 也许函数void process_message(const std_msgs::String::ConstPtr&amp; string_msg) 只需要msg 而不是string_msg?我在发布者和订阅者教程中找到了它。无论如何,即使我改变它,我也会得到几乎相同的错误。对不起我的无知
  • @Vtik 谢谢!现在它编译了!它运行。但我找不到文本文件。我错过了什么吗?
  • std::ofstream data_file("my_data_file.txt");将此行更改为您需要的任何路径和名称。
  • @Vtik 我试过了,我用我选择的名称创建了一个空文本文件,但其中没有写入数据。也许我不清楚,但是,我想要的是一个文本文件作为输出,而不是输入。输入是 ROS 主题消息。也许使用此代码,程序会搜索文本文件作为输入?我不明白。非常感谢.. 对你们俩!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2016-03-29
  • 1970-01-01
  • 2021-04-02
  • 2015-01-27
  • 2017-06-07
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多