This ROS package contains a single, simple Python script that simply prints
out the absolute path of the script itself. It also contains a very simple
launch file that simply runs the Python script as a required node – thus,
when the node exits, the roslaunch
process also dies. Both the launch file
and the Python script are installed in the CMakeLists.txt
file according to
the official catkin documentation. See here for docs on installing arbitrary files and here for docs on installing Python scripts.
With this package we will illustrate the effects of using the devel/
and the
install/
result spaces that catkin produces. Below we will provide some
simple setup instructions, and then we will have a set of exercises that
should help the reader understand the implications of using each of these
spaces.
We begin by creating a catkin workspace that we will use for all demos. We
will assume the workspace is located at ~/demows
and that you are using ROS
melodic
. If that is not your situation, some of the commands below may
require a bit of editing.
Let’s begin by initializing the workspace, and cloning this package into the
src/
directory:
# change directory to home:
cd
# create workspace directories:
mkdir -p demows/src
# initialize workspace and clone package:
cd demows/src
source /opt/ros/melodic/setup.bash
catkin_init_workspace
git clone https://github.com/NU-MSR/demo_install_devel.git
Now we are ready to build the workspace which will create the build/
directory, and by default, the devel/
result space.
# change directory to the root of this workspace:
cd ~/demows/
# compile the whole workspace into the devel/ result space
catkin_make
# activate the devel/ result space
source devel/setup.bash
Now we want to create the install/
result space, but we need to make sure
that we don’t “extend” or “chain” the devel/
space – we want these two
result spaces to be completely independent. When a result space is first
created, the setup scripts (e.g. setup.bash
) are automatically generated to
have the new result space extend whatever result spaces are already “active”
in the current terminal. So we will explicitly set only the base ROS melodic
installation as the active space before creating the install/
result space:
# change directory to the root of this workspace:
cd ~/demows/
# activate only the "base" result space:
source /opt/ros/melodic/setup.bash
# compile the whole workspace into the install/ result space
catkin_make install
# activate the install/ result space
source install/setup.bash
Now we have both a devel/
and an install/
result space. To choose which
one is currently active, all we have to do is “source” the setup.bash
file
from each respective space. To see this in action, see the snippet below where
I source each setup file, and then print the relevant environment variables.
jarvis@test2018:~/demows⟫ source /opt/ros/melodic/setup.bash
jarvis@test2018:~/demows⟫ alias rget='env |grep "ROS\|CMAKE_PREFIX_PATH\|PYTHONPATH" |sort'
jarvis@test2018:~/demows⟫ source install/setup.bash
jarvis@test2018:~/demows⟫ rget > install_env.txt
jarvis@test2018:~/demows⟫ source devel/setup.bash
jarvis@test2018:~/demows⟫ rget > devel_env.txt
jarvis@test2018:~/demows⟫ diff install_env.txt devel_env.txt
The diff from the last line above is nicely formatted as:
1,2c1,2
< CMAKE_PREFIX_PATH=/home/jarvis/demows/install:/opt/ros/melodic
< PYTHONPATH=/home/jarvis/demows/install/lib/python2.7/dist-packages:/opt/ros/melodic/lib/python2.7/dist-packages:/home/jarvis/.local/lib/python2.7/site-packages:/usr/local/lib:/usr/lib/python2.7/config:/usr/local/lib/python2.7/site-packages
---
> CMAKE_PREFIX_PATH=/home/jarvis/demows/devel:/opt/ros/melodic
> PYTHONPATH=/home/jarvis/demows/devel/lib/python2.7/dist-packages:/opt/ros/melodic/lib/python2.7/dist-packages:/home/jarvis/.local/lib/python2.7/site-packages:/usr/local/lib:/usr/lib/python2.7/config:/usr/local/lib/python2.7/site-packages
6c6
< ROSLISP_PACKAGE_DIRECTORIES=
---
> ROSLISP_PACKAGE_DIRECTORIES=/home/jarvis/demows/devel/share/common-lisp
8c8
< ROS_PACKAGE_PATH=/home/jarvis/demows/install/share:/opt/ros/melodic/share
---
> ROS_PACKAGE_PATH=/home/jarvis/demows/src:/opt/ros/melodic/share
The environment variables that differ are the variables that control which result space is “active”.
For this exercise, you will simply active each result space by sourcing the
appropriate setup.bash
file, and then use rosrun demo_install_devel
show_file_directory
and verify that the path that is printed out is in a
different location (don’t forget that in another terminal you’ll also need to
run roscore
). Pay attention to the exact location of the script. When the
devel/
space is active, you should see that the script is located in its
original location inside of the src/
directory. When the install/
space
is active you’ll see that the script is instead located in the install/
directory itself.
For this exercise, you first verify that you can run roslaunch
demo_install_devel show_path.launch
with each result space active. This
should work with no issues. A logical question is then, when you run that
roslaunch
command, where is ROS finding the launch file? The answer is
different depending on which result space you are using – this is one of the
most important implications of using these different result spaces. Note that
in the diff from above the ROS_PACKAGE_PATH
for the install/
space starts
with /home/jarvis/demows/install/share
, while in the devel/
result space
the first entry is /home/jarvis/demows/src
. Thus the devel/
space
searches within the src/
directory for ROS packages, while the install/
space only searches within the install/
directory.
In the previous exercises we’ve noted that the location of the node is
dependent on which result space is active, and we’ve noted that the ROS
environment variables are also a function of which result space is active. In
this exercise, we will use some of the ROS command line tools to further see
the effects of these variables. Start by using rospack
to find the location
of the current package (e.g. rospack find demo_install_devel
). Does this
return different results depending on which result space is active? It
should!
The aforementioned varying results when using the rospack
command-line tool
to locate our package have cascading effects in many ROS tools, because many
tools use rospack’s Python or C++ API for performing package introspection.
This is true for rosrun
, roslaunch
, roscd
, rosed
, and more. Try
running roscd demo_install_devel
with each result space active. Do you end
up in different directories?
Let’s think about the impact that the aforementioned exercises have on a
standard development workflow. If we were to edit the launch file or the
Python script in this package, while the devel/
space was active, then
because the various ROS tools automatically find the copies of these files in
the src/
directory, the edits would be instantly picked up. To see this,
let’s edit both the launch file and the Python script and verify that when we
use these files the edits immediately take effect.
- First let’s activate the
devel/
space withsource ~/catkinws/devel/setup.bash
- Now let’s edit the Python script to include some built-in ROS introspection. Edit the script such that it looks like the following:
#!/usr/bin/env python
import os
import rospkg
OKBLUE = '\033[94m'
ENDC = '\033[0m'
def main():
# all we want to do in here is show the location of the executable and the current package:
rospack = rospkg.RosPack()
pkgdir = rospack.get_path("demo_install_devel")
print ""
print OKBLUE+"================================================================================"
print "Path of the executable itself is = ", os.path.abspath(__file__)
print "Path returned by rospkg = ", pkgdir
print "================================================================================"+ENDC
print ""
return
if __name__ == '__main__':
main()
- Now, verify that running this node (using
rosrun demo_install_devel show_file_directory
) immediately prints out the new line that returns the path to thedemo_install_devel
package. - Activate the
install/
result space, and try running the node again. Does the new line show up? The new line shouldn’t show up becauserospack
is finding the package in theinstall/
directory, where it still contains the old copy of the code. - We can update the code in the
install/
directory by runningcatkin_make install
. After running this, does the new line show up when you run the node (it should)?
So note, that if one were to use the install/
result space, you would need
to run catkin_make install
after every edit to the package. This is not
very convenient for regular development, and a key reason why most ROS
developers use the devel/
space nearly 100% of the time when developing ROS
packages. In our course notes, there are some descriptions of situations
where one might want to use the install/
space. In my experience, the most
useful application of the install/
space is when working on actually
releasing packages as a way to ensure that all required files have proper
install
targets.
Try to repeat the above exercise with the launch file. You could try changing
modifying the required="true"
to be false, and see that your roslaunch
process now requires you to kill it with Ctrl-c
instead of it automatically
dying after the node exits.
As a final step, let’s see what the install targets in the CMakeLists.txt
file actually do. Note that if you cd
into
~/demows/install/lib/demo_install_devel
you will see there is an executable
script there that is simply a copy of the show_file_directory node. This
comes from the following lines in the CMakeLists.txt file:
catkin_install_python(PROGRAMS src/show_file_directory
DESTINATION ${CATKIN_PACKAGE_BIN_DESTINATION})
Similarly, if you look at the
~/demows/install/share/demo_install_devel/launch
directory, you’ll see a
copy of the launch file that is part of this package that was placed there
during a call to catkin_make install
. The corresponding lines in the
CMakeLists.txt file are here:
install(DIRECTORY launch/
DESTINATION ${CATKIN_PACKAGE_SHARE_DESTINATION}/launch)
Try removing your install space with rm -r ~/demows/install
and then
removing the two aforementioned install targets from this package’s
CMakeLists.txt file. Now re-run catkin_make install
and check to see that
the launch file and node are missing from the install/
result space. Note
now that running trying to run this package’s node or launch file results in
the following errors:
jarvis@test2018:~/demows⟫ roslaunch demo_install_devel show_path.launch
RLException: [show_path.launch] is neither a launch file in package [demo_install_devel] nor is [demo_install_devel] a launch file name
The traceback for the exception was written to the log file
jarvis@test2018:~/demows⟫ rosrun demo_install_devel show_file_directory
[rosrun] Couldn't find executable named show_file_directory below /home/jarvis/demows/install/share/demo_install_devel
These install targets are used when actually building a package for release
to the ROS buildfarm. If things don’t properly work when using the install/
space, then that is a good indication that things won’t work when you try to
release the package.