2

How to input data (numerical values) in a CSV file (values separated by commas), to a C++ file-executable to be run in a terminal to see the motion of a robot in rviz? The data contains the position of robot joints at different times; part of the CSV file contains values like these, each column representing each joint. Each line of the file contains 17 floating point numbers separated by commas, and there are over 100 lines in my sample data file. One line is:

 1.388106,-0.593356,-1.524699,-1.468721,1.585204,-88.993656,20.192482,-46.047969,-31.037494,12.317457,1.535528,-29.353799,-89.148412,-20.592636,20.303178,22.044684,19.933448

The following code is the publishJoint.cpp file:

    #include <string>
    #include <ros/ros.h>
    #include <sensor_msgs/JointState.h>

    int main(int argc, char** argv) 
    {
        ros::init(argc, argv, "publishJoints");
        ros::NodeHandle n;
        ros::Publisher joint_pub = n.advertise<sensor_msgs::JointState>("joint_states", 100);
        ros::Rate loop_rate(1000000);

        const double degree = M_PI/180;

        // robot state
        double swivel=0;
        double tilt=0;


       // message declarations
       sensor_msgs::JointState joint_state;

       joint_state.name.resize(17);
       joint_state.position.resize(17);

       while (ros::ok()) 
       {
           //update joint_state
           joint_state.header.stamp = ros::Time::now();

           swivel=0;
           joint_state.name[0] ="m3joint_mt4_j0";
           joint_state.position[0] = swivel;

           joint_state.name[1] ="m3joint_mt4_j1";
           joint_state.position[1] = tilt;

           joint_state.name[2] ="m3joint_slave_mt4_j2";
           joint_state.position[2] = swivel;

           joint_state.name[3] ="left_shoulder_pan_joint";
           joint_state.position[3] = tilt;

           joint_state.name[4] ="left_shoulder_lift_joint";
           joint_state.position[4] = tilt;

           joint_state.name[5] ="left_elbow_pan_joint";
           joint_state.position[5] = tilt;

           joint_state.name[6] ="left_elbow_lift_joint";
           joint_state.position[6] = tilt;

           joint_state.name[7] ="m3joint_ma14_j4";
           joint_state.position[7] = tilt;

           joint_state.name[8] ="m3joint_ma14_j5";
           joint_state.position[8] = tilt;

           joint_state.name[9] ="m3joint_ma14_j6";
           joint_state.position[9] = tilt;

           joint_state.name[10] ="right_shoulder_pan_joint";
           joint_state.position[10] = swivel;

           joint_state.name[11] ="right_shoulder_lift_joint";
           joint_state.position[11] = swivel;

           joint_state.name[12] ="right_elbow_pan_joint";
           joint_state.position[12] = swivel;

           joint_state.name[13] ="right_elbow_lift_joint";
           joint_state.position[13] = swivel;

           joint_state.name[14] ="m3joint_ma12_j4";
           joint_state.position[14] = swivel;

           joint_state.name[15] ="m3joint_ma12_j5";
           joint_state.position[15] = swivel;

           joint_state.name[16] ="m3joint_ma12_j6" ;
           joint_state.position[16] = swivel;

           tilt += 0.000001;

           //send the joint state and transform
           joint_pub.publish(joint_state);

           // This will adjust as needed per iteration
           loop_rate.sleep();
       }
   return 0;
}

How can I read the data from the file into my program?

Jonathan Leffler
  • 730,956
  • 141
  • 904
  • 1,278
ram
  • 25
  • 2
  • 5
  • 3
    So what's the problem, exactly? I mean you have some code, so it implies that you have some clue as to what you're doing. – In silico Jun 27 '11 at 05:28
  • @ram: Phew, tedious code edit, First one is free, Indent your code better from nnext time. – Alok Save Jun 27 '11 at 05:33
  • how to add in code for reading a csv file with data as stated above, as inputs to the joints at different instances ,in the cpp file? – ram Jun 27 '11 at 05:34
  • Wild guess: store them in a file named `publishJoints`? What does `ros::init()` do with that string, if not read in the file of commands? – sarnold Jun 27 '11 at 05:35
  • @Als, and also @ram: most IDEs and even some editors contain a **prettyfier** available in a single keystroke or two. E.g., Code::Blocks IDE has one, and Notepad++ editor has one. I'm pretty sure there must be one also in highly devolved Visual Studio 10, for those who use that beast? – Cheers and hth. - Alf Jun 27 '11 at 05:41
  • @sarnold ros::init() -this provides command line arguments to ROS, and allows to name the node and specify other options. – ram Jun 27 '11 at 05:47
  • @Alf P. Steinbach: Sure must be, I usually work on Linux, and Visual mode of vim works like a charm for such a case, Made a note: to use that henceforth! – Alok Save Jun 27 '11 at 05:54
  • 2
    The data file doesn't appear to contain any commas, which makes it an odd CSV format. Are you sure you don't just need to read a line from the file into a string and then split it into the 17 or so fields? Actually, the two sample lines don't have the same number of entries (74 and 21, which are mutually prime), which makes it very hard to guess what the data format should really be. – Jonathan Leffler Jun 27 '11 at 06:06
  • @Als, the `scripts/Lindent` script in the Linux kernel source tree is _wonderful_ for fixing up C, C++, Java, Obj-C (sort-of), PHP, Perl, programs. (It's just some well-chosen arguments to `indent(1)`.) It'll take out 90% of the tedium of fixing up poorly-designed programs _and_ markdown-based catastrophes. – sarnold Jun 27 '11 at 06:25
  • @Jonathan Leffler thanks for the comments,the actual file does contain commas but i posted the xls format of the file,my bad(have edited now).there are actually 17 columns and 120 rows,but i did not post everything here.these are the position of all the 17 joints in sequence,each column for each joint.should i have to create another cpp and call it in the main cpp?? – ram Jun 27 '11 at 06:32
  • See this answer [how-can-i-read-and-manipulate-csv-file-data-in-c++](http://stackoverflow.com/questions/415515/how-can-i-read-and-manipulate-csv-file-data-in-c/415553#415553) – Bo Persson Jun 27 '11 at 07:12

1 Answers1

3

Since there are supposed to be 17 entries per line, I would read each line into a string, and then carve the string into 17 values using a string stream. Here is some outline code that does the job; it can certainly be enhanced and would have to be adapted to fit your program.

#include <iostream>
#include <sstream>
#include <string>
#include <cstdlib>
using namespace std;

static void err_exit(int line, int field, const char *tag, string &s)
{
    cerr << "Format error: line " << line << ", field " << field << ": " << tag << '\n';
    cerr << "Data: " << s << endl;
    exit(1);
}

int main(void)
{
    string s;
    int lineno = 0;
    while (cin >> s)
    {
        cout << "<<" << s << ">>" << endl;
        lineno++;
        stringstream ss(s);
        enum { NUM_ENTRIES = 17 };
        double v[NUM_ENTRIES];
        char delim;
        for (int i = 0; i < NUM_ENTRIES; i++)
        {
            if (!(ss >> v[i]))
                err_exit(lineno, i, "extract failed", s);
            else if (i < NUM_ENTRIES - 1 && !((ss >> delim) && delim == ','))
                err_exit(lineno, i, "delimiter incorrect", s);
            else if (i == NUM_ENTRIES - 1 && (ss >> delim))
                err_exit(lineno, i, "extra data at end of line", s);
        }
        // Process v
        cout << "Line: " << lineno << '\n';
        for (int i = 0; i < NUM_ENTRIES; i++)
        {
            cout << "Entry " << i << ": " << v[i] << '\n';
        }
        cout << endl;
    }
}

Given your input line above, it produces the output:

<<1.388106,-0.593356,-1.524699,-1.468721,1.585204,-88.993656,20.192482,-46.047969,-31.037494,12.317457,1.535528,-29.353799,-89.148412,-20.592636,20.303178,22.044684,19.933448>>
Line: 1
Entry 0: 1.38811
Entry 1: -0.593356
Entry 2: -1.5247
Entry 3: -1.46872
Entry 4: 1.5852
Entry 5: -88.9937
Entry 6: 20.1925
Entry 7: -46.048
Entry 8: -31.0375
Entry 9: 12.3175
Entry 10: 1.53553
Entry 11: -29.3538
Entry 12: -89.1484
Entry 13: -20.5926
Entry 14: 20.3032
Entry 15: 22.0447
Entry 16: 19.9334
Jonathan Leffler
  • 730,956
  • 141
  • 904
  • 1,278