Go to the documentation of this file.00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038 #include <ros/ros.h>
00039 #include <tf/transform_broadcaster.h>
00040 #include <nav_msgs/Odometry.h>
00041 #include <geometry_msgs/Twist.h>
00042 #include <lse_sensor_msgs/Nostril.h>
00043
00044 #include "miniQ.h"
00045
00046
00047 class Robot
00048 {
00049 public:
00050 Robot(int id) : robot(), odom_pub(), cmd_vel_sub(), prefix(), nose_pub()
00051 {
00052 robot.setId(id);
00053
00054 prefix = "/robot_";
00055 prefix.append<int>(1, 48+id);
00056 };
00057
00058 Robot(const Robot& r) : robot(), odom_pub(), cmd_vel_sub(), prefix(), nose_pub()
00059 {
00060 robot = r.robot;
00061
00062 odom_pub = r.odom_pub;
00063 cmd_vel_sub = r.cmd_vel_sub;
00064 prefix = r.prefix;
00065 nose_pub = r.nose_pub;
00066 };
00067
00068
00069 miniQ robot;
00070
00071 ros::Publisher odom_pub;
00072 ros::Subscriber cmd_vel_sub;
00073
00074 ros::Publisher nose_pub;
00075
00076 std::string prefix;
00077 };
00078
00079
00080 std::vector<Robot> miniqs;
00081
00082
00083 void cmdVelReceived(int index, const geometry_msgs::Twist::ConstPtr& cmd_vel)
00084 {
00085 miniqs[index].robot.setVelocities(cmd_vel->linear.x, cmd_vel->angular.z);
00086 }
00087
00088
00089 int main(int argc, char** argv)
00090 {
00091 ros::init(argc, argv, "miniq_node");
00092
00093 ROS_INFO("miniQ for ROS - Multi robot version.");
00094
00095 ros::NodeHandle n;
00096 ros::NodeHandle pn("~");
00097
00098 std::string port;
00099 pn.param<std::string>("port", port, "/dev/ttyUSB0");
00100 int baudrate;
00101 pn.param("baudrate", baudrate, 57600);
00102
00103 if(!miniQ::openPort((char*)port.c_str(), baudrate))
00104 {
00105 ROS_FATAL("miniQ -- Failed to open serial port %s at %d baud!", port.c_str(), baudrate);
00106 ROS_BREAK();
00107 }
00108 ROS_INFO("miniQ -- Successfully connected to the miniQ!");
00109
00110 std::vector<int> ids;
00111
00112
00113 XmlRpc::XmlRpcValue list_of_ids;
00114 if( n.getParam("/list_of_ids", list_of_ids) )
00115 {
00116 ROS_ASSERT(list_of_ids.getType() == XmlRpc::XmlRpcValue::TypeArray);
00117
00118 for(int i=0 ; i<list_of_ids.size() ; ++i)
00119 {
00120 ROS_ASSERT(list_of_ids[i].getType() == XmlRpc::XmlRpcValue::TypeInt);
00121 ids.push_back(static_cast<int>(list_of_ids[i]));
00122 }
00123 }
00124 else
00125
00126 {
00127 ROS_INFO("miniQ -- A list of IDs was not provided, scanning for robots...");
00128
00129 for(int i=0 ; i<=10 ; i++)
00130 {
00131 int id = miniQ::scanForId(i);
00132 if(id>0)
00133 {
00134 ids.push_back(id);
00135 ROS_INFO("miniQ -- Found id %d", id);
00136 }
00137 }
00138 }
00139 if(ids.size() == 0)
00140 {
00141 ROS_FATAL("miniQ -- Could not find any miniQs!!!");
00142 ROS_BREAK();
00143 }
00144 ROS_INFO("miniQ -- Finished scanning for robots!");
00145
00146 for(int i=0 ; i<ids.size() ; ++i)
00147 {
00148 miniqs.push_back(Robot(ids[i]));
00149
00150 std::string odom_topic = miniqs[i].prefix;
00151 odom_topic.append("/odom");
00152 miniqs[i].odom_pub = n.advertise<nav_msgs::Odometry>(odom_topic, 50);
00153
00154 std::string cmd_vel_topic = miniqs[i].prefix;
00155 cmd_vel_topic.append("/cmd_vel");
00156 miniqs[i].cmd_vel_sub = n.subscribe<geometry_msgs::Twist>(cmd_vel_topic, 10, boost::bind(cmdVelReceived, i, _1) );
00157
00158 std::string nose_topic = miniqs[i].prefix;
00159 nose_topic.append("/nose");
00160 miniqs[i].nose_pub = n.advertise<lse_sensor_msgs::Nostril>(nose_topic, 20);
00161 }
00162
00163 tf::TransformBroadcaster odom_broadcaster;
00164
00165 ros::Time current_time;
00166
00167 std::string frame_id;
00168
00169 ros::Rate r(MINIQ_RATE);
00170 while(n.ok())
00171 {
00172 current_time = ros::Time::now();
00173
00174 for(int i=0 ; i<miniqs.size() ; i++)
00175 {
00176 ros::Time start_time = ros::Time::now();
00177 if(!miniqs[i].robot.update()) ROS_WARN("miniQ -- Failed to update the data for robot %d!!!", miniqs[i].robot.getID());
00178
00179 ros::Duration elapsed_time = ros::Time::now() - start_time;
00180
00181
00182 double odom_x = miniqs[i].robot.getX();
00183 double odom_y = miniqs[i].robot.getY();
00184 double odom_yaw = miniqs[i].robot.getYaw();
00185
00186
00187
00188
00189 geometry_msgs::Quaternion odom_quat = tf::createQuaternionMsgFromYaw(odom_yaw);
00190
00191
00192 tf::Transform new_tf(tf::createQuaternionFromYaw(odom_yaw), tf::Vector3(odom_x, odom_y, 0.0));
00193 ros::Time transform_expiration = current_time + ros::Duration(1/(MINIQ_RATE)*2.0);
00194 std::string odom_frame_id = miniqs[i].prefix;
00195 odom_frame_id.append("/odom");
00196 std::string base_frame_id = miniqs[i].prefix;
00197 base_frame_id.append("/base_link");
00198 tf::StampedTransform odom_trans(new_tf, transform_expiration, odom_frame_id, base_frame_id);
00199
00200
00201 odom_broadcaster.sendTransform(odom_trans);
00202
00203
00204 nav_msgs::Odometry odom;
00205 odom.header.stamp = current_time;
00206 frame_id = miniqs[i].prefix;
00207 frame_id.append("/odom");
00208 odom.header.frame_id = frame_id;
00209
00210
00211 odom.pose.pose.position.x = odom_x;
00212 odom.pose.pose.position.y = odom_y;
00213 odom.pose.pose.orientation = odom_quat;
00214
00215
00216 frame_id = miniqs[i].prefix;
00217 frame_id.append("/base_link");
00218 odom.child_frame_id = frame_id;
00219 odom.twist.twist.linear.x = miniqs[i].robot.getLinearVelocity();
00220 odom.twist.twist.angular.z = miniqs[i].robot.getAngularVelocity();
00221
00222
00223 miniqs[i].odom_pub.publish(odom);
00224
00225
00226 lse_sensor_msgs::Nostril nose_msg;
00227
00228 nose_msg.header.stamp = current_time;
00229 nose_msg.header.frame_id = frame_id;
00230
00231 nose_msg.sensor_model = "e2v MiCS 5524";
00232 nose_msg.reading = miniqs[i].robot.getGas();
00233 nose_msg.min_reading = 0.0;
00234 nose_msg.max_reading = 1.0;
00235 nose_msg.clean_air = 0.0;
00236 nose_msg.raw_data = miniqs[i].robot.getRawGas();
00237
00238 miniqs[i].nose_pub.publish(nose_msg);
00239
00240 ros::Duration((1/MINIQ_RATE)/(double)(miniqs.size())-elapsed_time.toSec()*2.0).sleep();
00241 }
00242 ros::spinOnce();
00243 r.sleep();
00244 }
00245 return 0;
00246 }
00247
00248