<jupyter_start><jupyter_text>ROS Tutorial Chapter 1In this tutorial you should learn the basics of using the Robot Operating System (ROS) in a simulation environment.Rather than a real Operating System ROS core feature is the standarized communication between different hardware related applications. This enhances resuasability of different methods e.g. of a navigation stack across different platforms. Tips for Using TerminalsYou can skip that section if you know terminals else if you new to them here are some tips:- Autocomplete your command and file paths with the tab key- Use the arrow key to go to the history or type !! to repeat the last command- Search the command history with ctrl + r- Copy past with ctrl + c/v (in other terminals usually additionally + shift)- Terminate a running application with ctrl + c- Still not stopping? Find all running processes with ```ps -a```, then find the right process id to kill with ```kill -9 PROCESS_ID```- run ```ls``` shows the current directories folder + files and ```cd FOLDER_NAME``` to change to a folder- run ```clear``` to clean up the terminal log Basic communication in ROS1. Now lets open a terminal on our dockerized ROS system. (File->New->Terminal)2. Log in as the super user with the ```su``` 3. Now run ```roscore```You run your first ROS application which is the most essential to enable a communication between ROS application also called ROS nodes.Let us take a look at the output of this roscore command. We see the output ```ROS_MASTER_URI=X.X:X:X:113111``` this is the IP adress + Port to which all other ros nodes have to be referenced. If you run it on one plattform it automatically references to the local IP or local host. If you want to communicate between multiple devices you have to set the right IP in each terminal you open before. You can do this with ```export ROS_MASTER_URI=http://IP:PORT```.4. Let us open a new terminal as in stept 1.-2. and run the command ```rostopic list```We see a list of the current published topics which are ```/rosout```and ```/rosout_agg```. These topics are the adresses in ROS to which data can be published or subscribed. This is the basic input and output system of ROS. Let us open our own rostopic.5. For that we run in a third terminal ```rostopic pub /hello_world_publisher std_msgs/String "data: 'Hello World'" -r 1```. This will advertise first a rostopic with the name ```/hello_world_publisher``` then it will transmit or publish data of the type ```std_msgs/String``` and with the payload ```"Hello World"```. The ```-r 1``` parameter publishes the message in a one second interval. You can check other parameter with the ```--help``` parameter.6. Let us go back to our second terminal and check again the advertised topics to our roscore with ```rostopic list```. Now we see the ```/hello_world_publisher``` topic.7. Run ```rostopic echo /hello_world_publisher``` to actually recieve the message. You will see the message printed out every second in the terminal. Our first ROS NodeNow we know how basic commucation in ROS works, so let's try it on a simulated robot. For that we need a robot simulator. In our case we use a simulator called _Gazebo_ with a web visualization. To start everything necessary for the robot simulation we use a ```/.launch```/ file. A launch file is the ROS method to start one more ROS nodes with specific parameters. We use ```roslaunch turtlebot3_gazebo turtlebot3_house_no_gui.launch``` which starts the gazebo server simulating the turtlbot3 robot on a household map without a native gui. So lets start.1. Run ```roslaunch turtlebot3_gazebo turtlebot3_house_no_gui.launch``` to start the launch file and the gazebo server. This will also start a roscore/masterThe simulation environment is starting wait 1-2 minutes until you recive```[ INFO] [1564341937.572245889, 0.022000000]: waitForService: Service [/gazebo/set_physics_properties] is now available.[ INFO] [1564341937.608315624, 0.056000000]: Physics dynamic reconfigure ready.```Now you can start the web visulization server of gazebo.2. For that run ```gzweb``` in another terminal3. Now you should be able to see the web visualization at http://127.0.0.1:8080/The robot should be visible in the living room. You can move around with left-click, zoom with right-click and turn with shift + left-click. You can rest the world or inspect and create objects in the left menu bar. If you left click an object you can make it transparent or toggle visualizations for joints. If you have selected an object you can move or turn in with the buttons on the upper right side. There you can also easily add obstacles like boxes or balls.With our knowledge about topics, publishers, and subscribers we can now try to move the robot.So let us start with our first ROS node in python.4. We import first the rospy package in python<jupyter_code>import rospy<jupyter_output><empty_output><jupyter_text>Now we can initiate the ROS node.Then take a look at the current advertised ros node in the terminal with ```rosnode list``` cmd vel and matplotlib record<jupyter_code>rospy.init_node('our_first_node')<jupyter_output><empty_output><jupyter_text>Now let us take a look back at the aviable rostopics with ```rostopic list```. Interesting for us are following topics: - ```/cmd_vel``` : with this topic we can move the robot - ```/imu``` : short for Inertial Measurement Unit, lets us know if the robot's body interacts with any forces - ```/odom``` : the position and velocity of the robot relative to a fixed frame - ```/joint_states``` : the positions of the joints, for the turtlebot only the wheel position - ```/tf``` : all the transformations of frames aviable e.g. from the base_frame of the robot to the odom fixed frame - ```/scan ```: Data of the robots lidar First we want to move the robot so we have to publish to the /cmd_vel topic. With ```rostopic info /cmd_vel``` we can get information of the message type which is geometry_msgs/Twist(http://docs.ros.org/api/geometry_msgs/html/msg/Twist.html). This message has two properties which take each a 3d vector one for the desired linear and one for the angular velocity.So let us import this message. After that we advertise and create our publisher object with the function ```rospy.publisher("/topic_name",data_type,queue_size)```.<jupyter_code>from geometry_msgs.msg import Twist
publisher = rospy.Publisher('/cmd_vel', Twist, queue_size=10)<jupyter_output><empty_output><jupyter_text>Initially, let's create a mesasge which makes the robot drives in a circle. Since the robot front is in the x-axis and the axis are according to the right-hand rule it follows that the rotation is then around the z-axis. We create following message data:<jupyter_code>data = Twist()
data.linear.x = 0.2  # meters per second
data.angular.z = 0.25 #?Radians per second?
print(data)<jupyter_output>linear: 
  x: 0.2
  y: 0.0
  z: 0.0
angular: 
  x: 0.0
  y: 0.0
  z: 0.25<jupyter_text>Note: if the robot get's stuck you can use the ```Reset Model Poses``` button in the Gazebo web simulator to unstuck your robot.Now let us publish the data to make the robot drive. You can also open the gazebo webapp in a browser from you smart phone if you know your pc local ip address in the wifi.<jupyter_code>publisher.publish(data)<jupyter_output><empty_output><jupyter_text>In the next step we learn how to recieve ros data in python. We want to compare the target velocity with the measured velocity. To recieve data we need to define a subscriber ```rospy.Subscriber("/topic_name",data_type, callback_function)```. The subscriber object needs a *callback_function* as a parameter which we have to define first. The *callback_function* is executed automatically whenever a new message (new data) is available from the data source (publisher) we subscribed to. We want to subscribe to the ```/odom``` topic which gives the measured pose, orientation, and velocity of the robot from its Inertial Measurement Unit (IMU) and other sensors. We can take a look at the message type again by calling ```rostopic info``` and ```rostopic echo```.In the next step below we import the necessary message type and create an empty list. We append all data to the list with our callback function ```odom_handler```. At last we create our subscriber.<jupyter_code>from nav_msgs.msg import Odometry
data_list = []
def odom_handler(data):
    data_list.append(data)
    
rospy.Subscriber("/odom",Odometry, odom_handler)
# As we see in the next step the data_list is growing.
print(len(data_list))
rospy.sleep(1.)
print(len(data_list))<jupyter_output>247
276<jupyter_text>This is why we cannot use directly ```data_list``` but rather limit it to a length of samples at one time step. The following code creates arrays (numpy arrays) with the targets and measurements. We then plot them in the next steps using the matplot library.<jupyter_code>import numpy as np
current_len = len(data_list)
print("Data Sample Count: "+str(current_len))
lin_x_target = 0.2*np.ones(current_len)
ang_z_target = 0.25*np.ones(current_len)
lin_x_measured = np.zeros(current_len)
ang_z_measured = np.zeros(current_len)
pose_x_measured = np.zeros(current_len)
pose_y_measured = np.zeros(current_len)

for index in range(current_len):
    lin_x_measured[index] = data_list[index].twist.twist.linear.x
    ang_z_measured[index] = data_list[index].twist.twist.angular.z
    pose_x_measured[index] = data_list[index].pose.pose.position.x
    pose_y_measured[index] = data_list[index].pose.pose.position.y
# In this plot we compare the linear velocity
%matplotlib widget
import matplotlib.pyplot as plt
plt.plot(lin_x_measured)
plt.plot(lin_x_target)
plt.show()
# In this plot we compare the angular velocity
%matplotlib widget
import matplotlib.pyplot as plt
plt.plot(ang_z_measured)
plt.plot(ang_z_target)
plt.show()
# This is a plot of the position reached
%matplotlib widget
import matplotlib.pyplot as plt
import matplotlib as mpl
    
heatmap, xedges, yedges = np.histogram2d(pose_x_measured, pose_y_measured, bins=500)
extent = [xedges[0], xedges[-1], yedges[0], yedges[-1]]
cmap = mpl.colors.ListedColormap(['w', 'k'])

bounds = [0.,1.0, 2.]
norm = mpl.colors.BoundaryNorm(bounds, cmap.N)

plt.clf()
plt.imshow(heatmap.T, extent=extent, cmap=cmap, origin='lower', interpolation='none', norm=norm)
plt.show()<jupyter_output><empty_output>
{'fraction_non_alphanumeric': 0.08135265700483092, 'fraction_numerical': 0.013816425120772947, 'mean_word_length': 4.938611589213999, 'pattern_counts': {'":': 0, '<': 27, '<?xml version=': 0, '>': 29, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 1, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'chain_length': '7', 'dir': 'jupyter-structured-clean-dedup', 'id': '317150', 'license': 'MIT', 'n_tokens_mistral': 3124, 'n_tokens_neox': 2920, 'n_words': 1410, 'path': 'src/ch1/ch1.ipynb', 'repo_name': 'robomuc/robo_tut', 'size': '10350'}