# 2021 培訓 ROS教學
###### tags: `教學`
## ROS簡介

* Source setup.bash
## 依檔案結構
### Workspace
http://wiki.ros.org/ROS/Tutorials/InstallingandConfiguringROSEnvironment#Create_a_ROS_Workspace
**1. 創建Workspace:**
`mkdir -p catkin_ws/src`
`cd catkin_ws/`
`catkin_make`
:::success
記得Source!!(最好加入.bashrc中)
:::
**2. Workspace 內容物:**
```
workspace_folder/ -- WORKSPACE
build/
devel/
src/ -- SOURCE SPACE
```
### Package
http://wiki.ros.org/ROS/Tutorials/CreatingPackage
http://wiki.ros.org/ROS/Tutorials/BuildingPackages
**1. 創建 Package**
`catkin_create_pkg test_pkg std_msgs rospy roscpp`
`cd "workspace_folder"`
`catkin_make`
**2. Workspace/src 放置Package**
```
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
```
**3. Package 內容物**
```
my_package/
CMakeLists.txt
package.xml
src/
(launch/)
(msg/)
...
```
**4. package.xml**
```
<?xml version="1.0"?>
<package format="2">
<name>test_pkg</name>
<version>0.1.0</version>
<description>The test_pkg package</description>
<maintainer email="you@yourdomain.tld">Your Name</maintainer>
<license>BSD</license>
<url type="website">http://yourwebsite</url>
<author email="you@yourdomain.tld">Jane Doe</author>
<buildtool_depend>catkin</buildtool_depend>
<build_depend>roscpp</build_depend>
<build_depend>rospy</build_depend>
<build_depend>std_msgs</build_depend>
<exec_depend>roscpp</exec_depend>
<exec_depend>rospy</exec_depend>
<exec_depend>std_msgs</exec_depend>
</package>
```
**5. CMakeLists.txt**
## 依程式結構
### Node
http://wiki.ros.org/ROS/Tutorials/UnderstandingNodes

**1. 執行ROS的第一件事:** `roscore`
應該看到以下訊息:
```
... logging to ~/.ros/log/9cf88ce4-b14d-11df-8a75-00251148e8cf/roslaunch-machine_name-13039.log
Checking log directory for disk usage. This may take awhile.
Press Ctrl-C to interrupt
Done checking log file disk usage. Usage is <1GB.
started roslaunch server http://machine_name:33919/
ros_comm version 1.4.7
SUMMARY
======
PARAMETERS
* /rosversion
* /rosdistro
NODES
auto-starting new master
process[master]: started with pid [13054]
ROS_MASTER_URI=http://machine_name:11311/
setting /run_id to 9cf88ce4-b14d-11df-8a75-00251148e8cf
process[rosout-1]: started with pid [13067]
started core service [/rosout]
```
**2. rosnode**
`rosnode list`
`rosnode info`
`rosnode ping [node_name]`
**3. 執行node**
`rosrun [package_name] [node_name]`
### Topic
http://wiki.ros.org/ROS/Tutorials/UnderstandingTopics
1. **rostopic**
1. `rostopic list`
2. `rostopic echo`
3. `rostopic type`
4. `rostopic pub`
2. **rqt_graph**

### Message
http://wiki.ros.org/ROS/Tutorials/CreatingMsgAndSrv
1. 各個 message type: http://wiki.ros.org/std_msgs
2. `rosmsg show [message type]`
## RIVZ
* 啟動rivz: `rviz`

## Roslaunch
http://wiki.ros.org/ROS/Tutorials/UsingRqtconsoleRoslaunch
## Publisher & Subscriber
### Python
http://wiki.ros.org/ROS/Tutorials/WritingPublisherSubscriber%28python%29
#### Publisher:
```python
#!/usr/bin/env python
import rospy
from std_msgs.msg import String
def talker():
pub = rospy.Publisher('chatter', String, queue_size=10)
rospy.init_node('talker', anonymous=True)
rate = rospy.Rate(10) # 10hz
while not rospy.is_shutdown():
hello_str = "hello world %s" % rospy.get_time()
pub.publish(hello_str)
rate.sleep()
if __name__ == '__main__':
try:
talker()
except rospy.ROSInterruptException:
pass
```
#### Subscriber:
```python
#!/usr/bin/env python
import rospy
from std_msgs.msg import String
def callback(msg):
rospy.loginfo(msg.data)
def listener():
rospy.init_node('listener', anonymous=True)
rospy.Subscriber('chatter', String, callback)
rospy.spin()
if __name__ == '__main__':
listener()
```
#### 又接又丟的Node
```python=
#!/usr/bin/env python3
import rospy
from std_msgs.msg import Int64, String
class Auv(object):
def __init__(self):
self.pub = rospy.Publisher('Result', String, queue_size = 10)
def odd_or_even(self, value):
if (value.data % 2) == 0:
result = 'Even'
self.pub.publish(result)
else:
result = 'Odd'
self.pub.publish(result)
def listener():
rospy.init_node('test_sub', anonymous=True)
auv = Auv()
rospy.Subscriber('test', Int64, auv.odd_or_even)
rospy.spin()
if __name__=='__main__':
listener()
```
### C++
http://wiki.ros.org/ROS/Tutorials/WritingPublisherSubscriber%28c%2B%2B%29
#### Publisher:
```cpp=
#include "ros/ros.h"
#include "std_msgs/Int64.h"
int main(int argc, char **argv)
{
int x = 9;
std_msgs::Int64 x_topic;
ros::init(argc, argv, "cpp_pub_test");
ros::NodeHandle node;
ros::Publisher pub = node.advertise<std_msgs::Int64>("cpp_test", 1000);
ros::Rate r(1);
while (ros::ok())
{
x = (x + 1) % 5;
x_topic.data = x;
pub.publish(x_topic);
ros::spinOnce();
r.sleep();
}
return 0;
}
```
#### Subscriber:
```cpp=
#include "ros/ros.h"
#include "std_msgs/Int64.h"
void odd_or_even(const std_msgs::Int64::ConstPtr& n_topic)
{
if (n_topic->data % 2)
ROS_INFO("%s", "Odd");
else if (!(n_topic->data % 2))
ROS_INFO("%s", "Even");
}
int main(int argc, char **argv)
{
ros::init(argc, argv, "cpp_sub_test");
ros::NodeHandle node;
ros::Subscriber sub = node.subscribe("cpp_test", 1000, odd_or_even);
ros::spin();
return 0;
}
```
#### How to Build
To build the package (and the cpp node), follow the steps below:
1. **Add "genmsg" into `find_package`**
2. **Uncomment all part in `generate_messages`**
3. **Uncomment (or write it yourself) `add_executable(*nodename* *src/scriptfilename(.cpp file)*)`**
4. **Uncomment (or write it yourself) `target_link_libraries(*nodename* ${catkin_LIBRARIES})`**
5. **Do step 3&4 for each cpp file**
6. **`catkin_make`**
<br>
**CMakeLists.txt in the package:**
```cmake=
cmake_minimum_required(VERSION 3.0.2)
project(cpp_test)
find_package(catkin REQUIRED COMPONENTS
roscpp
rospy
std_msgs
genmsg
)
generate_messages(
DEPENDENCIES
std_msgs
)
catkin_package()
include_directories(include ${catkin_INCLUDE_DIRS})
add_executable(${PROJECT_NAME}_pub src/pub.cpp)
target_link_libraries(${PROJECT_NAME}_pub ${catkin_LIBRARIES})
add_executable(${PROJECT_NAME}_sub src/sub.cpp)
target_link_libraries(${PROJECT_NAME}_sub ${catkin_LIBRARIES})
```