example_mobile_robot_node.cpp
Go to the documentation of this file.
1 #include <ros/ros.h>
3 #include <nav_msgs/Odometry.h>
4 #include <std_srvs/Empty.h>
5 #include "sensor_msgs/JointState.h"
6 #include "hebiros/AddGroupFromNamesSrv.h"
7 
8 using namespace hebiros;
9 
10 
11 double x = 0.0;
12 double y = 0.0;
13 double th = 0.0;
14 geometry_msgs::Quaternion odom_quat;
15 
16 double vx = 0;
17 double vy = 0;
18 double vth = 0;
19 
20 //Radius of the wheel (m)
21 double wheel_radius = 0.1;
22 //Distance from the center to the wheel (m)
23 double wheel_distance = 0.087;
24 
25 //Set linear and angular velocity commands based on incoming /cmd_vel
26 void cmd_vel_callback(geometry_msgs::Twist msg){
27  vx = msg.linear.x;
28  vth = msg.angular.z;
29 }
30 
31 //Reset odometry position to 0
32 bool reset_callback(std_srvs::Empty::Request &req, std_srvs::Empty::Response &res) {
33  x = 0.0;
34  y = 0.0;
35  th = 0.0;
36 
37  return true;
38 }
39 
40 //Set odometry position and orientation from rtabmap
41 void odometry_callback(nav_msgs::Odometry data) {
42  x = data.pose.pose.position.x;
43  y = data.pose.pose.position.y;
44  odom_quat = data.pose.pose.orientation;
45 }
46 
47 
48 int main(int argc, char** argv){
49  ros::init(argc, argv, "example_mobile_robot_node");
50  ros::NodeHandle node;
51 
52  //This node while handle two transforms, one from "map" to "odom"
53  //and one from "odom" to "base_link" (the robot)
54  tf::TransformBroadcaster map_broadcaster;
55  tf::TransformBroadcaster odom_broadcaster;
56 
57  odom_quat.x = 0.0;
58  odom_quat.y = 0.0;
59  odom_quat.z = 0.0;
60  odom_quat.w = 1.0;
61 
62  std::string group_name = "mobile_robot";
63 
64  //Convenience service for resetting the odometry position to 0
65  ros::ServiceServer reset_service = node.advertiseService(
66  "/example_mobile_robot_node/reset", &reset_callback);
67 
68  //Receive visual odometry from rtabmap
69  ros::Subscriber odometry_subscriber = node.subscribe(
70  "/rtabmap/odom", 100, odometry_callback);
71 
72  //Publish odometry for move_base by copying the received odometry from rtabmap
73  //It would also be possible to fuse rtabmap odometry with other odometry sources before publishing
74  ros::Publisher odom_pub = node.advertise<nav_msgs::Odometry>("odom", 50);
75 
76  //Subscribe to command velocities for the robot to be translated into left and right velocities
77  ros::Subscriber cmd_vel_subscriber = node.subscribe("/cmd_vel", 10, &cmd_vel_callback);
78 
79  //Create a client which uses the service to create a group
80  ros::ServiceClient add_group_client = node.serviceClient<AddGroupFromNamesSrv>(
81  "/hebiros/add_group_from_names");
82 
83  //Create a publisher to send desired commands to a group
84  ros::Publisher command_publisher = node.advertise<sensor_msgs::JointState>(
85  "/hebiros/"+group_name+"/command/joint_state", 100);
86 
87  //Construct a group using 2 known modules
88  AddGroupFromNamesSrv add_group_srv;
89  add_group_srv.request.group_name = group_name;
90  add_group_srv.request.names = {"Left", "Right"};
91  add_group_srv.request.families = {"Wheels"};
92  while(!add_group_client.call(add_group_srv)) {}
93 
94  //Construct a JointState to command the modules
95  sensor_msgs::JointState command_msg;
96  command_msg.name.push_back("Wheels/Left");
97  command_msg.name.push_back("Wheels/Right");
98  command_msg.velocity.resize(2);
99 
100  ros::Rate rate(200.0);
101 
102  while(ros::ok()){
103  ros::spinOnce();
104 
105  ros::Time current_time = ros::Time::now();
106 
107  //Send the transform for "map" to "odom" to tf
108  //The map and odometry frame do not differ, so just send a 0 transform
109  map_broadcaster.sendTransform(
111  tf::Transform(tf::Quaternion(0, 0, 0, 1), tf::Vector3(0.0, 0.0, 0.0)),
112  current_time,"map", "odom"));
113 
114  //Send the transform for "odom" to "base_link" to tf
115  //The odometry position and orientation are simply copied from rtabmap's odometry
116  geometry_msgs::TransformStamped odom_trans;
117  odom_trans.header.stamp = current_time;
118  odom_trans.header.frame_id = "odom";
119  odom_trans.child_frame_id = "base_link";
120  odom_trans.transform.translation.x = x;
121  odom_trans.transform.translation.y = y;
122  odom_trans.transform.translation.z = 0.0;
123  odom_trans.transform.rotation = odom_quat;
124  odom_broadcaster.sendTransform(odom_trans);
125 
126  //Additionally publish the odometry over a rostopic
127  nav_msgs::Odometry odom;
128  odom.header.stamp = current_time;
129  odom.header.frame_id = "odom";
130  odom.child_frame_id = "base_link";
131  //The odometry position and orientation are simply copied from rtabmap's odometry
132  odom.pose.pose.position.x = x;
133  odom.pose.pose.position.y = y;
134  odom.pose.pose.position.z = 0.0;
135  odom.pose.pose.orientation = odom_quat;
136  //The twist is taken from the commanded velocity over /cmd_vel
137  odom.twist.twist.linear.x = vx;
138  odom.twist.twist.linear.y = vy;
139  odom.twist.twist.angular.z = vth;
140  odom_pub.publish(odom);
141 
142  //Apply standard differential drive equations to the wheel modules and publish as a command
143  //The right wheel velocity is negative because it is mounted in the opposite direction
144  command_msg.velocity[0] = 1.0 * ((vx - (wheel_distance * vth)) / wheel_radius);
145  command_msg.velocity[1] = -1.0 * ((vx + (wheel_distance * vth)) / wheel_radius);
146  command_publisher.publish(command_msg);
147 
148  rate.sleep();
149  }
150 
151  return 0;
152 }
153 
154 
155 
156 
157 
158 
159 
160 
161 
ServiceClient serviceClient(const std::string &service_name, bool persistent=false, const M_string &header_values=M_string())
void odometry_callback(nav_msgs::Odometry data)
void publish(const boost::shared_ptr< M > &message) const
Subscriber subscribe(const std::string &topic, uint32_t queue_size, void(T::*fp)(M), T *obj, const TransportHints &transport_hints=TransportHints())
int main(int argc, char **argv)
ROSCPP_DECL void init(int &argc, char **argv, const std::string &name, uint32_t options=0)
bool call(MReq &req, MRes &res)
bool reset_callback(std_srvs::Empty::Request &req, std_srvs::Empty::Response &res)
ServiceServer advertiseService(const std::string &service, bool(T::*srv_func)(MReq &, MRes &), T *obj)
double wheel_radius
void cmd_vel_callback(geometry_msgs::Twist msg)
ROSCPP_DECL bool ok()
void sendTransform(const StampedTransform &transform)
double wheel_distance
Publisher advertise(const std::string &topic, uint32_t queue_size, bool latch=false)
bool sleep()
static Time now()
ROSCPP_DECL void spinOnce()
geometry_msgs::Quaternion odom_quat


hebiros_advanced_examples
Author(s): Xavier Artache , Matthew Tesch
autogenerated on Thu Sep 3 2020 04:13:22