Robot Navigation and Path Planning
Robot Navigation and Path Planning
Project Report
Abstract 2
Index 3
List of Figures 4
Introduction 5
Project Objective 6
Literature Review 7
Methodology 14
Conclusion 25
Future Task 25
References 26
Appendices 26
LIST OF FIGURES
Figure 1: SLAM Flow Path 12
Figure 4: TurtleBot 16
This brings us to the problem of moving a robot in an environment that may have several
stationary or moving obstacles, especially humans. Here, the safety of humans is of utmost
priority and hence it is vital that the robot can accurately sense its surroundings and decide its
course of action. But sensor data is usually noisy and cannot provide a true estimate of the
surroundings. Also as the objects in the scene are moving, there could be a lack of stationary
landmarks for localization. But several probabilistic models are available for this state estimation
and each have their own advantages and shortcomings.
We started with the study of path planners like Dijkstra’s and A-star algorithms and move
towards studying Simultaneous Localization and Mapping. The reason for experimenting with
these two algorithms is that they are the most fundamental planners for navigation. Hence we
tested them for different goal and obstacle locations and comment on their efficiency. For SLAM
we would only provide an overview of its three types: Extended Kalman Filter, Particle Filter
and Graph-based SLAM.
To embrace the practical side of this project, we shift our focus towards understanding the ROS
environment for running Gazebo. This involved setting up the Gazebo, Rviz and Turtlebot in
ROS. We also learned how nodes are created, topics are published or subscribed to and how
python executables are compiled into a package. Using this knowledge we were able to create a
world in Gazebo for navigation of Turtlebot and tele-operate it for generating maps. This map
enabled us to re-implement the A-star algorithm in python and conclude a comprehensive study
of these algorithms.
PROJECT OBJECTIVE:
The main goal of this project is to learn ROS and gain a substantial knowledge of implementing
path planning and SLAM algorithms for mobile robots which will help us develop skills for
further research in this field. Also testing algorithms in simulated dynamic environments will
help us in developing robust algorithms for navigation tasks in social or medical settings.
LITERATURE REVIEW:
As background study for this project we looked at several existing path planning algorithms and
read papers on motion planning and SLAM techniques. We also explored the ROS environment
and learned how to create packages and run executables.
Grassfire Algorithm:
When a robot is moving in an environment of known dimensions, its floor space can be
discretized into several blocks. By assigning a coordinate axis to one of the corners of this space
we can represent each block with a pair of coordinates. Each block can be assigned a binary
value depending on whether it is empty or contains an obstacle. Now we start from the goal
location and mark it as 0 value. Each of the four neighboring cells that is empty is marked a
consecutive value 1. Now the neighbors of the cells that are marked as 1, are given the next value
2. This goes on till you reach the start location. Now each value of the cells surrounding the goal
location represents the number of steps required by the robot to reach the goal location from this
cell. Therefore, successfully selecting the minimum neighboring value will lead the robot to the
goal location via the shortest path.
The grassfire algorithm is also a complete algorithm, which means it considers all the possible
cases of navigation. While moving from the goal to the start location, if all the reachable empty
cells are numbered and yet the start location is not be assigned a value, it will indicate that no
path exists from the start to the end location. As the grassfire algorithm accesses all the available
cells, its computational efficiency is inversely proportional to the number of nodes.
Pseudocode[7]:
Its flow is similar to the Grassfire algorithm, but starts from the start location instead of the goal
location. We mark the starting cell as 0. Next we assign a value to the neighboring nodes
according to its corresponding edge weight. As we move forward we also maintain a matrix of
the parent cells for each node. When we finally arrive at the goal location we can trace back the
path with the minimum sum of edge weights from the starting node. Here we don’t need to
explore all the cells in the workspace, but we do need to explore all the neighboring cells until
we reach the goal location.
Pseudocode[6]:
A*(star) Algorithm:
A* is a modification of Dijkstra’s Algorithm that is optimized for a single destination. Dijkstra’s
Algorithm works well to find the shortest path, but it wastes time exploring in directions that
aren’t promising. Greedy Best First Search explores in promising directions but it may not find
the shortest path. The A* algorithm uses both the actual distance from the start and the estimated
distance to the goal; A* finds paths to one location. It prioritizes paths that seem to be leading
closer to the goal.
It is a best-first search algorithm, it solves problems by searching among all the possible paths to
the goal location and selects the one path that incurs the smallest cost i.e. least distance travelled
or shortest time taken to reach the goal location. A* is formulated in terms of weighted graphs, it
starts from a specific node of a graph, and constructs a tree of paths starting from that specific
node, it expands the paths one step at a time, until one of the paths ends at the goal node or goal
position. A* expands paths that are already less expensive by using this function:
where,
● n = the last node on the path
● f(n) = total estimated cost of path through node n
● g(n) = cost so far to reach node n
● h(n) = estimated cost from n to goal. This is the heuristic part of the cost function.
The heuristic is problem-specific. For the algorithm to find the actual shortest path, the heuristic
function must be admissible, which means that it should never overestimate the actual cost to get
to the nearest goal node. The heuristic function can be calculated in various ways:
● Manhattan Distance:
In this method h(n) is computed by calculating the total number of squares moved
horizontally and vertically to reach the target square from the current square. Here any
obstacles and diagonal movement are ignored.
ℎ = |𝑥𝑠𝑡𝑎𝑟𝑡 − 𝑥𝑑𝑒𝑠𝑡𝑖𝑛𝑎𝑛𝑡𝑖𝑜𝑛 | + |𝑦𝑠𝑡𝑎𝑟𝑡 − 𝑦𝑑𝑒𝑠𝑡𝑖𝑛𝑎𝑛𝑡𝑖𝑜𝑛 |
● Euclidean Distance Heuristic:
This heuristic is slightly more accurate than its Manhattan counterpart. If we try run both
simultaneously on the same maze, the Euclidean path finder favors a path along a straight
line. This is more accurate, but it is also slower because it has to explore a larger area to find
the path.
ℎ = √(𝑥𝑠𝑡𝑎𝑟𝑡 − 𝑥𝑑𝑒𝑠𝑡𝑖𝑛𝑎𝑡𝑖𝑜𝑛 )2 + (𝑥𝑠𝑡𝑎𝑟𝑡 − 𝑦𝑑𝑒𝑠𝑡𝑖𝑛𝑎𝑡𝑖𝑜𝑛 )2
All the above algorithms work under the assumption that we can accurately sense our
surroundings and predict its states. But in practical applications, the sensor data has some
inherent noise and we can never receive a true value of the location of the robot and its
environment. Therefore, we need some form of a probabilistic model like a Kalman Filter to
reasonably estimate the system states.
Pseudocode[8]:
// The set of currently discovered nodes that are not evaluated yet.
// Initially, only the start node is known.
openSet := {start}
// For each node, which node it can most efficiently be reached from.
// If a node can be reached from many nodes, cameFrom will eventually
contain the
// most efficient previous step.
cameFrom := an empty map
// For each node, the cost of getting from the start node to that
node.
gScore := map with default value of Infinity
// For each node, the total cost of getting from the start node to the
goal
// by passing by that node. That value is partly known, partly
heuristic.
fScore := map with default value of Infinity
openSet.Remove(current)
closedSet.Add(current)
return failure
Each technique has its own flaws. For using EKF we assume that the landmarks should be fully
visible. Also in EKF the resultant covariance matrix is quadratic and hence difficult to evaluate.
In particle filters every particle is a guess of the states of the system. At every step we evaluate
the value of each guess and eliminate poor guesses. We create a new sample of guess in the next
step and proceed. But there is a risk of particle depletion during resampling and fairly decent
estimates may be lost. Also the complexity of particle filters scales exponentially as it depends
on the number of particles and states in a system. Here we can employ Fast SLAM that combines
three techniques: Rao-Blackwellization, Conditional Independence and Re-Sampling.
Lastly we can use Graph Optimization where x and m are the nodes in the graph. But graph
based problems address the full SLAM problem and are hence not employed online.
In SLAM[9], the objective is to compute: 𝑷(𝒎𝒕 , 𝒙𝒕 |𝒐𝟏:𝒕 ), here 𝒐𝒕 are series of sensor
observations over time steps t, here we have to compute an estimate of 𝒙 𝒕 ’s location and a map
of the environment 𝒎𝒕 .
By applying Bayes ‘rule, we get a framework for updating the location posteriors, given a map
and a transition function 𝑷(𝒙𝒕 |𝒙𝒕−𝟏 ),
𝑷(𝒙𝒕 |𝒐𝟏:𝒕 , 𝒎𝒕 ) = ∑ 𝑷(𝒐𝒕 |𝒙𝒕 , 𝒎𝒕 ) ∑ 𝑷(𝒙𝒕 |𝒙𝒕−𝟏 )𝑷(𝒙𝒕−𝟏 |𝒎𝒕 , 𝒐𝟏:𝒕−𝟏 )/𝐙
𝑚𝑡−1 𝑥𝑡−1
Pseudocode:
1. Software Setup
The first steps in this project was to get the software stack ready. This course being one of the
first courses in this program there was no prior setup of the required software packages. So a
fresh install of Ubuntu 14.04 LTS was followed by installation of ROS indigo. This combination
was chosen over Ubuntu 16.04 and ROS kinetic as a few of Turtlebot packages haven't been
upgraded to Kinetic Kane. Performing a full installation of ROS ensured that Gazebo and
Turtlebot were also installed with it. Following the Wiki ROS Tutorials were beneficial in
learning how packages are created in ROS. A critical aspect of it was checking the dependencies
and executables in CMakeLists.txt and package.xml. The next step in improving our skills in
ROS was writing publishers and subscribers. This was essential for knowing how data can be
sent and listened to from a topic while trying to move the Turtlebot.
MoveIt! is another set of packages and tools for doing mobile manipulation in ROS. There are
many examples to demonstrate pick and place, grasping, simple motion planning, etc. MoveIt!
contains state of art software for motion planning, 3D perception, collision checking, control and
navigation. Apart from the command line interface, MoveIt! has some good GUI to interface a
new robot to MoveIt!. Also, there is a RViz plugin which enables motion planning from RViz
itself. But the need for using the C++ APIs of MoveIt! never rose as we stuck to teleoperation for
observing motion in Gazebo.
For simulation of the planned motion, PR2 was also considered along with Turtlebot. The
PR2 software system was installed and run for validating its use for our application.
The Navigation stack for PR2 contained implementation of the standard algorithms, such
as SLAM, A*(star), Dijkstra, AMCL, and so on, which can directly be used in our application.
Navigation stack provides a node name move_base which receives a goal pose and links to many
components to generate the output which is the command velocity which is then sent to the base
controller for moving the robot for achieving the goal pose.
2. Turtlebot
TurtleBot (Figure-4) is a low-cost, personal robot kit with open-source software that uses
a netbook as its main processor and Microsoft Kinect as its vision sensor. TurtleBot was
specifically designed by Willow Garage to be used with ROS. The TurtleBot has many built-in
sensors like bumper sensor, cliff sensor, wheel drop sensor, wheels encoder and gyro sensor.
ROS provides demo code for the 2D SLAM process using TurtleBot. The Microsoft Kinect can
be used to generate fake laser scan data from depth image, and using grid mapping for mapping
processes. TurtleBot is designed to work with many computers, the netbook on the robot is used
to read sensor data and control the robot movement. All heavy computation that is needed is to
be done on another computer that has more processing power. Data between computer and the
netbook is transmitted wirelessly through Wi-Fi. [2]
Fig. 4. TurtleBot
Fig. 5. TurtleBot in gazebo simulator and Tele-operating using keyboard with few obstacles
3. Dijkstra’s and A* Algorithm
MATLAB was preferred for implementing the Dijkstra’s and A* algorithms. We wrote a
code for Dijkstra’s algorithm in MATLAB and outsourced its visualization. Running the
RunScript.m file will run the Dijkstra’s or the A*(star) code. Figure 6 and 7 show the
visualization of Dijkstra’s and A* algorithms in MATLAB.
5. Gmapping
For path planning in this environment, a 2D map was required to be made for which we
decided to use the GMapping tool in Gazebo. By teleoperating the robot in the created world we
were able to generate the map by identifying free spaces from obstacles. This map was then used
to create a binary map and store it in a text file.
We also tried to plan the trajectory for the turtlebot between two fixed locations by using
the cubic polynomial method. The code can be seen in the appendix. We defined the start and
end locations and time frame as well.
Desired Position is given by below equation, where t is the timestamp, and a’s are the unknown
variables which can be obtained with the help of initial conditions.
𝑞(𝑡) = 𝑎0 + 𝑎1 𝑡 + 𝑎2 𝑡 2 + 𝑎3 𝑡 3
5. A* algorithm in Python
The A* algorithm written in MATLAB was ported to python by referring to the pseudo
codes from [8] and [11]. The binary map created of the world is shown in figure 13.
In this map the free locations are denoted by the value 0 and obstacles are denoted by an asterisk.
Fig. 14. Path found by A*
The path found by the A* algorithm is denoted by 1s and is the shortest path from the start to
the goal location.
The turtlebot has two castor wheels and two standard wheels. Therefore the two standard wheels
pose one sliding constraint each. The degree of mobility can hence be calculated as:
Therefore,
𝛿𝑚 = 1
𝛿𝑠 = 0
𝛿𝑀 = 𝛿𝑚 + 𝛿𝑠
𝛿𝑀 = 1
Fig 16: TurtleBot Wheel Constraints
CONCLUSION
Through this project we were able to accomplish several of our pre-defined objectives.
We completed a comprehensive study of different path planning algorithms and also an overview
of SLAM techniques. By the end of this project we gained substantial experience in ROS, which
perhaps might be the most useful skill gained in this project. Unfortunately, we had to truncate
our project aim of implementing SLAM as a group member had to leave midway through the
course. Still we were able to do considerable work in creating a world and mapping it in Gazebo
and simulating a few fundamental path planners in MATLAB.
FUTURE TASKS:
Having gained the required software skills in this project, it would be much easier now to
implement the SLAM algorithms we studied. Also, the map generated was static in nature and
should be replaced with a dynamic setting for a more accurate representation of a real world
scenario.
As a topic for future research, a robust full SLAM algorithm can be pursued wherein the
map is created online and hence is an unknown entity.
REFERENCES:
[1] A. Thallas, E. Tsardoulias and L. Petrou, "Particle filter — Scan matching SLAM recovery
under kinematic model failures," 2016 24th Mediterranean Conference on Control and
Automation (MED), Athens, 2016, pp. 232-237. doi: 10.1109/MED.2016.7535849.
[3] C. Stachniss, J. L. Leonard and S. Thrun, “Simultaneous Localization and Mapping” 2016
Springer Handbook of Robotics, Chapter 46, pp. 1153-1174
[4] J. Minguez, F. Lamiraux and J. P. Laumond, “Motion Planning and Obstacle Avoidance”
2016 Springer Handbook of Robotics, Chapter 47, pp. 1177-1201
[5] http://wiki.ros.org/ROS/Tutorials
[6]https://en.wikipedia.org/wiki/Dijkstra%27s_algorithm#Pseudocode
[7]https://en.wikipedia.org/wiki/Grassfire_transform
[8]https://en.wikipedia.org/wiki/A*_search_algorithm
[9]https://en.wikipedia.org/wiki/Simultaneous_localization_and_mapping
[10]http://gazebosim.org/tutorials?tut=build_world
[11] https://github.com/wordswords
APPENDICES:
A* in MATLAB:
Contents
▪ Construct route from start to dest by following the parent links
cmap = [1 1 1; ...
0 0 0; ...
1 0 0; ...
0 0 1; ...
0 1 0; ...
1 1 0; ...
0.5 0.5 0.5];
colormap(cmap);
drawMapEveryTime = true;
map = zeros(nrows,ncols);
map(~input_map) = 1;
map(input_map) = 2;
map(start_node) = 5;
map(dest_node) = 6;
parent = zeros(nrows,ncols);
xd = dest_coords(1);
yd = dest_coords(2);
f = Inf(nrows,ncols);
g = Inf(nrows,ncols);
g(start_node) = 0;
f(start_node) = H(start_node);
numExpanded = 0;
while true
map(start_node) = 5;
map(dest_node) = 6;
if (drawMapEveryTime)
image(1.5, 1.5, map);
grid on;
axis image;
drawnow;
end
[min_f, current] = min(f(:));
map(current) = 3;
f(current) = Inf;
% *********************************************************************
% Self written code:
[m, n] = size(min_f);
if (current == dest_node)
numExpanded = numExpanded + n -1;
else
numExpanded = numExpanded + n;
end
for I = 1:n
i = i(m,I);
j = j(m,I);
if (i>1 & i<=(nrows+1) & j>=1 & j<=ncols & input_map(i-1,j)~=1 & map(i-1,j)~=3
& map(i-1,j)~=5)
next_node = sub2ind(size(map),i-1,j);
map(next_node) = 4;
n_dist = g(i-1,j);
if (n_dist > (g(i,j) + 1))
n_dist = g(i,j) + 1;
g(i-1,j) = n_dist;
f(i-1,j) = g(i-1,j) + H(i-1,j)
end
parent(i-1,j) = current(m,I);
end
if (i>=1 & i<=nrows & j>1 & j<=(ncols+1) & input_map(i,j-1)~=1 & map(i,j-1)~=3
& map(i,j-1)~=5)
next_node = sub2ind(size(map),i,j-1);
map(next_node) = 4;
n_dist = g(i,j-1);
if (n_dist > (g(i,j) + 1))
n_dist = g(i,j) + 1;
g(i,j-1) = n_dist;
f(i,j-1) = g(i,j-1) + H(i,j-1)
end
parent(i,j-1) = current(m,I);
end
if (i>=1 & i<nrows & j>=1 & j<=ncols & input_map(i+1,j)~=1 & map(i+1,j)~=3 &
map(i+1,j)~=5)
next_node = sub2ind(size(map),i+1,j);
map(next_node) = 4;
n_dist = g(i+1,j);
if (n_dist > (g(i,j) + 1))
n_dist = g(i,j) + 1;
g(i+1,j) = n_dist;
f(i+1,j) = g(i+1,j) + H(i+1,j);
end
parent(i+1,j) = current(m,I);
end
if (i>=1 & i<=nrows & j>=1 & j<ncols & input_map(i,j+1)~=1 & map(i,j+1)~=3 &
map(i,j+1)~=5)
next_node = sub2ind(size(map),i,j+1);
map(next_node) = 4;
n_dist = g(i,j+1);
if (n_dist > (g(i,j) + 1))
n_dist = g(i,j) +1;
g(i,j+1) = n_dist;
f(i,j+1) = g(i,j+1) + H(i,j+1)
end
parent(i,j+1) = current(m,I);
end
end
%*********************************************************************
end
while (parent(route(1)) ~= 0)
route = [parent(route(1)), route];
end
for k = 2:length(route) - 1
map(route(k)) = 7;
pause(0.1);
image(1.5, 1.5, map);
grid on;
axis image;
end
end
end
A* algorithm
Define a small map
map = false(20);
% Add an obstacle
map (1:7, 4) = true;
map (3:9, 10) = true;
map (13, 1:10) = true;
start_coords = [1, 1];
dest_coords = [15, 15];
close all;
% [route, numExpanded] = DijkstraGrid (map, start_coords, dest_coords);
Dijkstra’s:
Contents
▪ Construct route from start to dest by following the parent links
cmap = [1 1 1; ...
0 0 0; ...
1 0 0; ...
0 0 1; ...
0 1 0; ...
1 1 0; ...
0.5 0.5 0.5];
colormap(cmap);
drawMapEveryTime = true;
map = zeros(nrows,ncols);
map(~input_map) = 1;
map(input_map) = 2;
map(start_node) = 5;
map(dest_node) = 6;
distanceFromStart = Inf(nrows,ncols);
parent = zeros(nrows,ncols);
distanceFromStart(start_node) = 0;
numExpanded = 0;
while true
map(start_node) = 5;
map(dest_node) = 6;
if (drawMapEveryTime)
image(1.5, 1.5, map);
grid on;
axis image;
drawnow;
end
map(current) = 3;
distanceFromStart(current) = Inf;
% *********************************************************************
% Self witten code:
[m, n] = size(min_dist);
if (current == dest_node)
numExpanded = numExpanded + n -1;
else
numExpanded = numExpanded + n;
end
for I = 1:n
i = i(m,I);
j = j(m,I);
if (i>1 & i<=(nrows+1) & j>=1 & j<=ncols & input_map(i-1,j)~=1 & map(i-1,j)~=3
& map(i-1,j)~=5)
next_node = sub2ind(size(map),i-1,j);
map(next_node) = 4;
n_dist = distanceFromStart(i-1,j);
if (n_dist > (min_dist(m,I) + 1))
n_dist = min_dist(m,I) +1;
distanceFromStart(i-1,j) = n_dist;
end
parent(i-1,j) = current(m,I);
end
if (i>=1 & i<=nrows & j>1 & j<=(ncols+1) & input_map(i,j-1)~=1 & map(i,j-1)~=3
& map(i,j-1)~=5)
next_node = sub2ind(size(map),i,j-1);
map(next_node) = 4;
n_dist = distanceFromStart(i,j-1);
if (n_dist > (min_dist(m,I) + 1))
n_dist = min_dist(m,I) +1;
distanceFromStart(i,j-1) = n_dist;
end
parent(i,j-1) = current(m,I);
end
if (i>=1 & i<nrows & j>=1 & j<=ncols & input_map(i+1,j)~=1 & map(i+1,j)~=3 &
map(i+1,j)~=5)
next_node = sub2ind(size(map),i+1,j);
map(next_node) = 4;
n_dist = distanceFromStart(i+1,j);
if (n_dist > (min_dist(m,I) + 1))
n_dist = min_dist(m,I) +1;
distanceFromStart(i+1,j) = n_dist;
end
parent(i+1,j) = current(m,I);
end
if (i>=1 & i<=nrows & j>=1 & j<ncols & input_map(i,j+1)~=1 & map(i,j+1)~=3 &
map(i,j+1)~=5)
next_node = sub2ind(size(map),i,j+1);
map(next_node) = 4;
n_dist = distanceFromStart(i,j+1);
if (n_dist > (min_dist(m,I) + 1))
n_dist = min_dist(m,I) +1;
distanceFromStart(i,j+1) = n_dist;
end
parent(i,j+1) = current(m,I);
end
end
%*********************************************************************
end
Construct route from start to dest by following the parent links
if (isinf(distanceFromStart(dest_node)))
route = [];
else
route = [dest_node];
while (parent(route(1)) ~= 0)
route = [parent(route(1)), route];
end
for k = 2:length(route) - 1
map(route(k)) = 7;
pause(0.1);
image(1.5, 1.5, map);
grid on;
axis image;
end
end
end
% Add an obstacle
map (1:7, 4) = true;
map (3:9, 10) = true;
map (13, 1:10) = true;
#!/usr/bin/env python
import math
import sys
import rospy
from block import block
from grid import grid
class a_star(object):
closedSet = set()
openSet = set()
cameFrom, gscore, fscore = {}, {}, {}
surface = ""
def __init__(self):
i = 0
for sq in self.run():
self.surface.units[sq.x][sq.y].state = '1'
i = i + 1
with open('path.txt','w') as file:
file.write(str(self.surface))
print self.surface
def run(self):
# setup grid
self.surface = grid(sys.argv[1], 8, 8)
start = self.surface.start
goal = self.surface.goal
if current == goal:
return self.find_path(goal)
try:
self.openSet.remove(current)
except KeyError,e:
pass
self.closedSet.add(current)
for neighbour in self.neighbour_nodes(current):
if neighbour not in self.closedSet:
temp_gscore = self.gscore[current] + 1
if (neighbour not in self.openSet) or
(temp_gscore < self.gscore[neighbour]):
# evaluate an unevaluated member or replace
its value with a smaller one
self.cameFrom[neighbour] = current
self.gscore[neighbour] = temp_gscore
self.fscore[neighbour] =
self.gscore[neighbour] + self.heuristic(neighbour,goal)
def neighbour_nodes(self,node):
""" Generate a set of neighbouring nodes """
neighbours = set()
if node.north != 0:
neighbours.add(node.north)
if node.east != 0:
neighbours.add(node.east)
if node.west != 0:
neighbours.add(node.west)
if node.south != 0:
neighbours.add(node.south)
return neighbours
def distance(self,start_node,end_node):
""" The distance in a straight line between two points on the
grid """
x = start_node.x - end_node.x
y = start_node.y - end_node.y
return 1 * max(abs(x),abs(y))
def evaluation_function(self,node,goal):
""" Our evaluation function is the distance function plus the
cost of the path so far """
return (node.self.distance(goal) + node.path_cost)
def heuristic(self,start_node,end_node):
heuristic = self.distance(start_node,end_node)
return heuristic
try:
self.cameFrom[current_node]
p = self.find_path(self.cameFrom[current_node])
path = []
path.extend(p)
path.append(current_node)
return path
except KeyError,e:
# we have reached the start node
return [current_node]
def count(self,set_to_count):
total_count = 0
for i in set_to_count:
total_count = total_count + 1
return total_count
a_star()
#!/usr/bin/env python
import rospy
from geometry_msgs.msg import Twist
import numpy as np
class Robot:
def __init__(self):
self._vel_pub =
rospy.Publisher('mobile_base/commands/velocity', Twist, queue_size=1)
#print(t)
b = [[0.5],[0],[0.6],[0]]
#for i in range(len(t)):
A = np.matrix( [ [1, 0, 0, 0],
[0, 1, 0, 0],
[1, t[1], t[1]**2, t[1]**3],
[0, 1, 2*t[1], 3*(t[1]**2)]])
a = np.array(np.linalg.inv(A)*b)
qd = a[0] + a[1]*t[1] + a[2]*(t[1]**2) + a[3]*(t[1]**3)
vd = a[1] + 2*a[2]*t[1] + 3*(a[3]*(t[1]**2))
#move_cmd.linear.x = 0
move_cmd.angular.z = 0.01
#if move_cmd.angular.z == 1.57:
move_cmd.linear.x = 0.1
move_cmd.linear.y = vd
while not rospy.is_shutdown():
# publish the velocity
self._vel_pub.publish(move_cmd)
# wait for 0.1 seconds (10 HZ) and publish again
r.sleep()
def shutdown(self):
# stop turtlebot
rospy.loginfo("Stop TurtleBot")
# a default Twist has linear.x of 0 and angular.z of 0. So
it'll stop TurtleBot
self.cmd_vel.publish(Twist())
# sleep just makes sure TurtleBot receives the stop command
prior to shutting down the script
rospy.sleep(1)
if __name__ == '__main__':
# rospy.sleep(1)
rospy.init_node('Move_turtlebot')
turtle = Robot()
#!/usr/bin/env python
import rospy
import sys
from geometry_msgs.msg import Twist
class Home:
def __init__(self):
self.vel_pub =
rospy.Publisher('mobile_base/commands/velocity', Twist,
queue_size=100)
r = rospy.Rate(1);
self.i = 0
while not rospy.is_shutdown():
vel = Twist()
if self.i == 2:
vel.linear.x = 0.0
vel.angular.z = -2.6
elif self.i == 4:
vel.linear.x = 0.86
vel.angular.z = 0.0
elif self.i == 6:
vel.linear.x = 0.0
vel.angular.z = 2.6
elif self.i == 8:
vel.linear.x = 0.86
vel.angular.z = 0.0
else:
vel.linear.x = 0.0
vel.angular.z = 0.0
vel.linear.y = 0.0
self.i = self.i + 1
print vel
self.vel_pub.publish(vel)
r.sleep()
if __name__ == '__main__':
rospy.init_node('Turtlebot_Home')
turtlebot = Home()