My apologies for the long haul considering that the last blog post. I began a PhD in AI as well as Robotics at Cambridge College, which has actually been soaking up all my extra time. This blog post is really fairly old, yet I never ever navigated to releasing it. Fortunately is that I have actually discovered a lot concerning robotics, biomimetics, ROS, MoveIt, deep understanding, the Jetson TX1 as well as even more, every one of which I want to cooperate due program. My apologies additionally for remarks that waited months to be authorized. When I lastly dragged myself back to remarks area I located just 4 actual remarks out of greater than 600 littles spam.

This instead details blog post outgrew an irritating effort to create a rather intricate ROS bundle in Python which was consistently obstructed by relatively arbitrary import mistakes when my node was released in various means. In justness, I am neither a seasoned Python designer neither a ROS specialist, so my troubles was because of lack of knowledge. Nonetheless, improving that lack of knowledge was non-trivial as well as led me down one bunny opening in regards to just how Python handles bundles as well as an additional bunny opening in regards to just how ROS does it.

This blog post is meant to be a faster way for beginner ROS designers that wish to establish a Python node that includes greater than one resource data as well as imports Python collections.

My earlier lack of knowledge (at the very least on this topic) can be summed up as:

  1. I really did not truly comprehend just how Python’s import declaration functioned
  2. I really did not recognize just how to structure the resource documents in a Python-based ROS bundle
  3. I really did not truly recognize what the objective of Catkin was for Python-based ROS bundles
  4. I really did not recognize what boilerplate required to be used to make sure that Catkin can handle my ROS bundle
  5. I really did not recognize just how to state dependences in my ROS bundle

Why we structure the resource documents in a Python-based ROS bundle the method we do

Python-based ROS bundles will usually have nodes, manuscripts as well as launch documents.

Introduce documents are a collection of guidelines to release several ROS nodes along with the ROS master if it isn’t currently running.

Nodes as well as Manuscripts

The distinction in between nodes as well as manuscripts is mainly semantic: they are both Python documents that can be carried out from the command line with

rosrun

Nodes are presumed to develop as well as release ROS Nodes, whereas manuscripts can be utilized for any type of objective. This difference is a convention to make our bundles much easier to comprehend, not a technological distinction.

For comfort we placed nodes as well as manuscripts right into folders called/ nodes as well as/ manuscripts specifically, although this isn’t purely required. They ought to be offered perform authorizations with chmod

cd
chmod +x nodes/mynode1
chmod +x scripts/myscript1

For visual appeals, mynode1 as well as myscript1 will not have a.py expansion (which suggests the very first line of the data have to be identified with #!/ usr/bin/env python). The individual can after that make use of

rosrun mypackage mynode1

as well as not the messier

rosrun mypackage mynode1.py

You can place your whole code in either of these documents as well as go on. That suffices to reach hi globe:

#!/ usr/bin/env python

if __ name __== ‘ __ major __ ’:
print “hello world”

Nonetheless, it is more probable that you wish to damage down any type of non-trivial Python code right into numerous different documents (referred to as “modules” in Python land). The most effective method to do this is to maintain your nodes as well as manuscripts as brief as feasible as well as have them just import as well as perform the major() feature from your actual code. As an example, mynode1 may have:

#!/ usr/bin/env python

from mypackage import major

if __ name __== ‘ __ major __ ’:
major()

Why trouble with this additional layer of documents if the actual job is being done somewhere else? The ROS command rosrun hooks right into nodes as well as manuscripts, as does roslaunch. However we might additionally wish to import our ROS bundle capability right into a 2nd ROS bundle. This is done by proclaiming Catkin dependences in the 2nd ROS bundle (for developing objectives) and after that making use of common Python systems for importing the code from the very first bundle right into the 2nd one. The “Python mechanisms” little bit is essential, as it suggests we ought to structure our importable code as a Python bundle, not to be puzzled with a ROS bundle!

Currently allow’s rely on where we placed the mass of our code.

Packing our code right into a Python bundle

So our ROS bundle requires to have a Python bundle with the mass of our code, at the very least if we wish to make it importable right into various other ROS bundles. The traditional method to do that is to place the code right into a directory site called

src/

By convention, the Python bundle name as well as the ROS Plan name coincide, also if purely talking they do not require to be. So if our ROS Plan is called mypackage, after that placed the mass of your Python code in

src/mypackage

The import declaration in our nodes as well as manuscripts will certainly appear like this:

from mypackage import major

When Python stumbles upon an import declaration of this type, it thinks that mypackage describes either a file called mypackage.py (a “module” in Python land) or a directory site consisting of an __ init __. py data as well as additionally various other Python documents (jointly referred to as a “Python package”). We’re mosting likely to be making use of the last.

So at a minimum, we require a data called

src/mypackage/ __ init __. py

This can have all our code if we desire, consisting of the major() feature called from our nodes as well as manuscripts. Most likely, we’ll wish to divide our code right into various documents with detailed names. So allow’s place major() right into src/mypackage/foo. py as well as have __ init __. py have the following:

from foo import major

This will certainly after that be carried out whenever a node or manuscript data states

from mypackage import major

So major() from foo.py obtains imported right into the __ init __. py data within mypackage, where it can be re-imported right into the node as well as manuscript documents. foo.py itself can look something such as this:

#!/ usr/bin/env python

# … The mass of our code can go below …

def major():
print “Now executing main() in foo.py”
# Call the mass of our code …

All done, right? Not fairly. We still have not informed the node as well as manuscript documents where to discover the Python bundle mypackage. Bear in mind that Python will certainly search in the present directory site for a component or Python bundle to import, or on PYTHONPATH. However the directory site mypackage is/ src which is not instantly easily accessible. Prepare to get in a bunny opening.

Exactly how does a node or manuscript data really import our major code?

Python seeks components or Python bundles in the present directory site or on the course defined by the setting variable PYTHONPATH. We should not control PYTHONPATH ourselves, yet obtain Catkin to do it for us. To do that, we require to set up a data called setup.py in.

setup.py is a common Python data utilized for producing a distributable, installable pieces of code (I decline to make use of words “package” with yet an additional significance). This procedure is dealt with by a Python device collection called distutils which is recorded below, for those that are interested. For our objectives, we just require to make use of setup.py to inform Catkin the name of our Python bundle (“mypackage”) as well as where it lies (in the directory site “src”). Right here is an instance of setup.py:

#!/ usr/bin/env python

from distutils.core import arrangement
from catkin_pkg. python_setup import generate_distutils_setup

setup_args = generate_distutils_setup(
bundles =[‘mypackage’],
package_dir= {”: ‘ src ’}
)

arrangement(** setup_args)

All you require to do is personalize the line bundles= … The remainder is boilerplate. For those thinking about what the boilerplate does: it obtains called by Catkin throughout the catkin_make procedure, analyzes package.xml for meta-data like writer, permit etc, includes the specified bundles as well as package_dir as well as passes the mixed collection of info to distutils which does the real setup right into the Catkin advancement work space.

To make all this job, there are 2 even more tweaks to do in Catkin’s CMakeLists.txt data.

Initially, make certain this line is uncommented:

catkin_python_setup()

This informs Catkin to focus throughout the catkin_make procedure to the setup.py data we simply set up.

2nd, in the set up() feature we require to provide the node as well as manuscript documents we specified right at the start. So:

set up( PROGRAMS
scripts/myscript1
nodes/mynode1
nodes/mynode2
LOCATION $ {CATKIN_PACKAGE_BIN_DESTINATION}
)

This informs Catkin to mount our executable documents right into an obtainable area in the Catkin advancement work space.

As soon as setup.py as well as CMakeLists.txt are set up, perform catkin_make:

cd ~/ catkin_ws
catkin_make

as well as you ought to have the ability to perform your nodes as well as manuscripts, as well as for that reason your code in src/mypackage/foo. py from rosrun:

rosrun my bundle mynode1

You can basically quit below. Include Python documents (“modules”) like bar.py, baz.py to src/mypackage as well as have them import features right into each various other with

from bar import fn1, fn2
from baz import fn3, fn4

For Python code of tool intricacy that’s most likely sufficient to include some respectable framework to your code. Gluttons for penalty might wish to additional divide the code right into sub-packages. Allow’s take a look at just how to do that.

Including Sub-packages to our major Python Plan

You can include additional Python bundles below our major Python bundle in src/mypackage. Each subdirectory takes the name of the sub-package as well as have to consist of an __ init _. py data as well as additionally, a few other Python documents.

src/mypackage/subpackage/ __ init __. py
src/mypackage/subpackage/ something.py

Customarily, we can insert all our code right into __ init __. py, yet we’ll likely wish to have it right into different documents like something.py.

So our sub-package __ init __. py may have:

from something import *

In our major Python bundle we after that import code making use of the common Python systems:

from subpackage import fn5, fn6

If additionally we wish to make these Python sub-packages readily available to import right into various other ROS bundles, we would certainly require to include them to bundles= … in setup.py. If they’re totally utilized inside by our code, after that there’s no demand.

An Operating Instance you can download and install

Right Here’s a an instance I intermingled as a picture, with one node, one manuscript, one launch data, the major Python bundle as well as one sub-package.

example-structure

You can see the code below https://github.com/SimonBirrell/simontest

rosrun simontest simon_node1

rosrun_simontest_simon_node1

Have a look at the code, focusing on setup.py as well as the numerous __ init __. py documents. Finding out what is being called when as well as just how ought to provide you a strong grounding for developing durable as well as intricate Python applications.

If you wish to download and install, construct it as well as run the commands on your own:

cd ~/ catkin_ws/ src
git duplicate https://github.com/SimonBirrell/simontest
cd.
catkin_make

Specifying Dependences for our Python-based ROS Plan

All the above suffices for ROS Bundles that do not call outside Python collections. Usually however, you will certainly be importing as well as making use of various other Python collections such as numpy. We can just set up these bundles on our advancement maker making use of pip, apt-get or a few other technique and after that import them customarily, with

import numpy

The only trouble with this strategy is when you involve disperse your ROS Plan to various other individuals to set up their equipments. You will certainly need to consist of guidelines to ask them to set up the very same needed Python collections prior to they run your ROS Plan. It is very easy to neglect what you have actually set up by yourself advancement maker, so a much better remedy is to clearly specify the dependences, to make sure that Catkin will certainly mount them if needed when individuals construct your ROS Plan.

Regarding I can inform, this requires to be done two times, as when would certainly be also very easy.

Specifying Conventional Dependences

Initially, you require to specify the dependences the Python degree, by notifying distutils of the Python bundles you call for. This is done with setup.py in the:

#!/ usr/bin/env python

from distutils.core import arrangement
from catkin_pkg. python_setup import generate_distutils_setup

setup_args = generate_distutils_setup(
bundles =[‘my package’],
package_dir= {”: ‘ src ’},
install_requires =[‘required_python_package1’, ‘required_python_package2’]
)

The dependences are provided in the line starting install_requires= … The names utilized are the Python names, i.e. the names you would certainly make use of if you were setting up by hand with pip.

sudo pip set up required_python_package1

The 2nd location you require to specify the dependences remains in package.xml. Why in the world do we require to specify them two times?

The factor is that Catkin has its very own collection of names for Python bundles that is different from the Python names. Python dependences are specified in package.xml with a tag such as this:

ros-python-dependency

where the name ros-python-dependency originates from the rosdistro listing. As an instance, on a current job I utilized the Python internet outlets collection ws4py, which is set up by hand such as this:

sudo pip set up ws4py

Searching for ws4py on the rosdistro listing we discover:

python-ws4py-pip:
ubuntu:
pip:
bundles: [ws4py]

The last line recommendations the set up target for pip. So we can make use of the very first line for our dependence name in package.xml:

python-ws4py-pip

As soon as this is included, your ROS Plan ought to be installable by Catkin on other individuals’ equipments as well as the dependences ought to be immediately set up as well as constructed as needed.

The rosdistro listing consists of most commonly-used Python bundles. Sometimes however, you will certainly have some uncommon Python dependence.

I ought to state at this moment that the easiest remedy is simply to ask your individuals to by hand set up the non-standard Python dependence, with pip or a few other installer. If you desire complete automation though, you’re mosting likely to need to fork the rosdistro listing, include the non-standard bundle as well as send a pull demand. Thinking your demand is approved, the following individuals to access the rosdistro listing will certainly have the ability to immediately set up the dependence.

There are flawlessly ample guidelines for doing this below.

Idea: Evaluating your Reliance Interpretations

It’s normally difficult to examine whether the numerous adjustments over job. As quickly as examination as soon as, your maker has actually transformed state; the bundles are currently set up. Preferably, each examination would certainly start with an immaculate ROS setup, after that mount your ROS Plan, run catkin_make and after that examine the code itself.

This is currently fairly simple making use of among the constant assimilation solutions like TravisCI or CircleCI. I make use of the last; subscribe fasts as well as use is complimentary for the kind of work you’ll likely be doing.

As an example, I directed CircleCI to my ROS Plan’s GitHub repo as well as included the adhering to circle.yaml data in:

dependences:
pre:
– sudo sh -c ‘ resemble “deb http://packages.ros.org/ros/ubuntu $(lsb_release -sc) main” >/ etc/apt/sources. list.d/ ros-latest. listing ’
– sudo apt-key adv – keyserver hkp:// ha.pool.sks-keyservers. web – recv-key 0xB01 FA116
– sudo apt-get upgrade
– sudo apt-get set up ros-indigo-ros-base
– sudo rosdep init
– rosdep upgrade
– resemble “source /opt/ros/indigo/setup.bash” >> ~/. bashrc
– mkdir -p ~/ catkin_ws/ src & & cd ~/ catkin_ws/ src & & catkin_init_workspace
– pip set up ‘ gevent== 1.0.2 ’
– cd ~/ catkin_ws/ & & catkin_make

This YAML data informs CircleCI to run a collection of guidelines prior to implementing the automated examinations. These guidelines are basically the common ROS setup guidelines up until the line

– mkdir -p ~/ catkin_ws/ src & & cd ~/ catkin_ws/ src & & catkin_init_workspace

This line produces the Catkin work space. Once again, this is common ROS.

– pip set up ‘ gevent== 1.0.2 ’

This sets up gevent, which you’ll remember was a plan that had not been readily available in the rosdistro listing.

– cd ~/ catkin_ws/ & & catkin_make

This line runs catkin_make, which will certainly construct your ROS bundle.

Obviously, you will preferably currently have some examinations (possibly with nose) that go through your code as well as do the numerous imports. CircleCI ought to be set up to run these examinations.

If you do not have examinations, you can simply do a rosrun command at the end of this area of the circle.yaml data. If it functions, penalty. Otherwise, CircleCI will certainly reveal you a mistake.

So with this, you can be positive that your dependences will certainly be set up properly on other individuals’s equipments. A minimum of as positive as you can ever before remain in Linux Heck.

In conclusion, I ought to state that the above stands for the most effective of my data base on treking with ROS Responses as well as StackOverflow. I’m really delighted to be remedied by any type of ROS experts around.