00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013 #include <errno.h>
00014 #include <fcntl.h>
00015 #include <geometry_msgs/PoseWithCovarianceStamped.h>
00016 #include <ros/ros.h>
00017 #include <sensor_msgs/LaserScan.h>
00018 #include <signal.h>
00019 #include <termios.h>
00020 #include <unistd.h>
00021
00022 int fdes;
00023 bool exit_;
00024
00025 void SigintHandler(int sig) {
00026 exit_ = true;
00027 close(fdes);
00028 ros::Duration(0.5).sleep();
00029 ros::shutdown();
00030 }
00031
00032 int set_interface_attribs(int fd, int speed, int parity) {
00033 struct termios tty;
00034 memset(&tty, 0, sizeof tty);
00035 if (tcgetattr(fd, &tty) != 0) {
00036 ROS_ERROR("error %d from tcgetattr", errno);
00037 return -1;
00038 }
00039
00040 cfsetospeed(&tty, speed);
00041 cfsetispeed(&tty, speed);
00042
00043 tty.c_cflag = (tty.c_cflag & ~CSIZE) | CS8;
00044
00045
00046 tty.c_iflag &= ~IGNBRK;
00047 tty.c_lflag = 0;
00048
00049 tty.c_oflag = 0;
00050 tty.c_cc[VMIN] = 0;
00051 tty.c_cc[VTIME] = 5;
00052
00053 tty.c_iflag &= ~(IXON | IXOFF | IXANY);
00054
00055 tty.c_cflag |= (CLOCAL | CREAD);
00056
00057 tty.c_cflag &= ~(PARENB | PARODD);
00058 tty.c_cflag |= parity;
00059 tty.c_cflag &= ~CSTOPB;
00060 tty.c_cflag &= ~CRTSCTS;
00061
00062 if (tcsetattr(fd, TCSANOW, &tty) != 0) {
00063 ROS_ERROR("error %d from tcsetattr", errno);
00064 return -1;
00065 }
00066 return 0;
00067 }
00068
00069 void set_blocking(int fd, int should_block) {
00070 struct termios tty;
00071 memset(&tty, 0, sizeof tty);
00072 if (tcgetattr(fd, &tty) != 0) {
00073 ROS_ERROR("error %d from tggetattr", errno);
00074 return;
00075 }
00076
00077 tty.c_cc[VMIN] = should_block ? 1 : 0;
00078 tty.c_cc[VTIME] = 5;
00079
00080 if (tcsetattr(fd, TCSANOW, &tty) != 0)
00081 ROS_ERROR("error %d setting term attributes", errno);
00082 }
00083
00084 bool isValidNumber(char a) {
00085 return ((a >= 48) && (a <= 57));
00086 }
00087
00088 int main(int argc, char **argv) {
00089 ros::init(argc, argv, "sf30_node");
00090 ros::NodeHandle n;
00091
00092 signal(SIGINT, SigintHandler);
00093
00094
00095 std::string s;
00096 std::string topic_name;
00097 std::string frame_id = "sf30";
00098 bool debug_;
00099 bool publish_as_pose;
00100 int update_rate;
00101 double variance_;
00102
00103 n.getParam("sf30_node/portname", s);
00104 n.getParam("sf30_node/debug", debug_);
00105 n.getParam("sf30_node/publish_as_pose", publish_as_pose);
00106 n.getParam("sf30_node/update_rate", update_rate);
00107 n.getParam("sf30_node/topic_name", topic_name);
00108 n.getParam("sf30_node/frame_id", frame_id);
00109 n.getParam("sf30_node/altitude_variance", variance_);
00110
00111 ros::Rate loop_rate(update_rate);
00112 ros::Publisher pub_;
00113
00114 if (publish_as_pose) {
00115 pub_ =
00116 n.advertise<geometry_msgs::PoseWithCovarianceStamped>(topic_name, 10);
00117 } else {
00118 pub_ = n.advertise<sensor_msgs::LaserScan>(topic_name, 10);
00119 }
00120
00121 const char *portname = s.c_str();
00122
00123 fdes = open(portname, O_RDWR | O_NOCTTY | O_SYNC);
00124 if (fdes < 0) {
00125 ROS_ERROR("Error %d opening %s: %s", errno, portname, strerror(errno));
00126 return 1;
00127 }
00128
00129
00130 set_interface_attribs(fdes, B115200, 0);
00131
00132 set_blocking(fdes, 1);
00133
00134 char buf[1];
00135 int nc, i;
00136 float num = 0.0;
00137 int confidence = 0;
00138 tcflush(fdes, TCIFLUSH);
00139 ros::Time last_time = ros::Time::now();
00140 exit_ = false;
00141
00142
00143 while (ros::ok() && !exit_) {
00144 tcflush(fdes, TCIFLUSH);
00145
00146 while (ros::ok() && !exit_) {
00147
00148 nc = read(fdes, buf, 1);
00149 ROS_INFO_COND(debug_, " char: %d ", (int)buf[0]);
00150
00151 if ((nc == 1) && (buf[0] == 'm')) {
00152
00153 num = 0.0;
00154 confidence = 0;
00155
00156 nc = read(fdes, buf, 1);
00157 ROS_INFO_COND(debug_, " char: %d ", (int)buf[0]);
00158 if ((nc != 1) || (buf[0] != 10 && buf[0] != 13)) {
00159 ROS_ERROR("First line break not found : %d", buf[0]);
00160 break;
00161 }
00162 nc = read(fdes, buf, 1);
00163 ROS_INFO_COND(debug_, " char: %d ", (int)buf[0]);
00164 if ((nc != 1) || buf[0] != 10) {
00165 ROS_ERROR("Second line break not found : %d", buf[0]);
00166 break;
00167 }
00168 i = 1;
00169 do {
00170 nc = read(fdes, buf, 1);
00171 ROS_INFO_COND(debug_, " char: %d ", (int)buf[0]);
00172 if ((nc == 1) && (isValidNumber(buf[0]))) {
00173 num = num * i + atof(buf);
00174 i = i * 10;
00175 } else {
00176 break;
00177 }
00178 } while (1);
00179
00180 if ((nc != 1) || (buf[0] != '.')) {
00181
00182
00183 num = 0.0;
00184 ROS_ERROR("Not decimal point: %c", buf[0]);
00185 break;
00186 }
00187
00188 nc = read(fdes, buf, 1);
00189 ROS_INFO_COND(debug_, " char: %d ", (int)buf[0]);
00190 if ((nc != 1) || (!isValidNumber(buf[0]))) {
00191 num = 0.0;
00192 ROS_ERROR("(2) Not valid number: %c", buf[0]);
00193 break;
00194 }
00195 num = num + atof(buf) / 10.0;
00196
00197 nc = read(fdes, buf, 1);
00198 ROS_INFO_COND(debug_, " char: %d ", (int)buf[0]);
00199 if ((nc != 1) || (!isValidNumber(buf[0]))) {
00200 num = 0.0;
00201 ROS_ERROR("(3) Not valid number: %c", buf[0]);
00202 break;
00203 }
00204 num = num + atof(buf) / 100.0;
00205
00206 confidence = 1;
00207
00208 break;
00209 }
00210
00211 }
00212
00213 ros::Time now = ros::Time::now();
00214 ros::Duration duration = now - last_time;
00215 last_time = now;
00216
00217 if (publish_as_pose) {
00218 geometry_msgs::PoseWithCovarianceStamped data;
00219 data.header.frame_id = frame_id;
00220 data.header.stamp = ros::Time::now();
00221 data.pose.pose.position.z = num;
00222 data.pose.covariance[14] = variance_;
00223 pub_.publish(data);
00224 } else {
00225 sensor_msgs::LaserScan data;
00226 data.header.frame_id = "sf30";
00227 data.header.stamp = ros::Time::now();
00228 data.scan_time = duration.toSec();
00229 data.range_max = 100.0;
00230 data.ranges.push_back(num);
00231
00232
00233 data.intensities.push_back((double)confidence);
00234 pub_.publish(data);
00235 }
00236
00237 ros::spinOnce();
00238 loop_rate.sleep();
00239 }
00240 }