-
Notifications
You must be signed in to change notification settings - Fork 0
/
Instructions.txt
108 lines (91 loc) · 7.37 KB
/
Instructions.txt
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
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
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
105
106
10820992 Gabriele De Santis
10632035 Alessandro Gaeta
Appendix:
We tried our best to make the code self explanatory and keep it simple and ordered.
Here follows a brief description of the project files, some instructions in order to launch the
program, the services and everything needed, a description of the ROS parameters, the structure
of the TF tree and the motivation of its choice, and the structure of the custom messages.
***Small description of the files inside the archive ***
In the main file which is odometry.cpp (inside the src folder) we created three classes:
1) Class twist_stamped, a class with a dedicated node in order to publish our twist_stamped message.
2) Class skid_steering, the "body of the project", inside this class we defined the two functions
euler_integration and runge_kutta_integration in order to compute the odometry with the skid steering
approximation kinematics. This class has its own node "skid_steering_node" (we chose
to assign a total of 4 nodes, one for each class and one inside the main, because we
think that it's the best way to obtain order and semplicity in reading the code). Inside this class
we also defined two publishers, one in order to publish our computed odometry message and the
other for the requested custom message. Inside this class we also defined the two services, we
chose to implement them here because we think that it's the best way to communicate and modify
our odometry which is also computed inside this class. Both the two publishers and the two services
are instantiated inside the class constructor. Furthermore, a function sets the initial pose through
the parameter specified in the lauch file. It saves the (x, y, theta) values in a vector and then
assign these values to the pose of the skid_steering object.
We then defined a function in order to publish our odometry, and a function wich operates a
transformation from quaternions to theta, this because the nav_msgs poses orientation works
with quaternions. We then defined a couple of simple functions inside the class in order to enable
the "skeleton" of the dynamic reconfigure in order to select the odometry integration method, and the
last two functions of the class are the servers of the two services. Initially we also defined two
additional files in order to configure a client for each service, but while progressing with the
project we realized that they were superfluous, and considering the space occupied by two extra files,
also in terms of order of the project, we decided to remove them.
3) Class tf_sub_pub, the third class is in order to implement the TF. Choices of the determined
TF are discussed afterwards.
We then defined three functions, the first in order to estimate the angular and linear velocity.
Considering the fact that we used the Skid Steering Approximation which assumes that the 4 wheeled
robot has all wheels always in contact with the ground, has the mass equally distributed on the four
wheels in each instant and that the wheels on the same side have the same speed, we decided that,
considering the noise, the best way to estimate the velocity of the wheels of each side was to make
an algebraic mean over the front and rear wheel. In order to estimate the two constants that we had
to find, we used an experimental method, the same that we used at first for the gear ratio and
afterwards for the apparent baseline, trying a value and computing our velocities, then comparing it
with the manufacturers', using the linear velocity in order to compute the gear ratio (because the
apparent baseline doesn't influence this velocity), and after obtaining satisfactory results with the
first constant, moving to estimate the apparent baseline comparing the angular velocities. We mainly
used data from the first bag, and for each "session" to try a determined value, we gathered a
collection of experiments of at least 30 samples, number of samples that we gathered which gradually
increased as the values of our velocities got closer to the manufacturers', and we deemed satisfied
when, upon more than 100 samples, our velocities with respect to the manufacturers' were half of the
time lower and half of the time higher (based individually on multiple sessions, also for bag number 2).
We chose this method because we assumed that the noise had a predominant high frequency component, and
so getting results which where "randomly" higher or lower, considering the tiny differences in the
comparision, was a sufficient result for us. We checked our achievings throughout the project with
the tool RVIZ. Our project currently reaches a maximum error, regarding the bag number 1, of around
15 centimeters on both the x and y axis. We then defined the callback function for the synchronization
of the messages of the 4 wheels' rpms deriving from the data in the bag, so that afterwards this data
could be used by our program consciously knowing that, in each instant, the 4 rpms were belonging to
the same time instant, because, if this wasn't the case, there would have been big problems with the
computation of our velocities, and consequently with the estimation of the parameters.
***INSTRUCTIONS FOR LAUNCHING THE PROGRAM***
$ roslaunch project_robotics launch.launch
This line command initializes the parameters and launches roscore and the project. The data to be
computed has to be provided in input from the outside (e.g. making the bag1.bag play).
***INSTRUCTIONS FOR CALLING THE INTEGRATION METHOD SELECTOR***
Euler -> $ rosrun dynamic_reconfigure dynparam set /odometry integration_method 0
Runga Kutta -> $ rosrun dynamic_reconfigure dynparam set /odometry integration_method 1
As you can see, the integration method can be chosen by using an integer. Euler integration method
corresponds to 0 and Runge Kutta integration method corresponds to 1.
The initial integration method is Euler.
***INSTRUCTIONS FOR CALLING THE RESET SERVICES***
In order to call the service which resets odometry to (0, 0) and keeps unaltered the angle theta:
$ rosservice call reset
In order to call the service which resets odometry to the given values (x, y, theta):
$ rosservice call given_reset x y theta
where you have to substitute <x y theta> with their values.
***Name and meaning of the ROS parameters***
A ROS parameter specifies the initial pose (x, y, theta) of the robot. Since we don't have any
constraints about the initial pose, we have choosen to set it as (0, 0, 0).
The parameter can be changed in the launch file.
***Structure of the TF tree***
We defined a Transformation Frame from /odom to /base_link using the odometry that we computed.
We chose this kind of TF because, according to us, it was the best choice in terms of simplicity
and also a great way to check that everything was working fine looking from ROS tools such as rviz,
this because we could simply and directly compare our data with the manufacturers odometry data,
without any sporadic unavailabilty of the data.
This transformation can simply be inspected using, among other options, the tool RVIZ, setting the
fixed frame to odom, and then adding, "By display type" TF, under rviz.
***Structure of the custom message***
The CustomOdometry message has the following structure:
nav_msgs/Odometry odom
std_msgs/String method
The odom message contains all the odometry calculated either with Euler or Runge Kutta while method
message specifies the integration method selected to calculate the current odometry value.