Professional Documents
Culture Documents
## block(
block( pose
pose [[ -13.924
-13.924 25.020
25.020 00 180.000
180.000 ]] color
color "red")
"red")
#include
#include <string>
<string>
using
using namespace std;
namespace std;
#define
#define MAX_ROBOTS_NUM
MAX_ROBOTS_NUM 20
20
#define
#define FORWARD_SPEED
FORWARD_SPEED 0.2
0.2
int
int robot_id;
robot_id;
ros::Publisher
ros::Publisher cmd_vel_pub;
cmd_vel_pub; //
// publisher
publisher for
for movement
movement commands
commands
void
void move_forward();
move_forward();
//
// Check
Check that
that robot
robot id
id is
is between
between 00 and
and MAX_ROBOTS_NUM
MAX_ROBOTS_NUM
if
if (robot_id
(robot_id > MAX_ROBOTS_NUM || robot_id << 00 )) {{
> MAX_ROBOTS_NUM || robot_id
ROS_ERROR("The
ROS_ERROR("The robot's
robot's ID
ID must
must be
be an
an integer
integer number
number between
between 00 an
an 19");
19");
return
return -1;
-1;
}}
ROS_INFO("moving
ROS_INFO("moving robot
robot no.
no. %d",
%d", robot_id);
robot_id);
//
// Create
Create aa unique
unique node
node name
name
string
string node_name
node_name == "move_robot_";
"move_robot_";
node_name
node_name +=
+= id;
id;
cout
cout <<
<< node_name;
node_name;
ros::init(argc,
ros::init(argc, argv,
argv, node_name);
node_name);
ros::NodeHandle
ros::NodeHandle nh;
nh;
cmd_vel_pub
cmd_vel_pub == nh.advertise<geometry_msgs::Twist>(cmd_vel_topic_name,
nh.advertise<geometry_msgs::Twist>(cmd_vel_topic_name, 10);
10);
move_forward();
move_forward();
return
return 0;
0;
}}
//
// Loop
Loop at
at 10Hz,
10Hz, publishing
publishing movement
movement commands
commands until
until we
we shut
shut down
down
ros::Rate
ros::Rate rate(10);
rate(10);
while
while (ros::ok())
(ros::ok()) //
// Keep
Keep spinning
spinning loop
loop until
until user
user presses
presses Ctrl+C
Ctrl+C
{{
cmd_vel_pub.publish(cmd_vel);
cmd_vel_pub.publish(cmd_vel);
rate.sleep();
rate.sleep();
}}
//
// Stop
Stop the
the robot
robot
geometry_msgs::Twist
geometry_msgs::Twist stop_cmd_vel;
stop_cmd_vel;
stop_cmd_vel.linear.x
stop_cmd_vel.linear.x == 0.0;
0.0;
stop_cmd_vel.angular.z
stop_cmd_vel.angular.z == 0.0;
0.0;
cmd_vel_pub.publish(stop_cmd_vel);
cmd_vel_pub.publish(stop_cmd_vel);
ROS_INFO("robot
ROS_INFO("robot no.
no. %d
%d stopped",
stopped", robot_id);
robot_id);
}}
##
## Add
Add cmake
cmake target
target dependencies
dependencies of
of the
the executable/library
executable/library
##
## as
as an
an example,
example, message
message headers
headers may
may need
need to
to be
be generated
generated before
before nodes
nodes
## add_dependencies(stage_multi_node
add_dependencies(stage_multi_node stage_multi_generate_messages_cpp)
stage_multi_generate_messages_cpp)
##
## Specify
Specify libraries
libraries to
to link
link aa library
library or
or executable
executable target
target against
against
target_link_libraries(move_robot
target_link_libraries(move_robot ${catkin_LIBRARIES})
${catkin_LIBRARIES})
After changing the file call catkin_make
(C)2015 Roi Yehoshua
Running the Node Inside Eclipse
Create a new launch configuration, by clicking on
Run --> Run configurations... --> C/C++
Application (double click or click on New).
Select the correct binary on the main tab (use
the Browse button)
~/catkin_ws/devel/lib/stage_multi/move_robot
Make sure roscore and stage are running
Click Run
#include
#include <string>
<string>
using
using namespace std;
namespace std;
#define
#define MAX_ROBOTS_NUM
MAX_ROBOTS_NUM 20
20
#define
#define FORWARD_SPEED
FORWARD_SPEED 0.2
0.2
#define
#define MIN_SCAN_ANGLE
MIN_SCAN_ANGLE -60.0/180*M_PI
-60.0/180*M_PI
#define
#define MAX_SCAN_ANGLE +60.0/180*M_PI
MAX_SCAN_ANGLE +60.0/180*M_PI
#define
#define MIN_PROXIMITY_RANGE
MIN_PROXIMITY_RANGE 0.5
0.5
int
int robot_id;
robot_id;
ros::Publisher
ros::Publisher cmd_vel_pub;
cmd_vel_pub; //
// publisher
publisher for
for movement
movement commands
commands
ros::Subscriber
ros::Subscriber laser_scan_sub; // subscriber to the robot's laser
laser_scan_sub; // subscriber to the robot's laser scan
scan topic
topic
bool
bool keepMoving
keepMoving == true;
true;
void
void move_forward();
move_forward();
void
void scanCallback(const
scanCallback(const sensor_msgs::LaserScan::ConstPtr&
sensor_msgs::LaserScan::ConstPtr& scan);
scan);
char
char *id
*id == argv[1];
argv[1];
robot_id
robot_id == atoi(id);
atoi(id);
...
...
//
// subscribe
subscribe to
to robot's
robot's laser
laser scan
scan topic
topic "robot_X/base_scan"
"robot_X/base_scan"
string
string laser_scan_topic_name
laser_scan_topic_name == "robot_";
"robot_";
laser_scan_topic_name
laser_scan_topic_name +=
+= id;
id;
laser_scan_topic_name += "/base_scan";
laser_scan_topic_name += "/base_scan";
laser_scan_sub
laser_scan_sub == nh.subscribe(laser_scan_topic_name,
nh.subscribe(laser_scan_topic_name, 1,
1, &scanCallback);
&scanCallback);
move_forward();
move_forward();
return
return 0;
0;
}}
//
// Loop
Loop at
at 10Hz,
10Hz, publishing
publishing movement
movement commands
commands until
until we
we shut
shut down
down
ros::Rate
ros::Rate rate(10);
rate(10);
while
while (ros::ok()
(ros::ok() &&
&& keepMoving)
keepMoving) //
// Keep
Keep spinning
spinning loop
loop until
until user
user presses
presses
Ctrl+C
Ctrl+C
{{
cmd_vel_pub.publish(cmd_vel);
cmd_vel_pub.publish(cmd_vel);
ros::spinOnce();
ros::spinOnce(); //
// Need
Need to
to call
call this
this function
function often
often to
to allow
allow ROS
ROS to
to
process incoming messages
process incoming messages
rate.sleep();
rate.sleep();
}}
...
...
}}
float
float closestRange
closestRange == scan->ranges[minIndex];
scan->ranges[minIndex];
for
for (int
(int currIndex
currIndex == minIndex
minIndex ++ 1;
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];
}}
}}
//ROS_INFO_STREAM("Closest
//ROS_INFO_STREAM("Closest range:
range: "" <<
<< closestRange);
closestRange);
if
if (closestRange < MIN_PROXIMITY_RANGE) {{
(closestRange < MIN_PROXIMITY_RANGE)
keepMoving
keepMoving == false;
false;
}}
}}
So it looks like:
generate_messages(
generate_messages(
DEPENDENCIES
DEPENDENCIES
std_msgs
std_msgs
))
typedef
typedef uint32_t
uint32_t _robot_id_type;
_robot_id_type;
_robot_id_type robot_id;
_robot_id_type robot_id;
typedef
typedef uint8_t
uint8_t _is_ready_type;
_is_ready_type;
_is_ready_type
_is_ready_type is_ready;
is_ready;
typedef
typedef boost::shared_ptr<
boost::shared_ptr< ::multi_sync::RobotStatus_<ContainerAllocator>
::multi_sync::RobotStatus_<ContainerAllocator> >> Ptr;
Ptr;
typedef
typedef boost::shared_ptr<
boost::shared_ptr< ::multi_sync::RobotStatus_<ContainerAllocator>
::multi_sync::RobotStatus_<ContainerAllocator> const>
const> ConstPtr;
ConstPtr;
boost::shared_ptr<std::map<std::string,
boost::shared_ptr<std::map<std::string, std::string>
std::string> >> __connection_header;
__connection_header;
};
}; //
// struct
struct RobotStatus_
RobotStatus_
typedef
typedef ::multi_sync::RobotStatus_<std::allocator<void> >> RobotStatus;
::multi_sync::RobotStatus_<std::allocator<void> RobotStatus;
After that call a function that will wait for all the
other team members to become ready:
waitForTeam();
waitForTeam();
(C)2015 Roi Yehoshua
Publishing Ready Status Message
Add the following function that will publish a status message
when the robot is ready:
void
void publishReadyStatus()
publishReadyStatus() {{
multi_sync::RobotStatus
multi_sync::RobotStatus status_msg;
status_msg;
status_msg.header.stamp
status_msg.header.stamp == ros::Time::now();
ros::Time::now();
status_msg.robot_id
status_msg.robot_id == robot_id;
robot_id;
status_msg.is_ready
status_msg.is_ready == true;
true;
//
// Wait
Wait for
for the
the publisher
publisher to
to connect
connect to
to subscribers
subscribers
sleep(1.0);
sleep(1.0);
team_status_pub.publish(status_msg);
team_status_pub.publish(status_msg);
ROS_INFO("Robot
ROS_INFO("Robot %d
%d published
published ready
ready status",
status", robot_id);
robot_id);
}}
//
// Wait
Wait until
until all
all robots
robots are
are ready...
ready...
while
while (!teamReady)
(!teamReady) {{
ROS_INFO("Robot
ROS_INFO("Robot %d:
%d: waiting
waiting for
for team",
team", robot_id);
robot_id);
ros::spinOnce();
ros::spinOnce();
loopRate.sleep();
loopRate.sleep();
}}
}}
##
## Specify
Specify libraries
libraries to
to link
link aa library
library or
or executable
executable target
target against
against
target_link_libraries(move_robot_sync
target_link_libraries(move_robot_sync
${catkin_LIBRARIES}
${catkin_LIBRARIES}
))