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 #include <labust/navigation/NavQuestSocketNode.hpp>
00038 #include <labust/navigation/DVLdataClass.h>
00039 #include <labust/navigation/NavQuestMessages.hpp>
00040 #include <labust/archive/delimited_iarchive.hpp>
00041 #include <labust/archive/delimited_oarchive.hpp>
00042 #include <labust/preprocessor/clean_serializator.hpp>
00043 #include <labust/tools/conversions.hpp>
00044 #include <labust/math/NumberManipulation.hpp>
00045 #include <labust/tools/StringUtilities.hpp>
00046
00047 #include <geometry_msgs/TwistStamped.h>
00048 #include <std_msgs/Bool.h>
00049 #include <std_msgs/Float32.h>
00050 #include <auv_msgs/RPY.h>
00051
00052 #include <boost/bind.hpp>
00053 #include <boost/regex.hpp>
00054 #include <boost/serialization/string.hpp>
00055
00056 #include <iosfwd>
00057
00058 PP_LABUST_CLEAN_ARRAY_OSERIALIZATOR_IMPL(labust::archive::delimited_oarchive)
00059 PP_LABUST_CLEAN_ARRAY_ISERIALIZATOR_IMPL(labust::archive::delimited_iarchive)
00060
00061 using namespace labust::navigation;
00062
00063 int labust::navigation::error_code(const NQRes& data)
00064 {
00065 std::stringstream ss(data.error_code);
00066 int error;
00067 ss>>std::hex>>error;
00068 return error;
00069 }
00070
00071 NavQuestSocketNode::NavQuestSocketNode():
00072 io(),
00073 socket(io),
00074 useFixed(true),
00075 base_orientation(0)
00076 {
00077 this->onInit();
00078 }
00079
00080 NavQuestSocketNode::~NavQuestSocketNode()
00081 {
00082 io.stop();
00083 runner.join();
00084 }
00085
00086 void NavQuestSocketNode::onInit()
00087 {
00088 ros::NodeHandle nh,ph("~");
00089 ros::Rate r(1);
00090 bool setupOk(false);
00091 while (!(setupOk = this->setup_socket()) && ros::ok())
00092 {
00093 ROS_ERROR("NavQuestSocketNode::Failed to open socket.");
00094 r.sleep();
00095 }
00096
00097 if (setupOk)
00098 {
00099
00100 beam_pub["velo_rad"].reset(new NavQuestBP(nh, "velo_rad"));
00101 beam_pub["wvelo_rad"].reset(new NavQuestBP(nh, "wvelo_rad"));
00102 speed_pub["velo_instrument"].reset(
00103 new TwistPublisher(nh, "velo_instrument", "dvl_frame"));
00104 speed_pub["velo_earth"].reset(
00105 new TwistPublisher(nh, "velo_earth", "local"));
00106 speed_pub["water_velo_instrument"].reset(
00107 new TwistPublisher(nh, "water_velo_instrument", "dvl_frame"));
00108 speed_pub["water_velo_earth"].reset(
00109 new TwistPublisher(nh, "water_velo_earth", "local"));
00110 lock = nh.advertise<std_msgs::Bool>("dvl_bottom",1);
00111 altitude = nh.advertise<std_msgs::Float32>("altitude",1);
00112 imuPub = nh.advertise<auv_msgs::RPY>("dvl_rpy",1);
00113
00114 useFixed = ph.getParam("fixed_orientation", base_orientation);
00115 nh.param("magnetic_declination",magnetic_declination, 0.0);
00116
00117
00118 this->start_receive();
00119 runner = boost::thread(boost::bind(&boost::asio::io_service::run,&io));
00120 setup_messaging();
00121
00122 }
00123 }
00124
00125 void NavQuestSocketNode::setup_messaging()
00126 {
00127
00128 }
00129
00130 void NavQuestSocketNode::setup_publishers()
00131 {
00132
00133 }
00134
00135 void NavQuestSocketNode::start_receive()
00136 {
00137 using namespace boost::asio;
00138 async_read_until(socket, buffer,
00139 boost::regex("\r\n"),
00140 boost::bind(&NavQuestSocketNode::onDvlData, this, _1,_2));
00141 }
00142
00143 bool NavQuestSocketNode::setup_socket()
00144 {
00145 ros::NodeHandle ph("~");
00146 std::string IPAddress("192.168.255.10");
00147 int tcpPort(10004);
00148
00149 ph.param("IPAdress",IPAddress,IPAddress);
00150 ph.param("tcpPort",tcpPort,tcpPort);
00151
00152 using namespace boost::asio;
00153 ip::tcp::endpoint endpoint(ip::address::from_string(IPAddress.c_str()), tcpPort);
00154 socket.connect(endpoint);
00155
00156 return socket.is_open();
00157 }
00158
00159 bool NavQuestSocketNode::test_header(const std::string& match, const std::string& stream)
00160 {
00161 return stream.substr(0,match.size()) == match;
00162 }
00163
00164 void NavQuestSocketNode::publishDvlData(const NQRes& data)
00165 {
00166 geometry_msgs::TwistStamped::Ptr twist(new geometry_msgs::TwistStamped());
00167
00168 bool testDVL = data.velo_instrument[0] == data.velo_instrument[1];
00169 testDVL = testDVL && (data.velo_instrument[1] == data.velo_instrument[2]);
00170 testDVL = testDVL && (data.velo_instrument[2] == 0);
00171
00172
00173 bool beamValidity = true;
00174 for (int i=0; i<4; ++i)
00175 {
00176 beamValidity = beamValidity && (data.beam_status[i] == 1);
00177
00178
00179 }
00180
00181 if (testDVL)
00182 {
00183 ROS_INFO("All zero dvl. Ignore measurement.");
00184 return;
00185 }
00186
00187 if (!beamValidity)
00188 {
00189
00190 return;
00191 }
00192 else
00193 {
00194 ROS_INFO("Beams are valid. Accept measurement: %f %f", data.velo_instrument[0]/1000, data.velo_instrument[1]/1000);
00195 }
00196
00197 (*beam_pub["velo_rad"])(data.velo_rad);
00198 (*beam_pub["wvelo_rad"])(data.wvelo_rad);
00199 (*speed_pub["velo_instrument"])(data.velo_instrument);
00200 (*speed_pub["velo_earth"])(data.velo_earth);
00201 (*speed_pub["water_velo_instrument"])(data.water_velo_instrument);
00202 (*speed_pub["water_velo_earth"])(data.water_velo_earth);
00203
00204 enum{valid_flag=3};
00205 bool water_lock= (data.velo_instrument[valid_flag]==2) || (data.velo_earth[valid_flag]==2);
00206 bool valid=data.velo_instrument[valid_flag] && data.velo_earth[valid_flag];
00207 std_msgs::Bool bottom_lock;
00208 bottom_lock.data = !water_lock && valid;
00209 lock.publish(bottom_lock);
00210
00211
00212 if (data.altitude_estimate > 0)
00213 {
00214 std_msgs::Float32Ptr alt(new std_msgs::Float32());
00215 alt->data = data.altitude_estimate;
00216 altitude.publish(alt);
00217 }
00218
00219
00220
00221 enum {roll=0, pitch, yaw};
00222 tf::Transform transform;
00223
00224 transform.setOrigin(tf::Vector3(1.4,0,0));
00225
00226 if (useFixed)
00227 {
00228 transform.setRotation(tf::createQuaternionFromRPY(0,0, base_orientation));
00229 broadcast.sendTransform(tf::StampedTransform(transform, ros::Time::now(), "base_link", "dvl_frame"));
00230 }
00231 else
00232 {
00233 Eigen::Quaternion<float> quat;
00234 labust::tools::quaternionFromEulerZYX(labust::math::wrapRad(data.rph[roll]/180*M_PI),
00235 labust::math::wrapRad(data.rph[pitch]/180*M_PI),
00236 labust::math::wrapRad(data.rph[yaw]/180*M_PI + magnetic_declination), quat);
00237 transform.setRotation(tf::Quaternion(quat.x(), quat.y(), quat.z(), quat.w()));
00238 broadcast.sendTransform(tf::StampedTransform(transform, ros::Time::now(), "local", "dvl_frame"));
00239 }
00240
00241
00242 auv_msgs::RPY::Ptr rpy(new auv_msgs::RPY());
00243 rpy->roll = labust::math::wrapRad(data.rph[roll]/180*M_PI);
00244 rpy->pitch = labust::math::wrapRad(data.rph[pitch]/180*M_PI);
00245 rpy->yaw = labust::math::wrapRad(data.rph[yaw]/180*M_PI);
00246 imuPub.publish(rpy);
00247 }
00248
00249 void NavQuestSocketNode::conditionDvlData(const NQRes& data)
00250 {}
00251
00252 void NavQuestSocketNode::onDvlData(const boost::system::error_code& e,
00253 std::size_t size)
00254 {
00255 if (!e)
00256 {
00257 std::istream is(&buffer);
00258 std::string data(size,'\0');
00259 is.read(&data[0],size);
00260
00261
00262 if (test_header("$#NQ.RES", data))
00263 {
00264 NQRes dvl_data;
00265 std::istringstream is;
00266 is.rdbuf()->pubsetbuf(&data[0],size);
00267 labust::archive::delimited_iarchive ia(is);
00268 ia>>dvl_data;
00269
00270 if (error_code(dvl_data) == 0) publishDvlData(dvl_data);
00271
00272 ROS_INFO("DVL decoded: header:%s, error:%s.",
00273 dvl_data.header.c_str(),
00274 dvl_data.error_code.c_str());
00275 }
00276 }
00277 else
00278 {
00279 ROS_ERROR("NavQuestSocketNode: %s",e.message().c_str());
00280 }
00281 this->start_receive();
00282 }
00283
00284
00285 int main(int argc, char* argv[])
00286 {
00287 ros::init(argc,argv,"navquest_socket_node");
00288 NavQuestSocketNode node;
00289 ros::spin();
00290
00291 return 0;
00292 }
00293