RoboStack / jupyter-ros

Jupyter widget helpers for ROS, the Robot Operating System
https://jupyter-ros.readthedocs.io/en/latest/
BSD 3-Clause "New" or "Revised" License
585 stars 114 forks source link

Error running ROS2 notebook rclpy.init and import jupyros.ros2 as jr2 #125

Closed robofoundry closed 2 years ago

robofoundry commented 2 years ago

Logging an issue to describe details of errors to answer question from Gitter thread. I tried to run the notebook named - Ros2 Pub_Sub_Communication.ipynb from pre-release https://github.com/RoboStack/jupyter-ros/tree/v0.6.0a0/notebooks and got following errors. It may be some issue with the way I installed the package and extensions. I tried to follow instructions from here to install from source.

I have an env named ros_env which has ROS2 humble installation with full desktop version of humble installed and it works correctly. I also tried to set ROS_DISTRO=humble in the terminal within jupyter-labs to see if it will make any difference but it didn't help.

I also have another env named ros2_foxy where ROS2 foxy is installed and main computer where ROS2 foxy is installed as well with ROS_DISTRO=foxy for main computer. I can see that in the error description it is still trying to look in the paths under /opt/ros/foxy even though I am running in humble so may be that's the main issue somehow.

Please suggest any options as I'm willing to try to get it to work with ROS2 in jypyter-labs. It will be a big help for community overall if I can document how to get it working.

I did make a change in the ~/mambaforge/envs/ros_env/jupyter-ros-0.6.0a0/jupyros/init.py file to change the ros version to 2 and name to humble like this, I thought this was necessary to use ROS2 but I could be wrong:

from ._version import __version__
import os

try:
    ros_version = os.environ['ROS_VERSION']
    ros_distro = os.environ['ROS_DISTRO']
except KeyError:
    # print('No ROS environment detected.')
    # print('Defaulting to ROS noetic.')
    ros_version = '2'
    ros_distro = 'humble'

While running following block of code in jupyter-labs:

## Relative pathing to the Jupyros module (jupyter-ros/jupyros), due to difficulty with with development install
## Remove at PR is Dev Install successful 
import sys
sys.path.append("./../")
import rclpy as rp
import jupyros.ros2 as jr2
from geometry_msgs.msg import Pose, Point
from sensor_msgs.msg import Image

Two main errors received - one saying jupyros not found and the other with context problem related to rp.init()

The rclpy package is not found in your $PYTHONPATH. Subscribe and publish are not going to work.
Do you need to activate your ros2 environment?
---------------------------------------------------------------------------
NameError                                 Traceback (most recent call last)
Input In [5], in <cell line: 6>()
      4 sys.path.append("./../")
      5 import rclpy as rp
----> 6 import jupyros.ros2 as jr2
      7 from geometry_msgs.msg import Pose, Point
      8 from sensor_msgs.msg import Image

File ~/mambaforge/envs/ros_env/jupyter-ros-0.6.0a0/jupyros/__init__.py:24, in <module>
     19     ros_distro = 'humble'
     21 if ros_version == '2':
     22     # Import ROS2 modules
     23     # print(f'ROS2 {ros_distro} environment detected.')
---> 24     from .ros2.publisher import *
     25     from .ros2.ros_widgets import *
     26     from .ros2.subscriber import *

File ~/mambaforge/envs/ros_env/jupyter-ros-0.6.0a0/jupyros/ros2/__init__.py:16, in <module>
      9 from .._version import __version__
     11 #from ..ros1.ipy import *
     12 #from ..ros1.ros3d import *
     13 #from ..ros1.server_extension import *
     14 #from ..ros1.turtle_sim import *
---> 16 from ..ros2.publisher import *
     17 from ..ros2.ros_widgets import *
     18 from ..ros2.subscriber import *

File ~/mambaforge/envs/ros_env/jupyter-ros-0.6.0a0/jupyros/ros2/publisher.py:42, in <module>
     38 # Used for documentation purposes only
     39 MsgType = TypeVar('MsgType')
---> 42 class Publisher():
     43     """
     44     Creates a class containing the form widget for message type `msg_type`.
     45     This class analyzes the fields of msg_type and creates
   (...)
     55 
     56     """
     57     def __init__(self, node: Node, msg_type: MsgType, topic: str) -> None:
     58         # Check if a ros2 node is provided.

File ~/mambaforge/envs/ros_env/jupyter-ros-0.6.0a0/jupyros/ros2/publisher.py:57, in Publisher()
     42 class Publisher():
     43     """
     44     Creates a class containing the form widget for message type `msg_type`.
     45     This class analyzes the fields of msg_type and creates
   (...)
     55 
     56     """
---> 57     def __init__(self, node: Node, msg_type: MsgType, topic: str) -> None:
     58         # Check if a ros2 node is provided.
     59         if (not isinstance(node, Node) or not issubclass(type(node), Node)):
     60             raise TypeError(
     61                 "Input argument 'node' is not of type rclpy.node.Node!")

NameError: name 'Node' is not defined
# Initialize ROS communications for a given context
rp.init()
---------------------------------------------------------------------------
ModuleNotFoundError                       Traceback (most recent call last)
Input In [4], in <cell line: 2>()
      1 # Initialize ROS communications for a given context
----> 2 rp.init()

File /opt/ros/foxy/lib/python3.8/site-packages/rclpy/__init__.py:70, in init(args, context)
     62 def init(*, args: Optional[List[str]] = None, context: Context = None) -> None:
     63     """
     64     Initialize ROS communications for a given context.
     65 
   (...)
     68         (see :func:`.get_default_context`).
     69     """
---> 70     context = get_default_context() if context is None else context
     71     return context.init(args)

File /opt/ros/foxy/lib/python3.8/site-packages/rclpy/utilities.py:34, in get_default_context(shutting_down)
     32 global g_default_context
     33 if g_default_context is None:
---> 34     g_default_context = Context()
     35 if shutting_down:
     36     old_context = g_default_context

File /opt/ros/foxy/lib/python3.8/site-packages/rclpy/context.py:37, in Context.__init__(self)
     36 def __init__(self):
---> 37     from rclpy.impl.implementation_singleton import rclpy_implementation
     38     from .handle import Handle
     39     self._handle = Handle(rclpy_implementation.rclpy_create_context())

File /opt/ros/foxy/lib/python3.8/site-packages/rclpy/impl/implementation_singleton.py:31, in <module>
     15 """
     16 Provide singleton access to the rclpy C modules.
     17 
   (...)
     26         # ...
     27 """
     29 from rclpy.impl import _import
---> 31 rclpy_implementation = _import('._rclpy')
     32 rclpy_action_implementation = _import('._rclpy_action')
     33 rclpy_logging_implementation = _import('._rclpy_logging')

File /opt/ros/foxy/lib/python3.8/site-packages/rclpy/impl/__init__.py:28, in _import(name)
     23 try:
     24     # Since Python 3.8, on Windows we should ensure DLL directories are
     25     # explicitly added to the search path.
     26     # See https://docs.python.org/3/whatsnew/3.8.html#bpo-36085-whatsnew
     27     with add_dll_directories_from_env('PATH'):
---> 28         return importlib.import_module(name, package='rclpy')
     29 except ImportError as e:
     30     if e.path is None:

File ~/mambaforge/envs/ros_env/lib/python3.9/importlib/__init__.py:127, in import_module(name, package)
    125             break
    126         level += 1
--> 127 return _bootstrap._gcd_import(name[level:], package, level)

ModuleNotFoundError: No module named 'rclpy._rclpy'
The C extension '/opt/ros/foxy/lib/python3.8/site-packages/rclpy/_rclpy.cpython-39-x86_64-linux-gnu.so' isn't present on the system. Please refer to 'https://index.ros.org/doc/ros2/Troubleshooting/Installation-Troubleshooting/#import-failing-without-library-present-on-the-system' for possible solutions
IsabelParedes commented 2 years ago

Hello!

Thanks for bringing up this issue. I'm curious, when you installed jupyter-ros from source, did you follow the instructions on the main README or the ones in the documentation? The documentation is more up to date than the README. However, the installation instructions are intended for ROS1 but the only difference would be how the environment is created.

mamba create -n ros2_env jupyterlab jupyter-packaging nodejs=15 ros-humble-desktop -c conda-forge -c robostack-humble

We are working under the assumption that users will only have one ROS distro installed in each environment. So whenever you import jupyros, it will check if ROS2 is installed otherwise it'll default to ROS1. And yes, you can change the default to ROS2 with the changes that you made. But ideally, that will be automatic if the environment has one ROS2 installed.

As you mentioned, it looks like the paths are conflicting with your foxy installation. Do you have anything in your .bashrc file which automatically activates Foxy? When you activate your ROS2 environment, do the environment variables get set correctly?

ROS_VERSION=2
ROS_PYTHON_VERSION=3
ROS_DISTRO=humble

And another suggestion which could be easily overlooked, JupyterLab needs to be launched from the ROS2 humble environment itself.

Hopefully this helps. And one more drastic suggestion would be to uninstall Foxy from your main computer, but that would be last resort.

robofoundry commented 2 years ago

Thanks so much for looking into the details and making all these suggestions. I'll probably start fresh by creating a new env as you suggested, unset the env variables in main computer bashrc file and set the ones within the env and then install everything. Hopefully everything will work, eager to make it all work from jupyter labs because it will make writing tutorials and other things in future much easy for people to follow without having to be comfortable with terminal commands for ROS.

robofoundry commented 2 years ago

Its finally working well from jupyter-lab with ROS2 humble and the example notebook!!! Thanks so much, here is what I had to do based on your suggestions to get it all working. And I didn't have to reinstall anything, so somehow I must have followed the right steps :)

  1. I closed all terminals and updated the bashrc in main computer to not run source /opt/ros/foxy/setup.bash which will stop setting ROS_DISTRO=foxy in future.
  2. I manually unset the ROS_DISTRO env variable by doing this ROS_DISTRO= unset ROS_DISTRO and then echo $ROS_DISTRO to make sure it has no value
  3. started a new terminal and then activated the ros_env mamba env mamba activate ros_env when I again displayed the ROS_DISTRO echo $ROS_DISTRO at this time it was properly set to ROS_DISTRO=humble
  4. I re-launched the jupyter-lab jupyter-lab
  5. navigated to example ROS2 notebook, opened it and everything started running correctly with no errors. I was able to get all the way to the end of notebook running all the steps with no errors.

This is pretty awesome. I'll document the steps in another blog article. Thanks @ihuicatl so much for all your help in getting around this issues.