- Why ROS ?
- ROS Basics
- C++ and Python, pick one
- ROS exercises
- Distributed System for Robots
- Testing and Safety
- A set of tools for C++
- A set of components for Robots
- Big Robotics Community
- Permissive Licensing
+++
C++ does NOT have "standard" tools (like python)
ROS provides :
- catkin => CMake made easy
- rosdoc => doxygen made easy
- rostest => gtest made easy
- ROSTCP => networking made easy
- rosmsg => serialization made easy
- etc.
+++
- calibration tools
- development tools
- visualisaton
- navigation
- manipulation
- ...
+++
- ROS wiki page views : 1,394,363
- International : US, CN, JP, DE > 25,000
- ROS wiki users : 5875
- ROS pkg downloads : 8,441,279 from 113,000 IPs
- ROS research papers : 2683
- ROS Robots : > 100 (http://wiki.ros.org/Robots)
source : http://wiki.ros.org/Metrics
+++
- ROS core BSD license (Free to use, modify, sell)
- ROS tools: Open Source/Free licenses (free to use)
- Environment and Tools
- Packages and Dependencies
- Launchers and Parameters
- Messages, Topics and Services
+++
$ source setup.bash
- modify your current SHELL (
bash
) environment. - GOOD : easy to modify quickly (
export MY_ROS_ENVVAR=42
) - BAD : hard to debug (
ps aux | grep my_ros_program
) => which environment configuration ?
+++
rosls
, roscd
, rospack
, etc.
- allows easy navigation in ROS environment
- GOOD : easy to play around in your ROS environment
- GOOD : allow plug-n-play for node / comm checking
- BAD : not fully isolated from the rest of the system
+++
package.xml
and CMakeLists.txt
- describes a ROS package
- GOOD : modular compilable source code (
catkin_make
orcatkin build
) - GOOD : modular interactive runtime (ROS API)
- BAD : not easy to compose, easy to shoot yourself
- GOOD : integrating with your package manager
- BAD : not quite integrated, it goes into
/opt/ros/<rosdistro>
+++
rosdep resolve depkey
- enable cross-platform package management
- GOOD : can edit github's
ros/rosdistro
repository to add dependencies - BAD : currently can confuse ROS packages and dependencies (BUG)
+++
rospy.init_node()
or ros::init()
- declares the current process as a ROS node
- GOOD : one node match one process
- BAD : special
rosmaster
,rosout
nodes - BAD : pollute your process global state
- BAD : async programming can be VERY confusing
+++
class MyNodeletClass : public nodelet::Nodelet
- declares the current class a nodelet
- GOOD : zero copy passing between nodelets
- GOOD : easily portable from node
- BAD : multithreaded if not purely callback based
- BAD : debugging a bit harder (multiple nodelets in same process)
+++
roslaunch my_pkg my_nodes.launch
- provides a centralised launch point for multiple process/nodes
- GOOD : can load yaml files to set parameters for the system
- GOOD : a launch file can include another
- BAD : namespaces logic and remapping is not as simple as it could
- BAD : XML, but more programming-style logic is needed
+++
$ rosparam get
or rospy.get_param()
or ros::NodeHandle::getParam()
- get/set parameters for the running ROS system
- GOOD : centralised structured data
- GOOD : dynamically configurable
+++
$ rosmsg show
- defines message structure
- GOOD : provide an API other can use
- GOOD : provides serialization/deserialization crossplatform
- BAD : doesnt always check and validate the data type
+++
rospy.Publisher()
or ros::Publisher
rospy.Subscriber()
or ros::Subscriber
- allow ROSTCP/ROSUDP Push communication / event notifications
- GOOD : low overhead (binary serialization)
- BAD : lossy
- BAD : Inverted control flow (deal with your callback threadS)
- BAD : Cannot be used to interface with non-ROS systems
- GOOD : need 2 to implement pull communication
+++
rospy.Service()
or ros::Service
rospy.ServiceProxy()
or ros::ServiceProxy
- allow XMLRPC Pull communication / Remote Procedure Calls
- BAD : high overhead (XML)
- GOOD : lossless
- GOOD : Direct control flow (deal with your main thread)
- GOOD : CAN be used to interface with non-ROS systems
- GOOD : need 2 to implement push communication
- Different tools, community, mindset. Pick a side !
- Can mix in different ways (cffi, bindings, ...)
- ROS provide the multi-process/local-network way.
- ROS adapts its C++-like tools to python.
+++
- Build : GNU make, CMake, QMake, Ninja, Gradle, SCons, Premake, etc.
- Docs : Doxygen, Sphinx, etc.
- Tests : Boost.Test, cppunit, CxxTest, gtest, etc.
- Logs : Boost.Log, log4cpp, log4cxx, etc.
- Style : astyle, uncrustify, etc.
- Analysis: cppcheck, cpplint, clang, etc.
- packaging: deb, rpm, CPack, etc.
+++
- Build : Python
- Docs : Sphinx
- Tests : unitest, doctest, nose, pytest
- Logs : logging
- Style : PEP8
- Analysis: mypy
- Packaging: pip + setuptools
+++
- Check what you can
- Compile what you need
- Don't change
- Be fast
+++
- Check if you can
- Compile if you need
- Change if you need
- Be flexible
+++
- Python API
- CPython interface
- CFFI
- documented & standardised
+++
- communicating asynchronous processes
- common message format
- compatible serialization/deserialization code
- basic network management code
+++
- A reference for ROS good practices
- "pure" C++ library
- C++ / ROS nodes and package
- ROS / python nodes and package
- "pure" python nodes and package
- Nothing beats DIY !
- Make a C++ package "without" ROS
- Make ROS package
- Combine packages
- Logging
- Nodelet interaction
+++
- CMake project
- Sum last x numbers library
- Demo Executable
- Add catkin and ROS package
- Add tests
+++
- Nodelet with standalone launcher
- Publish config file parameter
- Publish dyn. reconfigure parameter
- Add rostest which fails for negative number
+++
- Use library package in ROS package
- Publish sum of config parameter
- Add subscriber as additional input
+++
- Add logging, cout and rosconsole
- Separate logging file for package
+++
- Nodelets subscring in a circle
- Publish sum of input from before
- Trigger with command line publish
+++
- Two nodelets, pub-sub each other
- Publish sum of numbers before
- Synchronized publish after each other
- Make a ROS package
- Make a Python package
- Turn it into a ROS package
- Make a client python script
- Mutate client into a node
- Review
+++
- Follow ROS python tutorials
- Refer to ros1_pytemplate
- Implement a Number Node
- stores a number (initialized at 1)
- provides reset() for resetting it
- provides value() for getting its value
- provides a ROS API for reset() and value()
+++
- Follow http://packaging.python.org
- Refer to cookiecutters
- Provide a python package with Accumulator module
- Accumulator stores a number N (init at 1) and a constant C
- Accumulator can do inc_mod(m) -> (N + m) mod C
+++
- Use https://github.com/pyros-dev/catkin_pip
- Refer to ros1_pip_pytemplate)
- Unify tests
- Make a ROS Accumulator node
- Choose a ROS API to provide access to inc_mod
+++
- Not a node
- Uses Number & Accumulator ROS API
- Implements a Fibonacci modulo sequence
- Doesnt do any arithmetic (+, - *, /) itself
+++
- Can we improve the communication ?
- Is it really better ?
- What are the problems or risks ?
+++
- Questions ?
- Do the exercises !
- In groups if you want.
- We shall meet again...
+++
- We (just) implemented Fibonacci
- What can we say about the code ?
- What can we way about the potential bugs ?
- How can we explain it to someone else ?
- Distributed Computing Fallacies
- Forget what you think you know
- Recent research area
- No mainstream distributed programming environment.
- Murphy's Law: Everything that can possibly go wrong WILL go wrong.
- But Robot system must be reliable (enough) ?!?!
+++
- the network is reliable
- latency is zero
- bandwith is infinite
- network is secure
- Topology doesnt change
- There is one administrator
- Transport cost is zero
- Network is homogeneous
+++
This | can print: |
a=time.now() b=time.now() print(a>b) |
|
True | |
False | |
no idea | |
Error | |
Crash |
+++
This | can print: |
int a=1 a= a+1 print(a) |
|
1 | |
42 | |
... | |
Error | |
Crash |
- Grow-counter: we can count up ! (not down)
- Positive-Negative-counter: we can count down !
- Grow-only-set: we can group things together ! (not ungroup)
- Two-phase-set: we can ungroup things ! (only once)
- more coming...
+++
- Nothing mainstream, except Erlang (31 years old)
(Alice@alexv-pc)
1> net_kernel:connect_node('Bob@alexv-pc').
true
2> nodes().
['Bob@alexv-pc']
3> register(shell, self()).
true
4> receive {hello, from, Other} -> Other ! <<"whats up !">> end.
<<"whats up !">>
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
(Bob@alexv-pc)
1> nodes().
['Alice@alexv-pc']
2> {shell, 'Alice@alexv-pc'} ! {hello, from, self()}.
{hello,from,<0.39.0>}
3> flush().
Shell got <<"whats up !">>
ok
@[10](Two Erlang VMs) @[10,2-3](Connect a node to another) @[10,4-5](Check connections from Alice) @[10,12-13](Check connections from Bob) @[10,6-7](Register current REPL in a variable) @[10,14-15](Send message to Alice's REPL) @[10,8-9](Receive message and pattern match) @[10,16-18](Flush messages) @2,6,8,10,14
+++
Everything that can possibly go wrong WILL go wrong
- Fail-stop failures
- Crash failures
- Omission failures
- Performance failures
- Byzantines failures
+++
- Specifications : WHAT the robot has to do.
- Properties : What the robot has to NOT do.
- Formal Specs : HOW the robot does it.
- Model Checking : Formal spec is respected.
- Property testing : Properties are respected
- Validation testing : Specification is respected.