QAProcess: DevelopersGuide | Review Status | PackageProposalProcess | PackageDocumentation | APIReviewProcess | DocReviewProcess | CodeReviewProcess | StackDocumentation | StackVersionPolicy | AutomatedTesting | StackReleaseProcess | WritingTutorials | Graveyard
ROS developer's guide
Contents
ROS is a large system, with lots of people writing lots of code. To keep things manageable, we have established the following development guidelines. Please follow these guidelines as you code.
See also:
Source control
We support using Git, Mercurial, Subversion and Bazaar for source control. As the ROS community is distributed, you are welcome to host your code anywhere that is publicly accessible (GitHub, Bitbucket, Google Code). The main ROS code base is hosted in several organization units on github.com. For the recommended repository usage please see RecommendedRepositoryUsage
- Add to source control only the minimal set of manually written source and build files that are necessary to build your package. Don't add machine-generated files, such as objects (.o), libraries (.a, .so, .dll), or auto-generated configure scripts.
svn add on a directory will recursively add all of the directory's contents. Do a make clean before the svn add.
- Don't add large binary files: upload them to a web server and download them in your build file.
- Commit your code early and often. Anything not in source control should be considered temporary "scratch" storage.
- Try to keep commits focused on a particular change instead of lumping multiple changes together -- it is much easier to rollback that way.
- Give an informative message with each commit.
- Don't break the build. Verifies that your code compiles before checking it in.
Bug tracking
We use separate bug trackers for each package which include bug reports, enhancement requests, and task assignments. Usually you will find the link to the package-specific bug tracker on the Wiki page of the package.
For packages hosted on GitHub this is commonly the issue tracker of the repository.
The maintainer will assign a milestone to each reported issue. This should give the reporter a reasonable feedback when this issue will be addressed. These milestone are usually ROS releases (like Groovy or Hydro) or more fine grain milestones (like Hydro beta 1). Furthermore the milestone untargeted is used when a issue will likely not get fixed / implemented. That can be either due to lack of time of the developer or other viability considerations.
To give users some idea as to whether a fix has made it to the release repository, the maintainer should either mention the intended release version while closing the issue report, or setup milestones for every minor release and tag the issue report with the next milestone. This will make the issue self-contained in determining whether a fixed release is available to the user.
When you find a bug, open a ticket. When you want a feature, open a ticket. Emails or posting on answers.ros.org or the mailing list are more likely to get lost. It's far less likely to be forgotten if there's a ticket.
- Be as descriptive as possible in tickets.
- They should include instructions for reproducing the bug.
- They should mention information your system and state (what version of related packages are used etc.).
- Don't be afraid to open tickets. Many developers open tickets assigned to themselves, using Trac as a kind of external memory.
If you are unsure for which package the issue should be filled or if an issue you are facing is actually a bug please ask on answers.ros.org first.
Code layout
ROS code is organized into packages, and packages can be collected into a single repository. Packages are represent units of code that you build
Especially if using GitHub it is recommended to create a README.md at the root of your repository to explain to users what to find in the repository. It is recommended to link to the package documentation on the ROS wiki for the contained packages. See this article for formatting help.
Packaging
The ROS package and build system relies on manifest.xml files.
Every package must have a manifest.xml file, located in the package's top directory.
- At a minimum, the manifest file must contain:
- description
- author
- license
Here is a template you can fill in for roscpp nodes:
<package> <description brief="BRIEF DESCRIPTION"> LONGER DESCRIPTION </description> <author>You/you@willowgarage.com</author> <license>BSD</license> <url>http://wiki/YOURPACKAGE</url> <depend package="roscpp"/> </package>
And here is one for rospy nodes:
<package> <description brief="BRIEF DESCRIPTION"> LONGER DESCRIPTION </description> <author>You/you@willowgarage.com</author> <license>BSD</license> <url>http://wiki/YOURPACKAGE</url> <depend package="rospy"/> </package>
GUI toolkits
We have migrated all new GUI development to rqt, a Qt-based GUI framework for ROS. Much of the existing code that were built before fuerte used wxWidgets, which has not maintained good cross-platform compatibility. Please consider using rqt for any new GUI development. Development instruction (including license consideration when writing in python) is available there.
Building
The basic build tool is CMake (more).
Every package that has a build step must have a CMakeLists.txt file in the package's top directory.
For now, every package that has a build step must also have a Makefile, but it should be very short.
- Packages that don't have build steps don't need any build files.
Licensing
ROS is an Open Source project. We aim to support a wide variety of users and developers, from grad students to entrepreneurs.
- We prefer permissive Open Source licenses that facilitate commercial use of the code.
The preferred license for the project is the BSD license. Whenever possible, new code should be licensed under BSD. All ROS core code is licensed BSD. Reasons for choosing BSD
- The preference for BSD is based on many factors. Here are a few:
- BSD allows any kind of reuse, from academic to commercial, open or closed.
- BSD is compatible with all other OSI-approved licenses. (For example GPL v2 is not compatible with Apache 2).
BSD does not require that changes be contributed back but there are large thriving communities using the BSD license (e.g., http://www.openbsd.org, http://www.freebsd.org). Members of these communities frequently contribute improvements, without being required to do so.
- The preference for BSD is based on many factors. Here are a few:
Any OSI-approved license is acceptable (for non-core code).
We strongly recommend using a non-copyleft license (e.g. BSD) for ROS .msg and .srv files so that the auto-generated source files and data structures are not encumbered.
- The full text statements of all licenses used in the project should be placed in the LICENSES directory at the top of the repository. If you add a package under a license that is not included in LICENSES, add the license statement.
- Every source file should contain a commented license summary at the top. For convenience, the LICENSES directory also contains summaries, appropriately commented for different languages.
- We preserve license and copyright statements on all third-party code that we redistribute.
- We rigorously obey license terms on third-party software that we use. For example:
If a library is licensed GPL or LGPL and you modify it, you must release the modified code. Ideally you would send a patch to the library maintainer. Keeping the modified code in a publicly accessible repository (e.g., at SourceForge) also suffices.
If your package uses a GPL'd library, then your package code must also be licensed GPL.
If your package uses a GPL'd library, then it must not also use any code governed by a GPL-incompatible license. For example, the Creative Commons Attribution-Noncommercial-Share Alike license is GPL-incompatible, because it imposes extra constraints that the GPL does not (namely, requiring attribution, and prohibiting commercial use).
- Whenever possible, each ROS package is governed by a single license.
- Common special case: BSD-licensed code (e.g., the ROS core) is used in a package that also uses GPL-licensed code. To comply with the GPL, the BSD-licensed code is multiply-licensed under BSD and GPL, with the user given the choice of which license to use. This is not a big deal, because the GPL simply adds restrictions that are not in BSD.
- The ROS packaging and communication system allows for fine-grained licensing. Because nodes communicate via ROS messages, code from multiple nodes is not linked together. Thus the package provides a kind of "license boundary."
- Exception: when a package is a library that is actually linked to by other packages. In this situation, license terms mix in the resulting binary.
For reference: Maintaining Permissive-Licensed Files in a GPL-Licensed Project: Guidelines for Developers
Copyright
Under the Berne Convention, the author of a work automatically holds copyright, with or without a formal statement to that effect. However, making copyright explicit is helpful in long-term project management.
Each source file should contain a commented copyright line at the top, e.g.: Copyright 2008 Jim Bob. This statement is usually directly above the license summary.
- If you work for yourself, then you own the copyright.
- If you work for someone else (e.g. Willow Garage), then your employer owns the copyright.
Debugging
All standard debugging tools work within ROS, including but not limited to:
General advice:
If a program, say foo, crashes, first try running it inside GDB:
- You can supply command-line arguments if necessary:
(gdb) run arg1 arg2 arg3
When the program crashes, use gdb's bt command to get a backtrace and start digging.
- For tough bugs, especially those related to memory corruption, trying running inside valgrind:
valgrind -v foo arg1 arg2 arg3
Valgrind will track all memory access and generally can identify the cause of the problem. It will also likely find other problems that you didn't know about yet. One caveat is that valgrind will make your program run slower, sometimes much slower.
master and rospy logs are always created in ROS_ROOT/log. However, roscpp client node logs are not created by default. If you are debugging a nasty node, you can "or" in the WRITE_LOG_FILE constant to the (optional) second parameter of the constructor (along with other fancy options like ANONYMOUS_NAME and such). Alternatively, if you don't want to recompile the node, you can give it a command-line parameter of log:=BLAHBLAH where BLAHBLAH is anything at all (or nothing).
Testing
We use two level of testing:
Library: At the library level, we use standard unit-test frameworks. In C++, we use gtest. In Python, we use unittest.
Message: At the message level, we use rostest to set up a system of ROS nodes, run a test node, then tear down the system.
We have established best practices and policies for writing and running tests.
If you are developing in the ros, ros-pkg, or wg-ros-pkg repositories, a build farm is set up to regularly test the build and run automated tests on a variety of architectures. If the build or tests stop working after one of your commits, you will get an email informing you of the error and will be expected to fix it. See the AutomatedTesting guidelines for more details.
Documentation
All code should be documented according to QAProcess. Including:
- All externally visible code-level APIs must be documented
- All externally visible ROS-level APIs (topics, services, parameters) must be documented.
Releasing
The standard process for releasing code to the ROS community is described on the bloom documentation. Legacy releases were documented on the release page.
Standardization
- Code should use ROS services, follow guidelines for their use
Deprecation
As soon as there are users of your code, you have a responsibility not to pull the rug out from under them with sudden breaking changes. Instead, use a process of deprecation, which means marking a feature or component as being no longer supported, with a schedule for its removal. Give users time to adapt, which is usually one release cycle, then do the removal.
Deprecation can happen at multiple levels, including:
API features : Say you want to remove a method call from a library. First mark it as deprecated in the API documentation; with DOxgyen, use @deprecated. If the language supports it, also mark the code as being deprecated; in C/C++, use __attribute__ ((deprecated)). In the next release, note the deprecation in the ChangeList, with the future release at which you expect to remove it; if it's a widely used feature, make the deprecation notice prominent, and explain the reasoning behind it. In that future release, remove it.
Packages : Say you want to remove a package. Mark it as deprecated in the Wiki documentation (e.g., put DEPRECATED at the top), with a note as to when you expect to remove it. Include notice of the deprecation in the ChangeList with the next (stack) release. If it's a widely used package, you should also send mail to your users giving them as much advance warning as possible.
Large data files, Large test files
Large files (anything over 1MB, really) often don't belong in development repositories, especially if they are just used for unit tests. These large files affect the time that it takes to checkout the repository, whether or not someone is building your package.
Large data files should be hosted in a public web hosting site. You can also just place the file you need on a web server. Hosting for some files can be provided at download.ros.org. Please start a thread in the Release category on ROS Discourse to request uploading something. You're encouraged to search around if there are files that satisfy your need, before you'll open a upload request.
To download this file for building, use the catkin_download_test_data. OR if you're in older rosbuild era, rosbuild_download_test_data(URL MD5SUM) macro. For example:
catkin_download_test_data( ${PROJECT_NAME}_saloon.bag http://downloads.foo.com/bags/saloon.bag DESTINATION ${CATKIN_DEVEL_PREFIX}/${CATKIN_PACKAGE_SHARE_DESTINATION}/test MD5 01603ce158575da859b8afff5b676bf9) rosbuild_download_test_data(http://code.ros.org/svn/data/robot_pose_ekf/zero_covariance.bag test/zero_covariance.bag 0a51b4f5001f446e8466bf7cc946fb86)