Differences

This shows you the differences between two versions of the page.

Link to this comparison view

ros [2019/03/31 14:49] (current)
Line 1: Line 1:
 +====== ROS ======
 +
 +ROS stands for Robot Operating System. It is a collection of libraries and
 +utilities that make up a software framework that is a node based
 +publisher-subscriber model. It allows developers to quickly write modular code
 +for a robot that does a specifc task while providing a layer of useful libraries
 +and introspection tools. The publisher-subscriber principal allows for minimal
 +coupling by leaving it up to each node to subscribe and publish data as it
 +wishes to a common bus that is accessible to all other nodes.
 +
 +The following are a set of notes I have taken while learning how to use ROS, and
 +applying ROS to build an autonomous street robot name [[primo_robot|Primo]].
 +
 +===== ROS Package =====
 +
 +[[http://​wiki.ros.org/​Packages|Official ROS package page]].
 +
 +A package in ROS is the "​software organization unit of ROS code"​. ​ Think of a
 +package as software project that does one task. It might contain multiple
 +[[ros_nodes|nodes]],​ aka executable ROS processes, and a bunch of configuration
 +information. ​
 +
 +For example, say we have a robot with a robotic arm that uses a motor that is
 +connected to an output shaft via some gearing, and also cause we're fancy we
 +have a torque transducers on the output shaft along with an encoder for position
 +information. That is a good amount of stuff for just one arm joint, but this
 +"arm joint stuff" perfect candidate for a package. We can boil it down to set
 +of tasks relating to the joint and cease a package. On top of that we can create
 +the package in such a way that it can be configurable,​ and applied to more of
 +the similar joints. The package would be responsible for the following:
 +
 +**Sketch of package responsibilities**
 +  * Take in commands to control the joint in different ways
 +    * Position control to send the joint in a specific place
 +    * Force control to push against something or grip with a set force
 +    * Velocity control for a spinning joint such as a screwing task
 +  * Make sure the joint obeys within its limits of force, torque, velocity and position
 +  * Hold a set of configuration data such as position of the joint, name, etc
 +  * Have a driver interface to the motor controller which could be a serial, or CAN connection
 +  * Monitor any fault conditions and have a mechanism in place for what to do when bad things happen.
 +
 +With that sketch of responsibilities we can create engineering requirements that
 +fully define the tasks and then go on to either try to find a package that does
 +this already, or make our own. If we decide to make our own we'll build out our
 +package and have nodes that handle each of those tasks that can easily talk to
 +each other etc. Hope that gives you a good idea of what a ROS package is!
 +
 +===== ROS Node =====
 +
 +Nodes: A node is an executable that uses ROS to communicate with other nodes.
 +Messages: ROS data type used when subscribing or publishing to a topic.
 +Topics: Nodes can publish messages to a topic as well as subscribe to a topic to receive messages.
 +Master: Name service for ROS (i.e. helps nodes find each other)
 +rosout: ROS equivalent of stdout/​stderr
 +roscore: Master + rosout + parameter server (parameter server will be introduced later)
 + 
 +Use the rosnode command to get information about currently running nodes.
 +===== Package Structure =====
 +
 +The following is the simplest structure of a ROS package:
 +
 +<​code>​
 +my_package/
 +    CMakeLists.txt
 +    package.xml
 +</​code>​
 +
 +The manifest is a file called ''​%%package.xml%%''​ and is a description of the package.
 +
 +A package in a catkin workspace looks like this:
 +
 +<​code>​
 +workspace_folder/ ​       -- WORKSPACE
 +  src/                   -- SOURCE SPACE
 +    CMakeLists.txt ​      -- '​Toplevel'​ CMake file, provided by catkin
 +    package_1/
 +      CMakeLists.txt ​    -- CMakeLists.txt file for package_1
 +      package.xml ​       -- Package manifest for package_1
 +    ...
 +    package_n/
 +      CMakeLists.txt ​    -- CMakeLists.txt file for package_n
 +      package.xml ​       -- Package manifest for package_n
 +</​code>​
 +
 +===== ROS Services =====
 +
 +Services are another way nodes can communicate with each other. Services allow nodes
 +to send a request and receive a response.
 +
 +You can look up the type of a service. Then using ''​%%rossrv%%''​ you can get more information
 +on the that service. For example:
 +
 +<code bash>
 +rosservice type /spawn | rossrv show
 +</​code>​
 +
 +There is also such a thing as the ROS parameter server. It stores data. 
 +
 +You can look at all this data by using the ''​%%rosparam%%''​ command. You can
 +list the parameters, set them and even save and load them.
 +
 +Service files (srv) are just like msg files, except they contain two parts: a 
 +request and a response. The two parts are separated by a '​---'​ line. Here is an 
 +example of a srv file:
 +
 +<code bash>
 +int64 A
 +int64 B
 +---
 +int64 Sum
 +</​code>​
 +
 +==== Adding a ROS Service ====
 +Here are the steps to add a ROS service to a package. These are similar to adding a
 +message.
 +
 +  * Add a ''​%%.srv%%''​ file to the ''​%%srv/​%%''​ directory of a package
 +  * Make sure ''​%%message_generation%%''​ and ''​%%message_runtime%%''​ build and runtime dependencies are enabled in the ''​%%package.xml%%''​ file.
 +  * Add message_generation to the find_package() function
 +  * Make sure the service is added to the add_service_files() function
 +
 +When this is done, running ''​%%catkin_make install%%''​ will build all the necessary stuff and also generate the header files required.
 +
 +==== Building a ROS Service/​Client ====
 +
 +A service/​client is another form of communication in ROS. Instead of relying on
 +publisher/​subscriber messages, which are asynchronous,​ you have a synchronous service
 +based communication. A client calls a service and waits for a response.
 +
 +  - First define the service you will use in the package. See [[ros#​adding_a_ros_service|Adding a ROS service]].
 +  - Write a server node in the ''​%%srv/​%%''​ folder
 +    - Server node includes the generated header for the service
 +    - Server node has a function that returns a boolean and takes in the request and the response of the service.
 +    - Server node has a main function that:
 +      - calls ''​%%ros::​init%%''​
 +      - has a''​%%ros::​NodeHandle%%'' ​
 +      - advertises the service using ''​%%ros::​ServiceServer%%''​
 +      - ''​%%ros::​spin();​%%''​
 +  - Write a client node in the ''​%%src/​%%''​ folder
 +    - Has a main
 +    - ''​%%ros::​init()%%''​
 +    - ''​%%ros::​NodeHandle%%''​
 +    - ''​%%ros::​ServiceClient%%''​
 +    - calls ''​%%client.call(srv)%%''​ which acts as calling the service and gets returned with a response. Pretty neat.
 +  - Add the executables in the ''​%%CMakeLists.txt%%''​ files
 +
 +===== Compiling Node With Multiple Source Files =====
 +
 +<code c++>
 +## Declare a cpp executable
 +add_executable(executable_one src/​source_one.cpp src/​source_two.cpp src/​source_n.cpp) </​code>​
 +
 +To create multiple executables,​ you just add multiple instances of that line:
 +<code c++>
 +## Declare a cpp executable ​
 +add_executable(executable_one src/​source_one.cpp src/​source_two.cpp src/​source_n.cpp) ​
 +add_executable(executable_two src/​source_one.cpp src/​source_two.cpp src/​source_n.cpp) ​
 +add_executable(executable_three src/​source_one.cpp src/​source_two.cpp src/​source_n.cpp)
 +</​code>​
 +
 +===== tf =====
 +
 +tf keeps track of all these frames over time, and allows you to ask questions like:
 +
 +  * Where was the head frame relative to the world frame, 5 seconds ago?
 +  * What is the pose of the object in my gripper relative to my base?
 +  * What is the current pose of the base frame in the map frame?
 +  * A ROS transform contains a pose (x,y,z) and a quaternion rotation (w, r, p, y)
 +
 +Transform is a deprecated package with tf2 being the new one. 
 +
 +I did the tutorials where I created a broadcaster and a listener in c++. I also did
 +some stuff where you can compute the transform between two frames and convert it to a
 +velocity command to a robot.
 +
 +There are two things that you need to do to use tf. You have to listen and broadcast
 +them.
 +  * Listen - Receive and buffer all coordinate frames that are broadcaster in the system, and query for specific transforms between frames
 +  * Broadcast - Send out the relative prose of coordinate frames to the rest of the system
 +
 +There is a REP that outlines lots of good best practice stuff when defining your robot [[http://​www.ros.org/​reps/​rep-0105.html|link]].
 +
 +==== Quaternions ====
 +For learning about quaternions check out the
 +[[http://​www.ogre3d.org/​tikiwiki/​Quaternion+and+Rotation+Primer#​Prerequisites|OGRE
 +Quaternions intro]].
 +
 +For conversions use this calculator [[http://​www.energid.com/​resources/​orientation-calculator/​|link]].
 +
 +==== Transform Debugging ====
 +
 +You can use ''​%%rosrun tf2_tools view_frames.py%%''​ to show you information about the frames.
 +
 +You can use ''​%%rosrun tf tf_monitor frame1 frame2%%''​ to show you timing info.
 + 
 + 
 +==== tf::​MessageFilter ====
 +
 +''​%%tf::​MessageFilter%%''​ is a function that allows us to process stamped datatypes.
 +
 +turtle1 wants to know its position relative to itself
 +  * listen to the topic where turtle3'​s pose is being published
 +  * wait until transforms into the desired frame are ready
 +  * do its operations
 +
 +==== tf::​TransformListener ====
 +
 +Convenient class that allows to do the following:
 +
 +  * Create a listener for frames ​
 +  * Handle transforms such as points from one frame to another
 +
 +==== robot_state_publisher ====
 +
 +The robot state publisher helps you to broadcast the state of your robot to the tf
 +transform library.
 +
 +It needs two things to run:
 +  * The URDF file
 +  * A source that publishes the joint positions as a ''​%%sensor_msgs/​JointState%%'' ​
 +
 +It subscribes to joint_states topic for joint position information.
 +
 +It uses the following parameters
 +  * robot_description(URDF map)
 +  * tf_prefix(string)
 +  * publish_frequency(double)
 +
 +===== ROS Topic =====
 +
 +The ''​%%rostopic%%''​ command lets you monitor all aspects of a ROS topic.
 +
 +You can also use ''​%%rostopic%%''​ to publish data of any message into a ROS topic.
 +
 +  * ''​%%rostopic hz <​topic>​%%''​ : look at how often a message is being sent
 +  * ''​%%rostopic pub <​topic>​ <​data>​%%''​ : publish data to the topic
 +
 +When using ''​%%rostopic pub%%'',​ make sure you do not have a ''​%%/​%%''​ before the message name or
 +else autocomplete won't work!!!
 +
 +===== ROS Record =====
 +
 +Recording and playing back data is really nice and easy with ROS. 
 +
 +To record everything you run:
 +<code bash>
 +    rosbag record -a
 +</​code>​
 +
 +To play back a bag file you run:
 +<code bash>
 +    rosbag play <your bag file>
 +</​code>​
 +
 +===== URDF =====
 +
 +URDF is an XML file that stands for Unified Robot Description Format.
 +
 +Unfortunately the tutorials do not give you a step by step guide on how to make a
 +URDF. Instead they just explain a sample URDF tutorial project, which leaves me
 +guessing as to how integrate a URDF in an existing package.
 +
 +There is a Solidworks to URDF exporter but is old and does not work very well.
 +Do not use it! You are much better off learning how to code your own URDF files.
 +
 +In a URDF there is a tree structure with one root link. The way you organize these
 +links is with joints. You declare the links and then specify joints between them. If
 +you have two links with no joint specified, RViz will give you an error.
 +
 +If there are any joints in a mesh, you need to run the joint_state_publisher and also
 +the robot_state_publisher. That means in your launch file you will have the
 +following:
 +
 +<code xml>
 +<node name="​joint_state_publisher"​ pkg="​joint_state_publisher"​ type="​joint_state_publisher"​ />
 +<node name="​robot_state_publisher"​ pkg="​robot_state_publisher"​ type="​state_publisher"​ />
 +</​code>​
 +
 +You specify meshes in a URDF with the following:
 +<code xml><​mesh filename="​package://​NAME_OF_PACKAGE/​path"/>​
 +</​code>​
 +
 +You can use the command ''​%%check_urdf%%''​ to text the URDF file. [[#​URDF_basic]]
 +
 +For URDF files to work in gazebo they need to have the following:
 +  * A header robot tag with an optional xml namespace. Essentially,​ the following:
 +<code xml> ​
 +<robot name="​rrbot"​ xmlns:​xacro="​http://​www.ros.org/​wiki/​xacro"> ​
 +</​code>​
 +  * ''​%%<​intertia>​%%''​ element within each ''​%%<​link>​%%''​ element.
 +
 +==== Positioning ====
 +
 +The link tab has an origin tag with rpy and xyz params. These only change the origin
 +of the object. They do not change the position. To change the position you set up a
 +joint.
 +
 +:​URDF_basic:​ http://​wiki.ros.org/​urdf/​Tutorials/​Create%20your%20own%20urdf%20file
 +:​Gazebo_tut:​ http://​gazebosim.org/​tutorials/?​tut=ros_urdf#​Simplifycollisionmodel
 +
 +==== Xacro ====
 +
 +Xacro is a URDF macro scripting language that gives you functionality to create more
 +powerful and dynamically generated URDF code. It is a bit tricky to learn but it
 +is very helpful. ​
 +
 +The way it works is that you make a xacro file and then have the URDF get automatically generated.
 +
 +You need these two lines at the top of a xacro file.
 +<code xml>
 +<?xml version="​1.0"?>​
 +<robot xmlns:​xacro="​http://​www.ros.org/​wiki/​xacro"​ name="​firefighter">​
 +</​code>​
 +
 +[[http://​wiki.ros.org/​urdf/​Tutorials/​Using%20Xacro%20to%20Clean%20Up%20a%20URDF%20File#​CA-2595ee4c24086af97e963b00f75b8e9ddf9082b7_2|Here is a link to the best tutorial]]
  
  • ros.txt
  • Last modified: 2019/03/31 14:49
  • (external edit)