ros_ibeo_lux.cpp
Go to the documentation of this file.
00001 /*
00002  * Unpublished Copyright (c) 2009-2019 AutonomouStuff, LLC, All Rights Reserved.
00003  *
00004  * This file is part of the ibeo_lux ROS 1.0 driver which is released under the MIT license.
00005  * See file LICENSE included with this software or go to https://opensource.org/licenses/MIT for full license details.
00006  */
00007 
00008 #include <ibeo_lux/ibeo_lux_ros_msg_handler.h>
00009 #include <network_interface/network_interface.h>
00010 #include <network_interface/network_utils.h>
00011 
00012 // Tx
00013 #include <network_interface/TCPFrame.h>
00014 
00015 #include <unordered_map>
00016 #include <vector>
00017 #include <queue>
00018 #include <deque>
00019 #include <string>
00020 
00021 using std::string;
00022 using std::vector;
00023 using namespace AS::Network;
00024 using namespace AS::Drivers::IbeoLux;
00025 
00026 TCPInterface tcp_interface;
00027 IbeoLuxRosMsgHandler handler;
00028 std::unordered_map<int64_t, ros::Publisher> pub_list;
00029 
00030 // Main routine
00031 int main(int argc, char **argv)
00032 {
00033   // int c;
00034   string ip_address = "192.168.0.1";
00035   int port = 12002;
00036   string frame_id = "ibeo_lux";
00037   bool is_fusion = false;
00038   int buf_size = AS::Drivers::Ibeo::IBEO_PAYLOAD_SIZE;
00039   std::deque<uint8_t> grand_buffer;
00040   std::queue<std::vector<uint8_t>> messages;
00041 
00042   // ROS initialization
00043   ros::init(argc, argv, "ibeo_lux");
00044   ros::NodeHandle n;
00045   ros::NodeHandle priv("~");
00046   bool exit = false;
00047 
00048   if (priv.getParam("ip_address", ip_address))
00049   {
00050     ROS_INFO("Ibeo LUX - Got ip_address: %s", ip_address.c_str());
00051 
00052     if (ip_address == "")
00053     {
00054       ROS_ERROR("Ibeo LUX - IP Address Invalid");
00055       exit = true;
00056     }
00057   }
00058 
00059   if (priv.getParam("port", port))
00060   {
00061     ROS_INFO("Ibeo LUX - Got port: %d", port);
00062 
00063     if (port < 0)
00064     {
00065       ROS_ERROR("Ibeo LUX - Port Invalid");
00066       exit = true;
00067     }
00068   }
00069 
00070   if (priv.getParam("is_fusion", is_fusion))
00071   {
00072     ROS_INFO("Ibeo LUX - Is Fusion ECU: %s", (is_fusion) ? "true" : "false");
00073   }
00074 
00075   if (priv.getParam("sensor_frame_id", frame_id))
00076   {
00077     ROS_INFO("Ibeo LUX - Got sensor frame ID: %s", frame_id.c_str());
00078   }
00079 
00080   if (exit)
00081     return 0;
00082 
00083   // Advertise messages to send
00084   ros::Publisher raw_tcp_pub = n.advertise<network_interface::TCPFrame>("tcp_tx", 1);
00085   ros::Publisher pointcloud_pub = n.advertise<pcl::PointCloud <pcl::PointXYZ> >("as_tx/point_cloud", 1);
00086   ros::Publisher object_markers_pub = n.advertise<visualization_msgs::MarkerArray>("as_tx/objects", 1);
00087   ros::Publisher object_contour_points_pub = n.advertise<visualization_msgs::Marker>("as_tx/object_contour_points", 1);
00088 
00089   ros::Publisher scan_data_pub, object_data_pub, vehicle_state_pub, error_warn_pub;
00090   ros::Publisher fusion_scan_2204_pub,
00091     fusion_scan_2205_pub,
00092     fusion_object_2225_pub,
00093     fusion_object_2280_pub,
00094     fusion_img_2403_pub,
00095     fusion_vehicle_2806_pub,
00096     fusion_vehicle_2807_pub;
00097 
00098   // LUX Sensor Only
00099   if (!is_fusion)
00100   {
00101     scan_data_pub = n.advertise<ibeo_msgs::ScanData2202>("parsed_tx/scan_data_2202", 1);
00102     object_data_pub = n.advertise<ibeo_msgs::ObjectData2221>("parsed_tx/object_data_2221", 1);
00103     vehicle_state_pub = n.advertise<ibeo_msgs::HostVehicleState2805>("parsed_tx/host_vehicle_state_2805", 1);
00104     error_warn_pub = n.advertise<ibeo_msgs::ErrorWarning>("parsed_tx/error_warning", 1);
00105 
00106     pub_list.insert(std::make_pair(ErrorWarning::DATA_TYPE, error_warn_pub));
00107     pub_list.insert(std::make_pair(ScanData2202::DATA_TYPE, scan_data_pub));
00108     pub_list.insert(std::make_pair(ObjectData2221::DATA_TYPE, object_data_pub));
00109     pub_list.insert(std::make_pair(HostVehicleState2805::DATA_TYPE, vehicle_state_pub));
00110   }
00111   else  // Fusion ECU Only
00112   {
00113     fusion_scan_2204_pub = n.advertise<ibeo_msgs::ScanData2204>("parsed_tx/scan_data_2204", 1);
00114     fusion_scan_2205_pub = n.advertise<ibeo_msgs::ScanData2205>("parsed_tx/scan_data_2205", 1);
00115     fusion_object_2225_pub = n.advertise<ibeo_msgs::ObjectData2225>("parsed_tx/object_data_2225", 1);
00116     fusion_object_2280_pub = n.advertise<ibeo_msgs::ObjectData2280>("parsed_tx/object_data_2280", 1);
00117     fusion_img_2403_pub = n.advertise<ibeo_msgs::CameraImage>("parsed_tx/camera_image", 1);
00118     fusion_vehicle_2806_pub = n.advertise<ibeo_msgs::HostVehicleState2806>("parsed_tx/host_vehicle_state_2806", 1);
00119     fusion_vehicle_2807_pub = n.advertise<ibeo_msgs::HostVehicleState2807>("parsed_tx/host_vehicle_state_2807", 1);
00120 
00121     pub_list.insert(std::make_pair(ScanData2204::DATA_TYPE, fusion_scan_2204_pub));
00122     pub_list.insert(std::make_pair(ScanData2205::DATA_TYPE, fusion_scan_2205_pub));
00123     pub_list.insert(std::make_pair(ObjectData2225::DATA_TYPE, fusion_object_2225_pub));
00124     pub_list.insert(std::make_pair(ObjectData2280::DATA_TYPE, fusion_object_2280_pub));
00125     pub_list.insert(std::make_pair(CameraImage::DATA_TYPE, fusion_img_2403_pub));
00126     pub_list.insert(std::make_pair(HostVehicleState2806::DATA_TYPE, fusion_vehicle_2806_pub));
00127     pub_list.insert(std::make_pair(HostVehicleState2807::DATA_TYPE, fusion_vehicle_2807_pub));
00128   }
00129 
00130   // Wait for time to be valid
00131   ros::Time::waitForValid();
00132 
00133   network_interface::TCPFrame tcp_raw_msg;
00134 
00135   ReturnStatuses status;
00136 
00137   ros::Rate loop_rate = (is_fusion) ? ros::Rate(1100) : ros::Rate(40);
00138   // Loop as long as module should run
00139 
00140   bool fusion_filter_sent = false;
00141 
00142   while (ros::ok())
00143   {
00144     if (!tcp_interface.is_open())
00145     {
00146       if (is_fusion)
00147         fusion_filter_sent = false;
00148 
00149       status = tcp_interface.open(ip_address.c_str(), port);
00150 
00151       if (status != ReturnStatuses::OK)
00152         ROS_WARN("Ibeo LUX - Unable to connect to sensor at %s: %d - %s",
00153             ip_address.c_str(),
00154             static_cast<int>(status), return_status_desc(status).c_str());
00155 
00156       ros::Duration(1.0).sleep();
00157     }
00158     else
00159     {
00160       if (is_fusion && !fusion_filter_sent)
00161       {
00162         std::vector<uint8_t> set_filter_cmd =
00163           {0xaf, 0xfe, 0xc0, 0xc2,
00164            0x00, 0x00, 0x00, 0x00,
00165            0x00, 0x00, 0x00, 0x08,
00166            0x00, 0x00, 0x20, 0x10,
00167            0x00, 0x00, 0x00, 0x00,
00168            0x00, 0x00, 0x00, 0x00,
00169            0x00, 0x05, 0x00, 0x02,
00170            0x00, 0x00, 0xff, 0xff};
00171 
00172         ROS_INFO_THROTTLE(3, "Ibeo LUX - Sending Fusion filter command to begin transmission.");
00173 
00174         status = tcp_interface.write(set_filter_cmd);
00175 
00176         if (status != ReturnStatuses::OK)
00177           ROS_ERROR_THROTTLE(3, "Ibeo LUX - Failed to send Fusion filter command.");
00178         else
00179           fusion_filter_sent = true;
00180 
00181         ros::Duration(0.5).sleep();
00182       }
00183       else
00184       {
00185         buf_size = IBEO_PAYLOAD_SIZE;
00186         std::vector<uint8_t> msg_buf;
00187         msg_buf.reserve(buf_size);
00188 
00189         status = tcp_interface.read(&msg_buf);  // Read a (big) chunk.
00190 
00191         if (status != ReturnStatuses::OK && status != ReturnStatuses::NO_MESSAGES_RECEIVED)
00192         {
00193           ROS_WARN("Ibeo ScaLa - Failed to read from socket: %d - %s",
00194               static_cast<int>(status),
00195               return_status_desc(status).c_str());
00196         }
00197         else if (status == ReturnStatuses::OK)
00198         {
00199           buf_size = msg_buf.size();
00200           grand_buffer.insert(grand_buffer.end(), msg_buf.begin(), msg_buf.end());
00201 
00202           int first_mw = 0;
00203 
00204           while (true)
00205           {
00206             first_mw = find_magic_word(grand_buffer, MAGIC_WORD);
00207 
00208             if (first_mw == -1)  // no magic word found. move along.
00209             {
00210               break;
00211             }
00212             else  // magic word found. pull out message from grand buffer and add it to the message list.
00213             {
00214               if (first_mw > 0)
00215                 grand_buffer.erase(
00216                     grand_buffer.begin(),
00217                     grand_buffer.begin() + first_mw);  // Unusable data in beginning of buffer.
00218 
00219               // From here on, the detected Magic Word should be at the beginning of the grand_buffer.
00220 
00221               IbeoDataHeader header;
00222               header.parse(std::vector<uint8_t>(grand_buffer.begin(), grand_buffer.begin() + IBEO_HEADER_SIZE));
00223 
00224               auto total_msg_size = IBEO_HEADER_SIZE + header.message_size;
00225 
00226               if (grand_buffer.size() < total_msg_size)
00227                 break;  // Incomplete message left in grand buffer. Wait for next read.
00228 
00229               std::vector<uint8_t> msg(
00230                   grand_buffer.begin(),
00231                   grand_buffer.begin() + total_msg_size);
00232               messages.push(msg);
00233               grand_buffer.erase(
00234                   grand_buffer.begin(),
00235                   grand_buffer.begin() + total_msg_size);
00236             }
00237 
00238             if (!ros::ok())
00239               break;
00240           }
00241         }
00242 
00243         while (!messages.empty())
00244         {
00245           auto message = messages.front();
00246 
00247           network_interface::TCPFrame raw_frame;
00248           raw_frame.address = ip_address;
00249           raw_frame.port = port;
00250           raw_frame.size = message.size();
00251           raw_frame.data.insert(raw_frame.data.end(), message.begin(), message.end());
00252           raw_frame.header.frame_id = frame_id;
00253           raw_frame.header.stamp = ros::Time::now();
00254 
00255           raw_tcp_pub.publish(raw_frame);
00256 
00257           IbeoDataHeader ibeo_header;
00258           ibeo_header.parse(message);
00259 
00260           // Instantiate a parser class of the correct type.
00261           auto class_parser = IbeoTxMessage::make_message(ibeo_header.data_type_id);
00262           // Look up the message publisher for this type.
00263           auto pub = pub_list.find(ibeo_header.data_type_id);
00264 
00265           // Only parse message types we know how to handle.
00266           if (class_parser != NULL && pub != pub_list.end())
00267           {
00268             // Parse the raw data into the class.
00269             class_parser->parse(message);
00270             // Create a new message of the correct type and publish it.
00271             handler.fillAndPublish(ibeo_header.data_type_id, frame_id, pub->second, class_parser.get());
00272 
00273             if (class_parser->has_scan_points)
00274             {
00275               pcl::PointCloud<pcl::PointXYZL> pcl_cloud;
00276               pcl_cloud.header.frame_id = frame_id;
00277               // pcl_cloud.header.stamp = ibeo_header.time;
00278               pcl_conversions::toPCL(ros::Time::now(), pcl_cloud.header.stamp);
00279               std::vector<Point3DL> scan_points = class_parser->get_scan_points();
00280               handler.fillPointcloud(scan_points, &pcl_cloud);
00281               pointcloud_pub.publish(pcl_cloud);
00282             }
00283 
00284             if (class_parser->has_contour_points)
00285             {
00286               visualization_msgs::Marker marker;
00287               marker.header.frame_id = frame_id;
00288               marker.header.stamp = ros::Time::now();
00289               std::vector<Point3D> contour_points = class_parser->get_contour_points();
00290 
00291               if (contour_points.size() > 0)
00292               {
00293                 handler.fillContourPoints(contour_points, &marker, frame_id);
00294                 object_contour_points_pub.publish(marker);
00295               }
00296             }
00297 
00298             if (class_parser->has_objects)
00299             {
00300               std::vector<IbeoObject> objects = class_parser->get_objects();
00301               visualization_msgs::MarkerArray marker_array;
00302               handler.fillMarkerArray(objects, &marker_array, frame_id);
00303 
00304               for (visualization_msgs::Marker m : marker_array.markers)
00305               {
00306                 m.header.frame_id = frame_id;
00307               }
00308 
00309               object_markers_pub.publish(marker_array);
00310             }
00311           }
00312 
00313           messages.pop();
00314         }  // Message parse loop
00315       }    // If fusion filter sent or != fusion
00316     }      // If sensor is connected
00317 
00318     loop_rate.sleep();
00319     // ros::spinOnce();  // No callbacks yet
00320   }
00321 
00322   status = tcp_interface.close();
00323 
00324   if (status != ReturnStatuses::OK)
00325     ROS_ERROR(
00326         "Ibeo LUX - Closing the connection to the LUX failed: %i - %s",
00327         static_cast<int>(status),
00328         return_status_desc(status).c_str());
00329 
00330   return 0;
00331 }


ibeo_lux
Author(s): Joe Kale , Joshua Whitley
autogenerated on Sat Jun 8 2019 19:59:06