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 #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
00051 void connect();
00052 bool ok()
00053 {
00054 return m_pantilt != NULL;
00055 }
00056 void disconnect();
00057
00058
00059 void spinCallback(const ros::TimerEvent&);
00060
00061
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
00101 if (ok())
00102 {
00103 disconnect();
00104 }
00105
00106
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
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
00164 m_joint_pub = m_node.advertise
00165 <sensor_msgs::JointState>("state", 1);
00166
00167
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;
00181 m_pantilt = NULL;
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
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
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 }
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
00275 flir_ptu_driver::Node ptu_node(n);
00276 ptu_node.connect();
00277
00278
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
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 }