TopsideRadio.cpp
Go to the documentation of this file.
00001 /*********************************************************************
00002  * Software License Agreement (BSD License)
00003  *
00004  *  Copyright (c) 2010, LABUST, UNIZG-FER
00005  *  All rights reserved.
00006  *
00007  *  Redistribution and use in source and binary forms, with or without
00008  *  modification, are permitted provided that the following conditions
00009  *  are met:
00010  *
00011  *   * Redistributions of source code must retain the above copyright
00012  *     notice, this list of conditions and the following disclaimer.
00013  *   * Redistributions in binary form must reproduce the above
00014  *     copyright notice, this list of conditions and the following
00015  *     disclaimer in the documentation and/or other materials provided
00016  *     with the distribution.
00017  *   * Neither the name of the LABUST nor the names of its
00018  *     contributors may be used to endorse or promote products derived
00019  *     from this software without specific prior written permission.
00020  *
00021  *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
00022  *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
00023  *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
00024  *  FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
00025  *  COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
00026  *  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
00027  *  BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
00028  *  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
00029  *  CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
00030  *  LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
00031  *  ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
00032  *  POSSIBILITY OF SUCH DAMAGE.
00033  *
00034  *  Author: Dula Nad
00035  *  Created: 06.05.2013.
00036  *********************************************************************/
00037 #include <labust/control/TopsideRadio.hpp>
00038 #include <labust/tools/GeoUtilities.hpp>
00039 #include <labust/tools/conversions.hpp>
00040 #include <labust/tools/MatrixLoader.hpp>
00041 #include <navcon_msgs/SetHLMode.h>
00042 #include <navcon_msgs/HLMessage.h>
00043 #include <cmath>
00044 
00045 #include <boost/archive/binary_oarchive.hpp>
00046 #include <boost/archive/binary_iarchive.hpp>
00047 #include <boost/bind.hpp>
00048 #include <boost/regex.hpp>
00049 
00050 #include <std_msgs/Bool.h>
00051 
00052 #include <stdexcept>
00053 
00054 using labust::control::TopsideRadio;
00055 
00056 TopsideRadio::TopsideRadio():
00057                                                                 ph("~"),
00058                                                                 lastModemMsg(ros::Time::now()),
00059                                                                 timeout(10),
00060                                                                 port(io),
00061                                                                 isTopside(true),
00062                                                                 twoWayComms(false),
00063                                                                 lastMode(0)
00064 {this->onInit();}
00065 
00066 TopsideRadio::~TopsideRadio()
00067 {
00068         io.stop();
00069         iorunner.join();
00070         if (client) client.shutdown();
00071 }
00072 
00073 void TopsideRadio::onInit()
00074 {
00075         ros::NodeHandle nh,ph("~");
00076 
00077         std::string portName("/dev/ttyUSB0");
00078         int baud(9600);
00079         ph.param("PortName",portName,portName);
00080         ph.param("BaudRate",baud,baud);
00081         ph.param("IsTopside",isTopside,isTopside);
00082         ph.param("TwoWay",twoWayComms,twoWayComms);
00083         ph.param("Timeout",timeout,timeout);
00084 
00085         port.open(portName);
00086         port.set_option(boost::asio::serial_port::baud_rate(baud));
00087 
00088         if (!port.is_open())
00089         {
00090                 ROS_ERROR("Cannot open port.");
00091                 throw std::runtime_error("Unable to open the port.");
00092         }
00093 
00094         if (isTopside)
00095         {
00096                 extPoint = nh.subscribe<auv_msgs::NavSts>("target_point", 1,
00097                                 &TopsideRadio::onExtPoint,this);
00098                 joyIn = nh.subscribe<sensor_msgs::Joy>("joy_in",1,&TopsideRadio::onJoy,this);
00099                 stateHatPub = nh.advertise<auv_msgs::NavSts>("stateHat",1);
00100                 stateMeasPub = nh.advertise<auv_msgs::NavSts>("meas",1);
00101                 info = nh.advertise<std_msgs::Float32MultiArray>("cart2_info",1);
00102                 selectedPoint = nh.advertise<geometry_msgs::PointStamped>("selected_point", 1);
00103                 selectedNavSts = nh.advertise<auv_msgs::NavSts>("selected_navsts", 1);
00104 
00105                 //Dynamic reconfigure
00106                 server.setCallback(boost::bind(&TopsideRadio::dynrec_cb, this, _1, _2));
00107 
00108                 nh.param("LocalOriginLat",originLat,originLat);
00109                 nh.param("LocalOriginLon",originLon,originLon);
00110         }
00111         else
00112         {
00113                 joyOut = nh.advertise<sensor_msgs::Joy>("joy_out",1);
00114                 launched = nh.advertise<std_msgs::Bool>("launched",1);
00115                 hlMsg = nh.advertise<navcon_msgs::HLMessage>("hl_message",1);
00116                 client = nh.serviceClient<navcon_msgs::SetHLMode>("SetHLMode", true);
00117                 stateHat = nh.subscribe<auv_msgs::NavSts>("stateHat",1,&TopsideRadio::onStateHat,this);
00118                 stateMeas = nh.subscribe<auv_msgs::NavSts>("meas",1,&TopsideRadio::onStateMeas,this);
00119                 sfFrame = nh.subscribe<auv_msgs::NavSts>("sf_diagnostics",1,&TopsideRadio::onSFMeas,this);
00120                 curMode = nh.subscribe<std_msgs::Int32>("current_mode",1,&TopsideRadio::onCurrentMode,this);
00121                 cartInfo = nh.subscribe<std_msgs::Float32MultiArray>("cart2_info",1,&TopsideRadio::onCartInfo,this);
00122         }
00123 
00124         populateDataFromConfig();
00125         cdata.origin_lat = 0;
00126         cdata.origin_lon = 0;
00127         cdata.mode = 0;
00128         cdata.sf_state[x]= cdata.sf_state[y]= cdata.sf_state[psi]= 0;
00129         data.mode = 0;
00130         data.surgeForce = data.torqueForce = 0;
00131 
00132         this->start_receive();
00133         iorunner = boost::thread(boost::bind(&boost::asio::io_service::run,&io));
00134 }
00135 
00136 void TopsideRadio::onJoy(const sensor_msgs::Joy::ConstPtr& joy)
00137 {
00138         boost::mutex::scoped_lock l(dataMux);
00139         data.surgeForce = joy->axes[1]*100;
00140         data.torqueForce = joy->axes[2]*100;
00141 }
00142 
00143 void TopsideRadio::onExtPoint(const auv_msgs::NavSts::ConstPtr& extPoint)
00144 {
00145         if (!config.ManualPoint)
00146         {
00147                 boost::mutex::scoped_lock l(dataMux);
00148                 if (extPoint->header.frame_id == "worldLatLon")
00149                 {
00150                         data.lat = extPoint->global_position.latitude*10000000;
00151                         data.lon = extPoint->global_position.longitude*10000000;
00152                 }
00153                 else if (extPoint->header.frame_id == "local")
00154                 {
00155                         local2LatLon(extPoint->position.north, extPoint->position.east);
00156                 }
00157                 else
00158                 {
00159                         ROS_ERROR("The specified point for the radio modem has to be in worldLatLon frame!.");
00160                 }
00161         }
00162 }
00163 
00164 void TopsideRadio::onCurrentMode(const std_msgs::Int32::ConstPtr& mode)
00165 {
00166         boost::mutex::scoped_lock l(cdataMux);
00167         cdata.mode = mode->data;
00168         lastMode = mode->data;
00169 }
00170 
00171 void TopsideRadio::onStateHat(const auv_msgs::NavSts::ConstPtr& estimate)
00172 {
00173         boost::mutex::scoped_lock l(cdataMux);
00174         cdata.state_hat[u] = estimate->body_velocity.x*100;
00175         //cdata.state_hat[r] = estimate->orientation_rate.yaw*100;
00176         cdata.state_hat[x] = estimate->position.north*100;
00177         cdata.state_hat[y] = estimate->position.east*100;
00178         cdata.state_hat[psi] = estimate->orientation.yaw*100;
00179 
00180         try
00181         {
00182                 tf::StampedTransform transformLocal;
00183                 listener.lookupTransform("/worldLatLon", "local", ros::Time(0), transformLocal);
00184                 cdata.origin_lat = transformLocal.getOrigin().y()*10000000;
00185                 cdata.origin_lon = transformLocal.getOrigin().x()*10000000;
00186         }
00187         catch(tf::TransformException& ex)
00188         {
00189                 ROS_ERROR("%s",ex.what());
00190         }
00191 }
00192 
00193 void TopsideRadio::onStateMeas(const auv_msgs::NavSts::ConstPtr& meas)
00194 {
00195         boost::mutex::scoped_lock l(cdataMux);
00196         //cdata.state_meas[u] = meas->body_velocity.x*100;
00197         //cdata.state_meas[r] = meas->orientation_rate.yaw*100;
00198         cdata.state_meas[x] = meas->position.north*100;
00199         cdata.state_meas[y] = meas->position.east*100;
00200         cdata.state_meas[psi] = meas->orientation.yaw*100;
00201 }
00202 
00203 void TopsideRadio::onSFMeas(const auv_msgs::NavSts::ConstPtr& meas)
00204 {
00205         boost::mutex::scoped_lock l(cdataMux);
00206         //cdata.state_meas[u] = meas->body_velocity.x*100;
00207         //cdata.state_meas[r] = meas->orientation_rate.yaw*100;
00208         cdata.sf_state[x] = meas->position.north*100;
00209         cdata.sf_state[y] = meas->position.east*100;
00210         cdata.sf_state[psi] = meas->orientation.yaw*100;
00211 }
00212 
00213 void TopsideRadio::onCartInfo(const std_msgs::Float32MultiArray::ConstPtr& info)
00214 {
00215         boost::mutex::scoped_lock l(cdataMux);
00216         enum {port_rpm_desired=0,
00217                 stbd_rpm_desired,
00218                 port_rpm_meas,
00219                 stbd_rpm_meas,
00220                 port_curr_desired,
00221                 stbd_curr_desired,
00222                 current,
00223                 temp,
00224                 voltage
00225         };
00226 
00227         cdata.portRPM = info->data[port_rpm_meas];
00228         cdata.stbdRPM = info->data[stbd_rpm_meas];
00229         cdata.voltage = info->data[voltage]/50*256;
00230         cdata.temp = info->data[temp]/100*256;
00231 }
00232 
00233 void TopsideRadio::local2LatLon(double x, double y)
00234 {
00235         std::pair<double, double> location = labust::tools::meter2deg(x,
00236                         y,
00237                         originLat);
00238         data.lat = (originLat + location.first)*10000000;
00239         data.lon = (originLon + location.second)*10000000;
00240 }
00241 
00242 void TopsideRadio::populateDataFromConfig()
00243 {
00244         boost::mutex::scoped_lock l(dataMux);
00245         data.mode_update = 1;
00246         data.mode = config.OpMode;
00247         data.launch = config.Launch;
00248         if (config.ManualPoint)
00249         {
00250                 if (config.UseLocal)
00251                 {
00252                         local2LatLon(config.PointN, config.PointE);
00253                 }
00254                 else
00255                 {
00256                         data.lat = config.PointLat*10000000;
00257                         data.lon = config.PointLon*10000000;
00258                 }
00259         }
00260         data.radius = config.Radius;
00261         data.surge = config.Surge*100;
00262         data.yaw = std::floor(config.Yaw/M_PI*128+0.5);
00263 }
00264 
00265 void TopsideRadio::dynrec_cb(cart2::RadioModemConfig& config, uint32_t level)
00266 {
00267         if ((config.OpMode != this->config.OpMode) &&
00268                         (config.OpMode == 0))
00269         {
00270                 //Prevent re-launching when stopped
00271                 config.Launch = 0;
00272                 server.updateConfig(config);
00273         }
00274         this->config = config;
00275         this->populateDataFromConfig();
00276 
00277         if (config.ManualPoint && config.UseLocal)
00278         {
00279                 geometry_msgs::PointStamped point;
00280                 point.header.frame_id = "local";
00281                 point.header.stamp = ros::Time::now();
00282                 point.point.x = this->config.PointN;
00283                 point.point.y = this->config.PointE;
00284                 selectedPoint.publish(point);
00285         }
00286 }
00287 
00288 void TopsideRadio::start_receive()
00289 {
00290         boost::asio::async_read(port, sbuffer.prepare(sync_length),
00291                         boost::bind(&TopsideRadio::onSync,this,_1,_2));
00292 }
00293 
00294 void TopsideRadio::onSync(const boost::system::error_code& error, const size_t& transferred)
00295 {
00296         if (!error)
00297         {
00298                 sbuffer.commit(transferred);
00299 
00300                 if (transferred == 1)
00301                 {
00302                         ringBuffer.push_back(sbuffer.sbumpc());
00303                         if (ringBuffer.size() > sync_length)
00304                         {
00305                                 ringBuffer.erase(ringBuffer.begin());
00306                         }
00307                 }
00308                 else
00309                 {
00310                         std::istream is(&sbuffer);
00311                         ringBuffer.clear();
00312                         is >> ringBuffer;
00313                 }
00314 
00315                 if ((ringBuffer.size() >= sync_length) && (ringBuffer.substr(0,sync_length) == "@T"))
00316                 {
00317                         ROS_INFO("Synced on @ONTOP");
00318                         assert(!isTopside && "Cannot receive topside messages if on topside.");
00319                         boost::asio::async_read(port,sbuffer.prepare(topside_package_length),boost::bind(&TopsideRadio::onIncomingData,this,_1,_2));
00320                 }
00321                 else if ((ringBuffer.size() >= sync_length) && (ringBuffer.substr(0,sync_length) == "@C"))
00322                 {
00323                         ROS_INFO("Synced on @CART2");
00324                         assert(isTopside && "Cannot receive CART messages if on cart.");
00325                         boost::asio::async_read(port,sbuffer.prepare(cart_package_length),boost::bind(&TopsideRadio::onIncomingData,this,_1,_2));
00326                 }
00327                 else
00328                 {
00329                         ROS_INFO("No sync: %s",ringBuffer.c_str());
00330                         boost::asio::async_read(port, sbuffer.prepare(1),
00331                                         boost::bind(&TopsideRadio::onSync,this,_1,_2));
00332                 }
00333         }
00334 }
00335 
00336 void TopsideRadio::onIncomingData(const boost::system::error_code& error, const size_t& transferred)
00337 {
00338         sbuffer.commit(transferred);
00339 
00340         if (!error)
00341         {
00342                 boost::archive::binary_iarchive dataSer(sbuffer, boost::archive::no_header);
00343                 ROS_INFO("Received:%d", transferred);
00344 
00345                 ROS_INFO("Received %d bytes.",transferred);
00346 
00347                 if (!isTopside)
00348                 {
00349                         boost::mutex::scoped_lock l(dataMux);
00350                         uint16_t chksum(0);
00351                         try
00352                         {
00353                                 dataSer >> data >> chksum;
00354                         }
00355                         catch (std::exception& e)
00356                         {
00357                                 ROS_ERROR("Exception while deserializing: %s",e.what());
00358                         }
00359 
00360                         uint16_t chksum_calc = calculateCRC16(data);
00361                         if (chksum_calc != chksum)
00362                         {
00363                                 ROS_ERROR("Wrong checksum! Got: %d, expected: %d",chksum, chksum_calc);
00364                                 start_receive();
00365                                 return;
00366                         }
00367 
00368                         sensor_msgs::Joy joy;
00369                         joy.axes.assign(6,0);
00370                         //Sanity check
00371                         if (fabs(data.surgeForce) > 100)
00372                         {
00373                                 ROS_ERROR("Remote joystick force is above 1.");
00374                                 data.surgeForce = 0;
00375                         }
00376 
00377                         if (fabs(data.torqueForce) > 100)
00378                         {
00379                                 ROS_ERROR("Remote joystick force is above 1.");
00380                                 data.torqueForce = 0;
00381                         }
00382 
00383                         joy.axes[1] = data.surgeForce/100.;
00384                         joy.axes[2] = data.torqueForce/100.;
00385 
00386                         std_msgs::Bool launcher;
00387                         launcher.data = data.launch;
00388 
00389 
00390                         //\todo Update this to some real constant
00391                         if (data.mode > 8)
00392                         {
00393                                 data.mode = 0;
00394                                 ROS_ERROR("Wrong mode.");
00395                                 return;
00396                         }
00397                         navcon_msgs::HLMessagePtr msg(new navcon_msgs::HLMessage());
00398                         bool update = data.mode_update;
00399                         msg->mode = data.mode;
00400                         msg->radius = data.radius;
00401                         msg->ref_point.header.stamp=ros::Time::now();
00402                         msg->ref_point.header.frame_id="worldLatLon";
00403                         msg->ref_point.point.x = data.lat/10000000.;
00404                         msg->ref_point.point.y = data.lon/10000000.;
00405                         msg->surge = data.surge/100.;
00406                         l.unlock();
00407 
00408                         joyOut.publish(joy);
00409                         if (update)
00410                         {
00411                                 hlMsg.publish(msg);
00412                                 launched.publish(launcher);
00413                         }
00414 
00415                         boost::mutex::scoped_lock l2(clientMux);
00416                         lastModemMsg = ros::Time::now();
00417                         if (!client)
00418                         {
00419                                 ROS_ERROR("HLManager client not connected. Trying reset.");
00420                                 client = nh.serviceClient<navcon_msgs::SetHLMode>("SetHLMode", true);
00421                         }
00422                         else
00423                         {
00424                                 boost::mutex::scoped_lock l(dataMux);
00425                                 navcon_msgs::SetHLMode mode;
00426                                 if (update)
00427                                 {
00428                                         lastMode = mode.request.mode = data.mode;
00429                                 }
00430                                 else
00431                                 {
00432                                         mode.request.mode = lastMode;
00433                                 }
00434                                 mode.request.ref_point.header.stamp=ros::Time::now();
00435                                 mode.request.ref_point.header.frame_id="worldLatLon";
00436                                 mode.request.ref_point.point.x = data.lat/10000000.;
00437                                 mode.request.ref_point.point.y = data.lon/10000000.;
00438                                 mode.request.radius = data.radius;
00439                                 mode.request.surge = data.surge/100.;
00440                                 mode.request.yaw = M_PI*data.yaw/128.;
00441                                 l.unlock();
00442                                 if (!(data.launch && (data.mode == 0))) client.call(mode);
00443                         }
00444                         l2.unlock();
00445 
00446                         if (twoWayComms)
00447                         {
00448                                 boost::asio::streambuf output;
00449                                 std::ostream out(&output);
00450                                 //Prepare sync header
00451                                 out<<"@C";
00452                                 boost::archive::binary_oarchive dataSer(output, boost::archive::no_header);
00453                                 boost::mutex::scoped_lock l(cdataMux);
00454                                 uint16_t chksum_calc = calculateCRC16(cdata);
00455                                 try
00456                                 {
00457                                         dataSer << cdata << chksum_calc;
00458                                 }
00459                                 catch (std::exception& e)
00460                                 {
00461                                         ROS_ERROR("Exception while serializing: %s",e.what());
00462                                 }
00463                                 l.unlock();
00464                                 //write data
00465                                 int n = boost::asio::write(port, output.data());
00466                                 ROS_INFO("Transferred:%d",n);
00467                         }
00468                 }
00469                 else
00470                 {
00471                         boost::mutex::scoped_lock l(cdataMux);
00472                         uint16_t chksum(0);
00473                         try
00474                         {
00475                                 dataSer >> cdata >> chksum;
00476                         }
00477                         catch (std::exception& e)
00478                         {
00479                                 ROS_ERROR("Exception while serializing: %s",e.what());
00480                         }
00481 
00482                         uint16_t chksum_calc = calculateCRC16(cdata);
00483                         if (chksum_calc != chksum)
00484                         {
00485                                 ROS_ERROR("Wrong checksum! Got: %d, expected: %d",chksum, chksum_calc);
00486                                 start_receive();
00487                                 return;
00488                         }
00489 
00490                         auv_msgs::NavStsPtr state(new auv_msgs::NavSts());
00491                         auv_msgs::NavStsPtr meas(new auv_msgs::NavSts());
00492                         state->origin.latitude = cdata.origin_lat/10000000.;
00493                         state->origin.longitude = cdata.origin_lon/10000000.;
00494                         state->body_velocity.x = cdata.state_hat[u]/100.;
00495                         //state->orientation_rate.yaw = cdata.state_hat[r]/100.;
00496                         state->position.north = cdata.state_hat[x]/100.;
00497                         state->position.east = cdata.state_hat[y]/100.;
00498                         state->orientation.yaw = cdata.state_hat[psi]/100.;
00499                         meas->origin.latitude = cdata.origin_lat/10000000.;
00500                         meas->origin.longitude = cdata.origin_lon/10000000.;
00501                         //meas->body_velocity.x = cdata.state_meas[u]/100.;
00502                         //meas->orientation_rate.yaw = cdata.state_meas[r]/100.;
00503                         meas->position.north = cdata.state_meas[x]/100.;
00504                         meas->position.east = cdata.state_meas[y]/100.;
00505                         meas->orientation.yaw = cdata.state_meas[psi]/100.;
00506 
00507                         std::pair<double, double> location = labust::tools::meter2deg(
00508                                         state->position.north,
00509                                         state->position.east,
00510                                         state->origin.latitude);
00511                         state->global_position.latitude = state->origin.latitude + location.first;
00512                         state->global_position.longitude = state->origin.longitude + location.second;
00513 
00514                         location = labust::tools::meter2deg(
00515                                         meas->position.north,
00516                                         meas->position.east,
00517                                         meas->origin.latitude);
00518                         meas->global_position.latitude = state->origin.latitude + location.first;
00519                         meas->global_position.longitude = state->origin.longitude + location.second;
00520 
00521                         std_msgs::Float32MultiArray cinfo;
00522                         cinfo.data.resize(4);
00523                         cinfo.data[0] = cdata.voltage/256.*50;
00524                         cinfo.data[1] = cdata.temp/256.*100;
00525                         cinfo.data[2] = cdata.portRPM;
00526                         cinfo.data[3] = cdata.stbdRPM;
00527                         info.publish(cinfo);
00528 
00529                         ROS_INFO("Current CART2 mode:%d",cdata.mode);
00530 
00531                         tf::Transform transform;
00532                         transform.setOrigin(tf::Vector3(cdata.origin_lon/10000000., cdata.origin_lat/10000000., 0));
00533                         originLon = cdata.origin_lon/10000000.;
00534                         originLat = cdata.origin_lat/10000000.;
00535                         l.unlock();
00536 
00537                         transform.setRotation(tf::createQuaternionFromRPY(0,0,0));
00538                         broadcaster.sendTransform(tf::StampedTransform(transform, ros::Time::now(), "worldLatLon", "world"));
00539                         transform.setOrigin(tf::Vector3(0, 0, 0));
00540                         Eigen::Quaternion<float> q;
00541                         labust::tools::quaternionFromEulerZYX(M_PI,0,M_PI/2,q);
00542                         transform.setRotation(tf::Quaternion(q.x(),q.y(),q.z(),q.w()));
00543                         broadcaster.sendTransform(tf::StampedTransform(transform, ros::Time::now(), "world", "local"));
00544                         transform.setOrigin(tf::Vector3(state->position.north, state->position.east, 0));
00545                         labust::tools::quaternionFromEulerZYX(0,0,state->orientation.yaw,q);
00546                         transform.setRotation(tf::Quaternion(q.x(),q.y(),q.z(),q.w()));
00547                         broadcaster.sendTransform(tf::StampedTransform(transform, ros::Time::now(), "local", "base_link"));
00548                         transform.setOrigin(tf::Vector3(meas->position.north, meas->position.east, 0));
00549                         labust::tools::quaternionFromEulerZYX(0,0,meas->orientation.yaw,q);
00550                         transform.setRotation(tf::Quaternion(q.x(),q.y(),q.z(),q.w()));
00551                         broadcaster.sendTransform(tf::StampedTransform(transform, ros::Time::now(), "local", "base_link_meas"));
00552                         transform.setOrigin(tf::Vector3(cdata.sf_state[x]/100.,cdata.sf_state[y]/100., 0));
00553                         labust::tools::quaternionFromEulerZYX(0,0,cdata.sf_state[psi]/100.,q);
00554                         transform.setRotation(tf::Quaternion(q.x(),q.y(),q.z(),q.w()));
00555                         broadcaster.sendTransform(tf::StampedTransform(transform, ros::Time::now(), "local", "sf_frame"));
00556 
00557                         stateHatPub.publish(state);
00558                         stateMeasPub.publish(meas);
00559                 }
00560         }
00561         else
00562         {
00563                 ROS_ERROR("Communication failed.");
00564         }
00565 
00566         start_receive();
00567 }
00568 
00569 void TopsideRadio::onTimeout()
00570 {
00571         if (!client)
00572         {
00573                 ROS_ERROR("HLManager client not connected. Trying reset.");
00574                 client = nh.serviceClient<navcon_msgs::SetHLMode>("SetHLMode", true);
00575         }
00576         else
00577         {
00578                 navcon_msgs::SetHLMode mode;
00579                 mode.request.mode = 0;
00580                 client.call(mode);
00581         }
00582 
00583         ROS_ERROR("Lost connection with topside!");
00584 
00585         io.stop();
00586         iorunner.join();
00587         port.close();
00588 
00589         io.reset();
00590         lastModemMsg = ros::Time::now();
00591         ros::Rate rate(1);
00592         for(int i=0;i<3;++i) rate.sleep();
00593 
00594         std::string portName;
00595         int baud;
00596         ph.param("PortName",portName,portName);
00597         ph.param("BaudRate",baud,baud);
00598 
00599         port.open(portName);
00600         port.set_option(boost::asio::serial_port::baud_rate(baud));
00601 
00602         if (!port.is_open())
00603         {
00604                 ROS_ERROR("Cannot open port.");
00605                 throw std::runtime_error("Unable to open the port.");
00606         }
00607 
00608         this->start_receive();
00609         iorunner = boost::thread(boost::bind(&boost::asio::io_service::run,&io));
00610 }
00611 
00612 void TopsideRadio::start()
00613 {
00614         if (!isTopside)
00615         {
00616                 ros::Rate rate(20);
00617 
00618                 while (ros::ok())
00619                 {
00620                         rate.sleep();
00621                         ros::spinOnce();
00622                         boost::mutex::scoped_lock l(clientMux);
00623                         if ((ros::Time::now()-lastModemMsg).toSec() > timeout )
00624                         {
00625                                 this->onTimeout();
00626                         }
00627                 }
00628         }
00629         else
00630         {
00631                 double transmitRate(10);
00632                 ros::NodeHandle ph("~");
00633                 ph.param("TransmitRate",transmitRate,transmitRate);
00634                 ros::Rate rate(transmitRate);
00635                 while (nh.ok())
00636                 {
00637                         boost::asio::streambuf output;
00638                         std::ostream out(&output);
00639                         std::ostringstream chk;
00640                         //Prepare sync header
00641                         out<<"@T";
00642                         boost::archive::binary_oarchive dataSer(output, boost::archive::no_header);
00643                         boost::mutex::scoped_lock l(dataMux);
00644                         uint16_t chksum_calc = calculateCRC16(data);
00645                         try
00646                         {
00647                                 dataSer << data << chksum_calc;
00648                         }
00649                         catch (std::exception& e)
00650                         {
00651                                 ROS_ERROR("Exception while serializing: %s",e.what());
00652                         }
00653                         data.mode_update = 0;
00654                         l.unlock();
00655 
00656                         //write data
00657                         int n = boost::asio::write(port, output.data());
00658                         ROS_INFO("Transferred %d bytes.",n);
00659 
00660                         if (config.OpMode == 7)
00661                         {
00662                                 auv_msgs::NavSts selected;
00663                                 boost::mutex::scoped_lock l(cdataMux);
00664                                 std::pair<double, double> location = labust::tools::meter2deg(cdata.sf_state[x]/100.,
00665                                                 cdata.sf_state[y]/100.,
00666                                                 originLat);
00667                                 selected.global_position.latitude = originLat + location.first;
00668                                 selected.global_position.longitude = originLon + location.second;
00669                                 selected.position.north = cdata.sf_state[x]/100.;
00670                                 selected.position.east = cdata.sf_state[y]/100.;
00671                                 selected.orientation.yaw = cdata.sf_state[psi]/100.;
00672                                 selectedNavSts.publish(selected);
00673 
00674                                 geometry_msgs::PointStamped point;
00675                                 point.header.frame_id = "local";
00676                                 point.header.stamp = ros::Time::now();
00677                                 point.point.x = cdata.sf_state[x]/100.;
00678                                 point.point.y = cdata.sf_state[y]/100.;
00679                                 selectedPoint.publish(point);
00680 
00681                         }
00682 
00683                         if ((config.OpMode != 7) && config.ManualPoint)
00684                         {
00685                                 auv_msgs::NavSts selected;
00686                                 if (config.UseLocal)
00687                                 {
00688                                         std::pair<double, double> location = labust::tools::meter2deg(config.PointN,
00689                                                         config.PointE,
00690                                                         originLat);
00691                                         selected.global_position.latitude = originLat + location.first;
00692                                         selected.global_position.longitude = originLon + location.second;
00693                                         selected.position.north = config.PointN;
00694                                         selected.position.east = config.PointE;
00695                                 }
00696                                 else
00697                                 {
00698                                         selected.global_position.latitude = config.PointLat;
00699                                         selected.global_position.longitude = config.PointLon;
00700                                         std::pair<double, double> location = labust::tools::deg2meter(config.PointLat - originLat,
00701                                                         config.PointLon - originLon,
00702                                                         originLat);
00703                                         selected.position.north = location.first;
00704                                         selected.position.east = location.second;
00705                                 }
00706                                 selectedNavSts.publish(selected);
00707                         }
00708 
00709 
00710                         rate.sleep();
00711                         ros::spinOnce();
00712                 }
00713         }
00714 }
00715 


cart2
Author(s): Gyula Nagy
autogenerated on Fri Feb 7 2014 11:37:19