ROS Resources: Documentation | Support | Discussion Forum | Index | Service Status | ros @ Robotics Stack Exchange
Ask Your Question
0

How to read data from txt file python

asked 2019-02-25 12:00:35 -0500

Spyros gravatar image

I have a python script which reads data from 4 txt files and stores the values in 4 numpy arrays. I put the txt files in the same directory with my python node, but when I run the node the files cannot be located and I get the error:

IOError: [Errno 2] No such file or directory: 'xdot.txt'

That works when I run the code on a python IDE, but I don't know where is the problem here. I am new to ROS and I use ROS Kinetic, Python 2.7.12 on Ubuntu 16.04 LTS. Thank you in advance.

#!/usr/bin/python

import rospy
import serial
import time
from std_msgs.msg import String
from decimal import Decimal
import numpy as np
from scipy.integrate import odeint, solve_ivp
import matplotlib.pyplot as plt
from scipy.interpolate import interp1d

xdot_list = []
ydot_list = []
xdotdot_list = []
ydotdot_list = []

with open('xdot.txt', 'r') as filehandle:
    filecontents = filehandle.readlines()

    for line in filecontents:
        current_place = line[:-1]
        xdot_list.append(current_place)

xdot = np.array(xdot_list, dtype=np.float32) 

with open('ydot.txt', 'r') as filehandle:
    filecontents = filehandle.readlines()

    for line in filecontents:
        current_place = line[:-1]
        ydot_list.append(current_place)

ydot = np.array(ydot_list, dtype=np.float32) 

with open('xdotdot.txt', 'r') as filehandle:
    filecontents = filehandle.readlines()

    for line in filecontents:
        current_place = line[:-1]
        xdotdot_list.append(current_place)

xdotdot = np.array(xdotdot_list, dtype=np.float32) 

with open('ydotdot.txt', 'r') as filehandle:
    filecontents = filehandle.readlines()

    for line in filecontents:
        current_place = line[:-1]
        ydotdot_list.append(current_place)

ydotdot = np.array(ydotdot_list, dtype=np.float32)
edit retag flag offensive close merge delete

1 Answer

Sort by ยป oldest newest most voted
2

answered 2019-02-25 12:05:19 -0500

gvdhoorn gravatar image

updated 2019-02-27 06:12:44 -0500

I put the txt files in the same directory with my python node, but when I run the node the files cannot be located and I get the error:

IOError: [Errno 2] No such file or directory: 'xdot.txt'

That works when I run the code on a python IDE, but I don't know where is the problem here.

The problem is in the difference in working directory when running the script directly versus using roslaunch or rosrun.

See #q235337 for more info on that.

In short: don't use relative paths, but absolute ones. To avoid hard-coding paths specific to your own PC, use ROS parameters with substitution args.


Edit:

I checked the links you pointed out. In my occasion, it is not a problem to use an absolute path to open the file.

Absolute paths are not the problem. The problem would be to embed paths that are only valid on your own machine in your code. That is never a good idea.

But which is the recommended way to do it in ROS applications in general?

If you want to keep things relative to package locations, you could use either something like rospkg or the substitution args I mentioned earlier. If you have the option, I'd go for the substitution args (as you avoid adding another dependency to your program).


Edit2:

I have my 4 files in the path: ~/catkin_ws/src/usb_rs232/scripts in the usb_rs232 package. So the command would be:

rosrun usb_rs232 serial_connection.py _arg_name:=$(rospack find usb_rs232)~/catkin_ws/src/usb_rs232/scripts

No.

The command would be (provided you have an actual ROS parameter in your Python script called arg_name):

rosrun usb_rs232 serial_connection.py _arg_name:=$(rospack find usb_rs232)/scripts

There's no need to repeat the path. $(rospack find usb_rs232) returns the path to $HOME/catkin_ws/src/usb_rs232, but without hard-coding it. The /scripts part would be appended to that. So in the end, arg_name gets the value $HOME/catkin_ws/src/usb_rs232/scripts assigned to it. You can then retrieve that in your script using rospy.get_param('arg_name') and use it as a base path, relative to which you could then open your 4 files.


Edit 3:

I changed my code to:

rospy.get_param('arg_name')
with open('arg_name/xdot.txt', 'r') as filehandle:

with the same command and I get the error:

KeyError: 'arg_name'

This is starting to become more of a Python question and not so much a ROS question, but: that's not how this works.

rospy.get_param(..) returns a str object, so you'll have to store that somewhere. Then, you should use that str and prefix it to the filename to get a valid path.

Something like the following should work:

base_dir = rospy.get_param('~arg_name')
with open(base_dir + '/xdot.txt', 'r') as filehandle:
    ...

Note: you only need to retrieve arg_name once. And you'll probably want to add some error checking for when the user hasn't actually set arg_name to a legal/proper value.

I would actually recommend ... (more)

edit flag offensive delete link more

Comments

Thanks for the response. I checked the links you pointed out. In my occasion, it is not a problem to use an absolute path to open the file. But which is the recommended way to do it in ROS applications in general?

Spyros gravatar image Spyros  ( 2019-02-26 03:02:51 -0500 )edit

the substitution args can be applied with rosrun with the same way the do with roslaunch ? I prefer to use rosrun but I am a bit lost in the documentation of substitution args. How can this be applied with rosrun?

Spyros gravatar image Spyros  ( 2019-02-26 06:33:39 -0500 )edit

With rosrun it's no longer a substitution arg, as those are roslaunch specific.

But rospack find can be used on the command line, so something like this should work:

rosrun your_pkg your_script _arg_name:=$(rospack find pkg_with_txt_file)/path/to/file.txt
gvdhoorn gravatar image gvdhoorn  ( 2019-02-26 06:45:00 -0500 )edit

how can this work for several txt files that open in the same script? (4 in my case). The files are in the same directory.

Spyros gravatar image Spyros  ( 2019-02-26 07:21:53 -0500 )edit

Pass the path to a directory instead of a file?

gvdhoorn gravatar image gvdhoorn  ( 2019-02-26 07:37:16 -0500 )edit

it doesn't seems to work. I have already done it with absolute path, I just wanted to know my alternatives. But it is not really convenient to type all the path every time I run the node

Spyros gravatar image Spyros  ( 2019-02-26 08:20:17 -0500 )edit

it doesn't seems to work.

If you can show us what "doesn't work", perhaps we can help.

But it is not really convenient to type all the path every time I run the node

well, that is what roslaunch would be for.

gvdhoorn gravatar image gvdhoorn  ( 2019-02-26 08:25:38 -0500 )edit

I have my 4 files in the path: ~/catkin_ws/src/usb_rs232/scripts in the usb_rs232 package. So the command would be: rosrun usb_rs232 serial_connection.py _arg_name:=$(rospack find usb_rs232)~/catkin_ws/src/usb_rs232/scripts ?

Spyros gravatar image Spyros  ( 2019-02-26 08:38:43 -0500 )edit

Question Tools

1 follower

Stats

Asked: 2019-02-25 12:00:35 -0500

Seen: 2,800 times

Last updated: Feb 27 '19