├── Ch1 ROS Node & Topic ├── README.md ├── ROS_Node_Concept.png ├── ROS_Node_Description.png ├── ROS_Topic_Concept.png ├── ROS_Topic_Concept2.png └── ROS_Topic_Description.png ├── Ch2 ROS Service ├── Python_Service_Example.png ├── Python_Service_Example2.png ├── Python_Service_Example3.png ├── README.md ├── ROS_Service_Client.png ├── ROS_Service_Command.png ├── ROS_Service_Concept.png ├── ROS_Service_Concept2.png ├── ROS_Service_Concept3.png ├── ROS_Service_Server.png ├── Service_Call_Example.png ├── Service_Call_Example2.png └── Service_Msg_Type.png ├── Ch3 ROS Custom Message ├── README.md ├── ROS_Message1.png ├── ROS_Message2.png ├── ROS_Message3.png ├── ROS_Message_Concept.PNG └── ROS_Message_Concept2.PNG ├── Ch4 ROS Params & Launch Files ├── README.md ├── ROS_Launch_file_concept.PNG ├── ROS_Parameters.PNG ├── ROS_Parameters2.PNG └── ROS_Parameters_concept.PNG ├── Ch5 ROS Bag & OOP └── README.md ├── Ch6 ROS Gazebo ├── Ch1 Launch Your First Gazebo World Using ROS │ └── README.md ├── Ch10 Launch RViz using a configuration file │ └── README.md ├── Ch11 Use joint_state_publisher │ └── README.md ├── Ch12 Create custom gazebo model using heightmap │ └── README.md ├── Ch2 Add gazebo models to a simulation │ └── README.md ├── Ch3 Spawn a robot in gazebo │ └── README.md ├── Ch4 Create a gazebo model using SDF │ └── README.md ├── Ch5 Use a mesh file to create a gazebo model │ ├── README.md │ ├── cordless_drill.stl │ └── robot_car.stl ├── Ch6 Use an image file as texture for gazebo model │ ├── README.md │ └── seamless_texture.png ├── Ch7 Create a robot using URDF │ └── README.md ├── Ch8 Visualize a robot URDF using RVIZ │ └── README.md └── Ch9 Create a robot using URDF(Advance & RVIZ) │ └── README.md ├── Ch7 ROS Virtual RobotX ├── Ch01_Adding_Course_Elements.md ├── Ch02_Custom_WAM-V_Thruster_Sensor_Configuration.md ├── Ch03_Propulsion_Configurations.md ├── Ch04_Adding_Sensors.md ├── Ch05_Thruster_Articulation.md ├── Ch06_Driving.md ├── Ch07_Visualizing_with_RViz.md ├── Ch08_Plugin_Parameters.md ├── Ch09_Custom_Dock.md └── figure │ ├── driving_debug_before.png │ └── keyboard_debug_after.png ├── README.md └── src ├── my_robot_bringup ├── CMakeLists.txt ├── launch │ └── number_app.launch └── package.xml ├── my_robot_msgs ├── CMakeLists.txt ├── msg │ └── HardwareStatus.msg ├── package.xml └── srv │ ├── ComputeDiskArea.srv │ └── SetLed.srv └── my_robot_tutorials ├── CMakeLists.txt ├── package.xml ├── scripts ├── add_two_ints_client.py ├── add_two_ints_server.py ├── battery.py ├── hw_status_publisher.py ├── led_panel.py ├── my_first_node.py ├── number_counter.py ├── number_publisher.py ├── oop_number_counter.py ├── robot_news_radio_transmitter.py └── smartphone.py └── src ├── add_two_ints_client.cpp ├── add_two_ints_server.cpp ├── my_first_node.cpp ├── number_counter.cpp ├── number_publisher.cpp ├── oop_number_counter.cpp ├── robot_news_radio_transmitter.cpp └── smartphone_node.cpp /Ch1 ROS Node & Topic/README.md: -------------------------------------------------------------------------------- 1 | # Chapter **1.** ROS Node and Topic 2 | 3 | ## Install ROS and Setup Your Environment 4 | 5 | * [__Installation (ROS Melodic)__][0] 6 | 7 | [0]: http://wiki.ros.org/melodic/Installation/Ubuntu 8 | 9 | * __Update packages :__ 10 | ```console 11 | [alonzo@study ~]$ sudo apt-get update 12 | [alonzo@study ~]$ sudo apt-get install ros-melodic-packagename 13 | ``` 14 | 15 | ## ROS package 16 | 1. Create a workspace 17 | ```console 18 | [alonzo@study ~]$ mkdir ~/catkin_ws 19 | [alonzo@study ~]$ mkdir ~/catkin_ws/src 20 | [alonzo@study ~]$ cd ~/catkin_ws 21 | [alonzo@study ~]$ catkin_make 22 | [alonzo@study ~]$ vim ~/.bashrc 23 | # > Add: source ~/catkin_ws/devel/setup.bash (For exe files based on developer's workspace) 24 | # Note : source /opt/ros/melodic/setup.bash (For ros global application such as catkin_make, roscore) 25 | [alonzo@study ~]$ source ~/.bashrc 26 | ``` 27 | 2. Create packages 28 | ```console 29 | [alonzo@study ~/catkin_ws/src]$ catkin_create_pkg {name of package} {dependencies} 30 | [alonzo@study ~/catkin_ws/src]$ catkin_create_pkg my_robot_tutorials roscpp rospy std_msgs 31 | [alonzo@study ~/catkin_ws/src]$ ls ./my_robot_tutorials 32 | # > CMakeLists.txt include/ package.xml src/ 33 | [alonzo@study ~/catkin_ws/src]$ cd ~/catkin_ws 34 | [alonzo@study ~/catkin_ws]$ catkin_make 35 | ``` 36 | 37 | ## ROS Node 38 | 39 |
40 | 41 |

42 |

43 | 44 |
45 | 46 | * __Python Node:__ 47 | 1. Create python node 48 | ```console 49 | [alonzo@study ~/catkin_ws/src/package_name]$ mkdir scripts 50 | [alonzo@study ~/catkin_ws/src/package_name/scripts]$ touch my_first_node.py 51 | [alonzo@study ~/catkin_ws/src/package_name/scripts]$ chmod a+x my_first_node.py 52 | [alonzo@study ~/catkin_ws/src/package_name/scripts]$ vim my_first_node.py 53 | ``` 54 | 2. Edit python node 55 | ```python 56 | #! /usr/bin/env python 57 | 58 | import rospy 59 | 60 | if __name__ == '__main__': 61 | 62 | rospy.init_node('my_first_python_node') # input your node's name 63 | 64 | rospy.loginfo("This node has been started") # log features for ros 65 | 66 | rate = rospy.Rate(10) # 10 Hz 67 | 68 | while not rospy.is_shutdown(): 69 | rospy.loginfo("Hello") 70 | rate.sleep() 71 | 72 | rospy.loginfo("Exit now") 73 | ``` 74 | 3. Run python node 75 | ```console 76 | [alonzo@study ~/catkin_ws/src/package_name/scripts]$ roscore # Run roscore anywhere 77 | [alonzo@study ~/catkin_ws/src/package_name/scripts]$ python my_first_node.py 78 | Note : rosrun package_name my_first_node.py 79 | ``` 80 | 81 | * __C++ Node:__ 82 | 1. Create C++ node 83 | ```cpp 84 | [alonzo@study ~/catkin_ws/src/package_name/src]$ touch my_first_cpp_node.cpp 85 | [alonzo@study ~/catkin_ws/src/package_name/src]$ vim CMakeList.txt 86 | # > Add: 87 | # > add_executable({exe_name} src/my_first_cpp_node.cpp) 88 | # > target_link_libraries({exe_name} ${catkin_LIBRARIES}) 89 | [alonzo@study ~/catkin_ws]$ catkin_make 90 | ``` 91 | 2. Edit C++ node 92 | ```cpp 93 | #include 94 | 95 | int main(int argc, char** argv){ 96 | 97 | ros::init(argc, argv, "my_first_cpp_node"); // Can't be the same with other nodes 98 | ros::NodeHandle nh; // Start the node 99 | ROS_INFO("Node has been started"); 100 | //ros::Duration(1.0).sleep(); 101 | ros::Rate rate(10); 102 | while (ros::ok()){ 103 | ROS_INFO("Hello"); 104 | rate.sleep(); 105 | } 106 | ROS_INFO("Exit"); 107 | } 108 | ``` 109 | 3. Run C++ node 110 | ```console 111 | [alonzo@study ~/catkin_ws]$ catkin_make 112 | [alonzo@study ~/catkin_ws/devel/lib/package_name]$ ./{exe_name} # Same as exe_name in pkg CMakeLists 113 | Note : rosrun package_name {exe_name} 114 | ``` 115 | 116 | ## ROS Topic 117 | 118 |
119 | 120 |

121 |

122 | 123 |
124 | 125 | * __Python Publisher/Subscriber:__ 126 | * Publisher node: 127 | ```python 128 | #!/usr/bin/env python 129 | 130 | import rospy 131 | from std_msgs.msg import String 132 | 133 | if __name__ == '__main__': 134 | 135 | rospy.init_node('robot_news_radio_transmitter', anonymous = True) # Anonymous: If nodes have the same name, anonymous makes it possible to run both 136 | 137 | pub = rospy.Publisher("/robot_news_radio", String, queue_size=10) #Add buffer for subscriber in case they don't have time to process message 138 | 139 | rate = rospy.Rate(2) #two msg per second 140 | 141 | while not rospy.is_shutdown(): 142 | msg = String() #Create an object from String class, in String class there is a private member called data 143 | msg.data = "Hi this is Dan fron the Robot News Radio !" 144 | pub.publish(msg) 145 | rate.sleep() 146 | 147 | rospy.loginfo("Node wass stopped") 148 | ``` 149 | * Subscriber node: 150 | ```python 151 | #!/usr/bin/env python 152 | 153 | import rospy 154 | from std_msgs.msg import String 155 | 156 | def callback_recieve_radio_data(msg): 157 | rospy.loginfo("Message recieved : ") 158 | rospy.loginfo(msg) 159 | 160 | if __name__ == '__main__': 161 | 162 | rospy.init_node('smartphone') 163 | 164 | sub = rospy.Subscriber("/robot_news_radio", String, callback_recieve_radio_data) 165 | 166 | rospy.spin() # Keep running callbcak function 167 | ``` 168 | 169 | 170 | * __C++ Publisher/Subscriber:__ 171 | * Publisher node: 172 | ```cpp 173 | #include 174 | #include 175 | int main(int argc, char** argv){ 176 | 177 | ros::init(argc, argv, "robot_news_radio_transmitter", ros::init_options::AnonymousName); // Can't be the same with other node 178 | ros::NodeHandle nh; // To start the node 179 | 180 | ros::Publisher pub = nh.advertise("/robot_news_radio", 10); // (topic name, qeue size) 181 | ros::Rate rate(3); 182 | 183 | while (ros::ok()){ 184 | std_msgs::String msg; 185 | msg.data = "Hi this is logan from the robot news radio"; 186 | pub.publish(msg); 187 | rate.sleep(); 188 | } 189 | } 190 | ``` 191 | * Subscriber node: 192 | ```cpp 193 | #include 194 | #include 195 | 196 | void callback_recieve_radio_data(const std_msgs::String& msg) 197 | { 198 | ROS_INFO("Message recieved : %s", msg.data.c_str()); 199 | } 200 | 201 | int main(int argc, char** argv){ 202 | 203 | ros::init(argc, argv, "smartphone"); // Can't be the same with other node 204 | ros::NodeHandle nh; // To start the node 205 | 206 | ros::Subscriber sub = nh.subscribe("/robot_news_radio", 1000, callback_recieve_radio_data); //(topic name, qeue size, function) 207 | 208 | ros::spin(); 209 | } 210 | ``` 211 | -------------------------------------------------------------------------------- /Ch1 ROS Node & Topic/ROS_Node_Concept.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alonzo3569/ROS_Tutorial/595a93c0e960bfc832290e1c52995170cb525948/Ch1 ROS Node & Topic/ROS_Node_Concept.png -------------------------------------------------------------------------------- /Ch1 ROS Node & Topic/ROS_Node_Description.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alonzo3569/ROS_Tutorial/595a93c0e960bfc832290e1c52995170cb525948/Ch1 ROS Node & Topic/ROS_Node_Description.png -------------------------------------------------------------------------------- /Ch1 ROS Node & Topic/ROS_Topic_Concept.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alonzo3569/ROS_Tutorial/595a93c0e960bfc832290e1c52995170cb525948/Ch1 ROS Node & Topic/ROS_Topic_Concept.png -------------------------------------------------------------------------------- /Ch1 ROS Node & Topic/ROS_Topic_Concept2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alonzo3569/ROS_Tutorial/595a93c0e960bfc832290e1c52995170cb525948/Ch1 ROS Node & Topic/ROS_Topic_Concept2.png -------------------------------------------------------------------------------- /Ch1 ROS Node & Topic/ROS_Topic_Description.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alonzo3569/ROS_Tutorial/595a93c0e960bfc832290e1c52995170cb525948/Ch1 ROS Node & Topic/ROS_Topic_Description.png -------------------------------------------------------------------------------- /Ch2 ROS Service/Python_Service_Example.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alonzo3569/ROS_Tutorial/595a93c0e960bfc832290e1c52995170cb525948/Ch2 ROS Service/Python_Service_Example.png -------------------------------------------------------------------------------- /Ch2 ROS Service/Python_Service_Example2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alonzo3569/ROS_Tutorial/595a93c0e960bfc832290e1c52995170cb525948/Ch2 ROS Service/Python_Service_Example2.png -------------------------------------------------------------------------------- /Ch2 ROS Service/Python_Service_Example3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alonzo3569/ROS_Tutorial/595a93c0e960bfc832290e1c52995170cb525948/Ch2 ROS Service/Python_Service_Example3.png -------------------------------------------------------------------------------- /Ch2 ROS Service/README.md: -------------------------------------------------------------------------------- 1 | # Chapter **2.** ROS Service 2 | 3 | ## ROS Service 4 | 5 |
6 | 7 |

8 |

9 |

10 | 11 |
12 | 13 | * __Service message (Request/Response) :__ 14 | 15 |
16 | 17 |

18 | 19 |
20 | 21 | * __Python Server/Client :__ 22 | * Python Server 23 | ```python 24 | #!/usr/bin/env python 25 | 26 | import rospy 27 | from rospy_tutorials.srv import AddTwoInts 28 | 29 | def handle_add_two_ints(req): 30 | result = req.a + req.b 31 | rospy.loginfo("Sum of " + str(req.a) + " and " + str(req.b) + " is " + str(result)) 32 | return result 33 | 34 | if __name__ == '__main__': 35 | 36 | rospy.init_node('robot_news_radio_transmitter') 37 | rospy.loginfo("Add two ints server node created") 38 | 39 | service = rospy.Service("/add_two_ints", AddTwoInts, handle_add_two_ints) # name of the service, usually start with verb 40 | # wait for client AddTwoInts class object (int a, int b), in this code, it's req 41 | rospy.loginfo("Serrvice server has been started") 42 | 43 | rospy.spin() 44 | ``` 45 | 46 |
47 | 48 |

49 | Fig. Use rosservice call to poke msg to service "/add_two_ints"

50 |

51 | Fig. Service "/add_two_ints" response to incoming msg

52 | 53 |
54 | 55 | * Python Client 56 | ```python 57 | #!/usr/bin/env python 58 | 59 | import rospy 60 | from rospy_tutorials.srv import AddTwoInts 61 | 62 | if __name__ == '__main__': 63 | 64 | rospy.init_node('add_two_ints_client') 65 | rospy.wait_for_service("/add_two_ints") # Wait for service is setup 66 | 67 | try: # If service is not ready, catch exception 68 | add_two_ints = rospy.ServiceProxy("/add_two_ints", AddTwoInts) # Create client and give the type of client 69 | response = add_two_ints(2,6) # Call client, get AddTwoInts class object(int sum) from server and assign to response 70 | rospy.loginfo("Sum is: " + str(response.sum)) 71 | except rospy.ServiceException as e: 72 | #rospy.logwarn("Service failed: ", str(e)) 73 | rospy.loginfo(str(e)) 74 | ``` 75 | 76 |
77 | 78 |

79 | Fig. Run server and activate "/add_two_ints" service

80 | 81 |

82 | Fig. Run client

83 | 84 |
85 | 86 | * __C++ Server/Client :__ 87 | * C++ Server 88 | 1. Add library for service message (Remember to add executale and target link as well) 89 | ```console 90 | # pkg/src/CMakeLists.txt 91 | find_package(catkin REQUIRED COMPONENTS 92 | roscpp 93 | rospy 94 | std_msgs 95 | rospy_tutorials <= library for service msg 96 | ) 97 | 98 | # pkg/src/package.xml 99 | rospy_tutorials 100 | rospy_tutorials 101 | ``` 102 | 2. Edit C++ server 103 | ```cpp 104 | #include 105 | #include 106 | 107 | bool handle_add_two_ints(rospy_tutorials::AddTwoInts::Request &req, 108 | rospy_tutorials::AddTwoInts::Response &res) 109 | { 110 | int result = req.a + req.b; 111 | ROS_INFO("%d + %d = %d", (int)req.a, (int)req.b, (int)result); 112 | res.sum = result; 113 | return true; 114 | } 115 | 116 | int main(int argc, char** argv){ 117 | 118 | ros::init(argc, argv, "add_two_ints_server"); // Can't be the same with other node 119 | ros::NodeHandle nh; //To start the node 120 | 121 | ros::ServiceServer server = nh.advertiseService("/add_two_ints", handle_add_two_ints); // Service name & callback 122 | 123 | ros::spin(); 124 | 125 | } 126 | ``` 127 | * C++ Client 128 | ```cpp 129 | #include 130 | #include 131 | 132 | int main(int argc, char** argv){ 133 | 134 | ros::init(argc, argv, "add_two_ints_client"); // Can't be the same with other node 135 | ros::NodeHandle nh; // Start the node 136 | 137 | ros::ServiceClient client = nh.serviceClient("/add_two_ints"); 138 | 139 | rospy_tutorials::AddTwoInts srv; 140 | 141 | srv.request.a = 12; 142 | srv.request.b = 5; 143 | 144 | if(client.call(srv)){ // If server return true 145 | //process data 146 | ROS_INFO("Returned sum is %d", (int)srv.response.sum); 147 | } 148 | else{ 149 | ROS_WARN("Service call failed"); 150 | } 151 | 152 | ros::spin(); 153 | 154 | } 155 | ``` 156 | 157 | * __ROS Service command :__ 158 | 159 |
160 | 161 |

162 | 163 |
164 | 165 | 166 | * __Python example(Publisher/Subscriber/Service) :__ 167 | ```python 168 | #!/usr/bin/env python 169 | 170 | import rospy 171 | from std_msgs.msg import Int64 172 | from std_srvs.srv import SetBool # sudo apt-get install ros-melodic-std-srvs 173 | 174 | counter = 0 175 | pub = None 176 | 177 | # Function for subscriber 178 | def callback(num): 179 | rospy.loginfo(num) 180 | global counter 181 | counter += num.data 182 | pub.publish(counter) 183 | rospy.loginfo(counter) 184 | 185 | # Service function 186 | def handle_message(msg): 187 | #rospy.loginfo(msg.response.success) # error: input message doesn't include Response(success,message) 188 | #rospy.loginfo(msg.response.message) 189 | if (msg.data): 190 | global counter 191 | counter = 0 192 | return True,"Counter reset success" 193 | else: 194 | return False,"Counter has not been reset" 195 | 196 | if __name__ == '__main__': 197 | 198 | rospy.init_node('number_counter') 199 | 200 | sub = rospy.Subscriber("/number", Int64, callback) 201 | 202 | pub = rospy.Publisher("/number_count", Int64, queue_size=10) 203 | 204 | service = rospy.Service("/reset_number_count", SetBool, handle_message) # name of the service, usually start with verb 205 | 206 | rospy.spin() #Keep running callbcak function 207 | ``` 208 | * __Python example service message type :__ 209 | 210 |
211 | 212 |

213 | 214 |
215 | 216 | * __Python example output :__ 217 | 218 |
219 | 220 |

221 |

222 | 223 |
224 | 225 | -------------------------------------------------------------------------------- /Ch2 ROS Service/ROS_Service_Client.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alonzo3569/ROS_Tutorial/595a93c0e960bfc832290e1c52995170cb525948/Ch2 ROS Service/ROS_Service_Client.png -------------------------------------------------------------------------------- /Ch2 ROS Service/ROS_Service_Command.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alonzo3569/ROS_Tutorial/595a93c0e960bfc832290e1c52995170cb525948/Ch2 ROS Service/ROS_Service_Command.png -------------------------------------------------------------------------------- /Ch2 ROS Service/ROS_Service_Concept.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alonzo3569/ROS_Tutorial/595a93c0e960bfc832290e1c52995170cb525948/Ch2 ROS Service/ROS_Service_Concept.png -------------------------------------------------------------------------------- /Ch2 ROS Service/ROS_Service_Concept2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alonzo3569/ROS_Tutorial/595a93c0e960bfc832290e1c52995170cb525948/Ch2 ROS Service/ROS_Service_Concept2.png -------------------------------------------------------------------------------- /Ch2 ROS Service/ROS_Service_Concept3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alonzo3569/ROS_Tutorial/595a93c0e960bfc832290e1c52995170cb525948/Ch2 ROS Service/ROS_Service_Concept3.png -------------------------------------------------------------------------------- /Ch2 ROS Service/ROS_Service_Server.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alonzo3569/ROS_Tutorial/595a93c0e960bfc832290e1c52995170cb525948/Ch2 ROS Service/ROS_Service_Server.png -------------------------------------------------------------------------------- /Ch2 ROS Service/Service_Call_Example.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alonzo3569/ROS_Tutorial/595a93c0e960bfc832290e1c52995170cb525948/Ch2 ROS Service/Service_Call_Example.png -------------------------------------------------------------------------------- /Ch2 ROS Service/Service_Call_Example2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alonzo3569/ROS_Tutorial/595a93c0e960bfc832290e1c52995170cb525948/Ch2 ROS Service/Service_Call_Example2.png -------------------------------------------------------------------------------- /Ch2 ROS Service/Service_Msg_Type.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alonzo3569/ROS_Tutorial/595a93c0e960bfc832290e1c52995170cb525948/Ch2 ROS Service/Service_Msg_Type.png -------------------------------------------------------------------------------- /Ch3 ROS Custom Message/README.md: -------------------------------------------------------------------------------- 1 | # Chapter **3.** Customize Your Application With Msg and Srv Files 2 | 3 |
4 | 5 |

6 |

7 | 8 |
9 | 10 | ## Create and Build Your Own Custom Msg 11 | ```console 12 | # Create a "new" pkg for custom msg and srv 13 | [alonzo@study ~/catkin_ws/src]$ catkin_create_pkg my_robot_msgs roscpp rospy std_msgs 14 | [alonzo@study ~/catkin_ws/src]$ cd /my_robot_msgs 15 | 16 | # Remove /include /src directories 17 | [alonzo@study ~/catkin_ws/src/my_robot_msgs]$ rm -rf /include /src 18 | 19 | # Create msg/ directory and modify .msg file 20 | [alonzo@study ~/catkin_ws/src/my_robot_msgs]$ mkdir msg;cd msg/ 21 | [alonzo@study ~/catkin_ws/src/my_robot_msgs/msg]$ vim HardwareStatus.msg 22 | [alonzo@study ~/catkin_ws/src/my_robot_msgs/msg]$ cd .. 23 | 24 | # Modify CMakeLists.txt and package.xml in "Msg pkg" 25 | [alonzo@study ~/catkin_ws/src/my_robot_msgs]$ vim CMakeLists.txt 26 | [alonzo@study ~/catkin_ws/src/my_robot_msgs]$ vim package.xml 27 | 28 | # After editing CMakeLists.txt, package.xml and HardwareStatus.msg 29 | # Don't forget to catkin_make & source ~/.bashrc! 30 | [alonzo@study ~/catkin_ws/]$ catkin_make 31 | # Header file will be generated under ~/catkin_ws/devel/include/my_robot_msgs/ 32 | [alonzo@study ~/catkin_ws/]$ . ~/bashrc 33 | ``` 34 | * __CMakeLists.txt__ 35 | ``` 36 | 1. 37 | find_package(catkin REQUIRED COMPONENTS 38 | roscpp 39 | rospy 40 | std_msgs 41 | message_generation <==== Msg class .h/.cpp file will be generated after catkin_make 42 | ) 43 | 44 | 2. 45 | ## Generate messages in the 'msg' folder 46 | add_message_files( 47 | FILES 48 | HardwareStatus.msg <==== 49 | ) 50 | 51 | 3. 52 | ## Generate added messages and services with any dependencies listed here 53 | generate_messages( 54 | DEPENDENCIES 55 | std_msgs 56 | ) 57 | 58 | 4. 59 | catkin_package( 60 | # INCLUDE_DIRS include 61 | # LIBRARIES my_robot_msgs 62 | CATKIN_DEPENDS roscpp rospy std_msgs message_runtime <==== add "message_runtime" 63 | # DEPENDS system_lib 64 | ) 65 | ``` 66 | * __package.xml__ 67 | ``` 68 | message_generation 69 | message_runtime 70 | ``` 71 | 72 | * __HardwareStatus.msg__ 73 | ``` 74 | int64 temperature 75 | bool are_motors_up 76 | string debug_message 77 | ``` 78 | 79 | ## Use Your Custom Msg in Your Code 80 | ```console 81 | # Include msg pkg in another pkg to use your custom message 82 | [alonzo@study ~/catkin_ws/src/package_name/scripts]$ vim hw_status_publisher.py 83 | [alonzo@study ~/catkin_ws/src/package_name/scripts]$ chmod a+x hw_status_publisher.py 84 | [alonzo@study ~/catkin_ws/src/package_name/scripts]$ vim CMakeList.txt    package.xml 85 | ``` 86 | * __CMakeLists.txt__ 87 | ``` 88 | find_package(catkin REQUIRED COMPONENTS 89 | roscpp 90 | rospy 91 | std_msgs 92 | std_srvs 93 | rospy_tutorials 94 | my_robot_msgs <== add msg pkg 95 | ) 96 | ``` 97 | * __package.xml__ 98 | ``` 99 | my_robot_msgs 100 | ``` 101 | * __hw_status_publisher.py__ 102 | ```python 103 | #!/usr/bin/env python 104 | 105 | import rospy 106 | from my_robot_msgs.msg import HardwareStatus 107 | 108 | if __name__ == '__main__': 109 | 110 | rospy.init_node('hardware_status_publisher') 111 | 112 | pub = rospy.Publisher("/my_robot/hardware_status", HardwareStatus, queue_size = 10) 113 | 114 | rate = rospy.Rate(5) 115 | 116 | while not rospy.is_shutdown():\ 117 | # Create custom msg object 118 | msg = HardwareStatus(); 119 | 120 | # Call data in custom msg object 121 | msg.temperature = 45 122 | msg.are_motors_up = True 123 | msg.debug_message = "Everything is running well" 124 | pub.publish(msg) 125 | rate.sleep() 126 | ``` 127 | ## Create Your Own Custom Srv 128 | ```console 129 | [alonzo@study ~/catkin_ws/src/my_robot_msgs]$ mkdir srv 130 | [alonzo@study ~/catkin_ws/src/my_robot_msgs/srv]$ vim ComputeDiskArea.srv 131 | [alonzo@study ~/catkin_ws/src/my_robot_msgs/srv]$ vim CMakeList.txt     132 | [alonzo@study ~/catkin_ws]$ catkin_make 133 | # Check generated header file: cd ~/catkin_ws/devel/include/my_robot_msgs/ 134 | [alonzo@study ~/catkin_ws/devel/include/my_robot_msgs]$ ls 135 | # > ComputeDiskAreaRequest.h    ComputeDiskAreaResponse.h 136 | ``` 137 | * __ComputeDiskArea.srv__ 138 | ``` 139 | float64 radius 140 | --- 141 | float64 area 142 | ``` 143 | * __CMakeLists.txt__ 144 | ``` 145 | ## Generate services in the 'srv' folder 146 | add_service_files( 147 | FILES 148 | ComputeDiskArea.srv 149 | ) 150 | ``` 151 | 152 | ## Msg and Srv With Command 153 | ```console 154 | [alonzo@study ~]$ rosmsg -h 155 | [alonzo@study ~]$ rosmsg list 156 | [alonzo@study ~]$ rosmsg show 157 | [alonzo@study ~]$ rossrv -h 158 | ``` 159 |
160 | 161 |

162 |

163 | 164 |
165 | 166 | * __Note :__ 167 | ```python 168 | # spin() only let the node stay active after finishing all the line, doesn't "Loop" 169 | rospy.spin() <== only let the node stay active after finishing all the line, doesn't "Loop" 170 | 171 | # 2 ways to implement sleep() 172 | rate = rospy.Rate(10) 173 | rate.sleep() 174 | # Or 175 | rospy.sleep(3) 176 | ``` 177 | 178 | ## Practice 179 | * __led_panel.py__ 180 | ```python 181 | #!/usr/bin/env python 182 | 183 | import rospy 184 | from my_robot_msgs.srv import SetLed 185 | 186 | led_states = [0,0,0] 187 | 188 | def callback_set_led(req): 189 | led_number = req.led_number 190 | state = req.state 191 | global led_states 192 | 193 | if (led_number > len(led_states)) or (led_number <= 0): 194 | return False 195 | 196 | if not (state == 0 or state == 1): 197 | return False 198 | 199 | led_states[led_number - 1] = state 200 | 201 | return True 202 | 203 | if __name__ == '__main__': 204 | rospy.init_node('led_panel') 205 | 206 | server = rospy.Service("/set_led", SetLed, callback_set_led) 207 | 208 | rate = rospy.Rate(10) 209 | 210 | while not rospy.is_shutdown(): 211 | rospy.loginfo(led_states) 212 | rate.sleep() 213 | ``` 214 | 215 | * __battery.py__ 216 | ```python 217 | #!/usr/bin/env python 218 | 219 | import rospy 220 | from my_robot_msgs.srv import SetLed 221 | 222 | def set_led(battery_state): 223 | rospy.wait_for_service("/set_led") 224 | try: 225 | service = rospy.ServiceProxy("/set_led", SetLed) 226 | state = 0 227 | if battery_state == 'empty': 228 | state = 1 229 | resp = service(1, state) 230 | rospy.loginfo("Set led success flag : " + str(resp)) 231 | except rospy.ServiceException as e: 232 | rospy.logerr(e) 233 | 234 | 235 | if __name__ == '__main__': 236 | rospy.init_node('battery') 237 | 238 | battery_state = "full" 239 | 240 | while not rospy.is_shutdown(): 241 | rospy.sleep(7) 242 | battery_state = "empty" 243 | rospy.loginfo("The battery is empty !") 244 | set_led(battery_state) 245 | rospy.sleep(3) 246 | battery_state = "full" 247 | rospy.loginfo("The battery is now full") 248 | set_led(battery_state) 249 | ``` 250 | 251 | * __Setled.srv__ 252 | ``` 253 | int64 led_number 254 | int64 state 255 | --- 256 | bool success 257 | ``` 258 | -------------------------------------------------------------------------------- /Ch3 ROS Custom Message/ROS_Message1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alonzo3569/ROS_Tutorial/595a93c0e960bfc832290e1c52995170cb525948/Ch3 ROS Custom Message/ROS_Message1.png -------------------------------------------------------------------------------- /Ch3 ROS Custom Message/ROS_Message2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alonzo3569/ROS_Tutorial/595a93c0e960bfc832290e1c52995170cb525948/Ch3 ROS Custom Message/ROS_Message2.png -------------------------------------------------------------------------------- /Ch3 ROS Custom Message/ROS_Message3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alonzo3569/ROS_Tutorial/595a93c0e960bfc832290e1c52995170cb525948/Ch3 ROS Custom Message/ROS_Message3.png -------------------------------------------------------------------------------- /Ch3 ROS Custom Message/ROS_Message_Concept.PNG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alonzo3569/ROS_Tutorial/595a93c0e960bfc832290e1c52995170cb525948/Ch3 ROS Custom Message/ROS_Message_Concept.PNG -------------------------------------------------------------------------------- /Ch3 ROS Custom Message/ROS_Message_Concept2.PNG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alonzo3569/ROS_Tutorial/595a93c0e960bfc832290e1c52995170cb525948/Ch3 ROS Custom Message/ROS_Message_Concept2.PNG -------------------------------------------------------------------------------- /Ch4 ROS Params & Launch Files/README.md: -------------------------------------------------------------------------------- 1 | # Chapter **4.** ROS Params & Launch Files 2 | 3 |
4 | 5 |

6 |

7 | 8 |
9 | 10 | 11 | ## Manipulate Parameters With Command Line Tools 12 | ```console 13 | # Run roscore to initiate up ros parameter server 14 | [alonzo@study ~]$ roscore 15 | 16 | # Help for rosparam 17 | # rosparam is a cmd-line tool for setting up ros parameter server 18 | [alonzo@study ~]$ rosparam -h 19 | 20 | # list all the ros params in ros 21 | [alonzo@study ~]$ rosparam list 22 | 23 | # Set ros param 24 | # Usage: rosparam set {param_name} {param_value} 25 | [alonzo@study ~]$ rosparam set /robot_name "my_robot" 26 | [alonzo@study ~]$ rosparam set /sensors_read_frequency 40 27 | [alonzo@study ~]$ rosparam set /simulation_mode false 28 | 29 | # Check ros parameters 30 | [alonzo@study ~]$ rosparam list 31 | 32 | # Check ros params value 33 | [alonzo@study ~]$ rosparam get /robot_name 34 | [alonzo@study ~]$ rosparam get /sensors_read_frequency 35 | [alonzo@study ~]$ rosparam get /simulation_mode 36 | ``` 37 | 38 | 39 | ## Handle Parameters With Python 40 | ```python 41 | # Get param from ros parameter server 42 | publish_frequency = rospy.get_param("/number_publish_frequency") 43 | # Note : remember to set the param in ros server before calling it 44 | # cmd: rosparam set /number_publish_frequency 2 45 | 46 | # Set param in py file 47 | rospy.set_param("/another_param", "Hello") 48 | ``` 49 | ```console 50 | # Run .py file and kill it 51 | # Check in cmd 52 | [alonzo@study ~]$ rosparam list => see "/another_param" 53 | # ros param will till exist even after the node is killed 54 | [alonzo@study ~]$ rosparam get /another_param 55 | ``` 56 | 57 | ## Handle Parameters With C++ 58 | ```cpp 59 | # Get param from ros parameter server 60 | double publish_frequency; 61 | nh.getParam("/number_publish_frequency", publish_frequency); 62 | ros::Rate rate(publish_frequency); 63 | ``` 64 | ```console 65 | # Catkin_make 66 | # Before running node, set ros param first 67 | [alonzo@study ~]$ rosparam set /number_publish_frequency 2 68 | 69 | # Check 70 | [alonzo@study ~]$ rosparam list 71 | # Run your node 72 | ``` 73 | ```cpp 74 | # Set param in cpp file 75 | int number; 76 | nh.setParam("/just_another_param","Bye"); 77 | ``` 78 | ```console 79 | # Catkin_make 80 | [alonzo@study ~]$ rosparam get /just_another_param 81 | 82 | * Note: 83 | Once the node is executed, the value of ros param inside the node is immutable. 84 | Retstart the node to change the value of ros params. 85 | ``` 86 | 87 | 88 | ## ROS Launch File 89 | 90 |
91 | 92 |

93 |

94 | 95 |
96 | 97 | ## Create a Launch File to Start all Your Parameters and Nodes 98 | ```console 99 | # Create a pkg for launch file 100 | [alonzo@study ~/catkin_ws/src]$ catkin_create_pkg my_robot_bringup 101 | [alonzo@study ~/catkin_ws]$ catkin_make 102 | [alonzo@study ~/catkin_ws/src]$ cd my_robot_bringup 103 | [alonzo@study ~/catkin_ws/src/my_robot_bringup]$ mkdir launch 104 | [alonzo@study ~/catkin_ws/src/my_robot_bringup]$ cd launch 105 | [alonzo@study ~/catkin_ws/src/my_robot_bringup/launch]$ touch number_app.launch 106 | [alonzo@study ~/catkin_ws/src/my_robot_bringup/launch]$ vim number_app.launch 107 | ``` 108 | * __number_app.launch__ 109 | ```html 110 | 111 | # Add ros params in launch file 112 | 113 | 114 | 115 | # Add node Note "type => exe name" 116 | 117 | 118 | 119 | ``` 120 | * __Execute launch file__ 121 | ```console 122 | [alonzo@study ~]$ roslaunch my_robot_bringup number_app.launch 123 | 124 | # Kill ros node 125 | # Check ros parameter 126 | [alonzo@study ~]$ rosparams list 127 | [alonzo@study ~]$ rosnode list 128 | [alonzo@study ~]$ rostopic echo /number 129 | [alonzo@study ~]$ rostopic echo /number_count 130 | 131 | * Note: If using roslaunch, we don't have to run roscore manually 132 | ``` 133 | 134 | -------------------------------------------------------------------------------- /Ch4 ROS Params & Launch Files/ROS_Launch_file_concept.PNG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alonzo3569/ROS_Tutorial/595a93c0e960bfc832290e1c52995170cb525948/Ch4 ROS Params & Launch Files/ROS_Launch_file_concept.PNG -------------------------------------------------------------------------------- /Ch4 ROS Params & Launch Files/ROS_Parameters.PNG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alonzo3569/ROS_Tutorial/595a93c0e960bfc832290e1c52995170cb525948/Ch4 ROS Params & Launch Files/ROS_Parameters.PNG -------------------------------------------------------------------------------- /Ch4 ROS Params & Launch Files/ROS_Parameters2.PNG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alonzo3569/ROS_Tutorial/595a93c0e960bfc832290e1c52995170cb525948/Ch4 ROS Params & Launch Files/ROS_Parameters2.PNG -------------------------------------------------------------------------------- /Ch4 ROS Params & Launch Files/ROS_Parameters_concept.PNG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alonzo3569/ROS_Tutorial/595a93c0e960bfc832290e1c52995170cb525948/Ch4 ROS Params & Launch Files/ROS_Parameters_concept.PNG -------------------------------------------------------------------------------- /Ch5 ROS Bag & OOP/README.md: -------------------------------------------------------------------------------- 1 | # Chapter **5.** ROS Bag and OOP 2 | 3 | ## Replay a Topic With ROS Bags 4 | * A bag is a file format in ROS for storing ROS message data. 5 | * `rosbag` command can record, replay bags. 6 | 7 | ```console 8 | # Rosbag help 9 | rosbag -h 10 | 11 | # Run ros master and node 12 | [alonzo@study ~]$ roscore 13 | [alonzo@study ~]$ rosrun my_robot_tutorials hw_status_publisher.py 14 | [alonzo@study ~]$ rosnode list 15 | [alonzo@study ~]$ rostopic list 16 | [alonzo@study ~]$ rostopic echo /my_robot/hardware_status 17 | 18 | # Save the data in one topic 19 | # rosbag record {topic name} 20 | [alonzo@study ~]$ rosbag record /my_robot/hardware_status 21 | # This will generate .bag file 22 | 23 | # Replay topic 24 | [alonzo@study ~]$ rosbag play 2018-06-16-08-31-32.bag 25 | # rostopic /my_robot/hardware_status start printing 26 | ``` 27 | 28 | ## Use OOP With ROS Python 29 | ```python 30 | #!/usr/bin/env python 31 | 32 | import rospy 33 | from std_msgs.msg import Int64 34 | from std_srvs.srv import SetBool 35 | 36 | 37 | class NumberCounter: 38 | 39 | def __init__(self): 40 | self.counter = 0 41 | 42 | self.number_subscriber = rospy.Subscriber("/number", Int64, self.callback_number) 43 | 44 | self.pub = rospy.Publisher("/number_count", Int64, queue_size=10) 45 | 46 | self.reset_service = rospy.Service("/reset_counter", SetBool, self.callback_reset_counter) 47 | 48 | def callback_number(self, msg): 49 | self.counter += msg.data 50 | new_msg = Int64() 51 | new_msg.data = self.counter 52 | self.pub.publish(new_msg) 53 | 54 | def callback_reset_counter(self, req): 55 | if req.data: 56 | self.counter = 0 57 | return True, "Counter has been successfully reset" 58 | return False, "Counter has not been reset" 59 | 60 | 61 | if __name__ == '__main__': 62 | rospy.init_node('number_counter') 63 | NumberCounter() 64 | rospy.spin() 65 | ``` 66 | 67 | ## Use OOP With ROS C++ 68 | ```cpp 69 | #include 70 | #include 71 | #include 72 | 73 | class NumberCounter { 74 | 75 | private: 76 | int counter; 77 | ros::Publisher pub; 78 | ros::Subscriber number_subscriber; 79 | ros::ServiceServer reset_service; 80 | 81 | public: 82 | NumberCounter(ros::NodeHandle *nh) { 83 | counter = 0; 84 | 85 | pub = nh->advertise("/number_count", 10); 86 | 87 | number_subscriber = nh->subscribe("/number", 1000, 88 | &NumberCounter::callback_number, this); 89 | 90 | reset_service = nh->advertiseService("/reset_counter", 91 | &NumberCounter::callback_reset_counter, this); 92 | } 93 | 94 | void callback_number(const std_msgs::Int64& msg) { 95 | counter += msg.data; 96 | std_msgs::Int64 new_msg; 97 | new_msg.data = counter; 98 | pub.publish(new_msg); 99 | } 100 | 101 | bool callback_reset_counter(std_srvs::SetBool::Request &req, 102 | std_srvs::SetBool::Response &res) 103 | { 104 | if (req.data) { 105 | counter = 0; 106 | res.success = true; 107 | res.message = "Counter has been successfully reset"; 108 | } 109 | else { 110 | res.success = false; 111 | res.message = "Counter has not been reset"; 112 | } 113 | 114 | return true; 115 | } 116 | }; 117 | 118 | int main (int argc, char **argv) 119 | { 120 | ros::init(argc, argv, "number_counter"); 121 | ros::NodeHandle nh; 122 | NumberCounter nc = NumberCounter(&nh); 123 | ros::spin(); 124 | } 125 | ``` 126 | 127 | ## Work With Multiple Catkin Workspaces 128 | 129 | * __Note :__ 130 | Only the last setup.bash in ~/.bashrc will be implemented. 131 | Thus, source manually to overwrite env params or modify bashrc. 132 | 133 | -------------------------------------------------------------------------------- /Ch6 ROS Gazebo/Ch1 Launch Your First Gazebo World Using ROS/README.md: -------------------------------------------------------------------------------- 1 | ## Launch Your First Gazebo World Using ROS 2 | 1. **Create your own workspace and pkg** 3 | ```console 4 | [alonzo@study ~]$ mkdir -p simulation_ws/src 5 | [alonzo@study ~/simulation_ws/src]$ catkin_create_pkg my_simulations # No dependencies 6 | [alonzo@study ~/simulation_ws]$ catkin_make 7 | [alonzo@study ~/simulation_ws]$ source ~/simulation_ws/devel/setup.bash 8 | ``` 9 | 2. **Create launch and world folder** 10 | ```console 11 | [alonzo@study ~/simulation_ws/src/my_simulations]$ mkdir launch world 12 | ``` 13 | 14 | 3. **Create and edit your .launch file** 15 | ```console 16 | [alonzo@study ~/simulation_ws/src/my_simulations/launch]$ touch my_world.launch 17 | ``` 18 | 19 | 4. **Create and edit your .world file** 20 | ```console 21 | [alonzo@study ~/simulation_ws/src/my_simulations/world]$ touch empty_world.world 22 | ``` 23 | 24 | 5. **Launch your Gazebo world** 25 | ```console 26 | [alonzo@study ~]$ roslaunch my_simulations my_world.launch 27 | ``` 28 | 29 | ## Source code 30 | * my_world.launch 31 | ```xml 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | ``` 50 | 51 | * empty_world.world 52 | ```xml 53 | 54 | 55 | 56 | 57 | 58 | 59 | model://sun 60 | 61 | 62 | 63 | model://ground_plane 64 | 65 | 66 | 67 | 68 | ``` 69 | 70 | ## Appendix 71 | * empty_world.launch (Caution: "This is a launch file!") 72 | ```xml 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | 125 | ``` 126 | -------------------------------------------------------------------------------- /Ch6 ROS Gazebo/Ch10 Launch RViz using a configuration file/README.md: -------------------------------------------------------------------------------- 1 | ## Launch RViz using a configuration file 2 | * __.rviz configuration file :__ Save rviz config so that you don't have to reconfigure after roslaunch. 3 | 4 | 1. **Launch rviz** 5 | ```console 6 | [alonzo@study ~/simulation_ws/src/my_robot_description]$ roslaunch my_robot_description rviz.launch 7 | ``` 8 | 2. **Configure your rviz in GUI** 9 | 10 | 3. **Select "Save config as" option** 11 | 12 | 4. **Store .rivz in ~/simulation_ws/src/my_robot_description/rviz** 13 | 14 | 5. **Name it (robot.rviz)** 15 | 16 | 6. **Edit rviz.launch file** 17 | ```console 18 | [alonzo@study ~/simulation_ws/src/my_robot_description/launch]$ vim rviz.launch 19 | ``` 20 | 7. **Relaunch** 21 | ```console 22 | [alonzo@study ~/simulation_ws/src/my_robot_description/launch]$ roslaunch my_robot_description rviz.launch 23 | ``` 24 | ## Source code 25 | * rviz.launch 26 | ```xml 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | ``` 47 | -------------------------------------------------------------------------------- /Ch6 ROS Gazebo/Ch11 Use joint_state_publisher/README.md: -------------------------------------------------------------------------------- 1 | ## Use joint_state_publisher 2 | 3 | 1. **Edit rviz.launch file, change gui to "True"** 4 | * `` 5 | 6 | 2. **Launch rviz** 7 | ```console 8 | $ roslaunch my_robot_description rviz.launch 9 | ``` 10 | 11 | 3. **A joint1 terminal apprears on the screen** 12 | 4. **Drag joint bar to rotate joint1 object** 13 | 14 | ## Source code 15 | * rviz.launch 16 | ```xml 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | ``` 38 | 39 | ## Appendix 40 | * __ROS node :__ 41 | * __`joint_state_publisher`:__ 42 | * This package publishes [sensor_msgs/JointState][0] messages for a robot. 43 | * The package reads the __robot_description parameter__ from the parameter server, finds all of the __non-fixed joints__ and publishes a JointState message with all those joints defined. 44 | * __`robot_state_publisher`:__ 45 | * robot_state_publisher calculate the forward kinematics of the robot and publish the results via tf. 46 | * Source : URDF specified by the parameter robot_description 47 | * Subscribe topic : `joint_states` (provide joint positions to `robot_state_publisher`) 48 | * Subscribe message type : sensor_msgs/JointState 49 | 50 | [0]:http://docs.ros.org/api/sensor_msgs/html/msg/JointState.html 51 | -------------------------------------------------------------------------------- /Ch6 ROS Gazebo/Ch12 Create custom gazebo model using heightmap/README.md: -------------------------------------------------------------------------------- 1 | ## Gazebo Heightmap tutorial 2 | 3 | 1. **Install** [**GIMP**][0] 4 | 5 | [0]: https://tecadmin.net/install-gimp-on-ubuntu/ 6 | 7 | 8 | 2. **Create a New Image** 9 | 10 | 3. __Select Width and Height value (2**n+1: 129/129, 257/257, 513/513)__ 11 | * __Note :__ Gazebo requires these values be equal 12 | 13 | 4. **White is high & Black is low. Thus, start with all black** 14 | 15 | 5. **Draw your terrain** 16 | 17 | 6. **Export as .png file** 18 | 19 | 7. **In ~/.gazebo/models directory, these are models that you used in the past** 20 | ```console 21 | $ cd ~/.gazebo/models 22 | ``` 23 | 8. **Create a folder for your model** 24 | ```console 25 | $ mkdir ~/.gazebo/models/custom_lake 26 | ``` 27 | 9. **Copy model.sdf & model.config from other model** 28 | ```console 29 | $ cp -rp ~/.gazebo/models/playground ~/.gazebo/models/custom_lake 30 | ``` 31 | 32 | 10. **Overwrite model.sdf file** 33 | ```console 34 | $ cp /usr/share/gazebo-9/worlds/heightmap.world model.sdf 35 | ``` 36 | 37 | 11. **Edit model.sdf file. Remove tag and "sun" model** 38 | 39 | 12. **Remove all the "box" model in model.sdf** 40 | 41 | ## Source code 42 | * model.sdf 43 | ```xml 44 | 45 | 46 | 47 | 48 | true 49 | 50 | 51 | 52 | 53 | 54 | model://custom_lake/materials/textures/custom_lake.png 55 | 56 | 57 | 58 | 200 200 10 59 | 0 0 0 60 | 61 | 62 | 63 | 64 | 65 | 66 | false 67 | 68 | file://media/materials/textures/dirt_diffusespecular.png 69 | file://media/materials/textures/flat_normal.png 70 | 1 71 | 72 | 73 | file://media/materials/textures/grass_diffusespecular.png 74 | file://media/materials/textures/flat_normal.png 75 | 1 76 | 77 | 78 | file://media/materials/textures/fungus_diffusespecular.png 79 | file://media/materials/textures/flat_normal.png 80 | 1 81 | 82 | 83 | 2 84 | 5 85 | 86 | 87 | 4 88 | 5 89 | 90 | 91 | model://custom_lake/materials/textures/custom_lake.png 92 | 93 | 94 | 95 | 200 200 10 96 | 0 0 0 97 | 98 | 99 | 100 | 101 | 102 | 103 | ``` 104 | -------------------------------------------------------------------------------- /Ch6 ROS Gazebo/Ch2 Add gazebo models to a simulation/README.md: -------------------------------------------------------------------------------- 1 | ## Add gazebo models to a simulation 2 | * Online [__Gazebo models__][0] 3 | * Modify your .world file to import gazebo online models 4 | * empty_world.world 5 | ```xml 6 | 7 | 8 | 9 | 10 | 11 | 12 | model://sun 13 | 14 | 15 | 16 | model://ground_plane 17 | 18 | 19 | 20 | 21 | model://suv 22 | false 23 | 0 0 20 0 0 0 24 | 25 | 26 | 27 | ``` 28 | 29 | [0]: https://bitbucket.org/osrf/gazebo_models/src/default/ 30 | -------------------------------------------------------------------------------- /Ch6 ROS Gazebo/Ch3 Spawn a robot in gazebo/README.md: -------------------------------------------------------------------------------- 1 | ## Spawn a robot in gazebo 2 | 3 | 1. **Clone this repository (two-wheeled-robot-simulation pkg)** 4 | ```console 5 | [alonzo@study ~/simulation_ws/src]$ git clone https://bitbucket.org/theconstructcore/two-wheeled-robot-simulation 6 | ``` 7 | 8 | 2. **View .xacro file** 9 | ```console 10 | [alonzo@study ~/simulation_ws/src/two-wheeled-robot-simulation/urdf]$ vim m2wr.xacro 11 | ``` 12 | 13 | 3. **View .launch file** 14 | ```console 15 | [alonzo@study ~/simulation_ws/src/two-wheeled-robot-simulation/launch]$ vim spawn.launch 16 | ``` 17 | 18 | 4. **Launch** 19 | ```console 20 | [alonzo@study ~/simulation_ws/src/two-wheeled-robot-simulation/launch]$ roslaunch two-wheeled-robot-simulation spawn.launch 21 | ``` 22 | 23 | ## Source code 24 | * m2wr.xacro 25 | ```xml 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 0 0 0.1 0 0 0 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 0 64 | 0 65 | 1.0 66 | 1.0 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | ``` 115 | 116 | * spawn.launch 117 | ``` 118 | 119 | 120 | 121 | 122 | 123 | 124 | 125 | 126 | 127 | 128 | 129 | 130 | 131 | 132 | 133 | 134 | 135 | 136 | 137 | 138 | 139 | 140 | 141 | 142 | 143 | 145 | 146 | 147 | 148 | ``` 149 | -------------------------------------------------------------------------------- /Ch6 ROS Gazebo/Ch4 Create a gazebo model using SDF/README.md: -------------------------------------------------------------------------------- 1 | ## Create a gazebo model (Not Robot!) using SDF 2 | 3 | * __SDF__ v.s. __URDF__ 4 | * SDF : SDF is used for entire robotic simulation environments. 5 | * URDF : Only for robot description. 6 | 7 | 1. **Create a directory for gazebo model in a ros package** 8 | ```console 9 | [alonzo@study ~/simulation_ws/src/my_simulations]$ mkdir models 10 | [alonzo@study ~/simulation_ws/src/my_simulations/models]$ mkdir {your_model_name} 11 | [alonzo@study ~/simulation_ws/src/my_simulations/models]$ mkdir my1stmodel 12 | ``` 13 | 14 | 2. **Create .sdf and .config** 15 | ```console 16 | [alonzo@study ~/simulation_ws/src/my_simulations/models/my1stmodel]$ model.sdf 17 | [alonzo@study ~/simulation_ws/src/my_simulations/models/my1stmodel]$ model.config (paste code) 18 | ``` 19 | 20 | 4. **Add model path to env param GAZEBO_MODEL_PATH** 21 | ```console 22 | [alonzo@study ~/simulation_ws/src/my_simulations/models/my1stmodel]$ GAZEBO_MODEL_PATH=$GAZEBO_MODEL_PATH:{your_model_model_path} 23 | [alonzo@study ~/simulation_ws/src/my_simulations/models/my1stmodel]$ GAZEBO_MODEL_PATH=$GAZEBO_MODEL_PATH:/home/ual/simulation_ws/src/my_simulations/models 24 | ``` 25 | 5. **Modify .world file, "include" your model** 26 | ```console 27 | [alonzo@study ~/simulation_ws/src/my_simulations/world]$ vim empty_world.world 28 | # > Add : model://my1stmodel 29 | ``` 30 | 31 | 6. **Launch** 32 | ```console 33 | [alonzo@study ~/simulation_ws/src/my_simulations/world]$ roslaunch my_simulations my_world.launch 34 | ``` 35 | ## Source code 36 | * model.sdf 37 | ```xml 38 | 39 | 40 | 41 | true 42 | 43 | 44 | 45 | 46 | 3 2 5 47 | 48 | 49 | 50 | 51 | 52 | 100 53 | 50 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 3 2 5 62 | 63 | 64 | 65 | 69 | 70 | 71 | 72 | 73 | 74 | ``` 75 | 76 | * model.config 77 | ```xml 78 | 79 | 80 | 81 | My 1st model 82 | 1.0 83 | model.sdf 84 | 85 | 86 | Logan Zhang 87 | r07525074@ntu.edu.tw 88 | 89 | 90 | 91 | This is my first model for gazebo. 92 | 93 | 94 | ``` 95 | 96 | * empty_world.world 97 | ```xml 98 | 99 | 100 | 101 | 102 | 103 | model://sun 104 | 105 | 106 | 107 | model://ground_plane 108 | 109 | 110 | 111 | 112 | 113 | model://my1stmodel 114 | 115 | false 116 | 0 0 5 0 0 0 117 | 118 | 119 | 120 | ``` 121 | -------------------------------------------------------------------------------- /Ch6 ROS Gazebo/Ch5 Use a mesh file to create a gazebo model/README.md: -------------------------------------------------------------------------------- 1 | ## How to use a mesh file to create a gazebo model 2 | 1. **Create meshes folders** 3 | ```console 4 | [alonzo@study ~/simulation_ws/src/my_simulations/models/my1stmodel/]$ mkdir meshes 5 | ``` 6 | 7 | 2. **Download .stl file from my github repo to /meshes folder** 8 | 9 | 3. __Modify .sdf file, change box to mesh (Both "collision" and "visual" tag)__ 10 | ```console 11 | [alonzo@study ~/simulation_ws/src/my_simulations/models/my1stmodel/]$ vim model.sdf 12 | ``` 13 | 14 | 4. **Launch file** 15 | ```console 16 | [alonzo@study ~/simulation_ws/src/my_simulations/models/my1stmodel/]$ roslaunch my_simulations my_world.launch 17 | ``` 18 | 19 | ## Source code 20 | * model.sdf 21 | ```xml 22 | 23 | 24 | 25 | true 26 | 27 | 28 | 29 | 30 | 31 | model://my1stmodel/meshes/robot_car.stl 32 | 33 | 34 | 0.01 0.01 0.01 35 | 36 | 37 | 38 | 39 | 40 | 100 41 | 50 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | model://my1stmodel/meshes/robot_car.stl 51 | 52 | 53 | 0.01 0.01 0.01 54 | 55 | 56 | 57 | 61 | 62 | 63 | 64 | 65 | 66 | ``` 67 | -------------------------------------------------------------------------------- /Ch6 ROS Gazebo/Ch5 Use a mesh file to create a gazebo model/cordless_drill.stl: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alonzo3569/ROS_Tutorial/595a93c0e960bfc832290e1c52995170cb525948/Ch6 ROS Gazebo/Ch5 Use a mesh file to create a gazebo model/cordless_drill.stl -------------------------------------------------------------------------------- /Ch6 ROS Gazebo/Ch5 Use a mesh file to create a gazebo model/robot_car.stl: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alonzo3569/ROS_Tutorial/595a93c0e960bfc832290e1c52995170cb525948/Ch6 ROS Gazebo/Ch5 Use a mesh file to create a gazebo model/robot_car.stl -------------------------------------------------------------------------------- /Ch6 ROS Gazebo/Ch6 Use an image file as texture for gazebo model/README.md: -------------------------------------------------------------------------------- 1 | ## How to use an image file as texture for gazebo model 2 | 1. **Create materials/scripts and materials/textures folder** 3 | ```console 4 | [alonzo@study ~/simulation_ws/src/my_simulations/models/my1stmodel/]$ mkdir scripts texture 5 | ``` 6 | 2. **Touch .material file in scripts folder** 7 | ```console 8 | [alonzo@study ~/simulation_ws/src/my_simulations/models/my1stmodel/scripts]$ touch robot_car.material 9 | ``` 10 | 3. **Edit .material file** 11 | ```console 12 | [alonzo@study ~/simulation_ws/src/my_simulations/models/my1stmodel/scripts]$ vim robot_car.material 13 | ``` 14 | 4. **Download .png file from my github repo and store it inside the texture folder** 15 | 16 | 5. **Modify .sdf file "visual" tag** 17 | ```console 18 | [alonzo@study ~/simulation_ws/src/my_simulations/models/my1stmodel]$ vim model.sdf 19 | ``` 20 | 6. **Launch** 21 | ```console 22 | [alonzo@study ~/simulation_ws/src/my_simulations/models/my1stmodel/]$ roslaunch my_simulations my_world.launch 23 | ``` 24 | ## Source code 25 | * robot_car.material 26 | ```console 27 | material robot_car/Diffuse # name of your material 28 | { # Same as Gazebo/Grey in .sdf file 29 | recieve_shadows off 30 | technique 31 | { 32 | pass 33 | { 34 | texture_unit 35 | { 36 | texture seamless_texture.png # texture file 37 | } 38 | } 39 | } 40 | } 41 | ``` 42 | 43 | 44 | * model.sdf 45 | ```xml 46 | 47 | 48 | 49 | true 50 | 51 | 52 | 53 | 54 | model://my1stmodel/meshes/robot_car.stl 55 | 56 | 0.01 0.01 0.01 57 | 58 | 59 | 60 | 61 | 62 | 100 63 | 50 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | model://my1stmodel/meshes/robot_car.stl 72 | 73 | 74 | 0.01 0.01 0.01 75 | 76 | 77 | 78 | 84 | 85 | 86 | 87 | 88 | 89 | ``` 90 | -------------------------------------------------------------------------------- /Ch6 ROS Gazebo/Ch6 Use an image file as texture for gazebo model/seamless_texture.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alonzo3569/ROS_Tutorial/595a93c0e960bfc832290e1c52995170cb525948/Ch6 ROS Gazebo/Ch6 Use an image file as texture for gazebo model/seamless_texture.png -------------------------------------------------------------------------------- /Ch6 ROS Gazebo/Ch7 Create a robot using URDF/README.md: -------------------------------------------------------------------------------- 1 | ## Create a robot using URDF 2 | 3 | 1. **Create a pkg for your robot** 4 | ```console 5 | [alonzo@study ~/simulation_ws/src]$ catkin_create_pkg my_robot_description # No dependcies 6 | ``` 7 | 8 | 2. **Create folder urdf & launch in my_robot_description pkg** 9 | ```console 10 | [alonzo@study ~/simulation_ws/src/my_robot_description]$ mkdir urdf launch 11 | ``` 12 | 3. **Create .urdf file and edit** 13 | ```console 14 | [alonzo@study ~/simulation_ws/src/my_robot_description/urdf]$ touch robot.urdf 15 | ``` 16 | 17 | 4. **Create .launch file in launch folder** 18 | ```console 19 | [alonzo@study ~/simulation_ws/src/my_robot_description/urdf]$ touch spawn.launch 20 | ``` 21 | 22 | 5. **Launch** 23 | ```console 24 | [alonzo@study ~/simulation_ws/src/my_robot_description/urdf]$ roslaunch my_robot_description spawn.launch 25 | ``` 26 | 27 | ## Source code 28 | * robot.urdf 29 | ```xml 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 0 0 0.1 0 0 0 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | ``` 66 | 67 | * spawn.launch 68 | ```xml 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 97 | 98 | 99 | 100 | ``` 101 | -------------------------------------------------------------------------------- /Ch6 ROS Gazebo/Ch8 Visualize a robot URDF using RVIZ/README.md: -------------------------------------------------------------------------------- 1 | ## How to visualize a robot URDF using RVIZ 2 | 1. **Create rviz.launch in launch folder** 3 | ```console 4 | [alonzo@study ~/simulation_ws/src/my_robot_description/launch]$ touch rviz.launch 5 | ``` 6 | 7 | 2. **Launch** 8 | ```console 9 | [alonzo@study ~/simulation_ws/src/my_robot_description/launch]$ roslaunch my_robot_description rviz.launch 10 | ``` 11 | 3. **In Rviz GUI, press Add** 12 | 4. **Choose RobotModel option** 13 | 5. **To remove error, change global options "Fixed Frame: map" to link_chassis** 14 | 15 | ## Source code 16 | * rviz.launch 17 | ```xml 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | ``` 39 | -------------------------------------------------------------------------------- /Ch6 ROS Gazebo/Ch9 Create a robot using URDF(Advance & RVIZ)/README.md: -------------------------------------------------------------------------------- 1 | ## Create a robot using URDF (Advance + RVIZ) 2 | 1. **Edit .urdf, and link and joint** 3 | ```console 4 | [alonzo@study ~/simulation_ws/src/my_robot_description/urdf]$ vim robot.urdf 5 | ``` 6 | 7 | 2. **Launch** 8 | ```console 9 | [alonzo@study ~/simulation_ws/src/my_robot_description]$ roslaunch my_robot_description rviz.launch 10 | ``` 11 | 12 | 3. **In Rviz GUI, press Add** 13 | 4. **Choose RobotModel option** 14 | 5. **To remove error, change global options "Fixed Frame: map" to link_chassis** 15 | 16 | ## Source code 17 | * robot.urdf 18 | ```xml 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 0 0 0.1 0 0 0 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 0 0 0.1 0 0 0 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | ``` 90 | -------------------------------------------------------------------------------- /Ch7 ROS Virtual RobotX/Ch01_Adding_Course_Elements.md: -------------------------------------------------------------------------------- 1 | ## Adding course elements 2 | 3 | 1. **Create a ros pkg** 4 | ```console 5 | $ catkin_create_pkg example_vrx_package 6 | ``` 7 | 8 | 2. **Create a worlds folder for .world and .xacro** 9 | ```console 10 | $ mkdir worlds 11 | ``` 12 | 13 | 3. **Copy .xacro file from source pkg** 14 | ```console 15 | $ roscp vrx_gazebo example_course.world.xacro . 16 | ``` 17 | 18 | 4. **Modify .xcro file (Add new module)** 19 | 20 | 21 | 5. **Generate the compiled XML from the xacro file ("compile" your xacro files into static XML)** 22 | ```console 23 | $ rosrun xacro xacro --inorder example_course.world.xacro > my_world.world 24 | ``` 25 | 26 | 6. **Run simulation** 27 | ```console 28 | $ roslaunch vrx_gazebo sandisland.launch world:=`pwd`/my_world.world 29 | ``` 30 | 31 | ## Source code 32 | * __VRX example launch file: (vrx_gazebo) sandisland.launch__ 33 | * Create vrx model from `example_course.world.xacro` (Default) 34 | * Generate wamv robot urdf using `wamv_gazebo.urdf.xacro` 35 | * Spawn wamv robot 36 | 37 | ```xml 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 103 | 104 | 105 | 109 | 110 | 114 | 115 | ``` 116 | 117 | * __VRX example world file : example_course.world.xacro__ 118 | ```xml 119 | 120 | 121 | 122 | 123 | 124 | 125 | 126 | 127 | 128 | 129 | 130 | 131 | 132 | 133 | model://robotx_navigation_challenge 134 | 58 68 2 0 0 0.4 135 | 136 | 137 | model://robotx_light_buoy 138 | 110 28 0.25 0 0 0 139 | 140 | 141 | model://robotx_2016_qualifying_pinger_transit 142 | 55 -50 0 0 0 -1.3 143 | 144 | 145 | 146 | 147 | model://dock_2016 148 | 75 22 0.0 0 0 -2.78 149 | 150 | 151 | 152 | 153 | model://dock_2018 154 | -2 -18 0.0 0 0 0.2 155 | 156 | 157 | 158 | 159 | 160 | wamv 161 | base_link 162 | .5 .5 .33 163 | 164 | 165 | 166 | 167 | 168 | 169 | 170 | model://polyform_a3 171 | 172 | -10 2 0 0 0 0 173 | 174 | 175 | model://polyform_a7 176 | -15 8 0 0 0 0 177 | 178 | 179 | model://surmark950400 180 | -12.5 -3 0 0 0 0 181 | 182 | 183 | 184 | 185 | 186 | ``` 187 | 188 | 189 | * __WAMV robot example xacro: wamv_gazebo.urdf.xacro__ 190 | ```xml 191 | 192 | 193 | 195 | 196 | 197 | 198 | 199 | 200 | 201 | 202 | 203 | 204 | 205 | 206 | 207 | 208 | 210 | 211 | 212 | 213 | 214 | 215 | 216 | 217 | 218 | 219 | 220 | 221 | 222 | 223 | 224 | 225 | 226 | 227 | 228 | 229 | 230 | 231 | 232 | 233 | 234 | 235 | 236 | 237 | 238 | 239 | 240 | 241 | 242 | 243 | 244 | 245 | 246 | 247 | 248 | 249 | 250 | 251 | 252 | 253 | 254 | 255 | 256 | 257 | 258 | 259 | 260 | 261 | 262 | 263 | 264 | wamv::base_link 265 | wamv_external_link 266 | 267 | 1 0 0 268 | 269 | 270 | 0 1 0 271 | 272 | 273 | 274 | world 275 | wamv_external_link 276 | 277 | 278 | -3 279 | 3 280 | 281 | 0 0 1 282 | 283 | 284 | 285 | 286 | 287 | 288 | 289 | 290 | 291 | 292 | 293 | 294 | 295 | 296 | 297 | 298 | 299 | 300 | 301 | 302 | 303 | 304 | 305 | 306 | 307 | 308 | 309 | 310 | 311 | 312 | 313 | 314 | 315 | 316 | 317 | 318 | 319 | 320 | 321 | 322 | 323 | 324 | 325 | 326 | 327 | 328 | 329 | 330 | 331 | 332 | 333 | 334 | 335 | 336 | 337 | 338 | 339 | 340 | 341 | 342 | 343 | 344 | 345 | 346 | 347 | 348 | 349 | 350 | 351 | 352 | 353 | 354 | 355 | 356 | 357 | 358 | 359 | 360 | ``` 361 | 362 | ## Working with xacro files 363 | ### What is xacro? 364 | * A programmable xml file 365 | ### Functionality 366 | * Include other files 367 | * Define functions, store variables(macros). 368 | * VRX packages make heavy use of xacro to reduce code reuse and make composing new models/worlds easy. 369 | 370 | ### Generating XML from xacro 371 | * __From Terminal:__ To generate `my_wamv.urdf` from `my_wamv.urdf.xacro`, run this command: 372 | `$ rosrun xacro xacro --inorder my_wamv.urdf.xacro -o my_wamv.urdf` 373 | * __In CMakeLists.txt:__ (Allows you to find this issue at build time, not runtime) 374 | ``` 375 | find_package(catkin REQUIRED COMPONENTS 376 | xacro <= Add this line 377 | ) 378 | ``` 379 | ``` 380 | xacro_add_files( 381 | worlds/example_course.world.xacro 382 | INORDER INSTALL DESTINATION worlds <= This will generate devel/share/worlds/your_project_name/example_course.world in your workspace. 383 | ) 384 | ``` 385 | * __In launch file:__ 386 | ``` 387 | 388 | 389 | 390 | 391 | 392 | 393 | ``` 394 | 395 | ### Using Macros 396 | Here is an example macro included to create a gazebo camera sensor with the ROS plugin. 397 | * __wamv_camera.xacro__ (ROS plugin/Xacro template) 398 | ```xml 399 | 400 | 401 | 402 | 403 | 404 | 405 | 406 | 407 | 408 | ... 409 | 410 | 411 | ``` 412 | * __.urdf file__ 413 | ```xml 414 | 415 | 417 | ... 418 | 419 | 420 | 421 | 422 | ... 423 | 424 | ``` 425 | 426 | 427 | -------------------------------------------------------------------------------- /Ch7 ROS Virtual RobotX/Ch02_Custom_WAM-V_Thruster_Sensor_Configuration.md: -------------------------------------------------------------------------------- 1 | ## Custom WAM-V Thruster and Sensor Configuration 2 | 3 | 1. **Make a directory for your custom WAM-V** 4 | ```console 5 | $ mkdir ~/my_wamv 6 | ``` 7 | 2. **Touch and edit .yaml file** 8 | ```console 9 | $ vim ~/my_wamv/sensor_config.yaml 10 | $ vim ~/my_wamv/thruster_config.yaml 11 | ``` 12 | 13 | 3. **Generate .urdf from launch file** 14 | * Usage:

15 | `roslaunch vrx_gazebo generate_wamv.launch thruster_yaml:={ } sensor_yaml:={ } wamv_target:={ }` 16 | 17 | * Params: 18 | * thruster_yaml: Input, the full path of the thruster YAML 19 | * sensor_yaml: Input, the full path of the sensor YAML configuration 20 | * wamv_target: Output, the path where WAM-V URDF will be generated 21 | 22 | * Note: 23 | 1. If yaml path is not given, it uses default thruster/sensor yaml 24 | 2. Create WAM-V with no thruster and no sensors 25 | * thruster_yaml : empty_thruster_config.yaml 26 | * sensor_yaml : empty_sensor_config.yaml 27 | ```console 28 | # Case 1 29 | $ roslaunch vrx_gazebo generate_wamv.launch thruster_yaml:=$HOME/my_wamv/thruster_config.yaml sensor_yaml:=$HOME/my_wamv/sensor_config.yaml wamv_target:=$HOME/my_wamv/my_wamv.urdf 30 | 31 | # Case2 32 | $ roslaunch vrx_gazebo generate_wamv.launch thruster_yaml:=$HOME/my_wamv/thruster_config.yaml sensor_yaml:=$HOME/my_wamv/sensor_config.yaml wamv_target:=$HOME/my_wamv/my_wamv_2.urdf 33 | 34 | # Case 3 (Non-compliant) 35 | $ roslaunch vrx_gazebo generate_wamv.launch thruster_yaml:=$HOME/my_wamv/thruster_config.yaml sensor_yaml:=$HOME/my_wamv/sensor_config.yaml wamv_target:=$HOME/my_wamv/my_wamv_3.urdf 36 | ``` 37 | 38 | 4. **Launch the example world with your WAM-V** 39 | ```console 40 | # Case 1 41 | $ roslaunch vrx_gazebo sandisland.launch urdf:=$HOME/my_wamv/my_wamv.urdf 42 | 43 | # Case 2 44 | $ roslaunch vrx_gazebo sandisland.launch urdf:=$HOME/my_wamv/my_wamv_2.urdf 45 | 46 | # Case 3 47 | $ roslaunch vrx_gazebo sandisland.launch urdf:=$HOME/my_wamv/my_wamv_3.urdf 48 | ``` 49 | ## Source code 50 | * sensor_config.yaml 51 | ``` 52 | wamv_camera: 53 | - name: front_left_camera 54 | x: 0.75 55 | y: 0.1 56 | P: ${radians(15)} 57 | - name: front_right_camera 58 | x: 0.75 59 | y: -0.1 60 | P: ${radians(15)} 61 | - name: middle_right_camera 62 | x: 0.75 63 | y: 0.3 64 | P: ${radians(15)} 65 | wamv_gps: 66 | - name: gps_wamv 67 | x: -0.85 68 | wamv_imu: 69 | - name: imu_wamv 70 | y: -0.2 71 | wamv_p3d: 72 | - name: p3d_wamv 73 | lidar: 74 | - name: lidar_wamv 75 | type: 16_beam 76 | P: ${radians(8)} 77 | ``` 78 | ``` 79 | # Removed all cameras 80 | 81 | wamv_gps: 82 | - name: gps_wamv 83 | x: -0.85 84 | wamv_imu: 85 | - name: imu_wamv 86 | y: -0.2 87 | wamv_p3d: 88 | - name: p3d_wamv 89 | lidar: 90 | - name: lidar_wamv 91 | type: 16_beam 92 | P: ${radians(8)} 93 | ``` 94 | * __Non-compliant__ sensor_config.yaml 95 | ``` 96 | # Too many cameras 97 | wamv_camera: 98 | - name: front_left_camera 99 | x: 0.75 100 | y: 0.1 101 | P: ${radians(15)} 102 | - name: front_right_camera 103 | x: 0.75 104 | y: -0.1 105 | P: ${radians(15)} 106 | - name: front_far_left_camera 107 | x: 0.75 108 | y: 0.3 109 | P: ${radians(15)} 110 | - name: front_far_right_camera 111 | x: 0.75 112 | y: -0.3 113 | P: ${radians(15)} 114 | - name: middle_left_camera 115 | x: 0.6 116 | y: 0.4 117 | P: ${radians(15)} 118 | Y: ${radians(90)} 119 | post_Y: ${radians(90)} 120 | ``` 121 | * thruster_config.yaml 122 | ``` 123 | engine: 124 | - prefix: "left" 125 | position: "-2.373776 1.027135 0.318237" 126 | orientation: "0.0 0.0 0.0" 127 | - prefix: "right" 128 | position: "-2.373776 -1.027135 0.318237" 129 | orientation: "0.0 0.0 0.0" 130 | ``` 131 | ``` 132 | engine: 133 | - prefix: "left" 134 | position: "-2.373776 1.027135 0.318237" 135 | orientation: "0.0 0.0 0.0" 136 | - prefix: "right" 137 | position: "-2.373776 -1.027135 0.318237" 138 | orientation: "0.0 0.0 0.0" 139 | 140 | # Adding new thruster 141 | - prefix: "middle" 142 | position: "0 0 0.318237" 143 | orientation: "0.0 0.0 0.0" 144 | ``` 145 | * __Non-compliant__ thruster_config.yaml 146 | ``` 147 | engine: 148 | - prefix: "left" 149 | position: "-2.373776 1.027135 0.318237" 150 | orientation: "0.0 0.0 0.0" 151 | - prefix: "right" 152 | position: "-2.373776 -1.027135 0.318237" 153 | orientation: "0.0 0.0 0.0" 154 | 155 | # Adding new thruster in non-compliant position 156 | - prefix: "second_right" 157 | position: "-2.373776 -1.027135 0.318237" 158 | orientation: "0.0 0.0 0.0" 159 | ``` 160 | 161 | * generate_wamv.launch 162 | ```xml 163 | 164 | 165 | 166 | 167 | 168 | 169 | 170 | 171 | 172 | 173 | 174 | 175 | 176 | 177 | 178 | 179 | 180 | 181 | 182 | 183 | 184 | 185 | 186 | 187 | 188 | 189 | 190 | 191 | 192 | 193 | 194 | 195 | 196 | ``` 197 | 198 | * sandisland.launch 199 | ```xml 200 | 201 | 202 | 203 | 204 | 205 | 206 | 207 | 208 | 209 | 210 | 211 | 212 | 213 | 214 | 215 | 216 | 217 | 218 | 219 | 220 | 221 | 222 | 223 | 224 | 225 | 226 | 227 | 228 | 232 | 233 | 234 | 235 | 236 | 237 | 238 | 239 | 240 | 241 | 242 | 243 | 244 | 245 | 246 | 247 | 248 | 249 | 250 | 251 | 252 | 253 | 254 | 255 | 263 | 264 | 265 | 266 | 270 | 271 | 275 | 276 | ``` 277 | 278 | ## Compliance rules 279 | 1. All sensors must be contained within one of the sensor bounding boxes. 280 | 2. All thrusters must be contained within one of the thruster bounding boxes. 281 | 3. The number of each sensor and thruster in the configuration must be within the limit. 282 | 4. For thrusters, there can only be one thruster in each bounding box. 283 | * If you call __generate_wamv.launch__ on __non-compliant configuration YAML files__, red error messages will be printed but the URDF file will still be created. However, it is not a valid configuration for the VRX competition. 284 | 285 | * `generate_wamv.launch`: (generate_wamv python exe => import configure_wamv.py) 286 | * Input: Thruster/Sensor configurations YAML files 287 | * Output: Robot urdf file 288 | * Check YAML files compliance 289 | * Generate xacro files from YAML (YAML -> xacro) 290 | * Generate urdf file (xacro -> urdf -> robot) 291 | * In fact, it's configure_wamv.py doing all the stuff.(Compliance -> YAML -> xacro -> urdf) 292 | * To understand how to convert YAML to urdf, check out __configure_wamv.py__ 293 | 294 | * __Thruster/Sensor Required Parameters in thruster/sensor_config.yaml__ 295 | * In __wamv_camera.xacro__: (Import/Use by generate_wamv/configure_wamv.py(?) to generate wamv urdf) 296 | ```xml 297 | 298 | ``` 299 | * Required params: name (Must define in sensor_config.yaml) 300 | * Default params: x,y,z,R,P,Y 301 | * In __engine.xacro__: 302 | ```xml 303 | 304 | ``` 305 | * Required params: prefix (Must define in thruster_config.yaml) 306 | * Default params: position, orientation 307 | 308 | 309 | ## Boundary & Limitations 310 | * Sensor bounding box: 311 | ``` 312 | sensor_compliance_for: 313 | pose: '0.8 0 1.8 0 0 0' 314 | size: '1 1 1' 315 | capacity: '-1' 316 | sensor_compliance_aft: 317 | pose: '-0.9 0 1.8 0 0 0' 318 | size: '0.5 1 1' 319 | capacity: '-1' 320 | ``` 321 | * Thruster bounding box: 322 | ``` 323 | thruster_compliance_port_aft: 324 | pose: '-2.25 1 0 0 0 0' 325 | size: '1 1 1.2' 326 | capacity: '1' 327 | thruster_compliance_star_aft: 328 | pose: '-2.25 -1 0 0 0 0' 329 | size: '1 1 1.2' 330 | capacity: '1' 331 | thruster_compliance_port_for: 332 | pose: '1 1 0 0 0 0' 333 | size: '1 1 1.2' 334 | capacity: '1' 335 | thruster_compliance_star_for: 336 | pose: '1 -1 0 0 0 0' 337 | size: '1 1 1.2' 338 | capacity: '1' 339 | thruster_compliance_middle: 340 | pose: 0.25 0 0 0 0 0 341 | size: '2.5 1 1.2' 342 | capacity: '1' 343 | ``` 344 | * Sensor configuration limit 345 | ``` 346 | wamv_camera: 347 | num: 3 348 | allowed_params: 349 | x 350 | y 351 | z 352 | R 353 | P 354 | Y 355 | name 356 | post_Y 357 | 358 | wamv_gps: 359 | num: 1 360 | allowed_params: 361 | x 362 | y 363 | z 364 | R 365 | P 366 | Y 367 | name 368 | post_Y 369 | 370 | wamv_imu: 371 | num: 1 372 | allowed_params: 373 | x 374 | y 375 | z 376 | R 377 | P 378 | Y 379 | name 380 | post_Y 381 | 382 | lidar: 383 | num: 2 384 | allowed_params: 385 | x 386 | y 387 | z 388 | R 389 | P 390 | Y 391 | name 392 | post_Y 393 | type 394 | 395 | wamv_p3d: 396 | num: 0 397 | allowed_params: 398 | name 399 | ``` 400 | * Thruster configuration limit 401 | ``` 402 | engine: 403 | num: 4 404 | allowed_params: 405 | prefix 406 | position 407 | orientation 408 | 409 | ``` 410 | -------------------------------------------------------------------------------- /Ch7 ROS Virtual RobotX/Ch03_Propulsion_Configurations.md: -------------------------------------------------------------------------------- 1 | ## Propulsion Configurations 2 | 3 |
4 | 5 |

6 | 7 |
8 | 9 | * __"H": Differential Thrust :__ Two, Fixed Stern Thrusters (Default) 10 | ```console 11 | $ roslaunch vrx_gazebo sandisland.launch 12 | ``` 13 | 14 |
15 | 16 |

17 | 18 |
19 | 20 | * __"T": Differential Thrust :__ An Additional Lateral/Bow Thruster 21 | ```console 22 | $ roslaunch vrx_gazebo sandisland.launch thrust_config:=T 23 | ``` 24 | 25 |
26 | 27 |

28 | 29 |
30 | 31 | * __"X": Holonomic Thruster :__ Configuration with Four Fixed Thrusters 32 | ```console 33 | $ roslaunch vrx_gazebo sandisland.launch thrust_config:=X 34 | ``` 35 | 36 |
37 | 38 |

39 | 40 |
41 | -------------------------------------------------------------------------------- /Ch7 ROS Virtual RobotX/Ch04_Adding_Sensors.md: -------------------------------------------------------------------------------- 1 | ## Adding Sensors 2 | 3 | Create your own robot description file (URDF) for a custom WAM-V with your choice of sensors. 4 | 5 | 1. **Copy `wamv_gazebo wamv_gazebo.urdf.xacro`** 6 | ```console 7 | $ roscp wamv_gazebo wamv_gazebo.urdf.xacro my_wamv.urdf.xacro 8 | ``` 9 | 10 | 2. **Modify `my_wamv.urdf.xacro` (Remove all sensors on wamv and add lines below)** 11 | ```xml 12 | 13 | 14 | 15 | ``` 16 | 17 | * __Note :__ 18 | * A common property "stereo_x" is used so the value is not copied in multiple places 19 | * The x,y,z and P (pitch) set where the cameras are located **relative to the WAM-V base link** 20 | * A Python expression ${radians(15)} was used to convert 15 degrees to radians 21 | 22 | 3. **Compile xacro file** 23 | ```console 24 | $ rosrun xacro xacro --inorder my_wamv.urdf.xacro > my_wamv.urdf 25 | ``` 26 | 4. **Launch** 27 | ```console 28 | $ roslaunch vrx_gazebo sandisland.launch urdf:=`pwd`/my_wamv.urdf 29 | ``` 30 | ## Source file 31 | * my_wamv.urdf.xacro 32 | ```xml 33 | 34 | 35 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | wamv::base_link 105 | wamv_external_link 106 | 107 | 1 0 0 108 | 109 | 110 | 0 1 0 111 | 112 | 113 | 114 | world 115 | wamv_external_link 116 | 117 | 118 | -3 119 | 3 120 | 121 | 0 0 1 122 | 123 | 124 | 125 | 126 | 127 | 128 | 129 | 130 | 131 | 132 | 133 | ``` 134 | -------------------------------------------------------------------------------- /Ch7 ROS Virtual RobotX/Ch05_Thruster_Articulation.md: -------------------------------------------------------------------------------- 1 | ## Thruster Articulation 2 | 3 | 1. **Check out wamv_gazebo_thruster_config.xacro** 4 | ```console 5 | $ roscd wamv_gazebo/urdf/thruster_layouts 6 | $ vim wamv_gazebo_thruster_config.xacro 7 | ``` 8 | 2. **Launch** 9 | ```console 10 | $ roslaunch vrx_gazebo sandisland.launch 11 | ``` 12 | 13 | 3. **Run rqt_publisher to see params in topic** 14 | ```console 15 | $ rosrun rqt_publisher rqt_publisher 16 | ``` 17 | 18 | 4. **Click on the __topic dropdown menu__ and select:** 19 | * Topic `left_thrust_cmd` 20 | * Topic `left_thrust_angle` 21 | * Topic `right_thrust_cmd` 22 | * Topic `right_thrust_angle` 23 | 24 | 5. **Press plus sign on the right side to display select topic** 25 | 6. **Change the number by double clicking the value of the data** 26 | 7. **Click the box to start publishing** 27 | * __Note :__ 28 | * `Ctrl+Shift+R` to restart wamv position in Gazebo 29 | * `left/right_thrust_angle` value range from +1.57 to -1.57 (+90 degrees ~ -90 degrees) 30 | * If value > +1.57, value = 1.57 31 | * If value < -1.57, value = -1.57 32 | 33 | ## Source code 34 | * wamv_gazebo_thruster_config.xacro 35 | ```xml 36 | 37 | 38 | 39 | 40 | 41 | ${name}_propeller_link 42 | ${name}_engine_propeller_joint 43 | ${name}_chasis_engine_joint 44 | ${name}_thrust_cmd 45 | 46 | 47 | ${name}_thrust_angle 48 | 49 | true 50 | 51 | 52 | 1 53 | 1.0 54 | 250.0 55 | -100.0 56 | ${pi/2} 57 | 58 | 59 | 60 | ``` 61 | 62 | -------------------------------------------------------------------------------- /Ch7 ROS Virtual RobotX/Ch06_Driving.md: -------------------------------------------------------------------------------- 1 | ## Driving 2 | 3 | 1. **Launch simulation** 4 | ```console 5 | $ roslaunch vrx_gazebo sandisland.launch 6 | ``` 7 | 8 | 2. __Teleoperation :__ 9 | 1. __rostopic pub__ 10 | ```console 11 | $ rostopic pub --once /right_thrust_cmd std_msgs/Float32 "data: 1.0" 12 | ``` 13 | * This command will timeout after a pre-determined amount of time 14 | * Default is 1.0 s, but can be changed in the __wamv_gazebo_thruster_config.xacro__ 15 | * `1.0`

16 | 2. __Keyboard__ 17 | ```console 18 | $ roslaunch vrx_gazebo usv_keydrive.launch 19 | ``` 20 | * Make sure node `/twist2thrust` is publishing cmd to topic `left/right_thrust_cmd`(which gazebo is subscribing)

21 | 22 |
23 | 24 |

25 | 26 |
27 | 28 | * If gazebo isn't getting any message from node `/twist2thrust` (as shown in figure) 29 | * Modify `~/vrx_ws/src/vrx/vrx_gazebo/launch/usv_keydrive.launch` 30 | * Change `/wamv/thrusters/left_thrust_cmd` to `left_thrust_cmd`

31 | 32 | ```xml 33 | 34 | 35 | ``` 36 | 37 |
38 | 39 |

40 | 41 |
42 | 43 | * Debug: 44 | * `rosrun rqt_graph rqt_graph` 45 | * `rosnode/rostopic info/list` 46 |

47 | 48 |
49 | 50 |

51 | 52 |
53 | 54 | 3. __Gamepad__ 55 | ```console 56 | $ roslaunch vrx_gazebo usv_joydrive.launch 57 | ``` 58 | 59 | 60 | -------------------------------------------------------------------------------- /Ch7 ROS Virtual RobotX/Ch07_Visualizing_with_RViz.md: -------------------------------------------------------------------------------- 1 | ## Visualizing with RViz 2 | 3 | 1. __Launching Gazebo__ 4 | 5 | ```console 6 | $ roslaunch vrx_gazebo vrx.launch camera_enabled:=true gps_enabled:=true imu_enabled:=true 7 | ``` 8 | 9 | 2. __Publishing a TF tree__ 10 | * __Node :__ `robot_state_publisher` 11 | * `robot_state_publisher` will publish all the fixed/non-fixed joints in your URDF to the TF tree based on messages published to `/JointStates`. 12 | * `robot_state_publisher` is also in charge of deciding the relationship between map/odom/base_link (Rviz Frame). 13 | * Method 1: 14 | If you are using the example wamv_gazebo.urdf, run 15 | 16 | ```console 17 | $ roslaunch wamv_gazebo localization_example.launch 18 | ``` 19 | * Note : Odom frame 20 | 21 | * Method 2: 22 | Using a custom URDF without the standard GPS/IMU configuration, run the `robot_state_publisher` 23 | ```console 24 | $ rosrun robot_state_publisher robot_state_publisher 25 | ``` 26 | 27 | 3. Running RViz 28 | ```console 29 | $ roslaunch wamv_gazebo rviz_vrx.launch 30 | ``` 31 | -------------------------------------------------------------------------------- /Ch7 ROS Virtual RobotX/Ch08_Plugin_Parameters.md: -------------------------------------------------------------------------------- 1 | ## Plugin Parameters 2 | 3 | * __Changing the Wind__ 4 | * __sandisland.world.xacro__ include __usv_wind_plugin.xacro__ 5 | * Determine params such as __wind coefficient__ in __sandisland.world.xacro__ 6 | * Specify that the wind forces should be applied to the `wamv` model(?) 7 | 8 | * Method 1: Modify __usv_wind_plugin.xacro__ 9 | ```xml 10 | 11 | 12 | 21 | 22 | 23 | 24 | 25 | 26 | ${direction} 27 | ${mean_vel} 28 | ${var_gain} 29 | ${var_time} 30 | ${seed} 31 | ${ros_update_rate} 32 | 33 | 34 | 35 | ``` 36 | Note: Don't forget `catkin_make` before `roslaunch vrx_gazebo sandisland.launch` 37 | 38 | * Method 2: Modify __sandisland.world.xacro__ (X) 39 | ```xml 40 | 41 | 42 | 43 | 44 | wamv 45 | 8 <= Change Here! (X) 46 | base_link 47 | 0.5 0.5 0.33 48 | 49 | 50 | 51 | ``` 52 | Note: Any number of wind_obj's may be added under wind_objs. Only one link per model is supported. 53 | Note: Don't forget `catkin_make` before `roslaunch vrx_gazebo sandisland.launch` 54 | 55 | 56 | * Ways to change the wind plugin parameters: 57 | * Change the default wind parameters in __usv_wind_plugin.xacro__ 58 | * Override the default parameters in the __sandisland.world.xacro__ 59 | * Change the __models affected by wind__(?) or their coefficients in __sandisland.world.xacro__ 60 | * Make sure to run `catkin_make` after any changes to process the XML macros. 61 | 62 | * __Changing the Wave Field__ 63 | * Plugin file: `wave_gazebo/world_models/ocean_waves/model.xacro` 64 | * World file: `vrx_gazebo/worlds/example_course.world.xacro` 65 | ```xml 66 | 67 | 68 | 69 | 70 | ``` 71 | 72 | * Create ane environment without waves: 73 | * Method 1: Modify `wave_gazebo/world_models/ocean_waves/model.xacro` 74 | ```xml 75 | 78 | ``` 79 | Note: Don't forget `catkin_make` before `roslaunch vrx_gazebo vrx.launch` 80 | 81 | 82 | * Method 2: Modify `vrx_gazebo/worlds/example_course.world.xacro` 83 | ```xml 84 | 85 | 86 | <= Change Here! 87 | ``` 88 | Note: Don't forget `catkin_make` before `roslaunch vrx_gazebo vrx.launch` 89 | 90 | * __Changing Fog and Ambient Lighting__ 91 | * Modify `vrx_gazebo/worlds/sandisland.xacro` 92 | ```xml 93 | 94 | 95 | 96 | 12 97 | 98 | 99 | 0 100 | 0 101 | => Add tag 102 | linear 103 | 0.7 0.7 0.7 1 104 | 0.0 105 | 106 | 1.0 1.0 1.0 1 => Add tag 107 | 108 | ``` 109 | Note: Don't forget `catkin_make` before `roslaunch vrx_gazebo sandisland.launch` 110 | -------------------------------------------------------------------------------- /Ch7 ROS Virtual RobotX/Ch09_Custom_Dock.md: -------------------------------------------------------------------------------- 1 | ## Custom Dock 2 | 3 | 1. Create a new folder for your custom dock 4 | ```console 5 | $ mkdir -p ~/vrx_ws/src/vrx/vrx_gazebo/models/my_dock_base && cd ~/vrx_ws/src/vrx/vrx_gazebo/models/my_dock_base 6 | ``` 7 | 8 | 2. Create .config file 9 | ``` 10 | $ vim model.config 11 | ``` 12 | 13 | 3. Edit .config file 14 | ```xml 15 | 16 | 17 | my_dock_base 18 | 1.0 19 | model.sdf 20 | 21 | 22 | Carlos Agüero 23 | caguero@openrobotics.org 24 | 25 | 26 | 27 | My custom dock base. 28 | 29 | 30 | ``` 31 | 32 | 4. Create .sdf.erb file 33 | ``` 34 | $ vim model.sdf.erb 35 | ``` 36 | 37 | 5. Edit .sdf.erb file 38 | ```xml 39 | 40 | 41 | 42 | 43 | 44 | 45 | <% 46 | layout = [ 47 | 'X X', 48 | 'X X', 49 | 'X X', 50 | 'XXXXXXX', 51 | 'XXXX', 52 | 'XXXXXXX', 53 | 'X X', 54 | 'X X', 55 | 'X X', 56 | ] 57 | %> 58 | <%= ERB.new(File.read('dock_generator.erb'), 59 | nil, '-', 'dock').result(binding) %> 60 | 61 | 62 | ``` 63 | 64 | 6. Open the vrx_gazebo/CMakeLists.txt file and add your model 65 | ``` 66 | # Dock base files that need to be processed with erb 67 | set (dock_base_erb_files 68 | models/dock_2016_base/model.sdf.erb 69 | models/dock_2018_base/model.sdf.erb 70 | 71 | # THIS IS THE ONLY LINE THAT NEEDS TO BE ADDED. 72 | models/my_dock_base/model.sdf.erb <== Add this line 73 | ) 74 | ``` 75 | 76 | 7. Launch gazebo 77 | ``` 78 | $ roslaunch vrx_gazebo sandisland.launch 79 | ``` 80 | 81 | 8. Insert your new dock by clicking on `Insert->my_dock_base` 82 | -------------------------------------------------------------------------------- /Ch7 ROS Virtual RobotX/figure/driving_debug_before.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alonzo3569/ROS_Tutorial/595a93c0e960bfc832290e1c52995170cb525948/Ch7 ROS Virtual RobotX/figure/driving_debug_before.png -------------------------------------------------------------------------------- /Ch7 ROS Virtual RobotX/figure/keyboard_debug_after.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alonzo3569/ROS_Tutorial/595a93c0e960bfc832290e1c52995170cb525948/Ch7 ROS Virtual RobotX/figure/keyboard_debug_after.png -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ## Table of contents 2 | 1. **ROS Node & Topic** 3 | 2. **ROS Service** 4 | 3. **ROS Custom Message** 5 | 4. **ROS Params & Launch Files** 6 | 5. **ROS Bag & OOP** 7 | 6. **ROS Gazebo** 8 | * Launch Your First Gazebo World Using ROS 9 | * Add gazebo models to a simulation 10 | * Spawn a robot in gazebo 11 | * Create a gazebo model using SDF 12 | * Use a mesh file to create a gazebo model 13 | * Use an image file as texture for gazebo model 14 | * Create a robot using URDF 15 | * Visualize a robot URDF using RVIZ 16 | * Create a robot using URDF(Advance & RVIZ) 17 | 7. **ROS Virtual RobotX** 18 | * Adding Course Elements 19 | * Custom WAM-V Thruster and Sensor Configuration 20 | * Propulsion Configurations 21 | * Adding Sensors 22 | * Thruster Articulation 23 | * Driving 24 | * Visualizing with RViz 25 | * Plugin Parameters 26 | * Custom Dock 27 | -------------------------------------------------------------------------------- /src/my_robot_bringup/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 2.8.3) 2 | project(my_robot_bringup) 3 | 4 | ## Compile as C++11, supported in ROS Kinetic and newer 5 | # add_compile_options(-std=c++11) 6 | 7 | ## Find catkin macros and libraries 8 | ## if COMPONENTS list like find_package(catkin REQUIRED COMPONENTS xyz) 9 | ## is used, also find other catkin packages 10 | find_package(catkin REQUIRED) 11 | 12 | ## System dependencies are found with CMake's conventions 13 | # find_package(Boost REQUIRED COMPONENTS system) 14 | 15 | 16 | ## Uncomment this if the package has a setup.py. This macro ensures 17 | ## modules and global scripts declared therein get installed 18 | ## See http://ros.org/doc/api/catkin/html/user_guide/setup_dot_py.html 19 | # catkin_python_setup() 20 | 21 | ################################################ 22 | ## Declare ROS messages, services and actions ## 23 | ################################################ 24 | 25 | ## To declare and build messages, services or actions from within this 26 | ## package, follow these steps: 27 | ## * Let MSG_DEP_SET be the set of packages whose message types you use in 28 | ## your messages/services/actions (e.g. std_msgs, actionlib_msgs, ...). 29 | ## * In the file package.xml: 30 | ## * add a build_depend tag for "message_generation" 31 | ## * add a build_depend and a exec_depend tag for each package in MSG_DEP_SET 32 | ## * If MSG_DEP_SET isn't empty the following dependency has been pulled in 33 | ## but can be declared for certainty nonetheless: 34 | ## * add a exec_depend tag for "message_runtime" 35 | ## * In this file (CMakeLists.txt): 36 | ## * add "message_generation" and every package in MSG_DEP_SET to 37 | ## find_package(catkin REQUIRED COMPONENTS ...) 38 | ## * add "message_runtime" and every package in MSG_DEP_SET to 39 | ## catkin_package(CATKIN_DEPENDS ...) 40 | ## * uncomment the add_*_files sections below as needed 41 | ## and list every .msg/.srv/.action file to be processed 42 | ## * uncomment the generate_messages entry below 43 | ## * add every package in MSG_DEP_SET to generate_messages(DEPENDENCIES ...) 44 | 45 | ## Generate messages in the 'msg' folder 46 | # add_message_files( 47 | # FILES 48 | # Message1.msg 49 | # Message2.msg 50 | # ) 51 | 52 | ## Generate services in the 'srv' folder 53 | # add_service_files( 54 | # FILES 55 | # Service1.srv 56 | # Service2.srv 57 | # ) 58 | 59 | ## Generate actions in the 'action' folder 60 | # add_action_files( 61 | # FILES 62 | # Action1.action 63 | # Action2.action 64 | # ) 65 | 66 | ## Generate added messages and services with any dependencies listed here 67 | # generate_messages( 68 | # DEPENDENCIES 69 | # std_msgs # Or other packages containing msgs 70 | # ) 71 | 72 | ################################################ 73 | ## Declare ROS dynamic reconfigure parameters ## 74 | ################################################ 75 | 76 | ## To declare and build dynamic reconfigure parameters within this 77 | ## package, follow these steps: 78 | ## * In the file package.xml: 79 | ## * add a build_depend and a exec_depend tag for "dynamic_reconfigure" 80 | ## * In this file (CMakeLists.txt): 81 | ## * add "dynamic_reconfigure" to 82 | ## find_package(catkin REQUIRED COMPONENTS ...) 83 | ## * uncomment the "generate_dynamic_reconfigure_options" section below 84 | ## and list every .cfg file to be processed 85 | 86 | ## Generate dynamic reconfigure parameters in the 'cfg' folder 87 | # generate_dynamic_reconfigure_options( 88 | # cfg/DynReconf1.cfg 89 | # cfg/DynReconf2.cfg 90 | # ) 91 | 92 | ################################### 93 | ## catkin specific configuration ## 94 | ################################### 95 | ## The catkin_package macro generates cmake config files for your package 96 | ## Declare things to be passed to dependent projects 97 | ## INCLUDE_DIRS: uncomment this if your package contains header files 98 | ## LIBRARIES: libraries you create in this project that dependent projects also need 99 | ## CATKIN_DEPENDS: catkin_packages dependent projects also need 100 | ## DEPENDS: system dependencies of this project that dependent projects also need 101 | catkin_package( 102 | # INCLUDE_DIRS include 103 | # LIBRARIES my_robot_bringup 104 | # CATKIN_DEPENDS other_catkin_pkg 105 | # DEPENDS system_lib 106 | ) 107 | 108 | ########### 109 | ## Build ## 110 | ########### 111 | 112 | ## Specify additional locations of header files 113 | ## Your package locations should be listed before other locations 114 | include_directories( 115 | # include 116 | # ${catkin_INCLUDE_DIRS} 117 | ) 118 | 119 | ## Declare a C++ library 120 | # add_library(${PROJECT_NAME} 121 | # src/${PROJECT_NAME}/my_robot_bringup.cpp 122 | # ) 123 | 124 | ## Add cmake target dependencies of the library 125 | ## as an example, code may need to be generated before libraries 126 | ## either from message generation or dynamic reconfigure 127 | # add_dependencies(${PROJECT_NAME} ${${PROJECT_NAME}_EXPORTED_TARGETS} ${catkin_EXPORTED_TARGETS}) 128 | 129 | ## Declare a C++ executable 130 | ## With catkin_make all packages are built within a single CMake context 131 | ## The recommended prefix ensures that target names across packages don't collide 132 | # add_executable(${PROJECT_NAME}_node src/my_robot_bringup_node.cpp) 133 | 134 | ## Rename C++ executable without prefix 135 | ## The above recommended prefix causes long target names, the following renames the 136 | ## target back to the shorter version for ease of user use 137 | ## e.g. "rosrun someones_pkg node" instead of "rosrun someones_pkg someones_pkg_node" 138 | # set_target_properties(${PROJECT_NAME}_node PROPERTIES OUTPUT_NAME node PREFIX "") 139 | 140 | ## Add cmake target dependencies of the executable 141 | ## same as for the library above 142 | # add_dependencies(${PROJECT_NAME}_node ${${PROJECT_NAME}_EXPORTED_TARGETS} ${catkin_EXPORTED_TARGETS}) 143 | 144 | ## Specify libraries to link a library or executable target against 145 | # target_link_libraries(${PROJECT_NAME}_node 146 | # ${catkin_LIBRARIES} 147 | # ) 148 | 149 | ############# 150 | ## Install ## 151 | ############# 152 | 153 | # all install targets should use catkin DESTINATION variables 154 | # See http://ros.org/doc/api/catkin/html/adv_user_guide/variables.html 155 | 156 | ## Mark executable scripts (Python etc.) for installation 157 | ## in contrast to setup.py, you can choose the destination 158 | # install(PROGRAMS 159 | # scripts/my_python_script 160 | # DESTINATION ${CATKIN_PACKAGE_BIN_DESTINATION} 161 | # ) 162 | 163 | ## Mark executables and/or libraries for installation 164 | # install(TARGETS ${PROJECT_NAME} ${PROJECT_NAME}_node 165 | # ARCHIVE DESTINATION ${CATKIN_PACKAGE_LIB_DESTINATION} 166 | # LIBRARY DESTINATION ${CATKIN_PACKAGE_LIB_DESTINATION} 167 | # RUNTIME DESTINATION ${CATKIN_PACKAGE_BIN_DESTINATION} 168 | # ) 169 | 170 | ## Mark cpp header files for installation 171 | # install(DIRECTORY include/${PROJECT_NAME}/ 172 | # DESTINATION ${CATKIN_PACKAGE_INCLUDE_DESTINATION} 173 | # FILES_MATCHING PATTERN "*.h" 174 | # PATTERN ".svn" EXCLUDE 175 | # ) 176 | 177 | ## Mark other files for installation (e.g. launch and bag files, etc.) 178 | # install(FILES 179 | # # myfile1 180 | # # myfile2 181 | # DESTINATION ${CATKIN_PACKAGE_SHARE_DESTINATION} 182 | # ) 183 | 184 | ############# 185 | ## Testing ## 186 | ############# 187 | 188 | ## Add gtest based cpp test target and link libraries 189 | # catkin_add_gtest(${PROJECT_NAME}-test test/test_my_robot_bringup.cpp) 190 | # if(TARGET ${PROJECT_NAME}-test) 191 | # target_link_libraries(${PROJECT_NAME}-test ${PROJECT_NAME}) 192 | # endif() 193 | 194 | ## Add folders to be run by python nosetests 195 | # catkin_add_nosetests(test) 196 | -------------------------------------------------------------------------------- /src/my_robot_bringup/launch/number_app.launch: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /src/my_robot_bringup/package.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | my_robot_bringup 4 | 0.0.0 5 | The my_robot_bringup package 6 | 7 | 8 | 9 | 10 | ros 11 | 12 | 13 | 14 | 15 | 16 | TODO 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | catkin 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | -------------------------------------------------------------------------------- /src/my_robot_msgs/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 2.8.3) 2 | project(my_robot_msgs) 3 | 4 | ## Compile as C++11, supported in ROS Kinetic and newer 5 | # add_compile_options(-std=c++11) 6 | 7 | ## Find catkin macros and libraries 8 | ## if COMPONENTS list like find_package(catkin REQUIRED COMPONENTS xyz) 9 | ## is used, also find other catkin packages 10 | find_package(catkin REQUIRED COMPONENTS 11 | roscpp 12 | rospy 13 | std_msgs 14 | message_generation 15 | ) 16 | 17 | ## System dependencies are found with CMake's conventions 18 | # find_package(Boost REQUIRED COMPONENTS system) 19 | 20 | 21 | ## Uncomment this if the package has a setup.py. This macro ensures 22 | ## modules and global scripts declared therein get installed 23 | ## See http://ros.org/doc/api/catkin/html/user_guide/setup_dot_py.html 24 | # catkin_python_setup() 25 | 26 | ################################################ 27 | ## Declare ROS messages, services and actions ## 28 | ################################################ 29 | 30 | ## To declare and build messages, services or actions from within this 31 | ## package, follow these steps: 32 | ## * Let MSG_DEP_SET be the set of packages whose message types you use in 33 | ## your messages/services/actions (e.g. std_msgs, actionlib_msgs, ...). 34 | ## * In the file package.xml: 35 | ## * add a build_depend tag for "message_generation" 36 | ## * add a build_depend and a exec_depend tag for each package in MSG_DEP_SET 37 | ## * If MSG_DEP_SET isn't empty the following dependency has been pulled in 38 | ## but can be declared for certainty nonetheless: 39 | ## * add a exec_depend tag for "message_runtime" 40 | ## * In this file (CMakeLists.txt): 41 | ## * add "message_generation" and every package in MSG_DEP_SET to 42 | ## find_package(catkin REQUIRED COMPONENTS ...) 43 | ## * add "message_runtime" and every package in MSG_DEP_SET to 44 | ## catkin_package(CATKIN_DEPENDS ...) 45 | ## * uncomment the add_*_files sections below as needed 46 | ## and list every .msg/.srv/.action file to be processed 47 | ## * uncomment the generate_messages entry below 48 | ## * add every package in MSG_DEP_SET to generate_messages(DEPENDENCIES ...) 49 | 50 | ## Generate messages in the 'msg' folder 51 | add_message_files( 52 | FILES 53 | HardwareStatus.msg 54 | ) 55 | 56 | ## Generate services in the 'srv' folder 57 | add_service_files( 58 | FILES 59 | ComputeDiskArea.srv 60 | SetLed.srv 61 | ) 62 | 63 | ## Generate actions in the 'action' folder 64 | # add_action_files( 65 | # FILES 66 | # Action1.action 67 | # Action2.action 68 | # ) 69 | 70 | ## Generate added messages and services with any dependencies listed here 71 | generate_messages( 72 | DEPENDENCIES 73 | std_msgs 74 | ) 75 | 76 | ################################################ 77 | ## Declare ROS dynamic reconfigure parameters ## 78 | ################################################ 79 | 80 | ## To declare and build dynamic reconfigure parameters within this 81 | ## package, follow these steps: 82 | ## * In the file package.xml: 83 | ## * add a build_depend and a exec_depend tag for "dynamic_reconfigure" 84 | ## * In this file (CMakeLists.txt): 85 | ## * add "dynamic_reconfigure" to 86 | ## find_package(catkin REQUIRED COMPONENTS ...) 87 | ## * uncomment the "generate_dynamic_reconfigure_options" section below 88 | ## and list every .cfg file to be processed 89 | 90 | ## Generate dynamic reconfigure parameters in the 'cfg' folder 91 | # generate_dynamic_reconfigure_options( 92 | # cfg/DynReconf1.cfg 93 | # cfg/DynReconf2.cfg 94 | # ) 95 | 96 | ################################### 97 | ## catkin specific configuration ## 98 | ################################### 99 | ## The catkin_package macro generates cmake config files for your package 100 | ## Declare things to be passed to dependent projects 101 | ## INCLUDE_DIRS: uncomment this if your package contains header files 102 | ## LIBRARIES: libraries you create in this project that dependent projects also need 103 | ## CATKIN_DEPENDS: catkin_packages dependent projects also need 104 | ## DEPENDS: system dependencies of this project that dependent projects also need 105 | catkin_package( 106 | # INCLUDE_DIRS include 107 | # LIBRARIES my_robot_msgs 108 | CATKIN_DEPENDS roscpp rospy std_msgs message_runtime 109 | # DEPENDS system_lib 110 | ) 111 | 112 | ########### 113 | ## Build ## 114 | ########### 115 | 116 | ## Specify additional locations of header files 117 | ## Your package locations should be listed before other locations 118 | include_directories( 119 | # include 120 | ${catkin_INCLUDE_DIRS} 121 | ) 122 | 123 | ## Declare a C++ library 124 | # add_library(${PROJECT_NAME} 125 | # src/${PROJECT_NAME}/my_robot_msgs.cpp 126 | # ) 127 | 128 | ## Add cmake target dependencies of the library 129 | ## as an example, code may need to be generated before libraries 130 | ## either from message generation or dynamic reconfigure 131 | # add_dependencies(${PROJECT_NAME} ${${PROJECT_NAME}_EXPORTED_TARGETS} ${catkin_EXPORTED_TARGETS}) 132 | 133 | ## Declare a C++ executable 134 | ## With catkin_make all packages are built within a single CMake context 135 | ## The recommended prefix ensures that target names across packages don't collide 136 | # add_executable(${PROJECT_NAME}_node src/my_robot_msgs_node.cpp) 137 | 138 | ## Rename C++ executable without prefix 139 | ## The above recommended prefix causes long target names, the following renames the 140 | ## target back to the shorter version for ease of user use 141 | ## e.g. "rosrun someones_pkg node" instead of "rosrun someones_pkg someones_pkg_node" 142 | # set_target_properties(${PROJECT_NAME}_node PROPERTIES OUTPUT_NAME node PREFIX "") 143 | 144 | ## Add cmake target dependencies of the executable 145 | ## same as for the library above 146 | # add_dependencies(${PROJECT_NAME}_node ${${PROJECT_NAME}_EXPORTED_TARGETS} ${catkin_EXPORTED_TARGETS}) 147 | 148 | ## Specify libraries to link a library or executable target against 149 | # target_link_libraries(${PROJECT_NAME}_node 150 | # ${catkin_LIBRARIES} 151 | # ) 152 | 153 | ############# 154 | ## Install ## 155 | ############# 156 | 157 | # all install targets should use catkin DESTINATION variables 158 | # See http://ros.org/doc/api/catkin/html/adv_user_guide/variables.html 159 | 160 | ## Mark executable scripts (Python etc.) for installation 161 | ## in contrast to setup.py, you can choose the destination 162 | # install(PROGRAMS 163 | # scripts/my_python_script 164 | # DESTINATION ${CATKIN_PACKAGE_BIN_DESTINATION} 165 | # ) 166 | 167 | ## Mark executables and/or libraries for installation 168 | # install(TARGETS ${PROJECT_NAME} ${PROJECT_NAME}_node 169 | # ARCHIVE DESTINATION ${CATKIN_PACKAGE_LIB_DESTINATION} 170 | # LIBRARY DESTINATION ${CATKIN_PACKAGE_LIB_DESTINATION} 171 | # RUNTIME DESTINATION ${CATKIN_PACKAGE_BIN_DESTINATION} 172 | # ) 173 | 174 | ## Mark cpp header files for installation 175 | # install(DIRECTORY include/${PROJECT_NAME}/ 176 | # DESTINATION ${CATKIN_PACKAGE_INCLUDE_DESTINATION} 177 | # FILES_MATCHING PATTERN "*.h" 178 | # PATTERN ".svn" EXCLUDE 179 | # ) 180 | 181 | ## Mark other files for installation (e.g. launch and bag files, etc.) 182 | # install(FILES 183 | # # myfile1 184 | # # myfile2 185 | # DESTINATION ${CATKIN_PACKAGE_SHARE_DESTINATION} 186 | # ) 187 | 188 | ############# 189 | ## Testing ## 190 | ############# 191 | 192 | ## Add gtest based cpp test target and link libraries 193 | # catkin_add_gtest(${PROJECT_NAME}-test test/test_my_robot_msgs.cpp) 194 | # if(TARGET ${PROJECT_NAME}-test) 195 | # target_link_libraries(${PROJECT_NAME}-test ${PROJECT_NAME}) 196 | # endif() 197 | 198 | ## Add folders to be run by python nosetests 199 | # catkin_add_nosetests(test) 200 | -------------------------------------------------------------------------------- /src/my_robot_msgs/msg/HardwareStatus.msg: -------------------------------------------------------------------------------- 1 | int64 temperature 2 | bool are_motors_up 3 | string debug_message 4 | -------------------------------------------------------------------------------- /src/my_robot_msgs/package.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | my_robot_msgs 4 | 0.0.0 5 | The my_robot_msgs package 6 | 7 | 8 | 9 | 10 | ros 11 | 12 | 13 | 14 | 15 | 16 | TODO 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | catkin 52 | roscpp 53 | rospy 54 | std_msgs 55 | message_generation 56 | roscpp 57 | rospy 58 | std_msgs 59 | roscpp 60 | rospy 61 | std_msgs 62 | message_runtime 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | -------------------------------------------------------------------------------- /src/my_robot_msgs/srv/ComputeDiskArea.srv: -------------------------------------------------------------------------------- 1 | float64 radius 2 | --- 3 | float64 area 4 | -------------------------------------------------------------------------------- /src/my_robot_msgs/srv/SetLed.srv: -------------------------------------------------------------------------------- 1 | int64 led_number 2 | int64 state 3 | --- 4 | bool success 5 | -------------------------------------------------------------------------------- /src/my_robot_tutorials/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 2.8.3) 2 | project(my_robot_tutorials) 3 | 4 | ## Compile as C++11, supported in ROS Kinetic and newer 5 | # add_compile_options(-std=c++11) 6 | 7 | ## Find catkin macros and libraries 8 | ## if COMPONENTS list like find_package(catkin REQUIRED COMPONENTS xyz) 9 | ## is used, also find other catkin packages 10 | find_package(catkin REQUIRED COMPONENTS 11 | roscpp 12 | rospy 13 | std_msgs 14 | std_srvs 15 | rospy_tutorials 16 | my_robot_msgs 17 | ) 18 | 19 | ## System dependencies are found with CMake's conventions 20 | # find_package(Boost REQUIRED COMPONENTS system) 21 | 22 | 23 | ## Uncomment this if the package has a setup.py. This macro ensures 24 | ## modules and global scripts declared therein get installed 25 | ## See http://ros.org/doc/api/catkin/html/user_guide/setup_dot_py.html 26 | # catkin_python_setup() 27 | 28 | ################################################ 29 | ## Declare ROS messages, services and actions ## 30 | ################################################ 31 | 32 | ## To declare and build messages, services or actions from within this 33 | ## package, follow these steps: 34 | ## * Let MSG_DEP_SET be the set of packages whose message types you use in 35 | ## your messages/services/actions (e.g. std_msgs, actionlib_msgs, ...). 36 | ## * In the file package.xml: 37 | ## * add a build_depend tag for "message_generation" 38 | ## * add a build_depend and a exec_depend tag for each package in MSG_DEP_SET 39 | ## * If MSG_DEP_SET isn't empty the following dependency has been pulled in 40 | ## but can be declared for certainty nonetheless: 41 | ## * add a exec_depend tag for "message_runtime" 42 | ## * In this file (CMakeLists.txt): 43 | ## * add "message_generation" and every package in MSG_DEP_SET to 44 | ## find_package(catkin REQUIRED COMPONENTS ...) 45 | ## * add "message_runtime" and every package in MSG_DEP_SET to 46 | ## catkin_package(CATKIN_DEPENDS ...) 47 | ## * uncomment the add_*_files sections below as needed 48 | ## and list every .msg/.srv/.action file to be processed 49 | ## * uncomment the generate_messages entry below 50 | ## * add every package in MSG_DEP_SET to generate_messages(DEPENDENCIES ...) 51 | 52 | ## Generate messages in the 'msg' folder 53 | # add_message_files( 54 | # FILES 55 | # Message1.msg 56 | # Message2.msg 57 | # ) 58 | 59 | ## Generate services in the 'srv' folder 60 | # add_service_files( 61 | # FILES 62 | # Service1.srv 63 | # Service2.srv 64 | # ) 65 | 66 | ## Generate actions in the 'action' folder 67 | # add_action_files( 68 | # FILES 69 | # Action1.action 70 | # Action2.action 71 | # ) 72 | 73 | ## Generate added messages and services with any dependencies listed here 74 | # generate_messages( 75 | # DEPENDENCIES 76 | # std_msgs 77 | # ) 78 | 79 | ################################################ 80 | ## Declare ROS dynamic reconfigure parameters ## 81 | ################################################ 82 | 83 | ## To declare and build dynamic reconfigure parameters within this 84 | ## package, follow these steps: 85 | ## * In the file package.xml: 86 | ## * add a build_depend and a exec_depend tag for "dynamic_reconfigure" 87 | ## * In this file (CMakeLists.txt): 88 | ## * add "dynamic_reconfigure" to 89 | ## find_package(catkin REQUIRED COMPONENTS ...) 90 | ## * uncomment the "generate_dynamic_reconfigure_options" section below 91 | ## and list every .cfg file to be processed 92 | 93 | ## Generate dynamic reconfigure parameters in the 'cfg' folder 94 | # generate_dynamic_reconfigure_options( 95 | # cfg/DynReconf1.cfg 96 | # cfg/DynReconf2.cfg 97 | # ) 98 | 99 | ################################### 100 | ## catkin specific configuration ## 101 | ################################### 102 | ## The catkin_package macro generates cmake config files for your package 103 | ## Declare things to be passed to dependent projects 104 | ## INCLUDE_DIRS: uncomment this if your package contains header files 105 | ## LIBRARIES: libraries you create in this project that dependent projects also need 106 | ## CATKIN_DEPENDS: catkin_packages dependent projects also need 107 | ## DEPENDS: system dependencies of this project that dependent projects also need 108 | catkin_package( 109 | # INCLUDE_DIRS include 110 | # LIBRARIES my_robot_tutorials 111 | # CATKIN_DEPENDS roscpp rospy std_msgs 112 | # DEPENDS system_lib 113 | ) 114 | 115 | ########### 116 | ## Build ## 117 | ########### 118 | 119 | ## Specify additional locations of header files 120 | ## Your package locations should be listed before other locations 121 | include_directories( 122 | # include 123 | ${catkin_INCLUDE_DIRS} 124 | ) 125 | 126 | ## Declare a C++ library 127 | # add_library(${PROJECT_NAME} 128 | # src/${PROJECT_NAME}/my_robot_tutorials.cpp 129 | # ) 130 | 131 | ## Add cmake target dependencies of the library 132 | ## as an example, code may need to be generated before libraries 133 | ## either from message generation or dynamic reconfigure 134 | # add_dependencies(${PROJECT_NAME} ${${PROJECT_NAME}_EXPORTED_TARGETS} ${catkin_EXPORTED_TARGETS}) 135 | 136 | ## Declare a C++ executable 137 | ## With catkin_make all packages are built within a single CMake context 138 | ## The recommended prefix ensures that target names across packages don't collide 139 | # add_executable(${PROJECT_NAME}_node src/my_robot_tutorials_node.cpp) 140 | 141 | add_executable(node_cpp src/my_first_node.cpp) 142 | target_link_libraries(node_cpp ${catkin_LIBRARIES}) 143 | 144 | add_executable(robot_news_radio_transmitter src/robot_news_radio_transmitter.cpp) 145 | target_link_libraries(robot_news_radio_transmitter ${catkin_LIBRARIES}) 146 | 147 | add_executable(smartphone_node src/smartphone_node.cpp) 148 | target_link_libraries(smartphone_node ${catkin_LIBRARIES}) 149 | 150 | add_executable(number_publisher src/number_publisher.cpp) 151 | target_link_libraries(number_publisher ${catkin_LIBRARIES}) 152 | 153 | add_executable(number_counter src/number_counter.cpp) 154 | target_link_libraries(number_counter ${catkin_LIBRARIES}) 155 | 156 | add_executable(add_two_ints_server src/add_two_ints_server.cpp) 157 | target_link_libraries(add_two_ints_server ${catkin_LIBRARIES}) 158 | 159 | add_executable(add_two_ints_client src/add_two_ints_client.cpp) 160 | target_link_libraries(add_two_ints_client ${catkin_LIBRARIES}) 161 | 162 | add_executable(oop_number_counter src/oop_number_counter.cpp) 163 | target_link_libraries(oop_number_counter ${catkin_LIBRARIES}) 164 | 165 | ## Rename C++ executable without prefix 166 | ## The above recommended prefix causes long target names, the following renames the 167 | ## target back to the shorter version for ease of user use 168 | ## e.g. "rosrun someones_pkg node" instead of "rosrun someones_pkg someones_pkg_node" 169 | # set_target_properties(${PROJECT_NAME}_node PROPERTIES OUTPUT_NAME node PREFIX "") 170 | 171 | ## Add cmake target dependencies of the executable 172 | ## same as for the library above 173 | # add_dependencies(${PROJECT_NAME}_node ${${PROJECT_NAME}_EXPORTED_TARGETS} ${catkin_EXPORTED_TARGETS}) 174 | 175 | ## Specify libraries to link a library or executable target against 176 | # target_link_libraries(${PROJECT_NAME}_node 177 | # ${catkin_LIBRARIES} 178 | # ) 179 | 180 | ############# 181 | ## Install ## 182 | ############# 183 | 184 | # all install targets should use catkin DESTINATION variables 185 | # See http://ros.org/doc/api/catkin/html/adv_user_guide/variables.html 186 | 187 | ## Mark executable scripts (Python etc.) for installation 188 | ## in contrast to setup.py, you can choose the destination 189 | # install(PROGRAMS 190 | # scripts/my_python_script 191 | # DESTINATION ${CATKIN_PACKAGE_BIN_DESTINATION} 192 | # ) 193 | 194 | ## Mark executables and/or libraries for installation 195 | # install(TARGETS ${PROJECT_NAME} ${PROJECT_NAME}_node 196 | # ARCHIVE DESTINATION ${CATKIN_PACKAGE_LIB_DESTINATION} 197 | # LIBRARY DESTINATION ${CATKIN_PACKAGE_LIB_DESTINATION} 198 | # RUNTIME DESTINATION ${CATKIN_PACKAGE_BIN_DESTINATION} 199 | # ) 200 | 201 | ## Mark cpp header files for installation 202 | # install(DIRECTORY include/${PROJECT_NAME}/ 203 | # DESTINATION ${CATKIN_PACKAGE_INCLUDE_DESTINATION} 204 | # FILES_MATCHING PATTERN "*.h" 205 | # PATTERN ".svn" EXCLUDE 206 | # ) 207 | 208 | ## Mark other files for installation (e.g. launch and bag files, etc.) 209 | # install(FILES 210 | # # myfile1 211 | # # myfile2 212 | # DESTINATION ${CATKIN_PACKAGE_SHARE_DESTINATION} 213 | # ) 214 | 215 | ############# 216 | ## Testing ## 217 | ############# 218 | 219 | ## Add gtest based cpp test target and link libraries 220 | # catkin_add_gtest(${PROJECT_NAME}-test test/test_my_robot_tutorials.cpp) 221 | # if(TARGET ${PROJECT_NAME}-test) 222 | # target_link_libraries(${PROJECT_NAME}-test ${PROJECT_NAME}) 223 | # endif() 224 | 225 | ## Add folders to be run by python nosetests 226 | # catkin_add_nosetests(test) 227 | -------------------------------------------------------------------------------- /src/my_robot_tutorials/package.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | my_robot_tutorials 4 | 0.0.0 5 | The my_robot_tutorials package 6 | 7 | 8 | 9 | 10 | ros 11 | 12 | 13 | 14 | 15 | 16 | TODO 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | catkin 52 | roscpp 53 | rospy 54 | std_msgs 55 | std_srvs 56 | rospy_tutorials 57 | roscpp 58 | rospy 59 | std_msgs 60 | std_srvs 61 | rospy_tutorials 62 | roscpp 63 | rospy 64 | std_msgs 65 | std_srvs 66 | rospy_tutorials 67 | 68 | my_robot_msgs 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | -------------------------------------------------------------------------------- /src/my_robot_tutorials/scripts/add_two_ints_client.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | import rospy 4 | from rospy_tutorials.srv import AddTwoInts 5 | 6 | if __name__ == '__main__': 7 | rospy.init_node("add_two_ints_client") 8 | 9 | rospy.wait_for_service("/add_two_ints") 10 | 11 | try: 12 | add_two_ints = rospy.ServiceProxy("/add_two_ints", AddTwoInts) 13 | response = add_two_ints(2,6) 14 | rospy.loginfo("Sum is : " + str(response.sum)) 15 | except rospy.ServiceException as e: 16 | rospy.logwarn("Service failed: " + str(e)) 17 | -------------------------------------------------------------------------------- /src/my_robot_tutorials/scripts/add_two_ints_server.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | import rospy 4 | from rospy_tutorials.srv import AddTwoInts 5 | 6 | def handle_add_two_ints(req): 7 | result = req.a + req.b 8 | rospy.loginfo("Sum of " + str(req.a) + " and " + str(req.b) + " is " + str(result)) 9 | return result 10 | 11 | if __name__ == '__main__': 12 | rospy.init_node("add_two_ints_server") 13 | rospy.loginfo("Add two ints server node created") 14 | 15 | service = rospy.Service("/add_two_ints", AddTwoInts, handle_add_two_ints) 16 | rospy.loginfo("Service server has been started") 17 | 18 | rospy.spin() 19 | -------------------------------------------------------------------------------- /src/my_robot_tutorials/scripts/battery.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | import rospy 4 | from my_robot_msgs.srv import SetLed 5 | 6 | def set_led(battery_state): 7 | rospy.wait_for_service("/set_led") 8 | try: 9 | service = rospy.ServiceProxy("/set_led", SetLed) 10 | state = 0 11 | if battery_state == 'empty': 12 | state = 1 13 | resp = service(1, state) 14 | rospy.loginfo("Set led success flag : " + str(resp)) 15 | except rospy.ServiceException as e: 16 | rospy.logerr(e) 17 | 18 | 19 | if __name__ == '__main__': 20 | rospy.init_node('battery') 21 | 22 | battery_state = "full" 23 | 24 | while not rospy.is_shutdown(): 25 | rospy.sleep(7) 26 | battery_state = "empty" 27 | rospy.loginfo("The battery is empty !") 28 | set_led(battery_state) 29 | rospy.sleep(3) 30 | battery_state = "full" 31 | rospy.loginfo("The battery is now full") 32 | set_led(battery_state) 33 | -------------------------------------------------------------------------------- /src/my_robot_tutorials/scripts/hw_status_publisher.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | import rospy 4 | from my_robot_msgs.msg import HardwareStatus 5 | 6 | if __name__ == '__main__': 7 | rospy.init_node("hardware_status_publisher") 8 | 9 | pub = rospy.Publisher("/my_robot/hardware_status", HardwareStatus, queue_size=10) 10 | 11 | rate = rospy.Rate(5) 12 | 13 | while not rospy.is_shutdown(): 14 | msg = HardwareStatus() 15 | msg.temperature = 45 16 | msg.are_motors_up = True 17 | msg.debug_message = "Everything is running well" 18 | pub.publish(msg) 19 | rate.sleep() 20 | -------------------------------------------------------------------------------- /src/my_robot_tutorials/scripts/led_panel.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | import rospy 4 | from my_robot_msgs.srv import SetLed 5 | 6 | led_states = [0,0,0] 7 | 8 | def callback_set_led(req): 9 | led_number = req.led_number 10 | state = req.state 11 | global led_states 12 | 13 | if (led_number > len(led_states)) or (led_number <= 0): 14 | return False 15 | 16 | if not (state == 0 or state == 1): 17 | return False 18 | 19 | led_states[led_number - 1] = state 20 | 21 | return True 22 | 23 | if __name__ == '__main__': 24 | rospy.init_node('led_panel') 25 | 26 | 27 | server = rospy.Service("/set_led", SetLed, callback_set_led) 28 | 29 | rate = rospy.Rate(10) 30 | 31 | while not rospy.is_shutdown(): 32 | rospy.loginfo(led_states) 33 | rate.sleep() 34 | 35 | -------------------------------------------------------------------------------- /src/my_robot_tutorials/scripts/my_first_node.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | import rospy 4 | 5 | if __name__ == '__main__': 6 | rospy.init_node('my_first_python_node') 7 | rospy.loginfo("This node has been started") 8 | 9 | rate = rospy.Rate(10) 10 | 11 | while not rospy.is_shutdown(): 12 | rospy.loginfo("Hello") 13 | rate.sleep() 14 | -------------------------------------------------------------------------------- /src/my_robot_tutorials/scripts/number_counter.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | import rospy 4 | from std_msgs.msg import Int64 5 | from std_srvs.srv import SetBool 6 | 7 | counter = 0 8 | pub = None 9 | 10 | def callback_number(msg): 11 | global counter 12 | counter += msg.data 13 | new_msg = Int64() 14 | new_msg.data = counter 15 | pub.publish(new_msg) 16 | 17 | def callback_reset_counter(req): 18 | if req.data: 19 | global counter 20 | counter = 0 21 | return True, "Counter has been successfully reset" 22 | return False, "Counter has not been reset" 23 | 24 | if __name__ == '__main__': 25 | rospy.init_node('number_counter') 26 | 27 | sub = rospy.Subscriber("/number", Int64, callback_number) 28 | 29 | pub = rospy.Publisher("/number_count", Int64, queue_size=10) 30 | 31 | reset_service = rospy.Service("/reset_counter", SetBool, callback_reset_counter) 32 | 33 | rospy.spin() 34 | -------------------------------------------------------------------------------- /src/my_robot_tutorials/scripts/number_publisher.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | import rospy 4 | from std_msgs.msg import Int64 5 | 6 | if __name__ == '__main__': 7 | rospy.init_node("number_publisher", anonymous=True) 8 | 9 | pub = rospy.Publisher("/number", Int64, queue_size=10) 10 | 11 | publish_frequency = rospy.get_param("/number_publish_frequency") 12 | rate = rospy.Rate(publish_frequency) 13 | 14 | number = rospy.get_param("/number_to_publish") 15 | 16 | rospy.set_param("/another_param", "Helloooo") 17 | 18 | while not rospy.is_shutdown(): 19 | msg = Int64() 20 | msg.data = number 21 | pub.publish(msg) 22 | rate.sleep() 23 | -------------------------------------------------------------------------------- /src/my_robot_tutorials/scripts/oop_number_counter.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | import rospy 4 | from std_msgs.msg import Int64 5 | from std_srvs.srv import SetBool 6 | 7 | 8 | class NumberCounter: 9 | 10 | def __init__(self): 11 | self.counter = 0 12 | 13 | self.number_subscriber = rospy.Subscriber("/number", Int64, self.callback_number) 14 | 15 | self.pub = rospy.Publisher("/number_count", Int64, queue_size=10) 16 | 17 | self.reset_service = rospy.Service("/reset_counter", SetBool, self.callback_reset_counter) 18 | 19 | def callback_number(self, msg): 20 | self.counter += msg.data 21 | new_msg = Int64() 22 | new_msg.data = self.counter 23 | self.pub.publish(new_msg) 24 | 25 | def callback_reset_counter(self, req): 26 | if req.data: 27 | self.counter = 0 28 | return True, "Counter has been successfully reset" 29 | return False, "Counter has not been reset" 30 | 31 | 32 | if __name__ == '__main__': 33 | rospy.init_node('number_counter') 34 | NumberCounter() 35 | rospy.spin() 36 | -------------------------------------------------------------------------------- /src/my_robot_tutorials/scripts/robot_news_radio_transmitter.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | import rospy 4 | from std_msgs.msg import String 5 | 6 | if __name__ == '__main__': 7 | 8 | rospy.init_node('robot_news_radio_transmitter', anonymous=True) 9 | 10 | pub = rospy.Publisher("/robot_news_radio", String, queue_size=10) 11 | 12 | rate = rospy.Rate(2) 13 | 14 | while not rospy.is_shutdown(): 15 | msg = String() 16 | msg.data = "Hi, this is Dan from the Robot News Radio !" 17 | pub.publish(msg) 18 | rate.sleep() 19 | 20 | rospy.loginfo("Node was stopped") 21 | -------------------------------------------------------------------------------- /src/my_robot_tutorials/scripts/smartphone.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | import rospy 4 | from std_msgs.msg import String 5 | 6 | def callback_receive_radio_data(msg): 7 | rospy.loginfo("Message received : ") 8 | rospy.loginfo(msg) 9 | 10 | 11 | if __name__ == '__main__': 12 | rospy.init_node('smartphone') 13 | 14 | sub = rospy.Subscriber("/robot_news_radio", String, callback_receive_radio_data) 15 | 16 | rospy.spin() 17 | -------------------------------------------------------------------------------- /src/my_robot_tutorials/src/add_two_ints_client.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | int main (int argc, char **argv) 5 | { 6 | ros::init(argc, argv, "add_two_ints_client"); 7 | ros::NodeHandle nh; 8 | 9 | ros::ServiceClient client = 10 | nh.serviceClient("/add_two_ints"); 11 | 12 | rospy_tutorials::AddTwoInts srv; 13 | srv.request.a = 12; 14 | srv.request.b = 5; 15 | 16 | if (client.call(srv)) { 17 | ROS_INFO("Returned sum is %d", (int)srv.response.sum); 18 | } 19 | else { 20 | ROS_WARN("Service call failed"); 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /src/my_robot_tutorials/src/add_two_ints_server.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | bool handle_add_two_ints(rospy_tutorials::AddTwoInts::Request &req, 5 | rospy_tutorials::AddTwoInts::Response &res) 6 | { 7 | int result = req.a + req.b; 8 | ROS_INFO("%d + %d = %d", (int)req.a, (int)req.b, (int)result); 9 | res.sum = result; 10 | return true; 11 | } 12 | 13 | int main (int argc, char **argv) 14 | { 15 | ros::init(argc, argv, "add_two_ints_server"); 16 | ros::NodeHandle nh; 17 | 18 | ros::ServiceServer server = nh.advertiseService("/add_two_ints", 19 | handle_add_two_ints); 20 | 21 | ros::spin(); 22 | } 23 | -------------------------------------------------------------------------------- /src/my_robot_tutorials/src/my_first_node.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | int main (int argc, char **argv) 4 | { 5 | ros::init(argc, argv, "my_first_cpp_node"); 6 | ros::NodeHandle nh; 7 | ROS_INFO("Node has been started"); 8 | 9 | ros::Rate rate(10); 10 | 11 | while (ros::ok()) { 12 | ROS_INFO("Hello"); 13 | rate.sleep(); 14 | } 15 | 16 | } 17 | -------------------------------------------------------------------------------- /src/my_robot_tutorials/src/number_counter.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | int counter = 0; 6 | ros::Publisher pub; 7 | 8 | void callback_number(const std_msgs::Int64& msg) 9 | { 10 | counter += msg.data; 11 | std_msgs::Int64 new_msg; 12 | new_msg.data = counter; 13 | pub.publish(new_msg); 14 | } 15 | 16 | bool callback_reset_counter(std_srvs::SetBool::Request &req, 17 | std_srvs::SetBool::Response &res) 18 | { 19 | if (req.data) { 20 | counter = 0; 21 | res.success = true; 22 | res.message = "Counter has been successfully reset"; 23 | } 24 | else { 25 | res.success = false; 26 | res.message = "Counter has not been reset"; 27 | } 28 | 29 | return true; 30 | } 31 | 32 | 33 | int main (int argc, char **argv) 34 | { 35 | ros::init(argc, argv, "number_counter"); 36 | ros::NodeHandle nh; 37 | 38 | ros::Subscriber sub = nh.subscribe("/number", 1000, callback_number); 39 | 40 | pub = nh.advertise("/number_count", 10); 41 | 42 | ros::ServiceServer reset_service = nh.advertiseService("/reset_counter", 43 | callback_reset_counter); 44 | 45 | ros::spin(); 46 | } 47 | -------------------------------------------------------------------------------- /src/my_robot_tutorials/src/number_publisher.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | int main (int argc, char **argv) 5 | { 6 | ros::init(argc, argv, "number_publisher", ros::init_options::AnonymousName); 7 | ros::NodeHandle nh; 8 | 9 | ros::Publisher pub = nh.advertise("/number", 10); 10 | 11 | double publish_frequency; 12 | nh.getParam("/number_publish_frequency", publish_frequency); 13 | ros::Rate rate(publish_frequency); 14 | 15 | int number; 16 | nh.getParam("/number_to_publish", number); 17 | 18 | nh.setParam("/just_another_param", "Bye"); 19 | 20 | while (ros::ok()) { 21 | std_msgs::Int64 msg; 22 | msg.data = number; 23 | pub.publish(msg); 24 | rate.sleep(); 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /src/my_robot_tutorials/src/oop_number_counter.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | class NumberCounter { 6 | 7 | private: 8 | int counter; 9 | ros::Publisher pub; 10 | ros::Subscriber number_subscriber; 11 | ros::ServiceServer reset_service; 12 | 13 | public: 14 | NumberCounter(ros::NodeHandle *nh) { 15 | counter = 0; 16 | 17 | pub = nh->advertise("/number_count", 10); 18 | 19 | number_subscriber = nh->subscribe("/number", 1000, 20 | &NumberCounter::callback_number, this); 21 | 22 | reset_service = nh->advertiseService("/reset_counter", 23 | &NumberCounter::callback_reset_counter, this); 24 | } 25 | 26 | void callback_number(const std_msgs::Int64& msg) { 27 | counter += msg.data; 28 | std_msgs::Int64 new_msg; 29 | new_msg.data = counter; 30 | pub.publish(new_msg); 31 | } 32 | 33 | bool callback_reset_counter(std_srvs::SetBool::Request &req, 34 | std_srvs::SetBool::Response &res) 35 | { 36 | if (req.data) { 37 | counter = 0; 38 | res.success = true; 39 | res.message = "Counter has been successfully reset"; 40 | } 41 | else { 42 | res.success = false; 43 | res.message = "Counter has not been reset"; 44 | } 45 | 46 | return true; 47 | } 48 | }; 49 | 50 | int main (int argc, char **argv) 51 | { 52 | ros::init(argc, argv, "number_counter"); 53 | ros::NodeHandle nh; 54 | NumberCounter nc = NumberCounter(&nh); 55 | ros::spin(); 56 | } 57 | -------------------------------------------------------------------------------- /src/my_robot_tutorials/src/robot_news_radio_transmitter.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | int main (int argc, char **argv) 5 | { 6 | ros::init(argc, argv, "robot_news_radio_transmitter", 7 | ros::init_options::AnonymousName); 8 | ros::NodeHandle nh; 9 | 10 | ros::Publisher pub = nh.advertise("/robot_news_radio", 10); 11 | 12 | ros::Rate rate(3); 13 | 14 | while (ros::ok()) { 15 | std_msgs::String msg; 16 | msg.data = "Hi, this is William from the Robot News Radio"; 17 | pub.publish(msg); 18 | rate.sleep(); 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /src/my_robot_tutorials/src/smartphone_node.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | void callback_receive_radio_data(const std_msgs::String& msg) 5 | { 6 | ROS_INFO("Message received : %s", msg.data.c_str()); 7 | } 8 | 9 | 10 | int main (int argc, char **argv) 11 | { 12 | ros::init(argc, argv, "smartphone"); 13 | ros::NodeHandle nh; 14 | 15 | ros::Subscriber sub = nh.subscribe("/robot_news_radio", 16 | 1000, callback_receive_radio_data ); 17 | 18 | ros::spin(); 19 | } 20 | --------------------------------------------------------------------------------