From 23f2e453628ea4249b76067752cf9c34e831fbe2 Mon Sep 17 00:00:00 2001 From: Johann Mantel <j-mantel@gmx.net> Date: Wed, 28 Jul 2021 14:25:56 +0200 Subject: [PATCH] fix pointer problem --- .../drivers/SickLaserUnit/SickLaserUnit.cpp | 3 +- .../drivers/SickLaserUnit/SickLaserUnit.h | 1 + .../drivers/SickLaserUnit/SickScanAdapter.cpp | 464 ++++++++++++++++-- 3 files changed, 437 insertions(+), 31 deletions(-) diff --git a/source/RobotAPI/drivers/SickLaserUnit/SickLaserUnit.cpp b/source/RobotAPI/drivers/SickLaserUnit/SickLaserUnit.cpp index 1cc0f69d9..fbfe25bdd 100644 --- a/source/RobotAPI/drivers/SickLaserUnit/SickLaserUnit.cpp +++ b/source/RobotAPI/drivers/SickLaserUnit/SickLaserUnit.cpp @@ -163,7 +163,7 @@ namespace armarx << " (split size: " << deviceInfo.size() << ", expected: 3)"; continue; } - SickLaserScanDevice device; + SickLaserScanDevice& device = scanDevices.emplace_back(); device.scanTopic = topic; device.isSensorInitialized = false; device.frameName = deviceInfo[0]; @@ -192,7 +192,6 @@ namespace armarx { ARMARX_ERROR_S << "Could not create parser. Wrong Scanner name."; return; - scanDevices.push_back(device); } //addPlugin(heartbeat); diff --git a/source/RobotAPI/drivers/SickLaserUnit/SickLaserUnit.h b/source/RobotAPI/drivers/SickLaserUnit/SickLaserUnit.h index 2829a8e8f..8ea76934d 100644 --- a/source/RobotAPI/drivers/SickLaserUnit/SickLaserUnit.h +++ b/source/RobotAPI/drivers/SickLaserUnit/SickLaserUnit.h @@ -132,6 +132,7 @@ namespace armarx //scanner parameters std::string devices = "LaserScannerFront,192.168.8.133,2112"; std::string scannerType = "sick_tim_5xx"; + ScanProtocol protocol = ScanProtocol::ASCII; int timelimit = 5; double rangeMin = 0.0; double rangeMax = 10.0; diff --git a/source/RobotAPI/drivers/SickLaserUnit/SickScanAdapter.cpp b/source/RobotAPI/drivers/SickLaserUnit/SickScanAdapter.cpp index 0d2e9368b..54f94e7eb 100644 --- a/source/RobotAPI/drivers/SickLaserUnit/SickScanAdapter.cpp +++ b/source/RobotAPI/drivers/SickLaserUnit/SickScanAdapter.cpp @@ -154,9 +154,10 @@ namespace armarx unsigned char receiveBuffer[65536]; int actual_length = 0; int packetsInLoop = 0; + bool useBinaryProtocol = parser_ptr->getCurrentParamPtr()->getUseBinaryProtocol(); ros::Time recvTimeStamp = ros::Time::now(); // timestamp incoming package, will be overwritten by get_datagram - int result = get_datagram(recvTimeStamp, receiveBuffer, 65536, &actual_length, false, &packetsInLoop); + int result = get_datagram(recvTimeStamp, receiveBuffer, 65536, &actual_length, useBinaryProtocol, &packetsInLoop); //ros::Duration dur = recvTimeStampPush - recvTimeStamp; if (result != 0) { @@ -186,37 +187,442 @@ namespace armarx while (dataToProcess) { - size_t dlength; - int success = -1; - // Always Parsing Ascii-Encoding of datagram - dstart = strchr(buffer_pos, 0x02); - if (dstart != NULL) - { - dend = strchr(dstart + 1, 0x03); - } - if ((dstart != NULL) && (dend != NULL)) - { - dataToProcess = true; // continue parsing - dlength = dend - dstart; - *dend = '\0'; - dstart++; - } - else - { - dataToProcess = false; - break; - } - // HEADER of data followed by DIST1 ... DIST2 ... DIST3 .... RSSI1 ... RSSI2.... RSSI3... - // <frameid>_<sign>00500_DIST[1|2|3] - success = parseDatagram(dstart, dlength, scanData, scanInfo, updateScannerInfo); - if (success != sick_scan::ExitSuccess) + /* + if (useBinaryProtocol) + { + // if binary protocol used then parse binary message + std::vector<unsigned char> receiveBufferVec = std::vector<unsigned char>(receiveBuffer, + receiveBuffer + actual_length); + if (receiveBufferVec.size() > 8) { - ARMARX_WARNING << "parseDatagram returned ErrorCode: " << success; + long idVal = 0; + long lenVal = 0; + memcpy(&idVal, receiveBuffer + 0, 4); // read identifier + memcpy(&lenVal, receiveBuffer + 4, 4); // read length indicator + swap_endian((unsigned char *) &lenVal, 4); + + if (idVal == 0x02020202) // id for binary message + { + // binary message + if (lenVal < actual_length) + { + short elevAngleX200 = 0; // signed short (F5 B2 -> Layer 24 + // F5B2h -> -2638/200= -13.19° + int scanFrequencyX100 = 0; + double elevAngle = 0.00; + double scanFrequency = 0.0; + long measurementFrequencyDiv100 = 0; // multiply with 100 + int numOfEncoders = 0; + int numberOf16BitChannels = 0; + int numberOf8BitChannels = 0; + uint32_t SystemCountScan = 0; + uint32_t SystemCountTransmit = 0; + + memcpy(&elevAngleX200, receiveBuffer + 50, 2); + swap_endian((unsigned char *) &elevAngleX200, 2); + + memcpy(&SystemCountScan, receiveBuffer + 0x26, 4); + swap_endian((unsigned char *) &SystemCountScan, 4); + + memcpy(&SystemCountTransmit, receiveBuffer + 0x2A, 4); + swap_endian((unsigned char *) &SystemCountTransmit, 4); + + memcpy(&scanFrequencyX100, receiveBuffer + 52, 4); + swap_endian((unsigned char *) &scanFrequencyX100, 4); + + memcpy(&measurementFrequencyDiv100, receiveBuffer + 56, 4); + swap_endian((unsigned char *) &measurementFrequencyDiv100, 4); + + float scan_time = 1.0 / (scanFrequencyX100 / 100.0); + + //due firmware inconsistency + if (measurementFrequencyDiv100 > 10000) + { + measurementFrequencyDiv100 /= 100; + } + float time_increment = 1.0 / (measurementFrequencyDiv100 * 100.0); + timeIncrement = time_increment; + + memcpy(&numOfEncoders, receiveBuffer + 60, 2); + swap_endian((unsigned char *) &numOfEncoders, 2); + int encoderDataOffset = 6 * numOfEncoders; + int32_t EncoderPosTicks[4] = {0}; + int16_t EncoderSpeed[4] = {0}; + + if (numOfEncoders > 0 && numOfEncoders < 5) + { + FireEncoder = true; + for (int EncoderNum = 0; EncoderNum < numOfEncoders; EncoderNum++) + { + memcpy(&EncoderPosTicks[EncoderNum], receiveBuffer + 62 + EncoderNum * 6, 4); + swap_endian((unsigned char *) &EncoderPosTicks[EncoderNum], 4); + memcpy(&EncoderSpeed[EncoderNum], receiveBuffer + 66 + EncoderNum * 6, 2); + swap_endian((unsigned char *) &EncoderSpeed[EncoderNum], 2); + } + } + //TODO handle multi encoder with multiple encode msg or different encoder msg definition now using only first encoder + EncoderMsg.enc_position = EncoderPosTicks[0]; + EncoderMsg.enc_speed = EncoderSpeed[0]; + memcpy(&numberOf16BitChannels, receiveBuffer + 62 + encoderDataOffset, 2); + swap_endian((unsigned char *) &numberOf16BitChannels, 2); + + int parseOff = 64 + encoderDataOffset; + + char szChannel[255] = {0}; + float scaleFactor = 1.0; + float scaleFactorOffset = 0.0; + int32_t startAngleDiv10000 = 1; + int32_t sizeOfSingleAngularStepDiv10000 = 1; + double startAngle = 0.0; + double sizeOfSingleAngularStep = 0.0; + short numberOfItems = 0; + + static int cnt = 0; + cnt++; + // get number of 8 bit channels + // we must jump of the 16 bit data blocks including header ... + for (int i = 0; i < numberOf16BitChannels; i++) + { + int numberOfItems = 0x00; + memcpy(&numberOfItems, receiveBuffer + parseOff + 19, 2); + swap_endian((unsigned char *) &numberOfItems, 2); + parseOff += 21; // 21 Byte header followed by data entries + parseOff += numberOfItems * 2; + } + + // now we can read the number of 8-Bit-Channels + memcpy(&numberOf8BitChannels, receiveBuffer + parseOff, 2); + swap_endian((unsigned char *) &numberOf8BitChannels, 2); + + parseOff = 64 + encoderDataOffset; + enum datagram_parse_task + { + process_dist, + process_vang, + process_rssi, + process_idle + }; + int rssiCnt = 0; + int vangleCnt = 0; + int distChannelCnt = 0; + + for (int processLoop = 0; processLoop < 2; processLoop++) + { + int totalChannelCnt = 0; + + + bool bCont = true; + + datagram_parse_task task = process_idle; + bool parsePacket = true; + parseOff = 64 + encoderDataOffset; + bool processData = false; + + if (processLoop == 0) + { + distChannelCnt = 0; + rssiCnt = 0; + vangleCnt = 0; + } + + if (processLoop == 1) + { + processData = true; + numEchos = distChannelCnt; + ranges.resize(numberOfItems * numEchos); + if (rssiCnt > 0) + { + intensities.resize(numberOfItems * rssiCnt); + } + else + { + } + if (vangleCnt > 0) // should be 0 or 1 + { + vang_vec.resize(numberOfItems * vangleCnt); + } + else + { + vang_vec.clear(); + } + echoMask = (1 << numEchos) - 1; + + // reset count. We will use the counter for index calculation now. + distChannelCnt = 0; + rssiCnt = 0; + vangleCnt = 0; + + } + + szChannel[6] = '\0'; + scaleFactor = 1.0; + scaleFactorOffset = 0.0; + startAngleDiv10000 = 1; + sizeOfSingleAngularStepDiv10000 = 1; + startAngle = 0.0; + sizeOfSingleAngularStep = 0.0; + numberOfItems = 0; + + + #if 1 // prepared for multiecho parsing + + bCont = true; + bool doVangVecProc = false; + // try to get number of DIST and RSSI from binary data + task = process_idle; + do + { + task = process_idle; + doVangVecProc = false; + int processDataLenValuesInBytes = 2; + + if (totalChannelCnt == numberOf16BitChannels) + { + parseOff += 2; // jump of number of 8 bit channels- already parsed above + } + + if (totalChannelCnt >= numberOf16BitChannels) + { + processDataLenValuesInBytes = 1; // then process 8 bit values ... + } + bCont = false; + strcpy(szChannel, ""); + + if (totalChannelCnt < (numberOf16BitChannels + numberOf8BitChannels)) + { + szChannel[5] = '\0'; + strncpy(szChannel, (const char *) receiveBuffer + parseOff, 5); + } + else + { + // all channels processed (16 bit and 8 bit channels) + } + + if (strstr(szChannel, "DIST") == szChannel) + { + task = process_dist; + distChannelCnt++; + bCont = true; + numberOfItems = 0; + memcpy(&numberOfItems, receiveBuffer + parseOff + 19, 2); + swap_endian((unsigned char *) &numberOfItems, 2); + + } + if (strstr(szChannel, "VANG") == szChannel) + { + vangleCnt++; + task = process_vang; + bCont = true; + numberOfItems = 0; + memcpy(&numberOfItems, receiveBuffer + parseOff + 19, 2); + swap_endian((unsigned char *) &numberOfItems, 2); + + vang_vec.resize(numberOfItems); + + } + if (strstr(szChannel, "RSSI") == szChannel) + { + task = process_rssi; + rssiCnt++; + bCont = true; + numberOfItems = 0; + // copy two byte value (unsigned short to numberOfItems + memcpy(&numberOfItems, receiveBuffer + parseOff + 19, 2); + swap_endian((unsigned char *) &numberOfItems, 2); // swap + + } + if (bCont) + { + scaleFactor = 0.0; + scaleFactorOffset = 0.0; + startAngleDiv10000 = 0; + sizeOfSingleAngularStepDiv10000 = 0; + numberOfItems = 0; + + memcpy(&scaleFactor, receiveBuffer + parseOff + 5, 4); + memcpy(&scaleFactorOffset, receiveBuffer + parseOff + 9, 4); + memcpy(&startAngleDiv10000, receiveBuffer + parseOff + 13, 4); + memcpy(&sizeOfSingleAngularStepDiv10000, receiveBuffer + parseOff + 17, 2); + memcpy(&numberOfItems, receiveBuffer + parseOff + 19, 2); + + + swap_endian((unsigned char *) &scaleFactor, 4); + swap_endian((unsigned char *) &scaleFactorOffset, 4); + swap_endian((unsigned char *) &startAngleDiv10000, 4); + swap_endian((unsigned char *) &sizeOfSingleAngularStepDiv10000, 2); + swap_endian((unsigned char *) &numberOfItems, 2); + + if (processData) + { + unsigned short *data = (unsigned short *) (receiveBuffer + parseOff + 21); + + unsigned char *swapPtr = (unsigned char *) data; + // copy RSSI-Values +2 for 16-bit values +1 for 8-bit value + for (int i = 0; + i < numberOfItems * processDataLenValuesInBytes; i += processDataLenValuesInBytes) + { + if (processDataLenValuesInBytes == 1) + { + } + else + { + unsigned char tmp; + tmp = swapPtr[i + 1]; + swapPtr[i + 1] = swapPtr[i]; + swapPtr[i] = tmp; + } + } + int idx = 0; + + switch (task) + { + + case process_dist: + { + startAngle = startAngleDiv10000 / 10000.00; + sizeOfSingleAngularStep = sizeOfSingleAngularStepDiv10000 / 10000.0; + sizeOfSingleAngularStep *= (M_PI / 180.0); + + msg.angle_min = startAngle / 180.0 * M_PI - M_PI / 2; + msg.angle_increment = sizeOfSingleAngularStep; + msg.angle_max = msg.angle_min + (numberOfItems - 1) * msg.angle_increment; + + if (this->parser_->getCurrentParamPtr()->getScanMirroredAndShifted()) + { + msg.angle_min -= M_PI/2; + msg.angle_max -= M_PI/2; + + msg.angle_min *= -1.0; + msg.angle_increment *= -1.0; + msg.angle_max *= -1.0; + + } + float *rangePtr = NULL; + + if (numberOfItems > 0) + { + rangePtr = &msg.ranges[0]; + } + float scaleFactor_001 = 0.001F * scaleFactor;// to avoid repeated multiplication + for (int i = 0; i < numberOfItems; i++) + { + idx = i + numberOfItems * (distChannelCnt - 1); + rangePtr[idx] = (float) data[i] * scaleFactor_001 + scaleFactorOffset; + #ifdef DEBUG_DUMP_ENABLED + if (distChannelCnt == 1) + { + if (i == floor(numberOfItems / 2)) + { + double curTimeStamp = SystemCountScan + i * msg.time_increment * 1E6; + //DataDumper::instance().pushData(curTimeStamp, "DIST", rangePtr[idx]); + } + } + #endif + //XXX + } + + } + break; + case process_rssi: + { + // Das muss vom Protokoll abgeleitet werden. !!! + + float *intensityPtr = NULL; + + if (numberOfItems > 0) + { + intensityPtr = &msg.intensities[0]; + + } + for (int i = 0; i < numberOfItems; i++) + { + idx = i + numberOfItems * (rssiCnt - 1); + // we must select between 16 bit and 8 bit values + float rssiVal = 0.0; + if (processDataLenValuesInBytes == 2) + { + rssiVal = (float) data[i]; + } + else + { + unsigned char *data8Ptr = (unsigned char *) data; + rssiVal = (float) data8Ptr[i]; + } + intensityPtr[idx] = rssiVal * scaleFactor + scaleFactorOffset; + } + } + break; + + case process_vang: + float *vangPtr = NULL; + if (numberOfItems > 0) + { + vangPtr = &vang_vec[0]; // much faster, with vang_vec[i] each time the size will be checked + } + for (int i = 0; i < numberOfItems; i++) + { + vangPtr[i] = (float) data[i] * scaleFactor + scaleFactorOffset; + } + break; + } + } + parseOff += 21 + processDataLenValuesInBytes * numberOfItems; + + + } + totalChannelCnt++; + } while (bCont); + } + #endif + + elevAngle = elevAngleX200 / 200.0; + scanFrequency = scanFrequencyX100 / 100.0; + + + } + } } - // Start Point - if (dend != NULL) + + success = sick_scan::ExitSuccess; + // change Parsing Mode + dataToProcess = false; // only one package allowed - no chaining + } + else // Parsing of Ascii-Encoding of datagram, xxx + */ { - buffer_pos = dend + 1; + + size_t dlength; + int success = -1; + // Always Parsing Ascii-Encoding of datagram + dstart = strchr(buffer_pos, 0x02); + if (dstart != NULL) + { + dend = strchr(dstart + 1, 0x03); + } + if ((dstart != NULL) && (dend != NULL)) + { + dataToProcess = true; // continue parsing + dlength = dend - dstart; + *dend = '\0'; + dstart++; + } + else + { + dataToProcess = false; + break; + } + // HEADER of data followed by DIST1 ... DIST2 ... DIST3 .... RSSI1 ... RSSI2.... RSSI3... + // <frameid>_<sign>00500_DIST[1|2|3] + success = parseDatagram(dstart, dlength, scanData, scanInfo, updateScannerInfo); + if (success != sick_scan::ExitSuccess) + { + ARMARX_WARNING << "parseDatagram returned ErrorCode: " << success; + } + // Start Point + if (dend != NULL) + { + buffer_pos = dend + 1; + } } } // end of while loop return sick_scan::ExitSuccess; // return success to continue looping -- GitLab