I am wondering whether ROS programming for serious projects always ends up being in C++. In other words, is Python the “onramp” to lower the barriers, but everyone graduates to C++?
Our organization certainly has production Python code in use in our client sites. There’s always a matter of the right tool for the job, though - we don’t have any controls or perception code written in Python, that’s all in C++.
There are definitely serious things done in Python. In fact, a large amount of the every day tools we use are python-based. I think that performance reasons lead to the C++ favoritism, honestly.
Some other “serious” things done in Python:
There are also drivers done on Python (specially ones that deal with Serial devices):
And hey, lots of deep learning happening in Python (and then wrapped in ROS).
Everyone loves a good statistic, so I’ve put together a small python script that collects the major language used in each released ROS repository, as classified by GitHub. You can clearly see that C++ is the dominant language, but Python is also used a lot, including for “serious stuff”.
Some caveats in the statistics:
- The list only shows the major language used in a repo (winner takes it all). Often, ROS repos contain both C++ and Python (or other) code, but C++ wins by LOC, so smaller languages are underrepresented in the list below.
- I’m only counting repos, but the repos differ in size a lot. Some contain many packages with several 10,000 LOC, some are single-package repos with only a couple dozen LOC.
To answer the question, I wouldn’t say people “graduate” from Python to C++. Personally, I use both, depending on the task. My main criterion isn’t performance, but library support (although the two are linked). If you’re processing a lot of point clouds, you’re probably going to use things like PCL and Octomap, which means C++. For image processing, you’re probably going to use OpenCV, which has bindings both for C++ and Python. Most high-level executive frameworks (such as executive_smach
or one of the behavior tree frameworks) are written in Python. And for small helper nodes, one-off scripts, or anything involving web sockets or REST APIs, I also prefer Python.
Here are the results:
Main languages in ROS repos by popularity
rank | Language | repos | percent |
---|---|---|---|
1. | C++ | 350 | 55.0% |
2. | Python | 158 | 24.8% |
3. | CMake | 82 | 12.9% |
4. | C | 15 | 2.4% |
5. | Common Lisp | 8 | 1.3% |
6. | None | 7 | 1.1% |
7. | Java | 4 | 0.6% |
8. | EmberScript | 3 | 0.5% |
9. | Shell | 2 | 0.3% |
10. | HTML | 2 | 0.3% |
11. | Arduino | 1 | 0.2% |
12. | Emacs Lisp | 1 | 0.2% |
13. | Lua | 1 | 0.2% |
14. | Protocol Buffer | 1 | 0.2% |
15. | C# | 1 | 0.2% |
Top 100 ROS repos by GitHub stars
After the 2013 NASA Sample Return Robot Centennial Challenge I asked the teams about the software used. The results are on my blog:
The primary language was C++ whether the team used ROS or not. That was 7 of the 10 teams that provided information. Some python was used in conjunction with C++. One team that used a combination regretted, without further explanation, the python code in their system. (Please, no language war on that point. Just reporting…)
The results were similar for the 2014 challenge but I didn’t formally record the results.
I find this topic pretty interesting and starting from @Martin_Guenther work, I digged a bit more in.
I made another script (warning, I mostly executed everything on an ipython terminal by parts, so I may have missed something) to clone the repos (in github, I tried to clone also the ones in bitbucket but it fails on my machine for some unrelated reason) and to compute the LOC on them for C++ and Python.
The output is:
From 625 packages analysed
There are 413 packages using C++
There are 317 packages using Python
And, actually, using both languages: 193
88.8747413208 % is CPP code
11.1252586792 % is Python code
I also recreated the table with this LOC data:
rank | repo name | stars | language |
---|---|---|---|
1. | IntelRealSense/librealsense | 1295 | C++ (99.6), Python (0.4) |
2. | ros/ros | 697 | Python (95.6), C++ (4.4) |
3. | wjwwood/serial | 521 | C++ (99.7), Python (0.3) |
4. | introlab/rtabmap | 490 | C++ (100.0), Python (0.0) |
5. | OctoMap/octomap | 383 | C++ (99.7), Python (0.3) |
6. | ros-planning/navigation | 320 | C++ (99.1), Python (0.9) |
7. | ethz-asl/grid_map | 281 | C++ (99.7), Python (0.3) |
8. | AutonomyLab/ardrone_autonomy | 264 | C |
9. | ros/ros_comm | 239 | Python (44.8), C++ (55.2) |
10. | dartsim/dart | 214 | C++ (98.7), Python (1.3) |
11. | introlab/find-object | 210 | C++ (100.0), Python (0.0) |
12. | vrpn/vrpn | 201 | C |
13. | intel-ros/realsense | 194 | C++ (99.2), Python (0.8) |
14. | robopeak/rplidar_ros | 191 | C++ (100.0), Python (0.0) |
15. | ros-planning/moveit | 173 | C++ |
16. | ros-visualization/rviz | 171 | C++ (97.6), Python (2.4) |
17. | mavlink/mavros | 169 | C++ (92.1), Python (7.9) |
18. | ros-drivers/rosserial | 164 | C++ (67.2), Python (32.8) |
19. | introlab/rtabmap_ros | 162 | C++ (99.4), Python (0.6) |
20. | cra-ros-pkg/robot_localization | 161 | C++ (99.4), Python (0.6) |
21. | ros/ros_tutorials | 144 | C++ |
22. | RobotWebTools/rosbridge_suite | 139 | Python (100.0), C++ (0.0) |
23. | leggedrobotics/darknet_ros | 133 | C++ (100.0), Python (0.0) |
24. | ros/catkin | 130 | Python (97.6), C++ (2.4) |
25. | ros-perception/slam_gmapping | 128 | C++ (94.3), Python (5.7) |
26. | ros-drivers/velodyne | 128 | C++ (95.2), Python (4.8) |
27. | ros-industrial/universal_robot | 127 | Python (54.9), C++ (45.1) |
28. | ccny-ros-pkg/imu_tools | 125 | C++ (100.0), Python (0.0) |
29. | orocos/orocos_kinematics_dynamics | 122 | C++ (97.4), Python (2.6) |
30. | ros-simulation/gazebo_ros_pkgs | 120 | C++ (96.3), Python (3.7) |
31. | ros-controls/ros_control | 112 | C++ (92.0), Python (8.0) |
32. | rosjava/rosjava_core | 110 | Java |
33. | ros-perception/image_pipeline | 109 | C++ (77.9), Python (22.1) |
34. | turtlebot/turtlebot | 103 | C++ (88.9), Python (11.1) |
35. | facontidavide/PlotJuggler | 103 | C++ (100.0), Python (0.0) |
36. | ROBOTIS-GIT/turtlebot3 | 101 | Python (65.0), C++ (35.0) |
37. | ROBOTIS-GIT/DynamixelSDK | 94 | C# |
38. | rst-tu-dortmund/teb_local_planner | 90 | C++ (95.4), Python (4.6) |
39. | ros-perception/vision_opencv | 85 | C++ (84.7), Python (15.3) |
40. | turtlebot/turtlebot_apps | 79 | C++ (65.2), Python (34.8) |
41. | yujinrobot/kobuki | 76 | C++ (55.0), Python (45.0) |
42. | ros-controls/ros_controllers | 73 | C++ (96.3), Python (3.7) |
43. | ankitdhall/lidar_camera_calibration | 72 | C++ (100.0), Python (0.0) |
44. | PickNikRobotics/rviz_visual_tools | 69 | C++ (100.0), Python (0.0) |
45. | ipa320/cob_driver | 68 | C++ (94.2), Python (5.8) |
46. | swri-robotics/mapviz | 66 | C++ (100.0), Python (0.0) |
47. | plasmodic/ecto | 65 | C++ (71.6), Python (28.4) |
48. | ros-drivers/usb_cam | 65 | C++ (100.0), Python (0.0) |
49. | AutonomyLab/bebop_autonomy | 63 | C++ (94.9), Python (5.1) |
50. | wg-perception/people | 61 | C++ (97.0), Python (3.0) |
51. | ros/geometry | 59 | C++ (82.7), Python (17.3) |
52. | ipa320/cob_common | 59 | Python (100.0), C++ (0.0) |
53. | ros-perception/perception_pcl | 58 | C++ (99.6), Python (0.4) |
54. | AndreaCensi/csm | 57 | C |
55. | ipa320/cob_simulation | 57 | Python (100.0), C++ (0.0) |
56. | Intermodalics/tango_ros | 57 | C++ (100.0), Python (0.0) |
57. | clearpathrobotics/robot_upstart | 54 | Python (100.0), C++ (0.0) |
58. | jsk-ros-pkg/jsk_recognition | 52 | C++ (85.3), Python (14.7) |
59. | ipa320/cob_extern | 52 | C |
60. | intel/ros_intel_movidius_ncs | 50 | C++ (100.0), Python (0.0) |
61. | AutonomyLab/create_autonomy | 50 | C++ (100.0), Python (0.0) |
62. | lagadic/vision_visp | 49 | C++ (99.2), Python (0.8) |
63. | RobotWebTools/web_video_server | 48 | C++ (100.0), Python (0.0) |
64. | skasperski/navigation_2d | 46 | C++ (100.0), Python (0.0) |
65. | fkie/multimaster_fkie | 46 | Python (100.0), C++ (0.0) |
66. | ccny-ros-pkg/scan_tools | 44 | C++ (100.0), Python (0.0) |
67. | stdr-simulator-ros-pkg/stdr_simulator | 44 | C++ (98.6), Python (1.4) |
68. | ros-industrial/industrial_core | 43 | C++ (100.0), Python (0.0) |
69. | ros-planning/navigation_tutorials | 43 | C++ (100.0), Python (0.0) |
70. | ipa320/cob_robots | 43 | Python (100.0), C++ (0.0) |
71. | ros-drivers/pointgrey_camera_driver | 43 | C++ |
72. | orocos-toolchain/log4cpp | 42 | C++ (100.0), Python (0.0) |
73. | ros-perception/openslam_gmapping | 42 | C++ (100.0), Python (0.0) |
74. | yujinrobot/yujin_ocs | 41 | C++ (83.3), Python (16.7) |
75. | paulbovbel/frontier_exploration | 41 | C++ (100.0), Python (0.0) |
76. | ros-industrial/ros_canopen | 41 | C++ (100.0), Python (0.0) |
77. | ros-industrial/abb | 40 | C++ (100.0), Python (0.0) |
78. | ros/geometry2 | 39 | C++ (91.9), Python (8.1) |
79. | ros/executive_smach | 39 | Python (100.0), C++ (0.0) |
80. | OctoMap/octomap_mapping | 37 | C++ (99.0), Python (1.0) |
81. | ros-industrial/kuka_experimental | 37 | C++ (100.0), Python (0.0) |
82. | ipa320/schunk_modular_robotics | 36 | C++ (99.3), Python (0.7) |
83. | arebgun/dynamixel_motor | 35 | Python (100.0), C++ (0.0) |
84. | youbot/youbot_driver | 35 | C++ (100.0), Python (0.0) |
85. | davetcoleman/ros_control_boilerplate | 35 | C++ |
86. | ros/actionlib | 34 | C++ (68.3), Python (31.7) |
87. | beltransen/velo2cam_calibration | 34 | C++ (100.0), Python (0.0) |
88. | ros/common_msgs | 34 | C++ (82.5), Python (17.5) |
89. | hasauino/rrt_exploration | 33 | C++ (49.8), Python (50.2) |
90. | magazino/move_base_flex | 33 | C++ (97.0), Python (3.0) |
91. | turtlebot/turtlebot_simulator | 33 | EmberScript |
92. | vanadiumlabs/arbotix_ros | 32 | Python (93.1), C++ (6.9) |
93. | ros-visualization/visualization_tutorials | 32 | C++ (74.8), Python (25.2) |
94. | ros-drivers/joystick_drivers | 32 | Python (68.8), C++ (31.2) |
95. | cbandera/rosparam_handler | 31 | Python (54.3), C++ (45.7) |
96. | wg-perception/object_recognition_core | 31 | C++ (54.3), Python (45.7) |
97. | ros-naoqi/nao_robot | 30 | Python (95.1), C++ (4.9) |
98. | ipa320/cob_command_tools | 30 | Python (79.5), C++ (20.5) |
99. | mrpt-ros-pkg/mrpt_navigation | 30 | C++ (100.0), Python (0.0) |
100. | ethz-asl/rqt_multiplot_plugin | 30 | C++ (99.9), Python (0.1) |
I think Python has it’s position on glueing things together, dealing with text, making apps and tools, and overall taking advantage of the big amount of third party libraries that ease doing stuff. If you need speed, C++ for sure. If you need something done quick, Python I’d say.
Nice work, @awesomebytes!
I’ve digged a bit more, I was curious on what is Python doing in packages that have both Python and C++? (Updated the gist).
You can find a list of the Python filenames for every package that contains C++ & Python here: https://pastebin.com/aiY5c1t2
My conclusion by looking at it, just with the filenames and the folder hierarchy (193 is too many packages to check them all 1 by 1, sorry!) with some grepping and some manual reading:
- People make tools using Python (commandline tools, filtering tools, debugging tools).
- People make tests* using Python (1059 files with test in the name/folderpath).
- People script things (duh) using Python (robot motions, if this then that, migration scripts, calibrations).
- People make demos using Python (28 files using the word demo).
- People make graphical stuff with Python (344 files/paths with rqt).
- People make fake stuff with Python (14 files with the word fake, as in fake_publisher, probably for testing/tutorial purposes).
- People provide examples in Python (93 files with the word example).
*Haven’t checked if just in Python, or some kind of specific type of test is rather done in Python than C++, I personally do functional tests that way, as in, checking the topics/services/action servers do what they should, and I get the feeling it’s the same by the filenames I’ve glanced over (many ‘send’ ‘publish’ ‘pub’ ‘sub’ ).
I hope someone else finds it interesting!