Package templates for enhancing the developer experience

Over the few years I’ve been developing with ROS, I’ve gradually accumulated a collection of habits in how I structure new packages, how I configure my developer tools, etc. These typically get copied from one package to the next as I go along. However I feel that my practices are hardly best practices; there are definitely areas I’m lacking in, such as writing tests, or packaging my nodes for release.

In many other frameworks there exist tools for spinning up a new project from a standard template that incorporates best practices and a baseline configuration for tooling. For example, there’s create-react-app, or the more generic cookiecutter. These provide a very good developer experience, are easier than starting from scratch.

I’d like to brainstorm some ideas for how similar templates and tooling could enhance the ROS developer experience.

Ideally, the way the developer interacts with the template is by running a tool to create the project directory from a chosen template. Possibly, as is common in the Node world, the tool could also provide a wrapper around common tasks like build, test, etc. – but it should be transparent about what commands are being executed.

The intended audience is any ROS developer, not just new users (who benefit from the handholding a tutorial provides). The template accelerates the process of creating a new package, improves the developer experience, and assists in delivering quality code. It is not an “easy mode”.

I want to distinguish these templates from tutorials, which have an educational aim and therefore need to be explanatory. Undoubtedly it would be a good thing if there exist, in parallel, tutorials that refer to these templates.

Generally, a template strike a balance between function and minimalism. I would prefer to avoid extensive, boilerplate comment blocks that explain what every line in CMakeLists.txt does, as this belongs elsewhere.

It’s arguable whether these templates are considered examples or how-tos of how to do accomplish some task in ROS, like using tf2 or image_transport. Undoubtedly there will be some overlap. However the intention is not to cover every use case and to rely on the existing documentation.

Lastly, I want to acknowledge that there exists catkin create pkg but this mainly (or only?) produces boilerplate CMakeLists.txt and package.xml.

Here are some initial ideas for things to include in these templates, to kick off the discussion:

  • General

    • Unit tests (and other kinds of tests)
    • CMakeLists.txt and package.xml
    • Launch scripts
    • Dev containers
    • Integrated linter / code formatter
    • Continuous integration (GitHub CI, ROS Build Farm)
  • Python 3

    • With
    • Both sync and async templates
    • Using type hints
  • C++

    • Using modern C++1x or 2x
  • Packaging

    • Building .deb packages
    • Building container images
  • Other client libraries or implementations: Roslib.js, micro-ROS, “raw” DDS

  • Common (basic) patterns

    • Subscribers, publishers, actions, services
    • State machines
    • Message filters

Other questions for the community:

  • What would the ideal developer experience look like to you? What other frameworks or templating tools provide good developer experiences?

  • Is there enough consensus about what best practices even are in ROS?

  • How do we strike the balance between satisfying the needs of experienced users and beginners alike?

  • Are there existing packages that are good role models?

1 Like

Thanks for starting this discussion. I think that there’s a lot of potential here to help new developers learning about the system as well as provide a tool for experienced developers to speed up building a new packages.

To the end I’d like to highlight that there’s already a start on this in ROS 2 as well.

ros2 pkg create

It would be great to extend and improve that package once you’ve learned what the most valuable elements are.

And one suggestion might be that there be an extension point by which packages could add suggestions or options for pkg create if they’re installed on your system.

More info for those not aware of the capability:

usage: ros2 pkg create [-h] [--package-format {2,3}]
                       [--description DESCRIPTION] [--license LICENSE]
                       [--destination-directory DESTINATION_DIRECTORY]
                       [--build-type {cmake,ament_cmake,ament_python}]
                       [--dependencies DEPENDENCIES [DEPENDENCIES ...]]
                       [--maintainer-email MAINTAINER_EMAIL]
                       [--maintainer-name MAINTAINER_NAME]
                       [--node-name NODE_NAME] [--library-name LIBRARY_NAME]

Create a new ROS 2 package

positional arguments:
  package_name          The package name

  -h, --help            show this help message and exit
  --package-format {2,3}, --package_format {2,3}
                        The package.xml format.
  --description DESCRIPTION
                        The description given in the package.xml
  --license LICENSE     The license attached to this package; this can be an
                        arbitrary string, but a LICENSE file will only be
                        generated if it is one of the supported licenses (pass
                        '?' to get a list)
  --destination-directory DESTINATION_DIRECTORY
                        Directory where to create the package directory
  --build-type {cmake,ament_cmake,ament_python}
                        The build type to process the package with
  --dependencies DEPENDENCIES [DEPENDENCIES ...]
                        list of dependencies
  --maintainer-email MAINTAINER_EMAIL
                        email address of the maintainer of this package
  --maintainer-name MAINTAINER_NAME
                        name of the maintainer of this package
  --node-name NODE_NAME
                        name of the empty executable
  --library-name LIBRARY_NAME
                        name of the empty library

The implementation is at:

1 Like

I would love to use more complete version of ros2 pkg create. For me currently it seems very bare bones. Below are my thoughts on topics @rgov listed
Note: i use humble, but just in-case doc links are iron

  • General
  • Unit tests (and other kinds of tests):
    • a test related area is added to cmakelist in there lint checks are avaliable but need to add other tests. maybe something like this in docs could be added.
  • CMakeLists.txt and package.xml:
    • adding two executables is not supported (or i failed to do so :smiley: )
    • generated cmake uses some extra elements that are not in tutorials, so sometimes implementing part of a tutorial to generated project got confusing. To be more specific target_include_directories and target_compile_features are generated but not in tutorials. target_include_directories is used to add “include” directory. I would love it if both cli and tutorials are more similiar to encoruge best practices.
  • Launch scripts:
    • no launch script, maybe something can be generated as in docs with a new --launch-version flag that has options like none,yml,xml,python and default could be none. generated launch file could include a basic launch file if pkg has executable
  • Dev containers
    • docs says it is community contributed and instructions are for workspace level and not pkg level. Also i generally dont use it on pkg level, but it might be usefull?
  • Integrated linter / code formatter:
    • pkg create generates lint test. to auto lint cpp i use ament_uncrustify --reformat src but I handle cmake and package.xml errors manually and i think error messages are not beginner friendly enough. for example I fix package.xml errors by changeing order of elements, but errors say “unecpected element xxxx”
  • Continuous integration (GitHub CI, ROS Build Farm): no idea, but a flag on ros2 pkg create could allow to chose ci type and basic ci could be added to run tests, check builds etc.
  • Python 3 (no clue in general)
    • With
    • Both sync and async templates
    • Using type hints
  • C++
    • Using modern C++1x or 2x
      • dont know it is related but target_compile_features(main PUBLIC c_std_99 cxx_std_17) # Require C99 and C++17 is added in cmake
  • Packaging
    • Building .deb packages
      • would love to know how to do this, Can you explain or link a tutorial on how to do this ?. Also examples I see online are generally of snap packaging rather than debian.
    • Building container images
      • I think this can be be one liner by using osrf desktop image, volumeing current dir, workspaceing to parent dir etc, @rgov Do you have more specific thing in mind ?
  • Other client libraries or implementations: Roslib.js, micro-ROS, “raw” DDS (no clue)
  • Common (basic) patterns
    • Subscribers, publishers, actions, services
    • State machines
    • Message filters
      • I also want to add parameters, but probably use cases are too divergent to define best practices

I would love some auto doc generation.
Also there are probably other related thread about this like: How do you structure your projects and workspaces?

I search nav2, moveit, BT.ros2 etc. But generally wing it :pensive:

This topic was automatically closed 30 days after the last reply. New replies are no longer allowed.