00001 #include "evarobot_sonar/evarobot_sonar.h"
00002
00003
00004
00005
00006
00007
00008
00009
00010 int i_error_code = 0;
00011
00012 IMSONAR::IMSONAR(int fd,
00013 int id,
00014 int pin,
00015 boost::shared_ptr<IMDynamicReconfig> _dynamic_params):i_fd(fd), i_id(id), i_pin_no(pin),
00016 b_is_alive(false), dynamic_params(_dynamic_params)
00017 {
00018 struct sonar_ioc_transfer set_params;
00019 stringstream ss;
00020
00021
00022 ss << "sonar" << this->i_id;
00023 this->pub_sonar = this->n.advertise<sensor_msgs::Range>(ss.str().c_str(), 10);
00024
00025
00026 this->updater.setHardwareID("IM-SMO20");
00027 this->updater.add(ss.str().c_str(), this, &IMSONAR::ProduceDiagnostics);
00028
00029 this->min_freq = this->dynamic_params->d_min_freq;
00030 this->max_freq = this->dynamic_params->d_max_freq;
00031 this->pub_sonar_freq = new diagnostic_updater::HeaderlessTopicDiagnostic(ss.str().c_str(), this->updater,
00032 diagnostic_updater::FrequencyStatusParam(&min_freq, &max_freq, 0.1, 10));
00033
00034
00035
00036 ss.str("");
00037 ss << this->n.resolveName(n.getNamespace(), true) << "/sonar" << this->i_id << "_link";
00038
00039 this->sonar_msg.header.frame_id = ss.str();
00040 this->sonar_msg.radiation_type = 0;
00041
00042
00043 set_params.i_gpio_pin = this->i_pin_no;
00044 set_params.i_sonar_id = this->i_id;
00045 ioctl(this->i_fd, IOCTL_SET_PARAM, &set_params);
00046 }
00047
00048 IMSONAR::~IMSONAR()
00049 {
00050 delete pub_sonar_freq;
00051 }
00052
00053 bool IMSONAR::Check()
00054 {
00055 int ret_val = 0;
00056 char read_buf[100];
00057 stringstream ss;
00058
00059 ss << (this->i_id + 100);
00060
00061 int raw_dist = -1;
00062
00063 double start, stop;
00064
00065
00066 write(this->i_fd, ss.str().c_str(), sizeof(ss.str().c_str()));
00067 usleep(40000);
00068
00069 start = ros::Time::now().toSec();
00070
00071 while(raw_dist < 0)
00072 {
00073 stop = ros::Time::now().toSec();
00074
00075 if(stop - start > 0.02)
00076 {
00077 ROS_DEBUG("EvarobotSonar: Sonar[%d] is not ALIVE ", this->i_id);
00078 this->b_is_alive = false;
00079 return false;
00080 }
00081
00082
00083 ss.str("");
00084 ss << this->i_id;
00085 strcpy(read_buf, ss.str().c_str());
00086
00087 ret_val = read(this->i_fd, read_buf, sizeof(read_buf));
00088 raw_dist = atoi(read_buf);
00089
00090 }
00091
00092 this->b_is_alive = true;
00093 return true;
00094
00095 }
00096
00097 void IMSONAR::Trigger()
00098 {
00099 stringstream ss;
00100 int raw_dist = -1;
00101
00102 ss << this->i_id;
00103 write(this->i_fd, ss.str().c_str(), sizeof(ss.str().c_str()));
00104 }
00105
00106
00107 int IMSONAR::Echo()
00108 {
00109 stringstream ss;
00110 char read_buf[100];
00111 int raw_dist = -1;
00112 int ret_val;
00113
00114 ss << this->i_id;
00115
00116 strcpy(read_buf, ss.str().c_str());
00117
00118 ret_val = read(this->i_fd, read_buf, sizeof(read_buf));
00119 raw_dist = atoi(read_buf);
00120
00121 this->sonar_msg.range = (float)(raw_dist * 0.0001);
00122 this->sonar_msg.header.stamp = ros::Time::now();
00123 this->sonar_msg.field_of_view = this->dynamic_params->d_fov;
00124 this->sonar_msg.min_range = this->dynamic_params->d_min_range;
00125 this->sonar_msg.max_range = this->dynamic_params->d_max_range;
00126
00127 return ret_val;
00128 }
00129
00130 void IMSONAR::Wait()
00131 {
00132 usleep(300000);
00133 }
00134
00135 void IMSONAR::Publish()
00136 {
00137 if(this->pub_sonar.getNumSubscribers() > 0 || this->dynamic_params->b_always_on)
00138 {
00139 this->pub_sonar.publish(this->sonar_msg);
00140 this->pub_sonar_freq->tick();
00141 }
00142 }
00143
00144 void IMSONAR::ProduceDiagnostics(diagnostic_updater::DiagnosticStatusWrapper &stat)
00145 {
00146 if(i_error_code<0)
00147 {
00148 stat.summary(diagnostic_msgs::DiagnosticStatus::ERROR, GetErrorDescription(i_error_code).c_str());
00149 i_error_code = 0;
00150 }
00151 else if(this->b_is_alive)
00152 {
00153 stat.summaryf(diagnostic_msgs::DiagnosticStatus::OK, "Sonar%d is alive!", this->i_id);
00154 }
00155 else
00156 {
00157 stat.summaryf(diagnostic_msgs::DiagnosticStatus::ERROR, "Sonar%d is NOT alive!", this->i_id);
00158 }
00159 }
00160
00161
00162
00163
00164
00165
00166
00167
00168
00169 void IMDynamicReconfig::CallbackReconfigure(evarobot_sonar::SonarParamsConfig &config, uint32_t level)
00170 {
00171 ROS_DEBUG("EvarobotSonar: Updating Sonar Params...");
00172
00173 this->d_fov = config.field_of_view;
00174 this->d_min_range = config.minRange;
00175 this->d_max_range = config.maxRange;
00176 this->b_always_on = config.alwaysOn;
00177 }
00178
00179 IMDynamicReconfig::IMDynamicReconfig():n_private("~")
00180 {
00181
00182 n_private.param("alwaysOn", this->b_always_on, false);
00183 n_private.param("field_of_view", this->d_fov, 0.7);
00184 n_private.param("minRange", this->d_min_range, 0.0);
00185 n_private.param("maxRange", this->d_max_range, 5.0);
00186 n_private.param("maxFreq", this->d_max_freq, 10.0);
00187 n_private.param("minFreq", this->d_min_freq, 0.2);
00188
00189 ROS_DEBUG("EvarobotSonar: b_always_on: %d", this->b_always_on);
00190 ROS_DEBUG("EvarobotSonar: d_fov: %f", this->d_fov);
00191 ROS_DEBUG("EvarobotSonar: d_min_range: %f", this->d_min_range);
00192 ROS_DEBUG("EvarobotSonar: d_max_range: %f", this->d_max_range);
00193
00194
00195
00196 this->f = boost::bind(&IMDynamicReconfig::CallbackReconfigure, this, _1, _2);
00197 this->srv.setCallback(this->f);
00198 }
00199
00200
00201
00202
00203 int main(int argc, char **argv)
00204 {
00205 int i_fd;
00206 stringstream ss;
00207 vector<bool> b_sonar_alive;
00208 vector<IMSONAR *> sonar;
00209
00210
00211 vector<int> T_i_sonar_pins;
00212 int i_element_no;
00213 double d_frequency;
00214 string str_driver_path;
00215
00216
00217 unsigned int u_i_delay = 100*1000;
00218
00219 ros::init(argc, argv, "/evarobot_sonar");
00220 ros::NodeHandle n;
00221
00222
00223 n.param<string>("evarobot_sonar/driverPath", str_driver_path, "/dev/evarobotSonar");
00224 n.param<double>("evarobot_sonar/frequency", d_frequency, 10.0);
00225 n.param<int>("evarobot_sonar/element", i_element_no, 3);
00226 n.getParam("evarobot_sonar/sonarPins", T_i_sonar_pins);
00227
00228 if(T_i_sonar_pins.size() > MAX_SONAR)
00229 {
00230 ROS_INFO(GetErrorDescription(-120).c_str());
00231 i_error_code = -120;
00232 }
00233
00234
00235 ROS_DEBUG("EvarobotSonar: Number of sonars: %d", T_i_sonar_pins.size());
00236
00237 i_fd = open(str_driver_path.c_str(), O_RDWR);
00238
00239 if(i_fd < 0)
00240 {
00241 ROS_INFO(GetErrorDescription(-121).c_str());
00242 i_error_code = -121;
00243 exit(-1);
00244 }
00245
00246
00247
00248
00249 ros::Rate loop_rate(d_frequency);
00250
00251
00252
00253 boost::shared_ptr<IMDynamicReconfig> dyn_params(new IMDynamicReconfig);
00254
00255 for(uint i = 0; i < T_i_sonar_pins.size(); i++)
00256 {
00257 b_sonar_alive.push_back(true);
00258 if(T_i_sonar_pins[i] < MAX_SONAR)
00259 {
00260 IMSONAR * dummy_sonar = new IMSONAR(i_fd, T_i_sonar_pins[i], SONAR[T_i_sonar_pins[i]], dyn_params);
00261 sonar.push_back(dummy_sonar);
00262 }
00263 else
00264 {
00265 ROS_INFO(GetErrorDescription(-122).c_str());
00266 i_error_code = -122;
00267 }
00268 }
00269 double d_dummy = (double)T_i_sonar_pins.size() / (double)i_element_no;
00270 int i_group_max = (int)ceil(d_dummy);
00271 ROS_DEBUG("Group MAX -> %d", i_group_max);
00272 ROS_DEBUG("Pins -> %d", T_i_sonar_pins.size());
00273 ROS_DEBUG("element -> %d", i_element_no);
00274
00275 int i_check_sonar = 0;
00276
00277 while(ros::ok())
00278 {
00279
00280
00281
00282
00283
00284
00285
00286
00287
00288
00289 b_sonar_alive[i_check_sonar] = sonar[i_check_sonar]->Check();
00290 i_check_sonar++;
00291 if(i_check_sonar >= T_i_sonar_pins.size())
00292 i_check_sonar = 0;
00293
00294 for(int i_group_no = 0; i_group_no < i_group_max; i_group_no++)
00295 {
00296 for(int i = (i_group_no * i_element_no); i < ((i_group_no+1) * i_element_no) && i < T_i_sonar_pins.size(); i++)
00297 {
00298 if(b_sonar_alive[i])
00299 sonar[i]->Trigger();
00300 }
00301 usleep(40000);
00302
00303
00304
00305 for(int i = (i_group_no * i_element_no); i < ((i_group_no+1) * i_element_no) && i < T_i_sonar_pins.size(); i++)
00306 {
00307 if(b_sonar_alive[i])
00308 {
00309 sonar[i]->Echo();
00310 sonar[i]->Publish();
00311 }
00312 sonar[i]->updater.update();
00313
00314 }
00315 }
00316
00317 ros::spinOnce();
00318
00319
00320 }
00321
00322 close(i_fd);
00323 return 0;
00324 }