Creating ROS2 Snaps with Tensorflow dependencies

Hey everyone,

I’ve been learning a lot about snaps recently, and I’ve really liked the idea especially for some of the multi-agent robotic systems I use. I’ve been trying to learn to make some snaps but I’ve been running into an issue for python dependencies for some of my packages.

My current packages requires tensorflow and tensorflow-probability to run, but I can’t seem to get them to work with my package on runtime. Every time I try and run it I get the following error:

[INFO] [worker_node-1]: process started with pid [99433]
[worker_node-1] Traceback (most recent call last):
[worker_node-1]   File "/snap/mean-field/x1/lib/mean_field_worker/worker_node", line 6, in <module>
[worker_node-1]     from pkg_resources import load_entry_point
[worker_node-1]   File "/usr/lib/python3/dist-packages/pkg_resources/__init__.py", line 3254, in <module>
[worker_node-1]     def _initialize_master_working_set():
[worker_node-1]   File "/usr/lib/python3/dist-packages/pkg_resources/__init__.py", line 3237, in _call_aside
[worker_node-1]     f(*args, **kwargs)
[worker_node-1]   File "/usr/lib/python3/dist-packages/pkg_resources/__init__.py", line 3266, in _initialize_master_working_set
[worker_node-1]     working_set = WorkingSet._build_master()
[worker_node-1]   File "/usr/lib/python3/dist-packages/pkg_resources/__init__.py", line 584, in _build_master
[worker_node-1]     ws.require(__requires__)
[worker_node-1]   File "/usr/lib/python3/dist-packages/pkg_resources/__init__.py", line 901, in require
[worker_node-1]     needed = self.resolve(parse_requirements(requirements))
[worker_node-1]   File "/usr/lib/python3/dist-packages/pkg_resources/__init__.py", line 787, in resolve
[worker_node-1]     raise DistributionNotFound(req, requirers)
[worker_node-1] pkg_resources.DistributionNotFound: The 'tensorflow' distribution was not found and is required by mean-field-worker

The following are my snapcraft.yaml file and the package.xml file for the python package:

name: multi-agent
version: '0.1'
summary: Test ROS2 snap for multi-agent model.
description: |
  This example launches a ROS2 Worker.

base: core20
confinement: devmode

parts:
  multi-agent-ros:
    plugin: colcon
    source: .
    build-packages: [make, gcc, g++]
    stage-packages: [ros-foxy-ros2launch, python3-numpy, python3-dev, libblas3, liblapack3, libopenblas-dev, liblapack-dev]

apps:
  worker:
    command: opt/ros/foxy/bin/ros2 launch multi_agent_worker worker.launch.py
    plugs: [network, network-bind]
    extensions: [ros2-foxy]
    LD_LIBRARY_PATH: "$LD_LIBRARY_PATH:$SNAP/usr/lib/$SNAPCRAFT_ARCH_TRIPLET/blas:$SNAP/usr/lib/$SNAPCRAFT_ARCH_TRIPLET/lapack"
<?xml version="1.0"?>
<?xml-model href="http://download.ros.org/schema/package_format3.xsd" schematypens="http://www.w3.org/2001/XMLSchema"?>
<package format="3">
  <name>multi_agent_worker</name>
  <version>0.0.0</version>
  <description>TODO: Package description</description>
  <maintainer email="TODO@email.com">zmk5</maintainer>
  <license>TODO: License declaration</license>

  <exec_depend>rclpy</exec_depend>
  <exec_depend>std_msgs</exec_depend>
  <exec_depend>mean_field_msgs</exec_depend>
  <exec_depend>python3-numpy</exec_depend>
  <exec_depend>python3-pip</exec_depend>
  <exec_depend>python-tensorflow-pip</exec_depend>

  <test_depend>ament_copyright</test_depend>
  <test_depend>ament_flake8</test_depend>
  <test_depend>ament_pep257</test_depend>
  <test_depend>python3-pytest</test_depend>

  <export>
    <build_type>ament_python</build_type>
  </export>
</package>

Any help would be greatly appreciated! Thank you!

The experimental ROS2 extension does not yet automatically install the project’s python dependencies. It’s likely not installed.

You should be able to add a part to install them for the time being:

parts:
  hello:
    plugin: python
    python-packages:
      - tensorflow

Out of curiosity, did you see a log like: unhandled dependencies: tensorflow... ? Perhaps need to make it more obvious, or complete python support :smiley:

(CC @kyrofa)

1 Like

Hey @cjp256! Thank you for the reply! Interesting, I had no clue it doesn’t install the python dependencies since I saw rosdep installing it. I tried the method you mentioned below as:

tensorflow-py:
    plugin: python
    python-packages: [tensorflow]

and got the following error:

+ sed -r 1 s|#\!.*python3?$|#\!/usr/bin/env python3| -i /root/parts/tensorflow-py/install/bin/f2py3
+ head -1 /root/parts/tensorflow-py/install/bin/easy_install
+ grep -q python
+ sed -r 1 s|#\!.*python3?$|#\!/usr/bin/env python3| -i /root/parts/tensorflow-py/install/bin/easy_install
+ head -1 /root/parts/tensorflow-py/install/bin/pyrsa-keygen
+ grep -q python
+ sed -r 1 s|#\!.*python3?$|#\!/usr/bin/env python3| -i /root/parts/tensorflow-py/install/bin/pyrsa-keygen
+ head -1 /root/parts/tensorflow-py/install/bin/estimator_ckpt_converter
+ grep -q python
+ sed -r 1 s|#\!.*python3?$|#\!/usr/bin/env python3| -i /root/parts/tensorflow-py/install/bin/estimator_ckpt_converter
+ interp_path=/root/parts/tensorflow-py/install/bin/python3
+ [ -f /root/parts/tensorflow-py/install/bin/python3 ]
+ readlink /root/parts/tensorflow-py/install/bin/python3
+ current_link=/usr/bin/python3
+ echo /usr/bin/python3
+ grep -q /root/parts/tensorflow-py/install
Failed to stage: Parts 'multi-agent-ros' and 'tensorflow-py' have the following files, but with different contents:
    lib64

Snapcraft offers some capabilities to solve this by use of the following keywords:
    - `filesets`
    - `stage`
    - `snap`
    - `organize`

To learn more about these part keywords, run `snapcraft help plugins`.
Run the same command again with --debug to shell into the environment if you wish to introspect this failure.

Running with --debug gives me:

Skipping pull mean-field-ros (already ran)
Skipping pull ros2-foxy-extension (already ran)
Skipping pull tensorflow-py (already ran)
Skipping build mean-field-ros (already ran)
Skipping build ros2-foxy-extension (already ran)
Skipping build tensorflow-py (already ran)
Failed to stage: Parts 'multi-agent-ros' and 'tensorflow-py' have the following files, but with different contents:
    lib64

Snapcraft offers some capabilities to solve this by use of the following keywords:
    - `filesets`
    - `stage`
    - `snap`
    - `organize`

To learn more about these part keywords, run `snapcraft help plugins`.

The same error as the others :-/ I’m confused as what lib64 is. Are these the 64-bit binaries for the ROS and tensorflow parts in conflict? Also, I didn’t see a log. Pardon my ignorance, but is it a file or something printed out on the console?

Thank you for helping me btw. I am very new to this!

My guess is something is creating a directory, and another part is creating a symlink or something for lib64.

You can try to filter it out for one or both parts using the stage keyword:

parts:
 tensorflow-py:
    stage:
       - -lib64
1 Like

Interesting! I tried you suggestion as follows:

parts:
  tensorflow-py:
    plugin: python
    python-package: [tensorflow]
    stage:
      - lib64

and unfortunately the same error came up. I tried it in different configurations with the stage keyword in the ROS2 part instead and in both and they still came with the same error.

I did however sort of learn to use --debug mode and found out that lib64 is actually a directory and not a file! According to this documentation, the stage keyword takes files and not directories. So I changed it to:

parts:
  tensorflow-py:
    plugin: python
    python-package: [tensorflow]
    stage:
      - lib64/*

And it worked! :confetti_ball: :partying_face:

I initially tried it with both the ROS2 part and the python part but it gave me an error. This method only works if you do it to just the python plugin part and NOT the ROS2 part. Thank you for your help @cjp256!

4 Likes

I can explain that discrepancy. There are two moments when ROS deps come into play:

  1. When building the ROS workspace
  2. When making sure the ROS runtime deps are contained in the snap

(1) results in rosdep install being run on the host, which WILL install tensorflow and supports all types of rosdep dependencies, including pip. (2) however is where @cjp256’s comment comes into play: only deb dependencies are staged into the snap for runtime right now. pip support is a known shortcoming.

1 Like