SICKAG / sick_scan_xd

Based on the sick_scan drivers for ROS1, sick_scan_xd merges sick_scan, sick_scan2 and sick_scan_base repositories. The driver supports both Linux (native, ROS1, ROS2) and Windows (native and ROS2).
Apache License 2.0
101 stars 84 forks source link

Change angle resolution of LMS1xxx #304

Closed cblesing closed 6 months ago

cblesing commented 6 months ago

Hi everyone,

I have tried to change the angular resolution of the sensor. We initialize the sensor using the method SickScanApiInitByCli. To change the angular resolution, we have added the following parameters to the char* array: ang_res:=0.375 and scan_freq:=75. But it seams that this has no effect to the sensor at all. After setting this values we still get 369 scan points from the sensor. And if we have a deeper look in the logging we see that the two parameter are passed in.

[Info]: SickScanApiInitByCli: mwb scanner_type:=sick_lms_1xxx port:=2112 hostname:=192.168.0.1 add_transform_xyz_rpy:=0.000000,0.000000,0,0,0,0.000000 ang_res:=0.375 scan_freq:=75

Next we see this logging:


[Info]: [From:To] -48 [deg] to 228 [deg] (in 1/10000th deg: from -480000 to 2280000)
[Info]: MIN_ANG: -1.5708 [rad] -90 [deg]
[Info]: MAX_ANG: 1.5708 [rad] 90 [deg]
ROS_INFO: Angular start/stop settings for LMS 1000 not reliable.

[Info]: Sending  : <STX><STX><STX><STX><Len=0018>sRN LMPoutputRange CRC:<0x5e>
[Info]: Receiving: <STX>sRA LMPoutputRange \x00\x01\x00\x00\x0e\xa6\xff\xf8\xad\x00\x00\x22\xca\x40<ETX>
[Info]: Angle resolution of scanner is 0.375 [deg]  (in 1/10000th deg: 3750)
[Info]: MIN_ANG (after command verification): -2.40855 [rad] -138 [deg]
[Info]: MAX_ANG (after command verification): 2.40855 [rad] 138 [deg]
[Info]: Sending  : <STX><STX><STX><STX><Len=0032>sWN LMDscandatacfg 0x07 0x00 0x00 0x01 0x00 0x00 0x00 0x00 0x00 0x00 0x01 0x00 0x01 CRC:<0x44>
[Info]: Receiving: <STX>sWA LMDscandatacfg <ETX>
[Info]: Sending  : <STX><STX><STX><STX><Len=0018>sRN LMDscandatacfg CRC:<0x67>
[Info]: Receiving: <STX>sRA LMDscandatacfg \x07\x00\x00\x01\x00\x00\x00\x00\x00\x00\x01\x00\x01<ETX>
[Info]: Sending mLMPsetscancfg request: { scan_frequency=7500, active_sector_cnt=1, angular_resolution[0]=3750, start_angle[0]=-480000, stop_angle[0]=2280000 }
[Info]: Sending  : <STX><STX><STX><STX><Len=0037>sMN mLMPsetscancfg 0x00 0x00 0x1d 0x4c 0x00 0x01 0x00 0x00 0x0e 0xa6 0xff 0xf8 0xad 0x00 0x00 0x22 0xca 0x40 CRC:<0xa9>
[Info]: Receiving: <STX>sAN mLMPsetscancfg \x00\x00\x00\x1d\x4c\x00\x01\x00\x00\x0e\xa6\xff\xf8\xad\x00\x00\x22\xca...
[Info]: LMPscancfg reply: "sAN mLMPsetscancfg \x00\x00\x00\x1d\x4c\x00\x01\x00\x00\x0e\xa6\xff\xf8\xad\x00\x00\x22\xca\x40"
[Info]: LMPscancfg: { scan_frequency=7500, active_sector_cnt=1, angular_resolution[0]=3750, start_angle[0]=-480000, stop_angle[0]=2280000 }
[Info]: sAN mLMPsetscancfg: scan frequency = 75 Hz, angular resolution = 0.375 deg.
[Info]: Sending  : <STX><STX><STX><STX><Len=0014>sRN LMPscancfg CRC:<0x63>
[Info]: Receiving: <STX>sRA LMPscancfg \x00\x00\x1d\x4c\x00\x01\x00\x00\x0e\xa6\xff\xf8\xad\x00\x00\x22\xca\x40<ETX...
[Info]: LMPscancfg reply: "sRA LMPscancfg \x00\x00\x1d\x4c\x00\x01\x00\x00\x0e\xa6\xff\xf8\xad\x00\x00\x22\xca\x40"
[Info]: LMPscancfg: { scan_frequency=7500, active_sector_cnt=1, angular_resolution[0]=3750, start_angle[0]=-480000, stop_angle[0]=2280000 }
[Info]: sRA LMPscancfg: scan frequency = 75 Hz, angular resolution = 0.375 deg.```

Looks like the sesnor has applied the resolution. But why do we get still 369 Points and not 738? The current software version of the sensor is 2.3.0 

Thanks in advance.
rostest commented 6 months ago

Thanks for your feedback. With ang_res:=0.375 and scan_freq:=75, the scan data and point clouds are generated interlaced, i.e. two consecutive scan data resp. point clouds are shifted by 0.375 degree. Each point cloud has still 0.75 degree resolution (i.e. the azimuth of each scan point increases by 0.75 degree); their combination has 0.375 degree angular resolution.

image

Using ang_res:=0.1875 and scan_freq:=37.5, the scan data and pointclouds are generated with 4 times interlacing, i.e. four consecutive scan data resp. point clouds are shifted by 0.1875 degree and the combination of 4 point clouds has 0.1875 degree angular resolution.

See https://github.com/SICKAG/sick_scan_xd/blob/develop/FAQ.md#lms1xxx-angular-resolution for details.

cblesing commented 6 months ago

Thanks for your reply. If I understood this right we have to use two consecutive incomming point cloud messages and put them together in one data structure. A follow up question from me is how to do it? Do we have to use point1 from cloud1 and then put point2 from cloud2 in some array or vector or is it possible to just put all the points from cloud1 and then those from cloud2 into a structure?

rostest commented 6 months ago

Thanks for your reply. Yes, in interlaced mode you have to concatenate 2 (resp. 4) consecutive messages to get one point cloud in high resolution. If you do not require a point cloud sorted by azimuth angle, you can just concatenate all points of 2 consecutive messages. Example code to concatenate 2 messages (not tested):

static void cartesianPointCloudMsgCallback(SickScanApiHandle apiHandle, const SickScanPointCloudMsg* msg)
{
  // Copy and keep last point cloud memory buffer to accumulate scan data over interlaced scans.
  static std::vector<std::vector<uint8_t>> last_msg_data_buffer;
  static uint32_t concatenated_width = 0;
  std::vector<uint8_t> data_vec(msg->data.buffer, msg->data.buffer + msg->data.size);
  last_msg_data_buffer.push_back(data_vec);
  concatenated_width += msg->width;
  if (last_msg_data_buffer.size() >= 2) // interlaced mode (scans with 2x interlacing)
  {
    // Concatenate buffered memory data into one point cloud
    data_vec.clear();
    for (int n = 0; n < last_msg_data_buffer.size(); n++)
      data_vec.insert(data_vec.end(), last_msg_data_buffer[n].begin(), last_msg_data_buffer[n].end());
    SickScanPointCloudMsg concatenated_msg = *msg;
    concatenated_msg.width = concatenated_width;
    concatenated_msg.data.buffer = &data_vec[0];
    concatenated_msg.data.size = data_vec.size();
    concatenated_msg.data.capacity = data_vec.capacity();
    // Use concatenated_msg the same way as *msg ...

    // Start new accumulation
    last_msg_data_buffer.clear();
    concatenated_width = 0;
  }
}

Note that the sick_scan_xd-API is a C-API; type SickScanPointCloudMsg is a struct using C-style memory access. If you convert the point cloud from a SickScanPointCloudMsg into a different data type, concatenating point clouds might look different or easier in a different format. If you need a point cloud sorted by azimuth angle, you have to concatenate point1 from cloud1, point1 from cloud2, point2 from cloud1, point2 from cloud2, and so on.

cblesing commented 6 months ago

Thanks! Works. Issue can be closed.

rostest @.***> schrieb am Mi., 3. Apr. 2024, 13:09:

Thanks for your reply. Yes, in interlaced mode you have to concatenate 2 (resp. 4) consecutive messages to get one point cloud in high resolution. If you do not require a point cloud sorted by azimuth angle, you can just concatenate all points of 2 consecutive messages. Example code to concatenate 2 messages (not tested):

static void cartesianPointCloudMsgCallback(SickScanApiHandle apiHandle, const SickScanPointCloudMsg msg) { // Copy and keep last point cloud memory buffer to accumulate scan data over interlaced scans. static std::vector<std::vector> last_msg_data_buffer; static uint32_t concatenated_width = 0; std::vector data_vec(msg->data.buffer, msg->data.buffer + msg->data.size); last_msg_data_buffer.push_back(data_vec); concatenated_width += msg->width; if (last_msg_data_buffer.size() >= 2) // interlaced mode (scans with 2x interlacing) { // Concatenate buffered memory data into one point cloud data_vec.clear(); for (int n = 0; n < last_msg_data_buffer.size(); n++) data_vec.insert(data_vec.end(), last_msg_data_buffer[n].begin(), last_msg_data_buffer[n].end()); SickScanPointCloudMsg concatenated_msg = msg; concatenated_msg.width = concatenated_width; concatenated_msg.data.buffer = &data_vec[0]; concatenated_msg.data.size = data_vec.size(); concatenated_msg.data.capacity = data_vec.capacity(); // Use concatenated_msg the same way as *msg ...

// Start new accumulation
last_msg_data_buffer.clear();
concatenated_width = 0;

} }

Note that the sick_scan_xd-API is a C-API; type SickScanPointCloudMsg is a struct using C-style memory access. If you convert the point cloud from a SickScanPointCloudMsg into a different data type, concatenating point clouds might look different or easier in a different format. If you need a point cloud sorted by azimuth angle, you have to concatenate point1 from cloud1, point1 from cloud2, point2 from cloud1, point2 from cloud2, and so on.

— Reply to this email directly, view it on GitHub https://github.com/SICKAG/sick_scan_xd/issues/304#issuecomment-2034278117, or unsubscribe https://github.com/notifications/unsubscribe-auth/AHTKQ2DMI3OZYS7TZOMITXLY3PPNBAVCNFSM6AAAAABFMP3BEWVHI2DSMVQWIX3LMV43OSLTON2WKQ3PNVWWK3TUHMZDAMZUGI3TQMJRG4 . You are receiving this because you authored the thread.Message ID: @.***>