node.cpp
Go to the documentation of this file.
00001 /*
00002  * flir_ptu_driver ROS package
00003  * Copyright (C) 2014 Mike Purvis (mpurvis@clearpathrobotics.com)
00004  *
00005  * PTU ROS Package
00006  * Copyright (C) 2009 Erik Karulf (erik@cse.wustl.edu)
00007  *
00008  * Author: Toby Collett (University of Auckland)
00009  * Date: 2003-02-10
00010  *
00011  * Player - One Hell of a Robot Server
00012  * Copyright (C) 2000  Brian Gerkey   &  Kasper Stoy
00013  *                     gerkey@usc.edu    kaspers@robotics.usc.edu
00014  *
00015  *  This program is free software; you can redistribute it and/or modify
00016  *  it under the terms of the GNU General Public License as published by
00017  *  the Free Software Foundation; either version 2 of the License, or
00018  *  (at your option) any later version.
00019  *
00020  *  This program is distributed in the hope that it will be useful,
00021  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
00022  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00023  *  GNU General Public License for more details.
00024  *
00025  *  You should have received a copy of the GNU General Public License
00026  *  along with this program; if not, write to the Free Software
00027  *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00028  *
00029  */
00030 
00031 #include <diagnostic_updater/diagnostic_updater.h>
00032 #include <diagnostic_updater/publisher.h>
00033 #include <flir_ptu_driver/driver.h>
00034 #include <ros/ros.h>
00035 #include <sensor_msgs/JointState.h>
00036 #include <serial/serial.h>
00037 #include <std_msgs/Bool.h>
00038 
00039 #include <string>
00040 
00041 namespace flir_ptu_driver
00042 {
00043 
00044 class Node
00045 {
00046 public:
00047   explicit Node(ros::NodeHandle& node_handle);
00048   ~Node();
00049 
00050   // Service Control
00051   void connect();
00052   bool ok()
00053   {
00054     return m_pantilt != NULL;
00055   }
00056   void disconnect();
00057 
00058   // Service Execution
00059   void spinCallback(const ros::TimerEvent&);
00060 
00061   // Callback Methods
00062   void cmdCallback(const sensor_msgs::JointState::ConstPtr& msg);
00063   void resetCallback(const std_msgs::Bool::ConstPtr& msg);
00064 
00065   void produce_diagnostics(diagnostic_updater::DiagnosticStatusWrapper &stat);
00066 
00067 protected:
00068   diagnostic_updater::Updater* m_updater;
00069   PTU* m_pantilt;
00070   ros::NodeHandle m_node;
00071   ros::Publisher  m_joint_pub;
00072   ros::Subscriber m_joint_sub;
00073   ros::Subscriber m_reset_sub;
00074 
00075   serial::Serial m_ser;
00076   std::string m_joint_name_prefix;
00077   double default_velocity_;
00078 };
00079 
00080 Node::Node(ros::NodeHandle& node_handle)
00081   : m_pantilt(NULL), m_node(node_handle)
00082 {
00083   m_updater = new diagnostic_updater::Updater();
00084   m_updater->setHardwareID("none");
00085   m_updater->add("PTU Status", this, &Node::produce_diagnostics);
00086 
00087   ros::param::param<std::string>("~joint_name_prefix", m_joint_name_prefix, "ptu_");
00088 }
00089 
00090 Node::~Node()
00091 {
00092   disconnect();
00093   delete m_updater;
00094 }
00095 
00098 void Node::connect()
00099 {
00100   // If we are reconnecting, first make sure to disconnect
00101   if (ok())
00102   {
00103     disconnect();
00104   }
00105 
00106   // Query for serial configuration
00107   std::string port;
00108   int32_t baud;
00109   bool limit;
00110   ros::param::param<std::string>("~port", port, PTU_DEFAULT_PORT);
00111   ros::param::param<bool>("~limits_enabled", limit, true);
00112   ros::param::param<int32_t>("~baud", baud, PTU_DEFAULT_BAUD);
00113   ros::param::param<double>("~default_velocity", default_velocity_, PTU_DEFAULT_VEL);
00114 
00115   // Connect to the PTU
00116   ROS_INFO_STREAM("Attempting to connect to FLIR PTU on " << port);
00117 
00118   try
00119   {
00120     m_ser.setPort(port);
00121     m_ser.setBaudrate(baud);
00122     serial::Timeout to = serial::Timeout(200, 200, 0, 200, 0);
00123     m_ser.setTimeout(to);
00124     m_ser.open();
00125   }
00126   catch (serial::IOException& e)
00127   {
00128     ROS_ERROR_STREAM("Unable to open port " << port);
00129     return;
00130   }
00131 
00132   ROS_INFO_STREAM("FLIR PTU serial port opened, now initializing.");
00133 
00134   m_pantilt = new PTU(&m_ser);
00135 
00136   if (!m_pantilt->initialize())
00137   {
00138     ROS_ERROR_STREAM("Could not initialize FLIR PTU on " << port);
00139     disconnect();
00140     return;
00141   }
00142 
00143   if (!limit)
00144   {
00145     m_pantilt->disableLimits();
00146     ROS_INFO("FLIR PTU limits disabled.");
00147   }
00148 
00149   ROS_INFO("FLIR PTU initialized.");
00150 
00151   m_node.setParam("min_tilt", m_pantilt->getMin(PTU_TILT));
00152   m_node.setParam("max_tilt", m_pantilt->getMax(PTU_TILT));
00153   m_node.setParam("min_tilt_speed", m_pantilt->getMinSpeed(PTU_TILT));
00154   m_node.setParam("max_tilt_speed", m_pantilt->getMaxSpeed(PTU_TILT));
00155   m_node.setParam("tilt_step", m_pantilt->getResolution(PTU_TILT));
00156 
00157   m_node.setParam("min_pan", m_pantilt->getMin(PTU_PAN));
00158   m_node.setParam("max_pan", m_pantilt->getMax(PTU_PAN));
00159   m_node.setParam("min_pan_speed", m_pantilt->getMinSpeed(PTU_PAN));
00160   m_node.setParam("max_pan_speed", m_pantilt->getMaxSpeed(PTU_PAN));
00161   m_node.setParam("pan_step", m_pantilt->getResolution(PTU_PAN));
00162 
00163   // Publishers : Only publish the most recent reading
00164   m_joint_pub = m_node.advertise
00165                 <sensor_msgs::JointState>("state", 1);
00166 
00167   // Subscribers : Only subscribe to the most recent instructions
00168   m_joint_sub = m_node.subscribe
00169                 <sensor_msgs::JointState>("cmd", 1, &Node::cmdCallback, this);
00170 
00171   m_reset_sub = m_node.subscribe
00172                 <std_msgs::Bool>("reset", 1, &Node::resetCallback, this);
00173 }
00174 
00176 void Node::disconnect()
00177 {
00178   if (m_pantilt != NULL)
00179   {
00180     delete m_pantilt;   // Closes the connection
00181     m_pantilt = NULL;   // Marks the service as disconnected
00182   }
00183 }
00184 
00186 void Node::resetCallback(const std_msgs::Bool::ConstPtr& msg)
00187 {
00188   ROS_INFO("Resetting the PTU");
00189   m_pantilt->home();
00190 }
00191 
00193 void Node::cmdCallback(const sensor_msgs::JointState::ConstPtr& msg)
00194 {
00195   ROS_DEBUG("PTU command callback.");
00196   if (!ok()) return;
00197 
00198   if (msg->position.size() != 2)
00199   {
00200     ROS_ERROR("JointState command to PTU has wrong number of position elements.");
00201     return;
00202   }
00203 
00204   double pan = msg->position[0];
00205   double tilt = msg->position[1];
00206   double panspeed, tiltspeed;
00207 
00208   if (msg->velocity.size() == 2)
00209   {
00210     panspeed = msg->velocity[0];
00211     tiltspeed = msg->velocity[1];
00212   }
00213   else
00214   {
00215     ROS_WARN_ONCE("JointState command to PTU has wrong number of velocity elements; using default velocity.");
00216     panspeed = default_velocity_;
00217     tiltspeed = default_velocity_;
00218   }
00219 
00220   m_pantilt->setPosition(PTU_PAN, pan);
00221   m_pantilt->setPosition(PTU_TILT, tilt);
00222   m_pantilt->setSpeed(PTU_PAN, panspeed);
00223   m_pantilt->setSpeed(PTU_TILT, tiltspeed);
00224 }
00225 
00226 void Node::produce_diagnostics(diagnostic_updater::DiagnosticStatusWrapper &stat)
00227 {
00228   stat.summary(diagnostic_msgs::DiagnosticStatus::OK, "All normal.");
00229   stat.add("PTU Mode", m_pantilt->getMode() == PTU_POSITION ? "Position" : "Velocity");
00230 }
00231 
00232 
00237 void Node::spinCallback(const ros::TimerEvent&)
00238 {
00239   if (!ok()) return;
00240 
00241   // Read Position & Speed
00242   double pan  = m_pantilt->getPosition(PTU_PAN);
00243   double tilt = m_pantilt->getPosition(PTU_TILT);
00244 
00245   double panspeed  = m_pantilt->getSpeed(PTU_PAN);
00246   double tiltspeed = m_pantilt->getSpeed(PTU_TILT);
00247 
00248   // Publish Position & Speed
00249   sensor_msgs::JointState joint_state;
00250   joint_state.header.stamp = ros::Time::now();
00251   joint_state.name.resize(2);
00252   joint_state.position.resize(2);
00253   joint_state.velocity.resize(2);
00254   joint_state.name[0] = m_joint_name_prefix + "pan";
00255   joint_state.position[0] = pan;
00256   joint_state.velocity[0] = panspeed;
00257   joint_state.name[1] = m_joint_name_prefix + "tilt";
00258   joint_state.position[1] = tilt;
00259   joint_state.velocity[1] = tiltspeed;
00260   m_joint_pub.publish(joint_state);
00261 
00262   m_updater->update();
00263 }
00264 
00265 }  // namespace flir_ptu_driver
00266 
00267 int main(int argc, char** argv)
00268 {
00269   ros::init(argc, argv, "ptu");
00270   ros::NodeHandle n;
00271 
00272   while (ros::ok())
00273   {
00274     // Connect to PTU
00275     flir_ptu_driver::Node ptu_node(n);
00276     ptu_node.connect();
00277 
00278     // Set up polling callback
00279     int hz;
00280     ros::param::param<int>("~hz", hz, PTU_DEFAULT_HZ);
00281     ros::Timer spin_timer = n.createTimer(ros::Duration(1 / hz),
00282         &flir_ptu_driver::Node::spinCallback, &ptu_node);
00283 
00284     // Spin until there's a problem or we're in shutdown
00285     ros::spin();
00286 
00287     if (!ptu_node.ok())
00288     {
00289       ROS_ERROR("FLIR PTU disconnected, attempting reconnection.");
00290       ros::Duration(1.0).sleep();
00291     }
00292   }
00293 
00294   return 0;
00295 }


flir_ptu_driver
Author(s): Erik Karulf , David V. Lu , Nick Hawes
autogenerated on Tue Mar 19 2019 09:36:57