0% found this document useful (0 votes)
85 views33 pages

ROS Lecture11

The document summarizes a lecture on behavior-based robotics. It discusses how behavior-based robotics uses a library of behaviors (controllers) that are switched between based on environmental changes rather than extensive planning. Behaviors are independent and map sensory inputs to motor actions. The overall robot behavior emerges from the concurrent behaviors. An example behavior class structure and move forward behavior are presented to illustrate behavior-based control.

Uploaded by

rohan raj
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PPTX, PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
85 views33 pages

ROS Lecture11

The document summarizes a lecture on behavior-based robotics. It discusses how behavior-based robotics uses a library of behaviors (controllers) that are switched between based on environmental changes rather than extensive planning. Behaviors are independent and map sensory inputs to motor actions. The overall robot behavior emerges from the concurrent behaviors. An example behavior class structure and move forward behavior are presented to illustrate behavior-based control.

Uploaded by

rohan raj
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PPTX, PDF, TXT or read online on Scribd
You are on page 1/ 33

October 2016

ROS – Lecture 11
Behavior-Based Robotics
Where to go next?

Lecturer: Roi Yehoshua


[email protected]
Agenda
• Behavior-based robotics
• Decision making in ROS
• Where to go next?

(C)2016 Roi Yehoshua


Behavior-Based Robotics
• The world is fundamentally unknown and changing
• Does not make sense to over-plan
• Key idea: to develop a library of useful behaviors
(controllers)
• Switch among behaviors in response to
environmental changes

(C)2016 Roi Yehoshua


Behavior
• A behavior is a mapping of sensory inputs to a
pattern of motor actions
• Composed of:
– Start conditions (preconditions) - what must be true
to be executable
– Actions - what changes once behavior executes
– Stop conditions - when the behavior terminates

(C)2016 Roi Yehoshua


Behaviors
• Behaviors are independent and operate concurrently
– One behavior does not know what another behavior is
doing or perceiving
• The overall behavior of the robot is emergent
– There is no explicit “controller” module which determines
what will be done

(C)2016 Roi Yehoshua


Example: Navigation
• Problem: Go to a goal location without bumping
into obstacles

• Need at least two behaviors: Go-to-goal and


Avoid-obstacles

(C)2016 Roi Yehoshua


Behaviors
Plan changes

Identify objects

Monitor change

Map

Explore

Wander

Avoid object

(C)2016 Roi Yehoshua


Behavior-Based Example
• Create a new package gazebo_random_walk
$$ cd
cd ~/catkin_ws/src
~/catkin_ws/src
$$ catkin_create_pkg
catkin_create_pkg behavior_based
behavior_based std_msgs
std_msgs rospy
rospy roscpp
roscpp

• Create a launch subdirectory within the package and


add the following launch file to it

(C)2016 Roi Yehoshua


Behavior Class – Header File
#include
#include <vector>
<vector>
using
using namespace
namespace std;
std;
  
class
class Behavior
Behavior {{
private:
private:
vector<Behavior
vector<Behavior *> *> _nextBehaviors;
_nextBehaviors;
  
public:
public:
Behavior();
Behavior();
virtual
virtual bool
bool startCond()
startCond() == 0;
0;
virtual bool stopCond() =
virtual bool stopCond() = 0; 0;
virtual
virtual void
void action()
action() == 0;
0;
  
Behavior
Behavior *addNext(Behavior
*addNext(Behavior *beh);
*beh);
Behavior
Behavior *selectNext(); 
*selectNext(); 

virtual
virtual ~Behavior();
~Behavior();
};
};

(C)2016 Roi Yehoshua


Behavior Class – cpp File
#include
#include "Behavior.h"
"Behavior.h"
#include
#include <iostream>
<iostream>
  
Behavior::Behavior()
Behavior::Behavior() {{
}}
  
Behavior::~Behavior()
Behavior::~Behavior() {{
}}
  
Behavior
Behavior *Behavior::addNext(Behavior
*Behavior::addNext(Behavior *beh)
*beh) {{
_nextBehaviors.push_back(beh);
_nextBehaviors.push_back(beh);
return
return this;
this;
}}
  
Behavior
Behavior *Behavior::selectNext()
*Behavior::selectNext() {{
for
for (int
(int ii == 0;
0; ii << _nextBehaviors.size();
_nextBehaviors.size(); i++)
i++)
{{
if
if (_nextBehaviors[i]->startCond())
(_nextBehaviors[i]->startCond())
return
return _nextBehaviors[i];
_nextBehaviors[i];
}}
return
return NULL;
NULL;
}}

(C)2016 Roi Yehoshua


MoveForward Behavior - Header
#include
#include "Behavior.h"
"Behavior.h"
#include <ros/ros.h>
#include <ros/ros.h>
#include
#include "sensor_msgs/LaserScan.h"
"sensor_msgs/LaserScan.h"
#include
#include <cmath>
<cmath>
  
class
class MoveForward:
MoveForward: public
public Behavior
Behavior {{
public:
public:
MoveForward();
MoveForward();
virtual
virtual bool
bool startCond();
startCond();
virtual void action();
virtual void action();
virtual
virtual bool
bool stopCond();
stopCond();
virtual ~MoveForward();
virtual ~MoveForward();
private:
private:
const
const static
static double
double FORWARD_SPEED_MPS
FORWARD_SPEED_MPS == 0.5;
0.5;
const
const static
static double
double MIN_SCAN_ANGLE_RAD
MIN_SCAN_ANGLE_RAD == -30.0/180
-30.0/180 ** M_PI;
M_PI;
const
const static
static double
double MAX_SCAN_ANGLE_RAD
MAX_SCAN_ANGLE_RAD == +30.0/180
+30.0/180 ** M_PI;
M_PI;
const static float MIN_PROXIMITY_RANGE_M = 0.5;
const static float MIN_PROXIMITY_RANGE_M = 0.5;
  
ros::NodeHandle
ros::NodeHandle node;
node;
ros::Publisher commandPub;
ros::Publisher commandPub;
ros::Subscriber
ros::Subscriber laserSub;
laserSub;
  
void
void scanCallback(const
scanCallback(const sensor_msgs::LaserScan::ConstPtr&
sensor_msgs::LaserScan::ConstPtr& scan);
scan);
bool
bool keepMovingForward;
keepMovingForward;
};
};

(C)2016 Roi Yehoshua


MoveForward Behavior – cpp (1)
#include
#include "MoveForward.h"
"MoveForward.h"
#include
#include "geometry_msgs/Twist.h"
"geometry_msgs/Twist.h"
  
MoveForward::MoveForward()
MoveForward::MoveForward() {{
commandPub
commandPub == node.advertise<geometry_msgs::Twist>("cmd_vel",
node.advertise<geometry_msgs::Twist>("cmd_vel", 10);
10);
laserSub
laserSub = node.subscribe("base_scan", 1, &MoveForward::scanCallback, this);
= node.subscribe("base_scan", 1, &MoveForward::scanCallback, this);
keepMovingForward
keepMovingForward == true;
true;
}}
  
bool
bool MoveForward::startCond()
MoveForward::startCond() {{
return
return keepMovingForward;
keepMovingForward;
}}
  
void
void MoveForward::action()
MoveForward::action() {{
geometry_msgs::Twist
geometry_msgs::Twist msg;
msg;
msg.linear.x = FORWARD_SPEED_MPS;
msg.linear.x = FORWARD_SPEED_MPS;
commandPub.publish(msg);
commandPub.publish(msg);
ROS_INFO("Moving
ROS_INFO("Moving forward");
forward");
}}
  
bool
bool MoveForward::stopCond()
MoveForward::stopCond() {{
return
return !keepMovingForward;
!keepMovingForward;
}}

(C)2016 Roi Yehoshua


MoveForward Behavior – cpp (2)
void
void MoveForward::scanCallback(const
MoveForward::scanCallback(const sensor_msgs::LaserScan::ConstPtr&
sensor_msgs::LaserScan::ConstPtr& scan)
scan)
{{
//
// Find
Find the
the closest
closest range
range between
between the
the defined
defined minimum
minimum and
and maximum
maximum angles
angles
int
int minIndex
minIndex == ceil((MIN_SCAN_ANGLE_RAD
ceil((MIN_SCAN_ANGLE_RAD -- scan->angle_min)
scan->angle_min) // scan->angle_increment);
scan->angle_increment);
int
int maxIndex
maxIndex == floor((MAX_SCAN_ANGLE_RAD
floor((MAX_SCAN_ANGLE_RAD -- scan->angle_min)
scan->angle_min) // scan-
scan-
>angle_increment);
>angle_increment);
  
float
float closestRange
closestRange == scan->ranges[minIndex];
scan->ranges[minIndex];
for
for (int currIndex = minIndex ++ 1;
(int currIndex = minIndex 1; currIndex
currIndex <=
<= maxIndex;
maxIndex; currIndex++)
currIndex++) {{
if
if (scan->ranges[currIndex]
(scan->ranges[currIndex] << closestRange)
closestRange) {{
closestRange
closestRange == scan->ranges[currIndex];
scan->ranges[currIndex];
}}
}}
  
if
if (closestRange
(closestRange << MIN_PROXIMITY_RANGE_M)
MIN_PROXIMITY_RANGE_M) {{
keepMovingForward
keepMovingForward == false;
false;
}} else
else {{
keepMovingForward
keepMovingForward == true;
true;
}}
}}
  
MoveForward::~MoveForward()
MoveForward::~MoveForward() {  { 
}}

(C)2016 Roi Yehoshua


TurnLeft Behavior - Header
#include
#include "Behavior.h"
"Behavior.h"
#include <ros/ros.h>
#include <ros/ros.h>
#include
#include "sensor_msgs/LaserScan.h"
"sensor_msgs/LaserScan.h"
#include
#include <cmath>
<cmath>
  
class
class TurnLeft:
TurnLeft: public
public Behavior
Behavior {{
public:
public:
TurnLeft();
TurnLeft();
virtual
virtual bool
bool startCond();
startCond();
virtual void action();
virtual void action();
virtual
virtual bool
bool stopCond();
stopCond();
virtual ~TurnLeft();
virtual ~TurnLeft();
private:
private:
const
const static
static double
double TURN_SPEED_MPS
TURN_SPEED_MPS == 1.0;
1.0;
const
const static
static double
double MIN_SCAN_ANGLE_RAD
MIN_SCAN_ANGLE_RAD == -30.0/180
-30.0/180 ** M_PI;
M_PI;
const
const static
static double
double MAX_SCAN_ANGLE_RAD
MAX_SCAN_ANGLE_RAD == 0;
0;
const
const static float MIN_PROXIMITY_RANGE_M = 0.5;
static float MIN_PROXIMITY_RANGE_M = 0.5;
  
ros::NodeHandle
ros::NodeHandle node;
node;
ros::Publisher commandPub;
ros::Publisher commandPub;
ros::Subscriber
ros::Subscriber laserSub;
laserSub;
  
void
void scanCallback(const
scanCallback(const sensor_msgs::LaserScan::ConstPtr&
sensor_msgs::LaserScan::ConstPtr& scan);
scan);
bool
bool keepTurningLeft;
keepTurningLeft;
};
};

(C)2016 Roi Yehoshua


TurnLeft Behavior – cpp (1)
#include
#include "TurnLeft.h"
"TurnLeft.h"
#include
#include "geometry_msgs/Twist.h"
"geometry_msgs/Twist.h"
  
TurnLeft::TurnLeft()
TurnLeft::TurnLeft() {{
commandPub
commandPub == node.advertise<geometry_msgs::Twist>("cmd_vel",
node.advertise<geometry_msgs::Twist>("cmd_vel", 10);
10);
laserSub
laserSub = node.subscribe("base_scan", 1, &TurnLeft::scanCallback, this);
= node.subscribe("base_scan", 1, &TurnLeft::scanCallback, this);
keepTurningLeft
keepTurningLeft == true;
true;
}}
  
bool
bool TurnLeft::startCond()
TurnLeft::startCond() {{
return
return keepTurningLeft;
keepTurningLeft;
}}
  
void
void TurnLeft::action()
TurnLeft::action() {{
geometry_msgs::Twist
geometry_msgs::Twist msg;
msg;
msg.angular.z = TURN_SPEED_MPS;
msg.angular.z = TURN_SPEED_MPS;
commandPub.publish(msg);
commandPub.publish(msg);
ROS_INFO("Turning
ROS_INFO("Turning left");
left");
}}
  
bool
bool TurnLeft::stopCond()
TurnLeft::stopCond() {{
return
return !keepTurningLeft;
!keepTurningLeft;
}}

(C)2016 Roi Yehoshua


TurnLeft Behavior – cpp (2)
void
void TurnLeft::scanCallback(const
TurnLeft::scanCallback(const sensor_msgs::LaserScan::ConstPtr&
sensor_msgs::LaserScan::ConstPtr& scan)
scan)
{{
//
// Find
Find the
the closest
closest range
range between
between the
the defined
defined minimum
minimum and
and maximum
maximum angles
angles
int
int minIndex
minIndex == ceil((MIN_SCAN_ANGLE_RAD
ceil((MIN_SCAN_ANGLE_RAD -- scan->angle_min)
scan->angle_min) // scan->angle_increment);
scan->angle_increment);
int
int maxIndex
maxIndex == floor((MAX_SCAN_ANGLE_RAD
floor((MAX_SCAN_ANGLE_RAD -- scan->angle_min)
scan->angle_min) // scan-
scan-
>angle_increment);
>angle_increment);
  
float
float closestRange
closestRange == scan->ranges[minIndex];
scan->ranges[minIndex];
for
for (int currIndex = minIndex ++ 1;
(int currIndex = minIndex 1; currIndex
currIndex <=
<= maxIndex;
maxIndex; currIndex++)
currIndex++) {{
if
if (scan->ranges[currIndex]
(scan->ranges[currIndex] << closestRange)
closestRange) {{
closestRange
closestRange == scan->ranges[currIndex];
scan->ranges[currIndex];
}}
}}
  
if
if (closestRange
(closestRange << MIN_PROXIMITY_RANGE_M)
MIN_PROXIMITY_RANGE_M) {{
keepTurningLeft
keepTurningLeft == true;
true;
}} else
else {{
keepTurningLeft
keepTurningLeft == false;
false;
}}
}}
  
TurnLeft::~TurnLeft()
TurnLeft::~TurnLeft() {  { 
}}

(C)2016 Roi Yehoshua


Behavior-Based Robotics
Two main challenges in behavior-based robotics
• Behavior selection - How do we select the
correct behavior?
• Behavior fusion – if several behaviors run in
parallel:
– How to merge the results?
– How to determine weight of each behavior in the
result?

(C)2016 Roi Yehoshua


State-Based Selection

C
A A
C
B C
Start
A D
A

• Every state represents a behavior


• Transitions are triggered by sensor readings

(C)2016 Roi Yehoshua


Example: Robot Soccer

(C)2016 Roi Yehoshua


Plan Class – Header file
#include
#include <vector>
<vector>
#include
#include "Behavior.h"
"Behavior.h"
using
using namespace
namespace std;
std;
  
class
class Plan
Plan {{
public:
public:
Plan();
Plan();
Behavior
Behavior *getStartBehavior();
*getStartBehavior();
virtual
virtual ~Plan();
~Plan();
protected:
protected:
vector<Behavior
vector<Behavior *>*> behaviors;
behaviors;
Behavior
Behavior *startBehavior;
*startBehavior;
};
};

(C)2016 Roi Yehoshua


Plan Class – cpp File
#include
#include "Plan.h"
"Plan.h"
#include
#include <iostream>
<iostream>
  
Plan::Plan()
Plan::Plan() :: startBehavior(NULL)
startBehavior(NULL) {{
  
}}
  
Behavior
Behavior *Plan::getStartBehavior()
*Plan::getStartBehavior() {{
return
return startBehavior;
startBehavior;
}}
  
Plan::~Plan()
Plan::~Plan() {{
  
}}

(C)2016 Roi Yehoshua


ObstacleAvoidPlan – Header File
#include
#include "Plan.h"
"Plan.h"
  
class
class ObstacleAvoidPlan:
ObstacleAvoidPlan: public
public Plan
Plan {{
public:
public:
ObstacleAvoidPlan();
ObstacleAvoidPlan();
virtual
virtual ~ObstacleAvoidPlan();
~ObstacleAvoidPlan();
};
};  

(C)2016 Roi Yehoshua


ObstacleAvoidPlan – cpp File
#include
#include "ObstacleAvoidPlan.h"
"ObstacleAvoidPlan.h"
#include
#include "MoveForward.h"
"MoveForward.h"
#include
#include "TurnLeft.h"
"TurnLeft.h"
#include
#include "TurnRight.h"
"TurnRight.h"
  
ObstacleAvoidPlan::ObstacleAvoidPlan()
ObstacleAvoidPlan::ObstacleAvoidPlan() {{
//
// Creating
Creating behaviors
behaviors
behaviors.push_back(new
behaviors.push_back(new MoveForward());
MoveForward());
behaviors.push_back(new
behaviors.push_back(new TurnLeft());
TurnLeft());
behaviors.push_back(new
behaviors.push_back(new TurnRight());
TurnRight());
  
//
// Connecting
Connecting behaviors
behaviors
behaviors[0]->addNext(behaviors[1]);
behaviors[0]->addNext(behaviors[1]);
behaviors[0]->addNext(behaviors[2]);
behaviors[0]->addNext(behaviors[2]);
  
behaviors[1]->addNext(behaviors[0]);
behaviors[1]->addNext(behaviors[0]);
behaviors[2]->addNext(behaviors[0]);
behaviors[2]->addNext(behaviors[0]);
  
startBehavior
startBehavior == behaviors[0];
behaviors[0];
}}

(C)2016 Roi Yehoshua


Manager – Header File
#include
#include "Plan.h"
"Plan.h"
#include
#include "Behavior.h"
"Behavior.h"
  
class
class Manager
Manager {{
public:
public:
Manager(Plan
Manager(Plan *plan);
*plan);
void
void run();
run();
virtual
virtual ~Manager();
~Manager();
private:
private:
Plan
Plan *plan;
*plan;
Behavior
Behavior *currBehavior;
*currBehavior;
};
};

(C)2016 Roi Yehoshua


Manager – cpp File
#include
#include "Manager.h"
"Manager.h"
#include
#include <ros/ros.h>
<ros/ros.h>
  
Manager::Manager(Plan
Manager::Manager(Plan *plan)
*plan) :: plan(plan)
plan(plan) {{
currBehavior
currBehavior == plan->getStartBehavior();
plan->getStartBehavior();
}}
  
void
void Manager::run()
Manager::run()
{{
ros::Rate
ros::Rate rate(10); 
rate(10); 
if
if (!currBehavior->startCond())
(!currBehavior->startCond()) {{
ROS_ERROR("Cannot
ROS_ERROR("Cannot start
start the
the first
first behavior");
behavior");
return;
return;


while
while (ros::ok()
(ros::ok() &&
&& currBehavior
currBehavior !=
!= NULL)
NULL) {{
currBehavior->action();
currBehavior->action();
  
if
if (currBehavior->stopCond())
(currBehavior->stopCond()) {{
currBehavior
currBehavior == currBehavior->selectNext();
currBehavior->selectNext();
}}
ros::spinOnce();
ros::spinOnce();
rate.sleep();
rate.sleep();
}}
ROS_INFO("Manager
ROS_INFO("Manager stopped");
stopped");
}}

(C)2016 Roi Yehoshua


Run.cpp
#include
#include "Manager.h"
"Manager.h"
#include
#include "ObstacleAvoidPlan.h"
"ObstacleAvoidPlan.h"
#include <ros/ros.h>
#include <ros/ros.h>
  
int
int main(int
main(int argc,
argc, char
char **argv)
**argv) {{
ros::init(argc,
ros::init(argc, argv,
argv, "behavior_based_wanderer");
"behavior_based_wanderer");
  
ObstacleAvoidPlan
ObstacleAvoidPlan plan;
plan;
Manager manager(&plan);
Manager manager(&plan);
  
//
// Start
Start the
the movement
movement
manager.run();
manager.run();
  
return
return 0;
0;
};
};

(C)2016 Roi Yehoshua


Behavior-Based Example
• Create a launch subdirectory within the package and
copy the launch file from gazebo_random_walk package
• Change the following lines in the launch file

(C)2016 Roi Yehoshua


behavior_based_wanderer.launch
<launch>
<launch>
<param
<param name="/use_sim_time"
name="/use_sim_time" value="true"
value="true" />
/>

<!--
<!-- Launch
Launch world
world -->
-->
<include
<include file="$(find
file="$(find gazebo_ros)/launch/willowgarage_world.launch"/>
gazebo_ros)/launch/willowgarage_world.launch"/>

<arg
<arg name="init_pose"
name="init_pose" value="-x
value="-x -5
-5 -y
-y -2
-2 -z
-z 1"/>
1"/>

<param
<param name="robot_description"
name="robot_description" textfile="$(find
textfile="$(find r2d2_description)/urdf/r2d2.urdf"/>
r2d2_description)/urdf/r2d2.urdf"/>

<!--
<!-- Spawn
Spawn robot's
robot's model
model -->
-->
<node
<node name="spawn_urdf"
name="spawn_urdf" pkg="gazebo_ros"
pkg="gazebo_ros" type="spawn_model"
type="spawn_model" args="$(arg
args="$(arg init_pose)
init_pose) -urdf
-urdf
-param
-param robot_description
robot_description -model
-model my_robot"
my_robot" output="screen"/>
output="screen"/>

<node
<node name="joint_state_publisher"
name="joint_state_publisher" pkg="joint_state_publisher"
pkg="joint_state_publisher" type="joint_state_publisher"/>
type="joint_state_publisher"/>
<node
<node pkg="robot_state_publisher" type="robot_state_publisher" name="robot_state_publisher"
pkg="robot_state_publisher" type="robot_state_publisher" name="robot_state_publisher"
output="screen"/>
output="screen"/>

<!--
<!-- Launch
Launch random
random walk
walk node
node -->
-->
<node
<node name="behavior_based_wanderer"
name="behavior_based_wanderer" pkg="behavior_based"
pkg="behavior_based" type="behavior_based_wanderer"
type="behavior_based_wanderer"
output="screen"/>
output="screen"/>
</launch>
</launch>

(C)2016 Roi Yehoshua


Behavior-Based Example

(C)2016 Roi Yehoshua


Decision Making in ROS
• http://wiki.ros.org/decision_making
• Light-weight, generic and extendable tools for
writing, executing, debugging and monitoring
decision making models through ROS standard tools
• Supports different decision making models:
– Finite State Machines
– Hierarchical FSMs
– Behavior Trees
– BDI
• Developed by Cogniteam  
(C)2016 Roi Yehoshua
Where To Go Next?
• There are still many areas of ROS to explore:
– 3-D image processing using PCL
– Identifying your friends and family using
face_recognition
– Identifying and grasping objects on a table top
• or how about playing chess?
– Building knowledge bases with knowrob
– Learning from experience using
reinforcement_learning

(C)2016 Roi Yehoshua


Where To Go Next?
• There are now over 2000 packages and libraries
available for ROS
• Click on the Browse Software link at the top of
the ROS Wiki for a list of all ROS packages and
stacks that have been submitted for indexing.
• When you are ready, you can contribute your
own package(s) back to the ROS community
• Welcome to the future of robotics.
• Have fun and good luck!

(C)2016 Roi Yehoshua


(C)2016 Roi Yehoshua

You might also like