Exemplo n.º 1
0
void pollMessages(const ros::TimerEvent& event)
{
  static std::vector<uint8_t> payload(1,1);
  if (enabled["aid_alm"]) { 
    gps.poll(ublox_msgs::Class::AID, ublox_msgs::Message::AID::ALM, payload);
  }
  if (enabled["aid_eph"]) { 
    gps.poll(ublox_msgs::Class::AID, ublox_msgs::Message::AID::EPH, payload);
  }
  if (enabled["aid_hui"]) { 
    gps.poll(ublox_msgs::Class::AID, ublox_msgs::Message::AID::HUI);
  }
  payload[0]++;
  if (payload[0] > 32) { 
    payload[0] = 1;
  }
}
Exemplo n.º 2
0
int main(int argc, char **argv) {
  boost::asio::io_service io_service;
  ros::Timer poller;
  boost::shared_ptr<boost::asio::ip::tcp::socket> tcp_handle;
  boost::shared_ptr<boost::asio::serial_port> serial_handle;
  bool setup_ok = true;
  
  ros::init(argc, argv, "ublox_gps");
  nh.reset(new ros::NodeHandle("~"));
  if (!nh->hasParam("diagnostic_period")) {
    nh->setParam("diagnostic_period", 0.2); //  5Hz diagnostic period 
  }
  updater.reset(new diagnostic_updater::Updater());
  updater->setHardwareID("ublox");
  
  std::string device;
  int baudrate;
  int rate, meas_rate;
  bool enable_sbas, enable_glonass, enable_beidou, enable_ppp;
  std::string dynamic_model, fix_mode;
  int dr_limit;
  int ublox_version;
  ros::NodeHandle param("~");
  param.param("device", device, std::string("/dev/ttyUSB0"));
  param.param("frame_id", frame_id, std::string("gps"));
  param.param("baudrate", baudrate, 9600);
  param.param("rate", rate, 4); //  in Hz
  param.param("enable_sbas", enable_sbas, false);
  param.param("enable_glonass", enable_glonass, false);
  param.param("enable_beidou", enable_beidou, false);
  param.param("enable_ppp", enable_ppp, false);
  param.param("dynamic_model", dynamic_model, std::string("portable"));
  param.param("fix_mode", fix_mode, std::string("both"));
  param.param("dr_limit", dr_limit, 0);
  param.param("ublox_version", ublox_version, 6); /// @todo: temporary workaround
    
  if (enable_ppp) {
    ROS_WARN("Warning: PPP is enabled - this is an expert setting.");
  }
  
  if (rate <= 0) {
    ROS_ERROR("Invalid settings: rate must be > 0");
    return 1;
  }
  //  measurement rate param for ublox, units of ms
  meas_rate = 1000 / rate;
  
  if (dr_limit < 0 || dr_limit > 255) {
    ROS_ERROR("Invalid settings: dr_limit must be between 0 and 255");
    return 1;
  }
  
  DynamicModel dmodel;
  FixMode fmode;
  try {
    dmodel = ublox_gps::modelFromString(dynamic_model);
    fmode = ublox_gps::fixModeFromString(fix_mode);
  } catch (std::exception& e) {
    ROS_ERROR("Invalid settings: %s", e.what());
    return 1;
  }
  
  //  configure diagnostic updater for frequency
  updater->add("fix", &fix_diagnostic);
  updater->force_update();
  
  const double target_freq = 1000.0 / meas_rate;  //  actual update frequency
  double min_freq = target_freq;
  double max_freq = target_freq;
  diagnostic_updater::FrequencyStatusParam freq_param(&min_freq, &max_freq, 0.05, 10);
  diagnostic_updater::TimeStampStatusParam time_param(0,meas_rate * 1e-3 * 0.05);
  freq_diag.reset(new diagnostic_updater::TopicDiagnostic(std::string("fix"), 
                                                          *updater, 
                                                          freq_param,
                                                          time_param));
  
  boost::smatch match;
  if (boost::regex_match(device, match, boost::regex("(tcp|udp)://(.+):(\\d+)"))) {
    std::string proto(match[1]);
    std::string host(match[2]);
    std::string port(match[3]);
    ROS_INFO("Connecting to %s://%s:%s ...", proto.c_str(), host.c_str(), port.c_str());

    if (proto == "tcp") {
      boost::asio::ip::tcp::resolver::iterator endpoint;

      try {
        boost::asio::ip::tcp::resolver resolver(io_service);
        endpoint = resolver.resolve(boost::asio::ip::tcp::resolver::query(host, port));
      } catch(std::runtime_error& e) {
        ROS_ERROR("Could not resolve %s:%s: %s", host.c_str(), port.c_str(), e.what());
        return 1; //  exit
      }

      boost::asio::ip::tcp::socket *socket = new boost::asio::ip::tcp::socket(io_service);
      tcp_handle.reset(socket);

      try {
        socket->connect(*endpoint);
      } catch(std::runtime_error& e) {
        ROS_ERROR("Could not connect to %s:%s: %s", endpoint->host_name().c_str(), endpoint->service_name().c_str(), e.what());
        return 1; //  exit
      }
    
      ROS_INFO("Connected to %s:%s.", endpoint->host_name().c_str(), endpoint->service_name().c_str());
      gps.initialize(*socket, io_service);
    } else {
      ROS_ERROR("Protocol '%s' is unsupported", proto.c_str());
      return 1; //  exit
    }
  } else {
    boost::asio::serial_port *serial = new boost::asio::serial_port(io_service);
    serial_handle.reset(serial);

    // open serial port
    try {
      serial->open(device);
    } catch (std::runtime_error& e) {
      ROS_ERROR("Could not open serial port %s: %s", device.c_str(), e.what());
      return 1; //  exit
    }

    ROS_INFO("Opened serial port %s", device.c_str());
    gps.setBaudrate(baudrate);
    gps.initialize(*serial, io_service);
  }

  //  apply all requested settings
  try {
    if (!gps.isInitialized()) {
      throw std::runtime_error("Failed to initialize.");
    }
    if (!gps.setMeasRate(meas_rate)) {
      std::stringstream ss;
      ss << "Failed to set measurement rate to " << meas_rate << "ms.";
      throw std::runtime_error(ss.str());
    }
    if (!gps.enableSBAS(enable_sbas)) {
      throw std::runtime_error(std::string("Failed to ") + 
                               ((enable_sbas) ? "enable" : "disable") + " SBAS.");
    }
    if (!gps.setPPPEnabled(enable_ppp)) {
      throw std::runtime_error(std::string("Failed to ") +
                               ((enable_ppp) ? "enable" : "disable") + " PPP.");
    }
    if (!gps.setDynamicModel(dmodel)) {
      throw std::runtime_error("Failed to set model: " + 
                               dynamic_model + ".");
    }
    if (!gps.setFixMode(fmode)) {
      throw std::runtime_error("Failed to set fix mode: " + fix_mode + ".");
    }
    if (!gps.setDeadReckonLimit(dr_limit)) {
      std::stringstream ss;
      ss << "Failed to set dead reckoning limit: " << dr_limit << ".";
      throw std::runtime_error(ss.str());
    }
    
    if (ublox_version >= 7) {
      ublox_msgs::CfgGNSS cfgGNSS;
      if (gps.poll(cfgGNSS)) {
        ROS_INFO("Read GNSS config.");
        ROS_INFO("Num. tracking channels in hardware: %i",cfgGNSS.numTrkChHw);
        ROS_INFO("Num. tracking channels to use: %i",cfgGNSS.numTrkChUse);
      } else {
        throw std::runtime_error("Failed to read the GNSS config.");
      }
      
      cfgGNSS.numConfigBlocks = 1;  //  do services one by one
      cfgGNSS.msgVer = 0;
      cfgGNSS.resTrkCh = 8;   //  taken as defaults from ublox manual
      cfgGNSS.maxTrkCh = 16;
      
      //  configure glonass
      cfgGNSS.gnssId = ublox_msgs::CfgGNSS::GNSS_ID_GLONASS;
      cfgGNSS.flags = enable_glonass;
      if (!gps.configure(cfgGNSS)) {
        throw std::runtime_error(std::string("Failed to ") +
                                 ((enable_glonass) ? "enable" : "disable") + " GLONASS.");
      }
      if (ublox_version >= 8) {
        //  configure beidou
        cfgGNSS.gnssId = ublox_msgs::CfgGNSS::GNSS_ID_BEIDOU;
        cfgGNSS.flags = enable_beidou;
        if (!gps.configure(cfgGNSS)) {
          throw std::runtime_error(std::string("Failed to ") +
                                   ((enable_beidou) ? "enable" : "disable") + " BeiDou.");
        }
      } else {
        ROS_WARN("ublox_version < 8, ignoring BeiDou Settings");
      }
    } else {
      ROS_WARN("ublox_version < 7, ignoring GNSS settings");
    }
  } catch (std::exception& e) {
    setup_ok = false;
    ROS_ERROR("Error configuring device: %s", e.what());
  }

  if (setup_ok) {
    ROS_INFO("U-Blox configured successfully.");
    
    // subscribe messages
    param.param("all", enabled["all"], false);
    param.param("rxm", enabled["rxm"], false);
    param.param("aid", enabled["aid"], false);
    
    param.param("nav_sol", enabled["nav_sol"], true);
    if (enabled["nav_sol"]) gps.subscribe<ublox_msgs::NavSOL>(boost::bind(&publish<ublox_msgs::NavSOL>, _1, "navsol"), 1);
    param.param("nav_status", enabled["nav_status"], true);
    if (enabled["nav_status"]) gps.subscribe<ublox_msgs::NavSTATUS>(&publishNavStatus, 1);
    param.param("nav_svinfo", enabled["nav_svinfo"], enabled["all"]);
    if (enabled["nav_svinfo"]) gps.subscribe<ublox_msgs::NavSVINFO>(&publishNavSVINFO, 20);
    param.param("nav_clk", enabled["nav_clk"], enabled["all"]);
    if (enabled["nav_clk"]) gps.subscribe<ublox_msgs::NavCLOCK>(&publishNavCLK, 1);
    param.param("rxm_raw", enabled["rxm_raw"], enabled["all"] || enabled["rxm"]);
    if (enabled["rxm_raw"]) gps.subscribe<ublox_msgs::RxmRAW>(&publishRxmRAW, 1);
    param.param("rxm_sfrb", enabled["rxm_sfrb"], enabled["all"] || enabled["rxm"]);
    if (enabled["rxm_sfrb"]) gps.subscribe<ublox_msgs::RxmSFRB>(&publishRxmSFRB, 1);
    param.param("nav_posllh", enabled["nav_posllh"], true);
    if (enabled["nav_posllh"]) gps.subscribe<ublox_msgs::NavPOSLLH>(&publishNavPosLLH, 1);
    param.param("nav_velned", enabled["nav_velned"], true);
    if (enabled["nav_velned"]) gps.subscribe<ublox_msgs::NavVELNED>(&publishNavVelNED, 1);
    param.param("aid_alm", enabled["aid_alm"], enabled["all"] || enabled["aid"]);
    if (enabled["aid_alm"]) gps.subscribe<ublox_msgs::AidALM>(&publishAidALM);
    param.param("aid_eph", enabled["aid_eph"], enabled["all"] || enabled["aid"]);
    if (enabled["aid_eph"]) gps.subscribe<ublox_msgs::AidEPH>(&publishAidEPH);
    param.param("aid_hui", enabled["aid_hui"], enabled["all"] || enabled["aid"]);
    if (enabled["aid_hui"]) gps.subscribe<ublox_msgs::AidHUI>(&publishAidHUI);
    
    poller = nh->createTimer(ros::Duration(1.0), &pollMessages);
    poller.start();
    ros::spin();
  }

  if (gps.isInitialized()) {
    gps.close();
    ROS_INFO("Closed connection to %s.", device.c_str());
  }
  return 0;
}