ROS Resources: Documentation | Support | Discussion Forum | Index | Service Status | ros @ Robotics Stack Exchange |
1 | initial version |
First of all, you probably want to use the recommended python style for ROS.
Assuming these files are ros nodes:
scripts/knex_arduino_connector.py
scripts/knex_scratch_connector.py
scripts/range_filter.py
scripts/range_to_laser.py
the package directory style I follow for a ros package looks like this:
knex_pkg/
CMakesLists.txt
package.xml
launch/ # roslaunch files go here
msg/ # msg files go here
nodes/ # installable python nodes go here
knex_arduino_connector.py
knex_scratch_connector.py
range_filter.py
range_to_laser.py
src/ # this is where your python modules exported as libraries or used in your nodes go.
urdf/ # urdf and xacro files go here -- basically your robot model stuff, if any.
scripts/ # generally non-exported python scripts -- stuff that might be called to setup your package and code gen stuff
srv/ # service descriptions go here
__init__.py # only necessary if you want to use anything from the scripts directory in your package src and node files
setup.py # more on this later
In your CMakesLists.txt you need to add a catkin_python_setup()
(Handling of setup.py) line after your find_package()
calls and before your service, message generation, and add messages calls:
cmake_minimum_required(VERSION 2.8.3)
project(knex_ros)
find_package(catkin REQUIRED COMPONENTS
rospy
std_msgs
tf
roscpp
robot_state_publisher
differential_drive
)
catkin_python_setup()
...
setup.py
is the python distutils setup script. It's where you describe the structure of a python package. The python style guide for ros is pretty specific in how python packages should be layed out. Any modules used should go under src. If you are like me, and like a clearly defined source tree structure with directories as package names, your setup.py will look something like this:
## ! DO NOT MANUALLY INVOKE THIS setup.py, USE CATKIN INSTEAD
from distutils.core import setup
from catkin_pkg.python_setup import generate_distutils_setup
# fetch values from package.xml
setup_args = generate_distutils_setup(
packages=['my_package],
package_dir={'': 'src'},
requires=['std_msgs', 'rospy', 'message_filters', 'gps_common', 'sensor_msgs']
)
setup(**setup_args)
In setup_args
you are defining your package by calling generate_distutils_setup
.
The packages
argument is an array of package names. Use dot-delimited format (my_package.subpackage
) if you wish to explicitly name more than one package. I generally just use one package root and let distutils figure it out from there, and I think this is the simplest practice.
The package_dir
arg allows you to specify a source directory for a package name. If you have only one package, then you can omit the package name and give a relative path to the directory containing the modules for that package. If you follow the style guide, that directory will be src
. If you have multiple packages in different source directories, you can specify them in this dictionary.
The requires
arg is an array of python package names that are required by your package(s). In my example setup.py
above, I use std_msgs
so I've included it in the list. You will probably always have rospy
. I don't think this is explicitly required for ros packages, but I think it is good practice to list them here.
The directory structure under src
is important for the setup.py
to work properly. If you have a package named my_package
with submodules my_submodule_a
and my_submodule_b
, you need to set it up like this:
my_package/ # the root of the ros package
setup.py
src/
my_package/ # here's your python module root
__init__.py # put your python code for my_package here.
my_submodule_a/ # I prefer directories for submodules, but some prefer just a python file named my_submodule_a.py instead
__init__.py # this is your my_package.my_submodule_a source file.
my_submodule_b/
__init__.py # this is your my_package.my_submodule_b source file.
catkin_python_setup
will allow you to use the modules in src
in your executable node files by importing them from the my_package
namespace. Similarly, service descriptions and msgs can be imported from this same namespace -- for example:
#!/usr/bin/env python
import rospy
import roslib
roslib.load_manifest('my_package')
from std_msgs.msg import Header
from my_package.msg import MyMsg
import my_package.my_submodule_a
def run_my_node():
init_node("my_package_node")
spin()
if __name__ == "__main__":
run_my_node()
Don't forget to mark your nodes as executable with chmod +x nodes/my_package_node.py
!
I recommend setting up roslaunch launch files for your nodes, and parameterizing any arguments to them with the ros parameter server. You can set up any number of launch files and stack them together by using the include
tag in other launch files. Then run them with roslaunch my_package_name my_launchfile_name.launch
. It works out very nicely.
After you've done all that, update your installables in your CMakesList.txt
and you should get a better result.
2 | No.2 Revision |
First of all, you probably want to use the recommended python style for ROS.
Assuming these files are ros nodes:
scripts/knex_arduino_connector.py
scripts/knex_scratch_connector.py
scripts/range_filter.py
scripts/range_to_laser.py
the package directory style I follow for a ros package looks like this:
knex_pkg/
CMakesLists.txt
package.xml
launch/ # roslaunch files go here
msg/ # msg files go here
nodes/ # installable python nodes go here
knex_arduino_connector.py
knex_scratch_connector.py
range_filter.py
range_to_laser.py
src/ # this is where your python modules exported as libraries or used in your nodes go.
urdf/ # urdf and xacro files go here -- basically your robot model stuff, if any.
scripts/ # generally non-exported python scripts -- stuff that might be called to setup your package and code gen stuff
srv/ # service descriptions go here
__init__.py # only necessary if you want to use anything from the scripts directory in your package src and node files
setup.py # more on this later
In your CMakesLists.txt you need to add a catkin_python_setup()
(Handling of setup.py) line after your find_package()
calls and before your service, message generation, and add messages calls:
cmake_minimum_required(VERSION 2.8.3)
project(knex_ros)
find_package(catkin REQUIRED COMPONENTS
rospy
std_msgs
tf
roscpp
robot_state_publisher
differential_drive
)
catkin_python_setup()
...
setup.py
is the python distutils setup script. It's where you describe the structure of a python package. The python style guide for ros is pretty specific in how python packages should be layed out. Any modules used should go under src. If you are like me, and like a clearly defined source tree structure with directories as package names, your setup.py will look something like this:
## ! DO NOT MANUALLY INVOKE THIS setup.py, USE CATKIN INSTEAD
from distutils.core import setup
from catkin_pkg.python_setup import generate_distutils_setup
# fetch values from package.xml
setup_args = generate_distutils_setup(
packages=['my_package],
packages=['my_package'],
package_dir={'': 'src'},
requires=['std_msgs', 'rospy', 'message_filters', 'gps_common', 'sensor_msgs']
)
setup(**setup_args)
In setup_args
you are defining your package by calling generate_distutils_setup
.
The packages
argument is an array of package names. Use dot-delimited format (my_package.subpackage
) if you wish to explicitly name more than one package. I generally just use one package root and let distutils figure it out from there, and I think this is the simplest practice.
The package_dir
arg allows you to specify a source directory for a package name. If you have only one package, then you can omit the package name and give a relative path to the directory containing the modules for that package. If you follow the style guide, that directory will be src
. If you have multiple packages in different source directories, you can specify them in this dictionary.
The requires
arg is an array of python package names that are required by your package(s). In my example setup.py
above, I use std_msgs
so I've included it in the list. You will probably always have rospy
. I don't think this is explicitly required for ros packages, but I think it is good practice to list them here.
The directory structure under src
is important for the setup.py
to work properly. If you have a package named my_package
with submodules my_submodule_a
and my_submodule_b
, you need to set it up like this:
my_package/ # the root of the ros package
setup.py
src/
my_package/ # here's your python module root
__init__.py # put your python code for my_package here.
my_submodule_a/ # I prefer directories for submodules, but some prefer just a python file named my_submodule_a.py instead
__init__.py # this is your my_package.my_submodule_a source file.
my_submodule_b/
__init__.py # this is your my_package.my_submodule_b source file.
catkin_python_setup
will allow you to use the modules in src
in your executable node files by importing them from the my_package
namespace. Similarly, service descriptions and msgs can be imported from this same namespace -- for example:
#!/usr/bin/env python
import rospy
import roslib
roslib.load_manifest('my_package')
from std_msgs.msg import Header
from my_package.msg import MyMsg
import my_package.my_submodule_a
def run_my_node():
init_node("my_package_node")
spin()
if __name__ == "__main__":
run_my_node()
Don't forget to mark your nodes as executable with chmod +x nodes/my_package_node.py
!
I recommend setting up roslaunch launch files for your nodes, and parameterizing any arguments to them with the ros parameter server. You can set up any number of launch files and stack them together by using the include
tag in other launch files. Then run them with roslaunch my_package_name my_launchfile_name.launch
. It works out very nicely.
After you've done all that, update your installables in your CMakesList.txt
and you should get a better result.