diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index e4f7988..1d13ba5 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -1,6 +1,6 @@ -# Contributing to Jupyter-ROS +# Contributing -First off, thank you for considering contributing to Jupyter-ROS. It's people like you that make Jupyter-ROS such a great tool. +First off, thank you for considering contributing to Jupyter-ROS 🥳. It's people like you that make Jupyter-ROS such a great tool. Following these guidelines helps to communicate that you respect the time of the developers managing and developing this open source project. In return, they should reciprocate that respect in addressing your issue, assessing changes, and helping you finalize your pull requests. @@ -11,25 +11,25 @@ Jupyter-ROS is an open source project and we love to receive contributions from - submit bug reports or feature requests - write code to incorporate into Jupyter-ROS itself -# Ground Rules +## Ground Rules We welcome all kinds of contribution and value them highly. We pledge to treat everyone's contribution fairly and with respect, and we are here to bring awesome pull requests over the finish line. Please note that we adhere to the [Python Community Code of Conduct](https://www.python.org/psf/codeofconduct/) and by contributing to this project you also agree to follow the same guidelines. -# Your First Contribution +## Your First Contribution Working on your first Pull Request? Here are some resources to help you get started: - [First Timers Only](https://www.firsttimersonly.com/) - [Make a Pull Request](https://makeapullrequest.com/) - [How to Contribute to an Open Source Project on GitHub](https://egghead.io/courses/how-to-contribute-to-an-open-source-project-on-github) -At this point, you're ready to make your changes! Feel free to ask for help; everyone is a beginner at first :smile_cat: +At this point, you're ready to make your changes! Feel free to ask for help; everyone is a beginner at first 😸. If a maintainer asks you to "rebase" your PR, they're saying that a lot of code has changed and that you need to update your branch so that it's easier to merge. -# Getting started +## Getting Started 1. Create your own fork of the code. 2. Do the changes in your fork. @@ -45,17 +45,17 @@ If a maintainer asks you to "rebase" your PR, they're saying that a lot of code 7. If you are happy with your changes, create a pull request. -# How to report a bug +## How to Report a Bug -## Security +### Security -If you find a security vulnerability, do NOT open an issue. Email w.vollprecht@gmail.com instead. In order to determine whether you are dealing with a security issue, ask yourself these two questions: +If you find a security vulnerability, do NOT open an issue. Email [w.vollprecht@gmail.com](mailto:w.vollprecht@gmail.com) instead. In order to determine whether you are dealing with a security issue, ask yourself these two questions: - Can I access something that's not mine, or something I shouldn't have access to? - Can I disable something for other people? If the answer to either of those two questions are "yes", then you're probably dealing with a security issue. Note that even if you answer "no" to both questions, you may still be dealing with a security issue, so if you're unsure, just email us. -## Other bugs +### Other bugs When filing an issue, make sure to answer these five questions: @@ -68,7 +68,7 @@ When filing an issue, make sure to answer these five questions: General questions should be handled through [Gitter](https://gitter.im/RoboStack/Lobby) instead of the issue tracker. The maintainers there will answer or ask you to file an issue if you've tripped over a bug. -# How to suggest a feature or enhancement +## How to Suggest a Feature or Enhancement If you find yourself wishing for a feature that doesn't exist in Jupyter-ROS, you are probably not alone. There are bound to be others out there with similar needs. Many of the features that Jupyter-ROS has today have been added because our users saw the need. Open an issue on our [issues list](https://github.com/RoboStack/jupyter-ros/issues) on GitHub which includes the following: @@ -76,7 +76,7 @@ If you find yourself wishing for a feature that doesn't exist in Jupyter-ROS, yo 2. Why do you need it? 3. How should it work? -# Code review process +## Code Review Process Any change to resources in this repository must be through pull requests. This applies to all changes to documentation, code, binary files, etc. No pull request can be merged without being reviewed. @@ -85,9 +85,6 @@ The core team looks at Pull Requests on a regular basis and provides feedback af A pull request will be merged once all the feedback has been addressed and there are no objections by any of the committers. -# Community - -You can chat with the core team on https://gitter.im/RoboStack/Lobby. We try to answer all questions within 48 hours. - - +## Community +You can chat with the core team on [gitter.im/RoboStack](https://gitter.im/RoboStack/Lobby). We try to answer all questions within 48 hours. diff --git a/README.md b/README.md index b1c70b0..c6e4fd7 100644 --- a/README.md +++ b/README.md @@ -6,8 +6,8 @@ robotics community has not jumped on the band wagon yet! Most tools around ROS, the Robot Operating System, are built using Python and QT. -However, using QT seperates the user away from the code. -We've built an initial version of the ROS tools for jupyter +However, using QT separates the user away from the code. +We've built a set of ROS tools for jupyter notebook, trying to promote a rich, interactive experience for Robotics developers utilizing the power of the jupyter notebook. @@ -19,10 +19,7 @@ notebook. With jupyter-ros, it's possible to easily create widgets for custom message types to send messages. -In the future, we plan to bring simple and fast real-time -plotting from ROS topics to this library. - -If you find this initial package useful, don't hesitate to +If you find this package useful, don't hesitate to contribute! You can also always reach out to w.vollprecht@gmail.com or on twitter: https://twitter.com/wuoulf, or join us on [Gitter](https://gitter.im/RoboStack/Lobby) @@ -60,9 +57,7 @@ To update the `defaults.js` javascript you need to run `python jupyros/ros3d.py` You might see a warning like "The rospy package is not found in your $PYTHONPATH. Subscribe and publish are not going to work. Do you need to activate your ROS environment?" -This is harmless during installation, but if you see this warning in a notebook, you should -check that your ROS environment is activated. You can also set the path from inside the notebook -using +This is harmless during installation, but if you see this warning in a notebook, you should check that your ROS environment is activated. You can also set the path from inside the notebook using ``` import sys diff --git a/docs/README.md b/docs/README.md new file mode 100644 index 0000000..8a995d5 --- /dev/null +++ b/docs/README.md @@ -0,0 +1,32 @@ +# Building Jupyter-ROS Documentation + +1. Create a new environment with the following dependencies + + - `sphinx` + - `myst-parser` + - `jinja2=3.0` + - `sphinx-rtd-theme` + + ```sh + $ mamba create jupyros_docs sphinx myst-parser jinja2=3.0 -c conda-forge + $ mamba activate jupyros_docs + $ pip install sphinx-rtd-theme + ``` + +1. [Optional] Install `jupyter-ros` in the environment. This is only necessary for the _References_ page to display correctly; otherwise, there will be a few warnings in the next step. + +1. Build the documents + + ```sh + $ cd jupyter-ros/docs/ + $ make html + ``` + +1. Open the documentation locally + + ```sh + $ cd build/html/ + $ python -m http.server + ``` + +1. From a web browser, navigate to `localhost:8000` diff --git a/docs/source/_static/images/action_client.png b/docs/source/_static/images/action_client.png new file mode 100644 index 0000000..15433ea Binary files /dev/null and b/docs/source/_static/images/action_client.png differ diff --git a/docs/source/_static/images/publisher.png b/docs/source/_static/images/publisher.png new file mode 100644 index 0000000..7d89159 Binary files /dev/null and b/docs/source/_static/images/publisher.png differ diff --git a/docs/source/_static/images/service_client.png b/docs/source/_static/images/service_client.png new file mode 100644 index 0000000..c7b75f1 Binary files /dev/null and b/docs/source/_static/images/service_client.png differ diff --git a/docs/source/_static/images/subscriber.png b/docs/source/_static/images/subscriber.png new file mode 100644 index 0000000..1e0674b Binary files /dev/null and b/docs/source/_static/images/subscriber.png differ diff --git a/docs/source/_static/images/turtlesim.gif b/docs/source/_static/images/turtlesim.gif new file mode 100644 index 0000000..1549421 Binary files /dev/null and b/docs/source/_static/images/turtlesim.gif differ diff --git a/docs/source/conf.py b/docs/source/conf.py index b1831b0..4192534 100644 --- a/docs/source/conf.py +++ b/docs/source/conf.py @@ -19,11 +19,11 @@ # -- Project information ----------------------------------------------------- project = 'jupyter-ros' -copyright = '2020, Wolf Vollprecht' +copyright = '2022, Wolf Vollprecht' author = 'Wolf Vollprecht' # The full version, including alpha/beta/rc tags -release = '0.3.0' +release = '0.6.0' # -- General configuration --------------------------------------------------- @@ -34,6 +34,7 @@ extensions = [ 'sphinx.ext.autodoc', 'sphinx.ext.napoleon', + 'myst_parser', # 'sphinx.ext.intersphinx', # 'sphinx.ext.autosummary', # 'sphinx.ext.viewcode', diff --git a/docs/source/dev_contributing.md b/docs/source/dev_contributing.md new file mode 100644 index 0000000..9ebe1f3 --- /dev/null +++ b/docs/source/dev_contributing.md @@ -0,0 +1,88 @@ +# Contributing + +First off, thank you for considering contributing to Jupyter-ROS 🥳. It's people like you that make Jupyter-ROS such a great tool. + +Following these guidelines helps to communicate that you respect the time of the developers managing and developing this open source project. In return, they should reciprocate that respect in addressing your issue, assessing changes, and helping you finalize your pull requests. + +Jupyter-ROS is an open source project and we love to receive contributions from our community — you! There are many ways to contribute. For example, you can + +- write a new tutorial or a blog post +- improve the documentation or the existing examples +- submit bug reports or feature requests +- write code to incorporate into Jupyter-ROS itself + +## Ground Rules + +We welcome all kinds of contribution and value them highly. We pledge to treat everyone's contribution fairly and with respect, and we are here to bring awesome pull requests over the finish line. + +Please note that we adhere to the [Python Community Code of Conduct](https://www.python.org/psf/codeofconduct/) and by contributing to this project you also agree to follow the same guidelines. + +## Your First Contribution + +Working on your first Pull Request? Here are some resources to help you get started: + +- [First Timers Only](https://www.firsttimersonly.com/) +- [Make a Pull Request](https://makeapullrequest.com/) +- [How to Contribute to an Open Source Project on GitHub](https://egghead.io/courses/how-to-contribute-to-an-open-source-project-on-github) + +At this point, you're ready to make your changes! Feel free to ask for help; everyone is a beginner at first 😸. + +If a maintainer asks you to "rebase" your PR, they're saying that a lot of code has changed and that you need to update your branch so that it's easier to merge. + +## Getting Started + +1. Create your own fork of the code. +2. Do the changes in your fork. +3. If your changes only involve spelling or grammar fixes, move to step 7. +4. Test your changes in a clean environment and update installation instructions and dependencies as needed. +5. When adding new features, make sure to update the documentation and provide an example under _notebooks/_. +6. New notebooks + - Remove all output. + - Remove unnecessary cells. + - Include a descriptive title. + - Specify ROS version in the notebook name, "_ROS Turtlesim.ipynb_" vs "_ROS**2** Turtlesim.ipynb_" + - Any additional steps the user needs to take to run all the cells in the notebook should be clearly stated in markdown cells. +7. If you are happy with your changes, create a pull request. + +## How to Report a Bug + +### Security + +If you find a security vulnerability, do NOT open an issue. Email [w.vollprecht@gmail.com](mailto:w.vollprecht@gmail.com) instead. In order to determine whether you are dealing with a security issue, ask yourself these two questions: + +- Can I access something that's not mine, or something I shouldn't have access to? +- Can I disable something for other people? + +If the answer to either of those two questions are "yes", then you're probably dealing with a security issue. Note that even if you answer "no" to both questions, you may still be dealing with a security issue, so if you're unsure, just email us. + +### Other bugs + +When filing an issue, make sure to answer these five questions: + +1. What version of _jupyros_ are you using? +2. What operating system and processor architecture are you using? +3. What did you do? +4. What did you expect to see? +5. What did you see instead? + +General questions should be handled through [Gitter](https://gitter.im/RoboStack/Lobby) instead of the issue tracker. The maintainers there will answer or ask you to file an issue if you've tripped over a bug. + +## How to Suggest a Feature or Enhancement + +If you find yourself wishing for a feature that doesn't exist in Jupyter-ROS, you are probably not alone. There are bound to be others out there with similar needs. Many of the features that Jupyter-ROS has today have been added because our users saw the need. Open an issue on our [issues list](https://github.com/RoboStack/jupyter-ros/issues) on GitHub which includes the following: + +1. A description of the feature you would like to see +2. Why do you need it? +3. How should it work? + +## Code Review Process + +Any change to resources in this repository must be through pull requests. This applies to all changes to documentation, code, binary files, etc. No pull request can be merged without being reviewed. + +The core team looks at Pull Requests on a regular basis and provides feedback after each review. Once feedback has been given, we expect responses within three weeks. After the three weeks have elapsed, we may close the pull request if it isn't showing any activity. + +A pull request will be merged once all the feedback has been addressed and there are no objections by any of the committers. + +## Community + +You can chat with the core team on [gitter.im/RoboStack](https://gitter.im/RoboStack/Lobby). We try to answer all questions within 48 hours. diff --git a/docs/source/dev_installation.rst b/docs/source/dev_installation.rst new file mode 100644 index 0000000..2daf004 --- /dev/null +++ b/docs/source/dev_installation.rst @@ -0,0 +1,89 @@ +.. _dev-install-label: + +Developer Installation +====================== + + +Install Jupyter-ROS +------------------- + +1. Clone repository + + .. code-block:: sh + + $ git clone git@github.com:RoboStack/jupyter-ros.git + $ cd jupyter-ros + +2. Create a conda environment for development with the following packages + + * ``python = 3.9`` + * ``jupyterlab`` + * ``jupyter-packaging`` + * ``nodejs <= 15`` + * ``ros-noetic-desktop`` + + .. code-block:: sh + + # You can use conda as well + $ mamba create -n jupyros_env python=3.9 jupyterlab jupyter-packaging nodejs=15 ros-noetic-desktop -c conda-forge -c robostack + + $ mamba activate jupyros_end + +3. Install *jupyter-ros* in editable mode + + .. code-block:: sh + + # From the jupyter-ros root directory + $ pip install -e . + +4. Symlink the JupyterLab extension + + .. code-block:: sh + + $ jupyter labextension develop . --overwrite + +5. Verify installation with Python + + .. code-block:: python + + import jupyros + print(jupyros.__file__) + # Should return /home/user/jupyter-ros/jupyros/__init__.py + + + +Build Documentation +------------------- + +1. Create a new conda environment with the following dependencies: + + * ``sphinx`` + * ``myst-parser`` + * ``jinja2 <= 3.0`` + * ``sphinx-rtd-theme`` + + .. code-block:: sh + + # You can use conda as well + $ mamba create -n jupyros_docs sphinx myst-parser jinja2=3.0 -c conda-forge + $ mamba activate jupyros_docs + $ pip install sphinx-rtd-theme + +2. **[Optional]** Install ``jupyter-ros`` in the environment. This is only necessary for the *References* page to display correctly; otherwise, there will be a few warnings in the next step. + +3. Build the documents + + .. code-block:: sh + + $ cd jupyter-ros/docs/ + $ make html + + +4. Open the documentation locally + + .. code-block:: sh + + $ cd build/html/ + $ python -m http.server + +5. From a web browser, navigate to ``localhost:8000`` diff --git a/docs/source/dev_testing.rst b/docs/source/dev_testing.rst new file mode 100644 index 0000000..48a245b --- /dev/null +++ b/docs/source/dev_testing.rst @@ -0,0 +1,67 @@ +Testing +======= + +The simplest way to test any additions to Jupyter-ROS is to create a fresh +environment and install the package in development mode. + +1. Create new test environment with minimal packages + + .. code-block:: sh + + $ conda create -n test_env python=3.9 jupyterlab nodejs=15 jupyter-packaging ros-noetic-desktop -c conda-forge -c robostack + + $ conda activate test_env + +2. Navigate to the root directory and install jupyter-ros + + .. code-block:: sh + + $ cd jupyter-ros/ + $ pip install -e . + + If there are any errors with this step, this indicates that the new + additions are not configured correctly for installation. This will require + some additional troubleshooting, but a common issue is to forget to include + newly required dependencies in the `setup.py` file. + + .. code-block:: python + + setup_args = { + 'install_requires': [ + 'ipywidgets>=7.0.0', + 'bqplot', + 'numpy', + 'rospkg', + 'ipycanvas' + ], + } + +3. Symlink the JupyterLab extension and verify that `jupyros` can be imported. + + .. code-block:: sh + + $ jupyter labextension develop . --overwrite + $ jupyter lab + + .. code-block:: python + + import jupyros + + This step may also require some troubleshooting depending on the changes + made to Jupyter-ROS. If you see interference from other conda environments, + e.g. additional lab extensions which should not be enabled in the test + environment, it is often helpful to remove the ``~/.jupyter`` directory. + + .. code-block:: sh + + # List all the lab extensions + $ jupyter labextension list + + # Remove jupyter directory [optional] + $ rm -r ~/.jupyter + + +4. Once the setup is complete, it is now time to test the new additions. This + type of testing will vary greatly depending on the changes, we suggest to + use your best judgement. + diff --git a/docs/source/gen_getting_started.rst b/docs/source/gen_getting_started.rst new file mode 100644 index 0000000..7acbe61 --- /dev/null +++ b/docs/source/gen_getting_started.rst @@ -0,0 +1,24 @@ +Getting Started +=============== + +The easiest way to get started is to create a ROS environment with conda or mamba with the following packages: + +* ``jupyter-ros`` +* ``jupyterlab`` +* ``ros-noetic-desktop`` + +.. code-block:: sh + + $ conda create -n ros_env jupyter-ros jupyterlab ros-noetic-desktop -c conda-forge -c robostack + $ conda activate ros_env + + # Launch JupyterLab + $ jupyter lab + +At this point, you should be able to use jupyter-ros from any Jupyter notebook in the same conda environment. + +.. code-block:: python + + import jupyros + +For alternative methods of installing Jupyter-ROS, please visit :ref:`usr-install-label` and :ref:`dev-install-label`. \ No newline at end of file diff --git a/docs/source/gen_support.rst b/docs/source/gen_support.rst new file mode 100644 index 0000000..6af13e7 --- /dev/null +++ b/docs/source/gen_support.rst @@ -0,0 +1,11 @@ +Support +======= + +If you stumble upon any issues or simply have general questions regarding +Jupyter-ROS, please reach out. The fastest way to communicate with the +core-team is through our Gitter channel +`RoboStack `_. We monitor this channel regularly +to help you get the most out of Jupyter-ROS. + +You can also post issues on `GitHub `_. +Please take a look at our contributing guidelines for information regarding what to include in a new issue. We are looking forward to your input! \ No newline at end of file diff --git a/docs/source/index.rst b/docs/source/index.rst index c517e0d..22f1fb6 100644 --- a/docs/source/index.rst +++ b/docs/source/index.rst @@ -15,27 +15,37 @@ pieces: - publishing and receiving messages from the notebook interface - a 3D widget for inspecting the robot and sensors in 3D -- playing back bag files and other helpers +- playing back bag files and other helpers .. toctree:: :maxdepth: 2 - :caption: Contents: + :caption: General - installation + gen_getting_started + gen_support + +.. toctree:: + :maxdepth: 3 + :caption: User Documentation + + user_installation + user_ros_essentials + user_3d_widgets + user_server + user_troubleshooting .. toctree:: :maxdepth: 2 - :caption: Usage: + :caption: Developer Documentation - publishing_receiving - ros_widgets - server_extension - troubleshooting + dev_installation + dev_testing + dev_contributing .. toctree:: :maxdepth: 2 - :caption: Reference: + :caption: Reference reference diff --git a/docs/source/installation.rst b/docs/source/installation.rst deleted file mode 100644 index e0adace..0000000 --- a/docs/source/installation.rst +++ /dev/null @@ -1,87 +0,0 @@ -Installation -============ - -jupyter-ros is distributed as a pip-package. We recommend installing it -inside a conda-environment. - -To install conda, we recommend using the `Miniconda installer `_. - -Once installed, you should use conda to install jupyter: - -.. code-block:: sh - - conda create -n jupyros_env python=2.7 bqplot pip -c conda-forge - conda activate jupyros_env - pip install jupyros - -The less recommended alternative is to install jupyter-ros in a virtual environment -or globally (least recommended for compatibility reasons with rosbridge). - -.. warning:: - - Never start the rosbridge server in the same environment as Jupyter. They rely - on incompatible versions of Tornado. The rosbridge server runs best with the - default Tornado version from the Ubuntu repositories! - -Once you have jupyter, and the jupyros-package installed, you can run the kernel -generator to install a special ROS Python kernel for Jupyter. This modifies a pre- -existing kernel in such a way that it knows about the catkin workspace. - -You can find the available jupyter kernels by running: - -.. code-block:: sh - - $ jupyter kernelspec list - - Available kernels: - julia ~/.local/share/jupyter/kernels/julia - python3 ~/miniconda3/share/jupyter/kernels/python3 - python2 ~/miniconda2/share/jupyter/kernels/python2 - xcpp11 ~/miniconda3/share/jupyter/kernels/xcpp11 - xcpp14 ~/miniconda3/share/jupyter/kernels/xcpp14 - xcpp17 ~/miniconda3/share/jupyter/kernels/xcpp17 - xonsh ~/miniconda3/share/jupyter/kernels/xonsh - -For maximum compatibility with ROS 1 releases, we want to base the ROS kernel on -the existing Python 2 kernel. - -To run the installed generator, run: - -.. code-block:: sh - - $ ros_kernel_generator python2 /home/$USER/catkin_ws/devel/setup.bash - -This will install a new kernel specification next to the installed python2 kernel -(in this case at ``~/miniconda2/share/jupyter/kernels/ros_python2``) with ROS specific -environment variables set to the ones from the catkin workspace (such as an additional -Python path to find the ROS Python libraries). - -The jupyter-ros server extension --------------------------------- - -The jupyter-ros package contains an optional server extension which can be used -to serve static files from a catkin workspace to the web browser. For the 3D -widgets we might have to load meshes to display robots correctly. These meshes -are usually part of a robot description package in ROS. In order to enable the -web browser to access those meshes, we can enable the jupyter-ros server -extension: - -.. code-block:: sh - - $ jupyter serverextension enable jupyros - - Enabling: jupyros - - Writing config: /home/wolfv/.jupyter - - Validating... - jupyros 0.3.0 OK - -The jupyter-ros server extension adds a handler to the Jupyter server that will -return contents from ROS packages. To check that it works, you can (re-)start the -Jupyter server and navigate to ``localhost:8888/rospkg/rospy/package.xml`` or any -other file that should exist in your catkin workspace. - -.. warning:: - - There are currently *no* security features in the jupyter-ros server extension. - If you have sensitive ROS packages, all contents (including uncompiled source code) - can be found through this extension. \ No newline at end of file diff --git a/docs/source/publishing_receiving.rst b/docs/source/publishing_receiving.rst deleted file mode 100644 index 09b90fe..0000000 --- a/docs/source/publishing_receiving.rst +++ /dev/null @@ -1,55 +0,0 @@ -Publishing and Receiving -======================== - -Subscribing to a ROS topic --------------------------- - -The jupyter-ros tools help publish and receive messages in the jupyter notebook. - -For the publishing, the package contains tools to automatically generate widgets -from message definitions. For receiving, the jupyter-ros package contains a helper -that redirects output to a specific output widget (instead of spamming the entire notebook). - -.. code-block:: python - - import jupyros as jr - import rospy - from std_msgs.msg import String - - rospy.init_node('jupyter_node') - jr.subscribe('/sometopic', String, lambda msg: print(msg)) - -This creates a output widget, and buttons to toggle (stop or start) receiving -messages. Internally, jupyter-ros will save a handle to the subscriber thread. -Note that we did not use the rospy-way of creating a subscriber but delegated this -to the jupyter-ros package. - -If we now send a message from the command line to the Notebook, we see message being -printed to the output widget below the cell where we executed the `jr.subscribe`. - -.. code-block:: shell - - $ rostopic pub /sometopic std_msgs/String "data: 'hello jupyter'" -r 10 - -Publishing to a ROS topic -------------------------- - -In the same way we can publish to a ROS topic by using the `jr.publish` helper. - -.. code-block:: python - - import jupyros as jr - import rospy - from std_msgs.msg import String - - rospy.init_node('jupyter_node') - jr.publish('/sometopic', String) - -This results in a jupyter widget where one can insert the desired message in the -text field. -The form fields (jupyter widgets) are generated automatically from the message -definition. If we use a a different message type, we will get different fields. -For example, a ``Vector3`` message type contains three float fields (x,y, and z) -for which we will get 3 ``FloatTextField`` instances -- these can only hold float -values (and not text). - diff --git a/docs/source/reference.rst b/docs/source/reference.rst index d22a989..cbbaf51 100644 --- a/docs/source/reference.rst +++ b/docs/source/reference.rst @@ -1,5 +1,20 @@ -Reference -========= +ROS Widgets +=========== -.. automodule:: jupyros.ros3d +.. automodule:: jupyros.ros1.pubsub :members: + +.. automodule:: jupyros.ros1.ros_widgets + :members: + +.. automodule:: jupyros.ros1.ros3d + :members: + +.. automodule:: jupyros.ros1.turtle_sim + :members: + + +ROS2 Widgets +============ + +Coming soon! diff --git a/docs/source/troubleshooting.rst b/docs/source/troubleshooting.rst deleted file mode 100644 index ee28c11..0000000 --- a/docs/source/troubleshooting.rst +++ /dev/null @@ -1,27 +0,0 @@ -Troubleshooting -=============== - -For trouble shooting the ROS 3D widgets, we have prepared the following tips. - -The 3D widgets of ROS communicate with the backend through websockets. To make -sure that a websocket connection is established, first, open the "Inspector" (in -FireFox or Chrome, right click -> Inspect Element) and navigate to the "Network" -panel of the Inspector. The network panel shows all requests. If the notebook -cells are now executed we should see a "Websocket" connection being established. - -If the websocket connection remains at "Pending..." then you might be using the -wrong Tornado version for the rosbridge websocket server. Using the wrong -Tornado version results in a **silent failure**. It's very important to not mix -the Jupyter Python environment with the rosbridge environment for the time -being, as Jupyter uses a more recent Tornado version than rosbridge websocket -(at least in the default version installed from the official ROS packages). - -Therefore, the fix is usually to reinstall the tornado version from the APT packages: - -.. code:: - - sudo apt-get install python-tornado - sudo apt-get install ros-melodic-rosbridge-suite --reinstall - -You can also check the network panel to make sure that mesh files are loaded -correctly. \ No newline at end of file diff --git a/docs/source/ros_widgets.rst b/docs/source/user_3d_widgets.rst similarity index 54% rename from docs/source/ros_widgets.rst rename to docs/source/user_3d_widgets.rst index 8056e6f..0a637e3 100644 --- a/docs/source/ros_widgets.rst +++ b/docs/source/user_3d_widgets.rst @@ -2,12 +2,13 @@ ROS 3D Widgets ============== In order to visualize robots in the Jupyter notebook, jupyter-ros ships with the -ros3d widgets. Jupyter widgets (`ipywidgets `_) +ros3d widgets. +Jupyter widgets (`ipywidgets `_) allow for communication between the Python "Kernel" and the JavaScript frontend. -For jupyter-ros, we have utilized the powerful `ROS3D.js `_ library to create widgets -for the jupyter notebook frontend. That means that it's easily possible to create -some robot viewers inside the notebook! +For jupyter-ros, we have utilized the powerful `ROS3D.js `_ library to create widgets for the jupyter notebook +frontend. That means that it's easily possible to create some robot viewers +inside the notebook! .. code-block:: py @@ -20,12 +21,12 @@ some robot viewers inside the notebook! .. image:: _static/images/jupyter_viewer.png -ROS3D communicates with ROS via websocket. This communication is configured through -the jupyter widgets protocol, but you are also required to run the "rosbridge websocket" -package in your ROS environment (or launch file). +ROS3D communicates with ROS via websocket. This communication is configured +through the jupyter widgets protocol, but you are also required to run the +"rosbridge websocket" package in your ROS environment (or launch file). -For this, you need to make sure that you have ``ros-melodic-rosbridge-suite`` and -``ros-melodic-tf2-webrepublisher``. +For this, you need to make sure that you have ``ros-noetic-rosbridge-suite`` +and ``ros-noetic-tf2-webrepublisher``. Then you can run the following launch file to start up the necessary servers: @@ -41,15 +42,16 @@ Then you can run the following launch file to start up the necessary servers: The currently shipped rosbridge suite uses a very old version of the Tornado web server. This version is *incompatible* with the more recent version used - by Jupyter. If you run both (Jupyter and rosbridge) from the same Python environment, - it is likely to silently fail (no connection from the ROS 3D widgets to the rosbridge). + by Jupyter. If you run both (Jupyter and rosbridge) from the same Python + environment, it is likely to silently fail (no connection from the ROS 3D + widgets to the rosbridge). - Therefore we recommend to seperate the two environments by using conda, and a - generated ROS kernel (see ... for instructions) + Therefore we recommend to separate the two environments by using conda, and a + generated ROS kernel. -Once the rosbridge websocket is running, we can configure a ROS connection in the -Jupyter notebook, and subscribe to a topic. For example, in order to subscribe to a -laser scan we can use the following code: +Once the rosbridge websocket is running, we can configure a ROS connection in +the Jupyter notebook, and subscribe to a topic. For example, in order to +subscribe to a laser scan we can use the following code: .. code-block:: python @@ -65,20 +67,21 @@ laser scan we can use the following code: v -This will now attempt to connect to the websocket at ``ws://lcoalhost:9090`` (which -should be the address given to the rosbridge). And if successful, it should receive -data from ``/scan`` topic and display it in the 3D viewer. +This will now attempt to connect to the websocket at ``ws://localhost:9090`` +(which should be the address given to the rosbridge). And if successful, it +should receive data from ``/scan`` topic and display it in the 3D viewer. -Note that, similar to RViz, you can select a fixed frame, which will appear at the -origin of the viewer. +Note that, similar to RViz, you can select a fixed frame, which will appear at +the origin of the viewer. -Besides the laser scan view, you can add many other visualizations to the viewer. -ROS3D contains classes for a Robot (``URDFModel``), occupancy grid (``OccupancyGrid``), -regular and interactive markers (``Marker`` and ``InteractiveMarker``), -``Pose``, ``Polygon``, ``PoseArray``, ``Path``, and ``PointCloud``. +Besides the laser scan view, you can add many other visualizations to the +viewer. ROS3D contains classes for a Robot (``URDFModel``), occupancy grid +(``OccupancyGrid``), regular and interactive markers (``Marker`` and +``InteractiveMarker``), ``Pose``, ``Polygon``, ``PoseArray``, ``Path``, and +``PointCloud``. -If you want to visually change how your Viewer looks, you can use the layout attribute -(this works the same way `across many of the ipywidgets `_). +If you want to visually change how your Viewer looks, you can use the layout +attribute (this works the same way `across many of the ipywidgets `_). .. code-block:: python @@ -91,4 +94,3 @@ If you want to visually change how your Viewer looks, you can use the layout att # v.layout.border = "3px solid red" ... .. image:: _static/images/red_border.png - diff --git a/docs/source/user_installation.rst b/docs/source/user_installation.rst new file mode 100644 index 0000000..7a5638a --- /dev/null +++ b/docs/source/user_installation.rst @@ -0,0 +1,56 @@ +.. _usr-install-label: + +Installation +============ + +Jupyter-ROS is distributed as a conda, pip, and npm package. We recommend +installing it inside a conda environment. To install conda, we suggest using +the `Miniconda installer `_. + +.. code-block:: sh + + # Option 1. conda or mamba [Recommended] + $ conda create -n jupyros_env python=3.9 + $ conda activate jupyros_env + $ conda install jupyter-ros -c robostack + +.. code-block:: sh + + # Option 2. pip + $ pip install jupyros + +.. code-block:: sh + + # Option 3. npm + $ npm i jupyter-ros + + +The jupyter-ros server extension +-------------------------------- + +The jupyter-ros package contains an optional server extension which can be used +to serve static files from a catkin workspace to the web browser. For the 3D +widgets we might have to load meshes to display robots correctly. These meshes +are usually part of a robot description package in ROS. In order to enable the +web browser to access those meshes, we can enable the jupyter-ros server +extension: + +.. code-block:: sh + + $ jupyter serverextension enable jupyros + + Enabling: jupyros + - Writing config: /home/user/.jupyter + - Validating... + jupyros 0.6.0 OK + +The jupyter-ros server extension adds a handler to the Jupyter server that will +return contents from ROS packages. To check that it works, you can (re-)start +the Jupyter server and navigate to ``localhost:8888/rospkg/rospy/package.xml`` +or any other file that should exist in your catkin workspace. + +.. warning:: + + There are currently **no** security features in the jupyter-ros server + extension. If you have sensitive ROS packages, all contents (including + uncompiled source code) can be found through this extension. \ No newline at end of file diff --git a/docs/source/user_ros_essentials.rst b/docs/source/user_ros_essentials.rst new file mode 100644 index 0000000..cfcb055 --- /dev/null +++ b/docs/source/user_ros_essentials.rst @@ -0,0 +1,167 @@ +ROS Essentials +============== + +Subscribing to a ROS topic +-------------------------- + +The Jupyter-ROS tools help publish and receive messages in a Jupyter notebook. + +For publishing, the package contains tools to automatically generate widgets +from message definitions. For receiving, the jupyter-ros package contains a +helper that redirects output to a specific output widget (instead of spamming +the entire notebook). + +.. code-block:: python + + import jupyros as jr + import rospy + from std_msgs.msg import String + + rospy.init_node('jupyter_node') + jr.subscribe('/sometopic', String, lambda msg: print(msg)) + +This creates a output widget, and buttons to toggle (stop or start) receiving +messages. Internally, jupyter-ros will save a handle to the subscriber thread. +Note that we did not use the rospy-way of creating a subscriber, but delegated +this to the jupyter-ros package. + +If we now send a message from a JupyterLab terminal, we see message being +printed to the output widget below the cell where we executed the +`jr.subscribe`. + +.. code-block:: shell + + $ rostopic pub /sometopic std_msgs/String "data: 'hello jupyter'" -r 10 + +.. image:: _static/images/subscriber.png + :width: 500 + +Publishing to a ROS topic +------------------------- + +In the same way we can publish to a ROS topic by using the `jr.publish` helper. + +.. code-block:: python + + import jupyros as jr + import rospy + from std_msgs.msg import String + + rospy.init_node('jupyter_node') + jr.publish('/sometopic', String) + +This results in a jupyter widget where one can insert the desired message in +the text field. The form fields (jupyter widgets) are generated automatically +from the message definition. If a different message type is used, different +fields will be generated. For example, a ``Vector3`` message type contains +three float fields (x,y, and z) for which we will get three ``FloatTextField`` +instances; these can only hold float values (and not text). + +.. code-block:: python + + from geometry_msgs.msg import Vector3 + + jr.publish('/vectortopic', Vector3) + +.. image:: _static/images/publisher.png + :width: 500 + + +Calling a ROS service +--------------------- + +The same principles of publishing and receiving messages are applied for +calling ROS services from a Jupyter notebook. Assuming that the service for +adding two integers is available, a service client widget can be created with +the following: + +.. code-block:: python + + import jupyros + import rospy + from rospy_tutorials.srv import AddTwoInts + + rospy.init_node('service_node') + jupyros.client('service_name', AddTwoInts) + +The generated widget will change depending on the message type being passed. + +.. image:: _static/images/service_client.png + :width: 400 + + +Calling a ROS action server +--------------------------- + +A widget can also be created to call ROS action servers. + +.. code-block:: python + + import jupyros + import rospy + from actionlib_tutorials.msg import FibonacciAction, FibonacciGoal + + rospy.init_node('action_node') + +As an example, the Fibonacci server can be initialized from a JupyterLab +terminal. + +.. code-block:: sh + + $ rosrun actionlib_tutorials fibonacci_server.py + +The widget for the server called ``'fibonacci'`` can then be generated as follows: + +.. code-block:: python + + jupyros.action_client('fibonacci', FibonacciAction, FibonacciGoal, callbacks={}) + +.. image:: _static/images/action_client.png + :width: 500 + +The fields for the widget depend on the definition for the action *goal*. + + +Turtlesim +--------- + +A widget for the most popular *turtlesim* animation is also included in +Jupyter-ROS. The widget can be displayed with the code below, showing the +default parameters. + +.. code-block:: python + + import jupyros + import rospy + from jupyros import TurtleSim + + turtlesim = TurtleSim(width=1600, + height=1600, + turtle_size=100, + background_color="#4556FF") + + display(turtlesim.canvas) + +When initialized, the widget will display a single turtle in the center of the canvas. The turtle images are randomized, so different turtles will appear after each run. Multiple turtles can also be spawned on the same canvas given a desired position (within the canvas limits) and orientation. + +.. code-block:: python + + turtlesim.spawn(name="turtle2", pose={"x": 630, + "y": 1260, + "theta": math.radians(90)}) + +.. image:: _static/images/turtlesim.gif + +The turtles can be moved around by subscribing to topics such as `/turtle1/pose` to receive new *Pose* messages. + +.. code-block:: python + + # Retrieve current poses of the two turtles + new_poses = {"turtle1": turtlesim.turtles["turtle1"].pose, + "turtle2": turtlesim.turtles["turtle2"].pose} + + # Change the pose for the second turtle + new_poses["turtle2"] = {"x": 800, "y": 300, "theta": 2.5} + + # Update the canvas + turtlesim.move_turtles(new_poses) \ No newline at end of file diff --git a/docs/source/server_extension.rst b/docs/source/user_server.rst similarity index 75% rename from docs/source/server_extension.rst rename to docs/source/user_server.rst index d321e3d..038684b 100644 --- a/docs/source/server_extension.rst +++ b/docs/source/user_server.rst @@ -1,5 +1,5 @@ -Server Extension -================ +ROS Server Extension +==================== The jupyter-ros package comes with a jupyter server extension to serve static files (such as robot models) from a catkin workspace. @@ -9,12 +9,11 @@ parameter to ``http://localhost:8888/rospkg/`` in order for it to search below that URL for the meshes and other required assets. The endpoint will use `rospkg` to find assets in your catkin workspace. For -example, the URL``http://localhost:8888/rospkg/roscpp/CMakeLists.txt`` should +example, the URL ``http://localhost:8888/rospkg/roscpp/CMakeLists.txt`` should return the CMakeLists file of the roscpp package. This feature is mainly useful for sending mesh files to the frontend. .. warning:: - Currently, there is no mechanism in place to filter requests based on file + Currently, there is **no** mechanism in place to filter requests based on file type. That means, all your source files can be accessed through this endpoint. - diff --git a/docs/source/user_troubleshooting.rst b/docs/source/user_troubleshooting.rst new file mode 100644 index 0000000..d35d057 --- /dev/null +++ b/docs/source/user_troubleshooting.rst @@ -0,0 +1,68 @@ +Troubleshooting +=============== + +When working with the official ROS packages, it may be necessary to modify +the Jupyter kernel. + +Once you have Jupyter and the `jupyros` package installed, you can run the +kernel generator to install a special ROS Python kernel for Jupyter. This +modifies a pre-existing kernel in such a way that it knows about the catkin +workspace. + +You can find the available jupyter kernels by running: + +.. code-block:: sh + + $ jupyter kernelspec list + + Available kernels: + julia ~/.local/share/jupyter/kernels/julia + python3 ~/miniconda3/share/jupyter/kernels/python3 + python2 ~/miniconda2/share/jupyter/kernels/python2 + xcpp11 ~/miniconda3/share/jupyter/kernels/xcpp11 + xcpp14 ~/miniconda3/share/jupyter/kernels/xcpp14 + xcpp17 ~/miniconda3/share/jupyter/kernels/xcpp17 + xonsh ~/miniconda3/share/jupyter/kernels/xonsh + +For maximum compatibility with ROS 1 releases, we want to base the ROS kernel on +the existing Python 2 kernel. + +Run the installed generator: + +.. code-block:: sh + + $ ros_kernel_generator python2 /home/$USER/catkin_ws/devel/setup.bash + +This will install a new kernel specification next to the installed python2 +kernel (in this case at ``~/miniconda2/share/jupyter/kernels/ros_python2``) +with ROS specific environment variables set to the ones from the catkin +workspace (such as an additional Python path to find the ROS Python libraries). + +Websocket Failure +----------------- + +For troubleshooting the ROS 3D widgets, we have prepared the following tips. + +The 3D widgets of ROS communicate with the backend through websockets. To make +sure that a websocket connection is established, first, open the "Inspector" (in +FireFox or Chrome, right click -> Inspect Element) and navigate to the "Network" +panel of the Inspector. The network panel shows all requests. If the notebook +cells are now executed we should see a "Websocket" connection being established. + +If the websocket connection remains at "Pending..." then you might be using the +wrong Tornado version for the rosbridge websocket server. Using the wrong +Tornado version results in a **silent failure**. In this case, it is very +important to **not** mix the Jupyter Python environment with the rosbridge +environment as Jupyter uses a more recent Tornado version than the default +rosbridge websocket installed from the official ROS packages. + +Therefore, the fix is usually to reinstall the tornado version from the APT +packages: + +.. code:: + + sudo apt-get install python-tornado + sudo apt-get install ros-melodic-rosbridge-suite --reinstall + +You can also check the network panel to make sure that mesh files are loaded +correctly.