Run ROS nodes in Python Virtual Environment

How to run a ROS Node in a python virtual environment

Zillur
4 min readMar 6, 2023

Python Virtual Environments are necessary nowadays, particularly when the project is related to deep learning and computer vision. A number of python modules/packages need to be installed specific to one project. Likewise, for different projects, different modules as well as module versions need to be installed. If we install all those modules in our root python directory, things will get messed up easily. So, using separate virtual environment for each project is a better idea. Now, when we have multiple virtual environments that use different python interpreters and need to run ROS nodes, many of us get confused. Which node is using which interpreter? If we do not understand this important part, we will see errors after running the nodes.

For this tutorial, we will use an Ubuntu 20 machine with ROS Noetic installation and Python 3.8.10 root installation. To install python virtual environments, we can use miniconda or virtualenv. We will use virtualenv here as it is easier to install and use. To install virtuaenv, run the following command:

sudo apt-get install -y python3-venv

After the installation, we create a new virtual environment name “ros_env”.

cd ~/
mkdir mypython
cd mypython
python3 -m venv ros_env

Now, that we have a virtual environment, we first activate it using the following command: use your virtual environment name if it is different

source ros_env/bin/activate

The environment name will be shown in our bash/terminal window. We can also check which python interpreter it is using by running

which python

Now, our virtual environment is ready to use. We first install a few packages using pip like:

pip install numpy
pip install scipy

Now, we have two packages installed inside of our virtual environment. For the simplicity, let’s assume our root python installation (/usr/bin/python) does not have those two packages. If yours has those modules, install something like PyTorch. That means if we try to import them using our root python installation, there will be ModuleNotFound error.

To use a new python interpreter with ROS, we also need to install a few additional packages. Run the following command. It will prepare our virtual environment for ROS usage.

pip install -U rosinstall msgpack empy defusedxml netifaces

There are two ways we can use virtual environment along with ROS. I name them

  1. Using Shebang
  2. Using catkin_make

Shebang method:

A Shebang indicates which Bash or Python interpreter to use to interpret an Python script. It is written on the first line of the code and starts with #!. Now let’s create a ROS Package named “test” and a ROS Python node named “test_venv.py” . To create a ROS package named “test”, we go to our catkin workspace directory and run

cd ~/catkin_ws/src/
catkin_create_pkg test roscpp rospy std_msgs
cd test/src/
touch test_venv.py

Fire up your favorite text editor and write the following lines in “test_venv.py”.

#!/home/$USER/mypython/ros_env/bin/python
import numpy as np
import scipy
import rospy
from std_msgs.msg import Float64
print(np.__version__)
# license removed for brevity
from std_msgs.msg import String

def talker():
pub = rospy.Publisher('chatter', String, queue_size=10)
rospy.init_node('talker', anonymous=True)
rate = rospy.Rate(10) # 10hz
while not rospy.is_shutdown():
hello_str = "hello world %s" % rospy.get_time()
rospy.loginfo(hello_str)
pub.publish(hello_str)
rate.sleep()

if __name__ == '__main__':
try:
talker()
except rospy.ROSInterruptException:
pass

In place of $USER, use your username. Now, save the file. To make it executable, run the following command inside the same directory

chmod +x test_venv.py

Now, our script is ready to use in ROS. Use the following line to start the ROS Master.

roscore

Then run the ROS Node in another terminal

rosrun test test_venv.py

If everything goes fine, we will see the printed Numpy version, and then continuous printing of “hello world”. That means, our script is using the virtual environment, not the root installation. At this time, it does not matter whether our virtual environment is active or not. Even if it is deactivated, because we used the correct shebang, the script will use that to execute the lines. Now, if you have 10 such nodes, you have to add the correct shebang for all of them. If you do not want to do that, follow the second method where all the nodes in the catkin workspace will be built together.

Catkin_make method:

We can build our ROS python node using catkin_make command. It builds all the packages and all the nodes in that workspace. To use this method, first let’s create another ROS Node called “talker.py” in ./src/talker.py

#!/usr/bin/env python
# license removed for brevity
import rospy
from std_msgs.msg import String

def talker():
pub = rospy.Publisher('chatter', String, queue_size=10)
rospy.init_node('talker', anonymous=True)
rate = rospy.Rate(10) # 10hz
while not rospy.is_shutdown():
hello_str = "hello world %s" % rospy.get_time()
rospy.loginfo(hello_str)
pub.publish(hello_str)
rate.sleep()

if __name__ == '__main__':
try:
talker()
except rospy.ROSInterruptException:
pass

Next, edit the CMakeLists.txt and add the following lines

catkin_install_python(PROGRAMS src/talker.py
DESTINATION ${CATKIN_PACKAGE_BIN_DESTINATION}
)

As we notice, the first line of the code defines the Shebang. This time we will not use that. We simply delete that line and proceed. However, we need to define the Python Interpreter during the package building. Run the following commands:

cd ~/catkin_ws
catkin_make -DPYTHON_EXECUTABLE=/usr/bin/python

Here, we define the Python Interpreter location. After successful building, we will be able to run the node using the following command:

rosrun test talker.py

We will see it’s working fine. At this time, we may add the Shebang in the first line. We may add the same interpreter or a different one like the virtual environment and build the package again. No matter which interpreter we use as Shebang, when we define python path during building, the node will use that only.

There are other considerations here when we need to execute some advanced stuffs. But, that’s it for today. Hope this helps new learners.

--

--