/* * SLAMTEC LIDAR * Ultra Simple Data Grabber Demo App * * Copyright (c) 2009 - 2014 RoboPeak Team * http://www.robopeak.com * Copyright (c) 2014 - 2020 Shanghai Slamtec Co., Ltd. * http://www.slamtec.com * */ /* * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * */ #include #include #include #include #include #include #include #include #include "sl_lidar.h" #include "sl_lidar_driver.h" #ifndef _countof #define _countof(_Array) (int)(sizeof(_Array) / sizeof(_Array[0])) #endif #ifdef _WIN32 #include #define delay(x) ::Sleep(x) #else #include static inline void delay(sl_word_size_t ms){ while (ms>=1000){ usleep(1000*1000); ms-=1000; }; if (ms!=0) usleep(ms*1000); } #endif using namespace sl; void print_usage(int argc, const char * argv[]) { printf("Usage:\n" " For serial channel\n %s --channel --serial [baudrate]\n" " The baudrate used by different models is as follows:\n" " A1(115200),A2M7(256000),A2M8(115200),A2M12(256000)," "A3(256000),S1(256000),S2(1000000),S3(1000000),C1(460800)\n" " For udp channel\n %s --channel --udp [port NO.]\n" " The T1 default ipaddr is 192.168.11.2,and the port NO.is 8089. Please refer to the datasheet for details.\n" , argv[0], argv[0]); } bool checkSLAMTECLIDARHealth(ILidarDriver * drv) { sl_result op_result; sl_lidar_response_device_health_t healthinfo; op_result = drv->getHealth(healthinfo); if (SL_IS_OK(op_result)) { // the macro IS_OK is the preperred way to judge whether the operation is succeed. printf("SLAMTEC Lidar health status : %d\n", healthinfo.status); if (healthinfo.status == SL_LIDAR_STATUS_ERROR) { fprintf(stderr, "Error, slamtec lidar internal error detected. Please reboot the device to retry.\n"); // enable the following code if you want slamtec lidar to be reboot by software // drv->reset(); return false; } else { return true; } } else { fprintf(stderr, "Error, cannot retrieve the lidar health code: %x\n", op_result); return false; } } bool ctrl_c_pressed; void ctrlc(int) { ctrl_c_pressed = true; } int main(int argc, const char * argv[]) { const char * opt_is_channel = NULL; const char * opt_channel = NULL; const char * opt_channel_param_first = NULL; sl_u32 opt_channel_param_second = 0; sl_u32 baudrateArray[2] = {115200, 256000}; sl_result op_result; int opt_channel_type = CHANNEL_TYPE_SERIALPORT; bool useArgcBaudrate = false; IChannel* _channel; std::ofstream outfile; std::ofstream buf_file_o; std::ifstream buf_file_i; int distances[360]; // int a, b; printf("Ultra simple LIDAR data grabber for SLAMTEC LIDAR.\n" "Version: %s\n", SL_LIDAR_SDK_VERSION); if (argc>1) { opt_is_channel = argv[1]; } else { print_usage(argc, argv); return -1; } if(strcmp(opt_is_channel, "--channel")==0){ opt_channel = argv[2]; if(strcmp(opt_channel, "-s")==0||strcmp(opt_channel, "--serial")==0) { // read serial port from the command line... opt_channel_param_first = argv[3];// or set to a fixed value: e.g. "com3" // read baud rate from the command line if specified... if (argc>4) opt_channel_param_second = strtoul(argv[4], NULL, 10); useArgcBaudrate = true; } else if(strcmp(opt_channel, "-u")==0||strcmp(opt_channel, "--udp")==0) { // read ip addr from the command line... opt_channel_param_first = argv[3];//or set to a fixed value: e.g. "192.168.11.2" if (argc>4) opt_channel_param_second = strtoul(argv[4], NULL, 10);//e.g. "8089" opt_channel_type = CHANNEL_TYPE_UDP; } else { print_usage(argc, argv); return -1; } } else { print_usage(argc, argv); return -1; } if(opt_channel_type == CHANNEL_TYPE_SERIALPORT) { if (!opt_channel_param_first) { #ifdef _WIN32 // use default com port opt_channel_param_first = "\\\\.\\com3"; #elif __APPLE__ opt_channel_param_first = "/dev/tty.SLAB_USBtoUART"; #else opt_channel_param_first = "/dev/ttyUSB0"; #endif } } // create the driver instance ILidarDriver * drv = *createLidarDriver(); if (!drv) { fprintf(stderr, "insufficent memory, exit\n"); exit(-2); } sl_lidar_response_device_info_t devinfo; bool connectSuccess = false; if(opt_channel_type == CHANNEL_TYPE_SERIALPORT){ if(useArgcBaudrate){ _channel = (*createSerialPortChannel(opt_channel_param_first, opt_channel_param_second)); if (SL_IS_OK((drv)->connect(_channel))) { op_result = drv->getDeviceInfo(devinfo); if (SL_IS_OK(op_result)) { connectSuccess = true; } else{ delete drv; drv = NULL; } } } else{ size_t baudRateArraySize = (sizeof(baudrateArray))/ (sizeof(baudrateArray[0])); for(size_t i = 0; i < baudRateArraySize; ++i) { _channel = (*createSerialPortChannel(opt_channel_param_first, baudrateArray[i])); if (SL_IS_OK((drv)->connect(_channel))) { op_result = drv->getDeviceInfo(devinfo); if (SL_IS_OK(op_result)) { connectSuccess = true; break; } else{ delete drv; drv = NULL; } } } } } else if(opt_channel_type == CHANNEL_TYPE_UDP){ _channel = *createUdpChannel(opt_channel_param_first, opt_channel_param_second); if (SL_IS_OK((drv)->connect(_channel))) { op_result = drv->getDeviceInfo(devinfo); if (SL_IS_OK(op_result)) { connectSuccess = true; } else{ delete drv; drv = NULL; } } } if (!connectSuccess) { (opt_channel_type == CHANNEL_TYPE_SERIALPORT)? (fprintf(stderr, "Error, cannot bind to the specified serial port %s.\n" , opt_channel_param_first)):(fprintf(stderr, "Error, cannot connect to the specified ip addr %s.\n" , opt_channel_param_first)); goto on_finished; } // print out the device serial number, firmware and hardware version number.. printf("SLAMTEC LIDAR S/N: "); for (int pos = 0; pos < 16 ;++pos) { printf("%02X", devinfo.serialnum[pos]); } printf("\n" "Firmware Ver: %d.%02d\n" "Hardware Rev: %d\n" , devinfo.firmware_version>>8 , devinfo.firmware_version & 0xFF , (int)devinfo.hardware_version); // check health... if (!checkSLAMTECLIDARHealth(drv)) { goto on_finished; } signal(SIGINT, ctrlc); if(opt_channel_type == CHANNEL_TYPE_SERIALPORT) drv->setMotorSpeed(); // start scan... drv->startScan(0,1); // fetech result and print it out... while (1) { sl_lidar_response_measurement_node_hq_t nodes[8192]; size_t count = _countof(nodes); op_result = drv->grabScanDataHq(nodes, count); if (SL_IS_OK(op_result)) { drv->ascendScanData(nodes, count); buf_file_o.open("distances_buf.txt"); for (int pos = 0; pos < (int)count ; ++pos) { int angle = std::floor((nodes[pos].angle_z_q14 * 90.f) / 16384.f); int dist = nodes[pos].dist_mm_q2/4.0f; if (dist > 0.0) { distances[angle] = dist; buf_file_o << angle << " " << distances[angle] << "\n"; } } buf_file_o.close(); // Instead of moving all values to file, rename buffer file // buf_file_i.open("distances_buf.txt"); // outfile.open("distances.txt"); // a = 0; // b = 0; // while (buf_file_i >> a >> b) { // outfile << a << " " << b << "\n"; // printf("Angle: %i, Dist: %i\n", a, b); //} std::rename("distances_buf.txt", "distances.txt"); // buf_file_i.close(); // outfile.close(); } if (ctrl_c_pressed){ break; } } drv->stop(); delay(200); if(opt_channel_type == CHANNEL_TYPE_SERIALPORT) drv->setMotorSpeed(0); // done! on_finished: if(drv) { delete drv; drv = NULL; } return 0; }