Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Sick PicoScan150 "add_transform_xyz_rpy" not working #399

Closed
ravikiransama opened this issue Oct 15, 2024 · 2 comments
Closed

Sick PicoScan150 "add_transform_xyz_rpy" not working #399

ravikiransama opened this issue Oct 15, 2024 · 2 comments

Comments

@ravikiransama
Copy link

Hi,
I have an issue with sick pico scan 150. The "add_transform_xyz_rpy" is not working. The moment i enter non zero values, no point clouds are published on that topic in rviz. I use ros2 humble and sick_scan_xd humble version. I had built the sick scan from source.

Here are my launch and config files.
`

<!-- Launch sick_picoscan -->
<!-- env name="ROSCONSOLE_CONFIG_FILE" value="/tmp/rosconsole_loglevel_warn.conf" / -->
<arg name="hostname" default="192.168.0.101"/>  <!-- IP address of picoScan150, overwrites default ip address "192.168.0.1" in sick_scansegment_xd.yaml -->
<arg name="udp_receiver_ip" default="192.168.0.100"/>        <!-- UDP destination IP address (ip address of udp receiver), overwrites default in sick_scansegment_xd.yaml -->
<arg name="nodename" default="sick_picoscan1"/>
<arg name="publish_frame_id" default="world" />                                 <!-- frame id of ros Laserscan messages, default: "world_<layer-id>" = "world_1" -->
<arg name="publish_laserscan_segment_topic" default="scan1_segment" />           <!-- topic of ros Laserscan segment messages -->
<arg name="publish_laserscan_fullframe_topic" default="scan1_fullframe" />       <!-- topic of ros Laserscan fullframe messages -->
<arg name="imu_topic" default="imu" />                                          <!-- topic of ros IMU messages -->
<arg name="add_transform_xyz_rpy" default="0,0,0,0,0,0"/>
<arg name="scandataformat" default="2"/>                  <!-- ScanDataFormat: 1 for msgpack or 2 for compact scandata, default: 2 -->
<arg name="performanceprofilenumber" default="-1"/>       <!-- Set performance profile by "sWN PerformanceProfileNumber" if performanceprofilenumber >= 0 (for picoScan: 1-10), default: -1 -->
<arg name="all_segments_min_deg" default="-138.0" />      <!-- angle range covering all segments: all segments pointcloud on topic publish_topic_all_segments is published,  -->
<arg name="all_segments_max_deg" default="+138.0" />      <!-- if received segments cover angle range from all_segments_min_deg to all_segments_max_deg. -180...+180 for multiScan136 (360 deg fullscan), -138...+138 for picoScan (fullscan) -->

<arg name="host_FREchoFilter" default="2" />              <!-- Optionally set FREchoFilter with 0 for FIRST_ECHO (default, EchoCount=1), 1 for ALL_ECHOS (EchoCount=3), or 2 for LAST_ECHO (EchoCount=1) -->

<arg name="custom_pointclouds" default="cloud_unstructured_segments cloud_unstructured_fullframe cloud_polar_unstructured_segments cloud_polar_unstructured_fullframe cloud_all_fields_fullframe"/> <!-- Default pointclouds: segmented and fullframe pointclouds, with all layers and echos in both cartesian and polar coordinates -->
<node name="$(arg nodename)" pkg="sick_scan_xd" type="sick_generic_caller" respawn="false" output="screen" required="true">    
    <param name="scanner_type" type="string" value="sick_picoscan"/>

    <!-- network settings: -->
    <param name="hostname" type="string" value="$(arg hostname)" />                     <!-- IP address of picoScan150 to post start and stop commands, f.e. "192.168.0.1" (default) -->
    <param name="port" type="int" value="2115" />                                       <!-- IP port of picoScan150 to post start and stop commands -->
    <param name="udp_receiver_ip" type="string" value="$(arg udp_receiver_ip)" />       <!-- UDP destination IP address (ip address of udp receiver), f.e. "192.168.0.140" -->

    <!-- sick_scansegment_xd basic settings: -->
    <param name="udp_sender" type="string" value="" />                                  <!-- Use "" (default) to receive msgpacks from any udp sender, use "127.0.0.1" to restrict to localhost (loopback device), or use the ip-address of a picoscan lidar or picoscan emulator -->
    <param name="udp_port" type="int" value="2115" />                                   <!-- default udp port for picoScan150 resp. picoScan150 emulator is 2115 -->
    <param name="all_segments_min_deg" type="double" value="$(arg all_segments_min_deg)" />              <!-- angle range covering all segments: all segments pointcloud on topic publish_topic_all_segments is published,  -->
    <param name="all_segments_max_deg" type="double" value="$(arg all_segments_max_deg)" />              <!-- if received segments cover angle range from all_segments_min_deg to all_segments_max_deg. -180...+180 for multiScan136 (360 deg fullscan), -138...+138 for picoScan (fullscan) -->
    <param name="publish_frame_id" type="string" value="$(arg publish_frame_id)" />     <!-- frame id of ros PointCloud2 messages, default: "world_<layer-id>" = "world_1" -->
    <param name="publish_laserscan_segment_topic" type="string" value="$(arg publish_laserscan_segment_topic)" />           <!-- topic of ros Laserscan segment messages -->
    <param name="publish_laserscan_fullframe_topic" type="string" value="$(arg publish_laserscan_fullframe_topic)" />       <!-- topic of ros Laserscan fullframe messages -->
    <param name="udp_input_fifolength" type="int" value="20" />                         <!-- max. udp input fifo length(-1: unlimited, default: 20 for buffering 1 second at 20 Hz), elements will be removed from front if number of elements exceeds the fifo_length -->
    <param name="msgpack_output_fifolength" type="int" value="20" />                    <!-- max. msgpack output fifo length(-1: unlimited, default: 20 for buffering 1 second at 20 Hz), elements will be removed from front if number of elements exceeds the fifo_length -->
    <param name="verbose_level" type="int" value="1" />                                 <!-- verbose_level <= 0: quiet mode, verbose_level == 1: print statistics, verbose_level == 2: print details incl. msgpack data, default: 1 -->
    <param name="measure_timing" type="bool" value="True" />                            <!-- measure_timing == true: duration and latency of msgpack conversion and export is measured, default: true -->
    <param name="export_csv" type="bool" value="False" />                               <!-- export msgpack data to csv file, default: false -->
    <param name="export_udp_msg" type="bool" value="False" />                           <!-- true : export binary udpand msgpack data to file(*.udp and* .msg), default: false -->
    <param name="logfolder" type="string" value="" />                                   <!-- output folder for logfiles, default: "" (no logging) -->
    <param name="send_udp_start" type="bool" value="False" />                           <!-- Send udp start string to picoScan150 -->
    <param name="send_udp_start_string" type="string" value="magicalActivate" />        <!-- udp string to start picoScan150 -->
    <param name="udp_timeout_ms" type="int" value="60000" />                            <!-- Timeout for udp messages in milliseconds, default: 60*1000 -->
    <param name="scandataformat" type="int" value="$(arg scandataformat)" />            <!-- ScanDataFormat: 1 for msgpack or 2 for compact scandata, default: 1 -->
    <param name="performanceprofilenumber" type="int" value="$(arg performanceprofilenumber)"/> <!-- Set performance profile by "sWN PerformanceProfileNumber" if performanceprofilenumber >= 0 (for picoScan: 1-9), default: -1 -->
    <!-- IMU support requires compact format and picoScan firmware version 1.1 or newer, see https://www.sick.com/de/en/downloads/media/swp680096 -->
    <param name="imu_enable" type="bool" value="True"/>                                 <!-- Enable inertial measurement unit IMU, compact format only -->
    <param name="imu_udp_port" type="int" value="7503"/>                                <!-- udp port for multiScan imu data (if imu_enable is true) -->
    <param name="imu_latency_microsec" type="int" value="0"/>                           <!-- imu latency in microseconds -->
    <param name="imu_topic" type="string" value="$(arg imu_topic)"/>                    <!-- topic of ros IMU messages -->
    
    <!-- Apply an additional transform to the cartesian pointcloud, default: "0,0,0,0,0,0" (i.e. no transform) -->
    <!-- Note: add_transform_xyz_rpy is specified by 6D pose x, y, z, roll, pitch, yaw in [m] resp. [rad] -->
    <!-- It transforms a 3D point in cloud coordinates to 3D point in user defined world coordinates: --> 
    <!-- add_transform_xyz_rpy := T[world,cloud] with parent "world" and child "cloud", i.e. P_world = T[world,cloud] * P_cloud -->
    <!-- The additional transform applies to cartesian lidar pointclouds and visualization marker (fields) -->
    <!-- It is NOT applied to polar pointclouds, radarscans, ldmrs objects or other messages -->
    <param name="add_transform_xyz_rpy" type="string" value="0.398 -0.213 0.12,0,0,-0.785398" /> 

    <!-- SOPAS settings: -->
    <param name="sopas_tcp_port" type="string" value="2111" />                          <!-- TCP port for SOPAS commands, default port: 2111 -->
    <param name="start_sopas_service" type="bool" value="True" />                       <!-- True: sopas services for CoLa-commands are started (ROS only), default: true -->
    <param name="send_sopas_start_stop_cmd" type="bool" value="True" />                 <!-- True: picoScan150 start and stop command sequence ("sWN ScanDataEnable 0/1" etc.) are sent after driver start and stop, default: true -->
    <param name="sopas_cola_binary" type="bool" value="False" />                        <!-- False: SOPAS uses CoLa-A (ascii, default, recommended), CoLa-B (true, binary) currently experimental -->
    <param name="sopas_timeout_ms" type="int" value="5000" />                           <!-- Timeout for SOPAS response in milliseconds, default: 5000 -->
    <param name="client_authorization_pw" type="string" value="F4724744" />             <!-- Default password for client authorization -->
    
    <!-- picoScan150 filter settings -->
    <param name="host_read_filtersettings" type="bool" value="True" />                                    <!-- Read picoScan150 settings for FREchoFilter, LFPangleRangeFilter and LFPlayerFilter at startup, default: true -->
    <param name="host_FREchoFilter" type="int" value="$(arg host_FREchoFilter)" />                        <!-- Optionally set FREchoFilter with 0 for FIRST_ECHO (default, EchoCount=1), 1 for ALL_ECHOS (EchoCount=3), or 2 for LAST_ECHO (EchoCount=1) -->
    <param name="host_set_FREchoFilter" type="bool" value="True" />                                       <!-- If true, FREchoFilter is set at startup -->
    
    <!-- Msgpack validation -->
    <param name="msgpack_validator_enabled" type="bool" value="False" />                                  <!-- true: check msgpack data for out of bounds and missing scan data, false: no msgpack validation (default) -->
    <param name="msgpack_validator_verbose" type="int" value="1" />                                       <!-- 0: print error messages, 1: print error and informational messages, 2: print error and all messages -->
    <param name="msgpack_validator_discard_msgpacks_out_of_bounds" type="bool" value="True" />            <!-- true: msgpacks are discarded if scan data out of bounds detected, false: error message if a msgpack is not validated -->
    <param name="msgpack_validator_check_missing_scandata_interval" type="int" value="9" />               <!-- check msgpack for missing scandata after collecting N msgpacks, default: N = 9 segments. Increase this value to tolerate udp packet drops. Use 9 to check each full scan. -->
    <param name="msgpack_validator_required_echos" type="string" value="0 1 2" />                         <!-- default: "0 1 2" for all echos (FREchoFilter=1) or "0" for one echo (FREchoFilter=0) -->
    <param name="msgpack_validator_azimuth_start" type="double" value="-138.0" />                         <!-- picoScan150: fullscan, -138 to +138 deg -->
    <param name="msgpack_validator_azimuth_end" type="double" value="+138.0" />                           <!-- picoScan150: fullscan, -138 to +138 deg -->
    <param name="msgpack_validator_elevation_start" type="double" value="0.0" />                          <!-- picoScan150: 1 layer -->
    <param name="msgpack_validator_elevation_end" type="double" value="0.0" />                            <!-- picoScan150: 1 layer -->
    <param name="msgpack_validator_valid_segments" type="string" value="0 1 2 3 4 5 6 7 8" />             <!-- indices of valid segmentes, default for full scan: 9 segments -->
    <param name="msgpack_validator_layer_filter" type="string" value="1" />                               <!-- picoScan150: 1 layer -->

    <!-- Configuration of laserscan messages (ROS only): -->
    <!-- Parameter "laserscan_layer_filter" sets a mask to create laserscan messages for configured layer (0: no laserscan message, 1: create laserscan messages for this layer) -->
    <!-- Use "1" to activate resp. "0" to deactivate laserscan messages (picoScan has just 1 layer) -->
    <param name="laserscan_layer_filter" type="string" value="1" />

    <!-- Configuration of customized pointclouds:

    Parameter "custom_pointclouds" lists all customized pointclouds to be published. Each pointcloud is given by its name and configured by the following parameters:
    "<name_of_custom_pointcloud>" type="string" value="list of key-value-pairs"
    
    The list of key-value-pairs defines the pointcloud properties. List of supported key-value-pairs for customized pointclouds:
    
    Parameter "coordinateNotation" is an enum to configure pointcloud coordinates:
        coordinateNotation=0: cartesian (default, pointcloud has fields x,y,z,i), identical to customized with fields=x,y,z,i
        coordinateNotation=1: polar (pointcloud has fields azimuth,elevation,r,i), identical to customized with fields=azimuth,elevation,range,i
        coordinateNotation=2: both cartesian and polar (pointcloud has fields x,y,z,azimuth,elevation,r,i), identical to customized with fields=x,y,z,azimuth,elevation,range,i
        coordinateNotation=3: customized pointcloud fields, i.e. the pointcloud has fields configured by parameter "fields"

    Parameter "updateMethod" is an enum to configure fullframe pointclouds versus segmented pointcloud:
        updateMethod=0: fullframe pointcloud (default)
        updateMethod=1: segmented pointcloud

    Parameter "fields" defines the fields of the pointcloud for coordinateNotation == 3 (customized pointcloud fields), e.g. 
        fields=x,y,z,i: cartesian pointcloud
        fields=range,azimuth,elevation: polar pointcloud
        or any other combination of x,y,z,i,range,azimuth,elevation,layer,echo,reflector
    
    Parameter "echos" defines which echos are included in the pointcloud, e.g.
        echos=0,1,2: all echos
        echos=2: last echo
        or any other combination of 0,1,2

    Parameter "layers" defines which layers are included in the pointcloud, e.g
        layers=1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16 for all layers
        layers=6 for the 0 degree layer
        or any other combination of 1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16
    Note: layer ids enumerate from 1 up to 16.

    Parameter "reflectors" filters the points by the reflector bit, i.e.
        reflectors=0,1 for points with reflector bit set or not set
        reflectors=0 for points with reflector bit not set
        reflectors=1 for points with reflector bit set

    Parameter "infringed" defines filters the points by infringement, i.e.
        infringed=0,1 for points with infringement bit set or not set
        infringed=0 for points with infringement bit not set
        infringed=1 for points with infringement bit set
    Parameter "infringed" is currently not supported (reserved for future use)

    Optional parameter "rangeFilter" configures how invalid measurements are filtered in the customized pointcloud.
        rangeFilter=<range_min>,<range_max>,<filter_flag>
    The range (distance) of invalid scan points is 0 and can be filtered, i.e. removed from the pointcloud or set to 0, FLT_MAX or NAN.
    If the range (distance) of a scan point is less than <range_min> or greater than <range_max>, this point is filtered depending on <filter_flag>:
        <filter_flag> = 0: RANGE_FILTER_DEACTIVATED,  do not apply range filter (default)
        <filter_flag> = 1: RANGE_FILTER_DROP,         drop point, if range is not within [range_min, range_max]
        <filter_flag> = 2: RANGE_FILTER_TO_ZERO,      set range to 0, if range is not within [range_min, range_max]
        <filter_flag> = 3: RANGE_FILTER_TO_RANGE_MAX, set range to range_max, if range is not within [range_min, range_max]
        <filter_flag> = 4: RANGE_FILTER_TO_FLT_MAX,   set range to FLT_MAX, if range is not within [range_min, range_max]
        <filter_flag> = 5: RANGE_FILTER_TO_NAN        set range to NAN, if range is not within [range_min, range_max]
    Note: Using range_filter_handling 4 or 5 requires handling of FLT_MAX and NAN values in an application.
    The working range of a picoScan is specified by 0.05 m up to 120 m. Example to drop invalid measurements:
        rangeFilter=0.05,120,1
    Note: "structured" pointclouds contain all scan points (valid and invalid), i.e. these pointclouds are not filtered. Each scan point has a fixed offset in a structured pointcloud.
    "unstructured" pointclouds contain all valid measurements, i.e. these pointclouds are filtered and contain valid scan points only. Azimuth and elevation of the n-th scan point is not constant.

    Parameter "topic" defines the ros topic, e.g. topic=/cloud_fullframe for cartesian fullframe pointclouds

    Parameter "frameid" defines the ros frame of the pointcloud, e.g. frameid=world, frameid=map or frameid=base_link

    Parameter "publish" activates or deactivates the pointcloud, e.g. publish=1 to generate and publish, or publish=0 to deactivate that pointcloud
    -->

    <!-- List of customized pointclouds: -->
    <param name="custom_pointclouds" type="string" value="$(arg custom_pointclouds)"/> <!-- Default pointclouds: segmented pointcloud and fullframe pointcloud with all layers and echos in cartesian coordinates -->
    
    <!-- A list predefined pointclouds is configured below. Use all of them or just a subset, according to your needs. Further customized pointclouds can be added in the following configuration -->
    <!-- param name="custom_pointclouds" type="string" value="cloud_unstructured_segments cloud_polar_unstructured_segments cloud_unstructured_fullframe cloud_unstructured_echo1 cloud_unstructured_echo1_segments cloud_unstructured_echo2 cloud_unstructured_echo2_segments cloud_unstructured_echo3 cloud_unstructured_echo3_segments cloud_unstructured_reflector cloud_unstructured_reflector_segments cloud_structured_hires0 cloud_structured_hires0_segments cloud_structured_hires1 cloud_structured_hires1_segments cloud_structured cloud_structured_segments cloud_all_fields_segments cloud_all_fields_fullframe"/ -->

    <!-- cloud_unstructured_segments: cartesian coordinates, segmented, all echos, all layers, range filter on, max. 2700 points, mean ca. 1000 points per cloud -->
    <param name="cloud_unstructured_segments" type="string" value="coordinateNotation=0 updateMethod=1 echos=0,1,2 layers=1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16 reflectors=0,1 infringed=0,1 rangeFilter=0.05,999,1 topic=/cloud_unstructured_segments frameid=world publish=1"/>
    
    <!-- cloud_unstructured_fullframe: cartesian coordinates, fullframe, all echos, all layers, range filter on, max. 32400 points, mean ca. 10000 points per cloud -->
    <param name="cloud_unstructured_fullframe" type="string" value="coordinateNotation=0 updateMethod=0 echos=0,1,2 layers=1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16 reflectors=0,1 infringed=0,1 rangeFilter=0.05,999,1 topic=/cloud_unstructured_fullframe frameid=world publish=1"/>

    <!-- cloud_polar_unstructured_segments: polar coordinates, segmented, all echos, all layers, range filter on, max. 2700 points, mean ca. 1000 points per cloud -->
    <param name="cloud_polar_unstructured_segments" type="string" value="coordinateNotation=1 updateMethod=1 echos=0,1,2 layers=1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16 reflectors=0,1 infringed=0,1 rangeFilter=0.05,999,1 topic=/cloud_polar_unstructured_segments frameid=world publish=1"/>

    <!-- cloud_polar_unstructured_fullframe: polar coordinates, fullframe, all echos, all layers, range filter on -->
    <param name="cloud_polar_unstructured_fullframe" type="string" value="coordinateNotation=1 updateMethod=0 echos=0,1,2 layers=1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16 reflectors=0,1 infringed=0,1 rangeFilter=0.05,999,1 topic=/cloud_polar_unstructured_fullframe frameid=world publish=1"/>

    <!-- cloud_unstructured_echo1: cartesian coordinates, fullframe, first echo, all layers, range filter on -->
    <param name="cloud_unstructured_echo1" type="string" value="coordinateNotation=0 updateMethod=0 echos=0 layers=1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16 reflectors=0,1 infringed=0,1 rangeFilter=0.05,999,1 topic=/cloud_unstructured_echo1 frameid=world publish=1"/>

    <!-- cloud_unstructured_echo1_segments: cartesian coordinates, segmented, first echo, all layers, range filter on -->
    <param name="cloud_unstructured_echo1_segments" type="string" value="coordinateNotation=0 updateMethod=1 echos=0 layers=1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16 reflectors=0,1 infringed=0,1 rangeFilter=0.05,999,1 topic=/cloud_unstructured_echo1_segments frameid=world publish=1"/>

    <!-- cloud_unstructured_echo2: cartesian coordinates, fullframe, first echo, all layers, range filter on -->
    <param name="cloud_unstructured_echo2" type="string" value="coordinateNotation=0 updateMethod=0 echos=1 layers=1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16 reflectors=0,1 infringed=0,1 rangeFilter=0.05,999,1 topic=/cloud_unstructured_echo2 frameid=world publish=1"/>

    <!-- cloud_unstructured_echo2_segments: cartesian coordinates, segmented, first echo, all layers, range filter on -->
    <param name="cloud_unstructured_echo2_segments" type="string" value="coordinateNotation=0 updateMethod=1 echos=1 layers=1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16 reflectors=0,1 infringed=0,1 rangeFilter=0.05,999,1 topic=/cloud_unstructured_echo2_segments frameid=world publish=1"/>

    <!-- cloud_unstructured_echo3: cartesian coordinates, fullframe, first echo, all layers, range filter on -->
    <param name="cloud_unstructured_echo3" type="string" value="coordinateNotation=0 updateMethod=0 echos=2 layers=1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16 reflectors=0,1 infringed=0,1 rangeFilter=0.05,999,1 topic=/cloud_unstructured_echo3 frameid=world publish=1"/>

    <!-- cloud_unstructured_echo3_segments: cartesian coordinates, segmented, first echo, all layers, range filter on -->
    <param name="cloud_unstructured_echo3_segments" type="string" value="coordinateNotation=0 updateMethod=1 echos=2 layers=1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16 reflectors=1 infringed=0,1 rangeFilter=0.05,999,1 topic=/cloud_unstructured_echo3_segments frameid=world publish=1"/>

    <!-- cloud_unstructured_reflector: cartesian coordinates, fullframe, first echo, all layers, range filter on -->
    <param name="cloud_unstructured_reflector" type="string" value="coordinateNotation=0 updateMethod=0 echos=0,1,2 layers=1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16 reflectors=1 infringed=0,1 rangeFilter=0.05,999,1 topic=/cloud_unstructured_reflector frameid=world publish=1"/>

    <!-- cloud_unstructured_reflector_segments: cartesian coordinates, segmented, first echo, all layers, range filter on -->
    <param name="cloud_unstructured_reflector_segments" type="string" value="coordinateNotation=0 updateMethod=1 echos=0,1,2 layers=1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16 reflectors=1 infringed=0,1 rangeFilter=0.05,999,1 topic=/cloud_unstructured_reflector_segments frameid=world publish=1"/>

    <!-- cloud_structured_hires0: cartesian and polar coordinates, fullframe, all echos, range filter off, high resolution layer 6, fields=x,y,z,i,range,azimuth,elevation, number of points: 2880 x NumEchos x NumSegments -->
    <param name="cloud_structured_hires0" type="string" value="coordinateNotation=3 updateMethod=0 fields=x,y,z,i,range,azimuth,elevation echos=0,1,2 layers=6 reflectors=0,1 infringed=0,1 rangeFilter=0,999,0 topic=/cloud_structured_hires0 frameid=world publish=1"/>

    <!-- cloud_structured_hires0_segments: cartesian and polar coordinates, segments, all echos, range filter off, high resolution layer 6, fields=x,y,z,i,range,azimuth,elevation -->
    <param name="cloud_structured_hires0_segments" type="string" value="coordinateNotation=3 updateMethod=1 fields=x,y,z,i,range,azimuth,elevation echos=0,1,2 layers=6 reflectors=0,1 infringed=0,1 rangeFilter=0,999,0 topic=/cloud_structured_hires0_segments frameid=world publish=1"/>

    <!-- cloud_structured_hires1: cartesian and polar coordinates, fullframe, all echos, range filter off, high resolution layer 14, fields=x,y,z,i,range,azimuth,elevation, number of points: 2880 x NumEchos x NumSegments -->
    <param name="cloud_structured_hires1" type="string" value="coordinateNotation=3 updateMethod=0 fields=x,y,z,i,range,azimuth,elevation echos=0,1,2 layers=14 reflectors=0,1 infringed=0,1 rangeFilter=0,999,0 topic=/cloud_structured_hires1 frameid=world publish=1"/>

    <!-- cloud_structured_hires1_segments: cartesian and polar coordinates, segments, all echos, range filter off, high resolution layer 14, fields=x,y,z,i,range,azimuth,elevation -->
    <param name="cloud_structured_hires1_segments" type="string" value="coordinateNotation=3 updateMethod=1 fields=x,y,z,i,range,azimuth,elevation echos=0,1,2 layers=14 reflectors=0,1 infringed=0,1 rangeFilter=0,999,0 topic=/cloud_structured_hires1_segments frameid=world publish=1"/>

    <!-- cloud_structured: cartesian and polar coordinates, fullframe, all echos, range filter off, low resolution layers 1,2,3,4,5,7,8,9,10,11,12,13,15,16, fields=x,y,z,i,range,azimuth,elevation, 12*360*14*3=181440 points per cloud -->
    <param name="cloud_structured" type="string" value="coordinateNotation=3 updateMethod=0 fields=x,y,z,i,range,azimuth,elevation echos=0,1,2 layers=1,2,3,4,5,7,8,9,10,11,12,13,15,16 reflectors=0,1 infringed=0,1 rangeFilter=0,999,0 topic=/cloud_structured frameid=world publish=1"/>

    <!-- cloud_structured_segments: cartesian and polar coordinates, segments, all echos, range filter off, low resolution layers 1,2,3,4,5,7,8,9,10,11,12,13,15,16, fields=x,y,z,i,range,azimuth,elevation, 360*14*3=15120 points per cloud -->
    <param name="cloud_structured_segments" type="string" value="coordinateNotation=3 updateMethod=1 fields=x,y,z,i,range,azimuth,elevation echos=0,1,2 layers=1,2,3,4,5,7,8,9,10,11,12,13,15,16 reflectors=0,1 infringed=0,1 rangeFilter=0,999,0 topic=/cloud_structured_segments frameid=world publish=1"/>

    <!-- cloud_all_fields_segments: all fields (x,y,z,i,range,azimuth,elevation,layer,echo,reflector), segments, all echos, all layers, range filter off -->
    <param name="cloud_all_fields_segments" type="string" value="coordinateNotation=3 updateMethod=1 fields=x,y,z,i,range,azimuth,elevation,layer,echo,reflector echos=0,1,2 layers=1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16 reflectors=0,1 infringed=0,1 rangeFilter=0,999,0 topic=/cloud_all_fields_segments frameid=world publish=1"/>

    <!-- cloud_all_fields_fullframe: all fields (x,y,z,i,range,azimuth,elevation,layer,echo,reflector), fullframe, all echos, all layers, range filter off -->
    <param name="cloud_all_fields_fullframe" type="string" value="coordinateNotation=3 updateMethod=0 fields=x,y,z,i,range,azimuth,elevation,layer,echo,reflector echos=0,1,2 layers=1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16 reflectors=0,1 infringed=0,1 rangeFilter=0,999,0 topic=/cloud_all_fields_fullframe frameid=world publish=1"/>

    <!-- 
    On ROS-1 and ROS-2, sick_scan_xd publishes TF messsages to map a given base frame (i.e. base coordinates system) to the lidar frame (i.e. lidar coordinates system) and vice versa.
    The default base frame id is "map" (which is the default frame in rviz). 
    The default 6D pose is (x,y,z,roll,pitch,yaw) = (0,0,0,0,0,0) defined by position (x,y,z) in meter and (roll,pitch,yaw) in radians.
    This 6D pose (x,y,z,roll,pitch,yaw) is the transform T[base,lidar] with parent "base" and child "lidar".
    For lidars mounted on a carrier, the lidar pose T[base,lidar] and base frame can be configured in this launchfile using the following parameter.
    The lidar frame id given by parameter "frame_id" resp. "publish_frame_id".
    Note that the transform is specified using (x,y,z,roll,pitch,yaw). In contrast, the ROS static_transform_publisher uses commandline arguments in order (x,y,z,yaw,pitch,roll).
    -->
    <param name="tf_base_frame_id" type="string" value="map" />              <!-- Frame id of base coordinates system, e.g. "map" (default frame in rviz) -->
    <param name="tf_base_lidar_xyz_rpy" type="string" value="0,0,0,0,0,0" /> <!-- T[base,lidar], 6D pose (x,y,z,roll,pitch,yaw) in meter resp. radians with parent "map" and child "cloud" -->
    <param name="tf_publish_rate" type="double" value="10" />                <!-- Rate to publish TF messages in hz, use 0 to deactivate TF messages -->

</node>
` `import os import sys from ament_index_python.packages import get_package_share_directory from launch import LaunchDescription from launch_ros.actions import Node from launch.actions import DeclareLaunchArgument

def generate_launch_description():

ld = LaunchDescription()
sick_scan_pkg_prefix = get_package_share_directory('sick_scan_xd')
launchfile = os.path.basename(__file__)[:-3] # convert "<lidar_name>.launch.py" to "<lidar_name>.launch"
launch_file_path = os.path.join(sick_scan_pkg_prefix, 'launch/' + launchfile) # 'launch/sick_picoscan.launch')
node_arguments=[launch_file_path]

# append optional commandline arguments in name:=value syntax
for arg in sys.argv:
    if len(arg.split(":=")) == 2:
        node_arguments.append(arg)

ROS_DISTRO = os.environ.get('ROS_DISTRO') # i.e. 'eloquent', 'foxy', etc.
if ROS_DISTRO[0] <= "e": # ROS versions eloquent and earlier require "node_executable", ROS foxy and later use "executable"
    node = Node(
        package='sick_scan_xd',
        node_executable='sick_generic_caller',
        output='screen',
        arguments=node_arguments
    )
else: # ROS versions eloquent and earlier require "node_executable", ROS foxy and later use "executable"
    node = Node(
        package='sick_scan_xd',
        executable='sick_generic_caller',
        output='screen',
        arguments=node_arguments
    )

ld.add_action(node)
return ld
<!-- Launch sick_picoscan -->
<!-- env name="ROSCONSOLE_CONFIG_FILE" value="/tmp/rosconsole_loglevel_warn.conf" / -->
<arg name="hostname" default="192.168.0.101"/>  <!-- IP address of picoScan150, overwrites default ip address "192.168.0.1" in sick_scansegment_xd.yaml -->
<arg name="udp_receiver_ip" default="192.168.0.100"/>        <!-- UDP destination IP address (ip address of udp receiver), overwrites default in sick_scansegment_xd.yaml -->
<arg name="nodename" default="sick_picoscan1"/>
<arg name="publish_frame_id" default="world" />                                 <!-- frame id of ros Laserscan messages, default: "world_<layer-id>" = "world_1" -->
<arg name="publish_laserscan_segment_topic" default="scan1_segment" />           <!-- topic of ros Laserscan segment messages -->
<arg name="publish_laserscan_fullframe_topic" default="scan1_fullframe" />       <!-- topic of ros Laserscan fullframe messages -->
<arg name="imu_topic" default="imu" />                                          <!-- topic of ros IMU messages -->
<arg name="add_transform_xyz_rpy" default="0,0,0,0,0,0"/>
<arg name="scandataformat" default="2"/>                  <!-- ScanDataFormat: 1 for msgpack or 2 for compact scandata, default: 2 -->
<arg name="performanceprofilenumber" default="-1"/>       <!-- Set performance profile by "sWN PerformanceProfileNumber" if performanceprofilenumber >= 0 (for picoScan: 1-10), default: -1 -->
<arg name="all_segments_min_deg" default="-138.0" />      <!-- angle range covering all segments: all segments pointcloud on topic publish_topic_all_segments is published,  -->
<arg name="all_segments_max_deg" default="+138.0" />      <!-- if received segments cover angle range from all_segments_min_deg to all_segments_max_deg. -180...+180 for multiScan136 (360 deg fullscan), -138...+138 for picoScan (fullscan) -->

<arg name="host_FREchoFilter" default="2" />              <!-- Optionally set FREchoFilter with 0 for FIRST_ECHO (default, EchoCount=1), 1 for ALL_ECHOS (EchoCount=3), or 2 for LAST_ECHO (EchoCount=1) -->

<arg name="custom_pointclouds" default="cloud_unstructured_segments cloud_unstructured_fullframe cloud_polar_unstructured_segments cloud_polar_unstructured_fullframe cloud_all_fields_fullframe"/> <!-- Default pointclouds: segmented and fullframe pointclouds, with all layers and echos in both cartesian and polar coordinates -->
<node name="$(arg nodename)" pkg="sick_scan_xd" type="sick_generic_caller" respawn="false" output="screen" required="true">    
    <param name="scanner_type" type="string" value="sick_picoscan"/>

    <!-- network settings: -->
    <param name="hostname" type="string" value="$(arg hostname)" />                     <!-- IP address of picoScan150 to post start and stop commands, f.e. "192.168.0.1" (default) -->
    <param name="port" type="int" value="2115" />                                       <!-- IP port of picoScan150 to post start and stop commands -->
    <param name="udp_receiver_ip" type="string" value="$(arg udp_receiver_ip)" />       <!-- UDP destination IP address (ip address of udp receiver), f.e. "192.168.0.140" -->

    <!-- sick_scansegment_xd basic settings: -->
    <param name="udp_sender" type="string" value="" />                                  <!-- Use "" (default) to receive msgpacks from any udp sender, use "127.0.0.1" to restrict to localhost (loopback device), or use the ip-address of a picoscan lidar or picoscan emulator -->
    <param name="udp_port" type="int" value="2115" />                                   <!-- default udp port for picoScan150 resp. picoScan150 emulator is 2115 -->
    <param name="all_segments_min_deg" type="double" value="$(arg all_segments_min_deg)" />              <!-- angle range covering all segments: all segments pointcloud on topic publish_topic_all_segments is published,  -->
    <param name="all_segments_max_deg" type="double" value="$(arg all_segments_max_deg)" />              <!-- if received segments cover angle range from all_segments_min_deg to all_segments_max_deg. -180...+180 for multiScan136 (360 deg fullscan), -138...+138 for picoScan (fullscan) -->
    <param name="publish_frame_id" type="string" value="$(arg publish_frame_id)" />     <!-- frame id of ros PointCloud2 messages, default: "world_<layer-id>" = "world_1" -->
    <param name="publish_laserscan_segment_topic" type="string" value="$(arg publish_laserscan_segment_topic)" />           <!-- topic of ros Laserscan segment messages -->
    <param name="publish_laserscan_fullframe_topic" type="string" value="$(arg publish_laserscan_fullframe_topic)" />       <!-- topic of ros Laserscan fullframe messages -->
    <param name="udp_input_fifolength" type="int" value="20" />                         <!-- max. udp input fifo length(-1: unlimited, default: 20 for buffering 1 second at 20 Hz), elements will be removed from front if number of elements exceeds the fifo_length -->
    <param name="msgpack_output_fifolength" type="int" value="20" />                    <!-- max. msgpack output fifo length(-1: unlimited, default: 20 for buffering 1 second at 20 Hz), elements will be removed from front if number of elements exceeds the fifo_length -->
    <param name="verbose_level" type="int" value="1" />                                 <!-- verbose_level <= 0: quiet mode, verbose_level == 1: print statistics, verbose_level == 2: print details incl. msgpack data, default: 1 -->
    <param name="measure_timing" type="bool" value="True" />                            <!-- measure_timing == true: duration and latency of msgpack conversion and export is measured, default: true -->
    <param name="export_csv" type="bool" value="False" />                               <!-- export msgpack data to csv file, default: false -->
    <param name="export_udp_msg" type="bool" value="False" />                           <!-- true : export binary udpand msgpack data to file(*.udp and* .msg), default: false -->
    <param name="logfolder" type="string" value="" />                                   <!-- output folder for logfiles, default: "" (no logging) -->
    <param name="send_udp_start" type="bool" value="False" />                           <!-- Send udp start string to picoScan150 -->
    <param name="send_udp_start_string" type="string" value="magicalActivate" />        <!-- udp string to start picoScan150 -->
    <param name="udp_timeout_ms" type="int" value="60000" />                            <!-- Timeout for udp messages in milliseconds, default: 60*1000 -->
    <param name="scandataformat" type="int" value="$(arg scandataformat)" />            <!-- ScanDataFormat: 1 for msgpack or 2 for compact scandata, default: 1 -->
    <param name="performanceprofilenumber" type="int" value="$(arg performanceprofilenumber)"/> <!-- Set performance profile by "sWN PerformanceProfileNumber" if performanceprofilenumber >= 0 (for picoScan: 1-9), default: -1 -->
    <!-- IMU support requires compact format and picoScan firmware version 1.1 or newer, see https://www.sick.com/de/en/downloads/media/swp680096 -->
    <param name="imu_enable" type="bool" value="True"/>                                 <!-- Enable inertial measurement unit IMU, compact format only -->
    <param name="imu_udp_port" type="int" value="7503"/>                                <!-- udp port for multiScan imu data (if imu_enable is true) -->
    <param name="imu_latency_microsec" type="int" value="0"/>                           <!-- imu latency in microseconds -->
    <param name="imu_topic" type="string" value="$(arg imu_topic)"/>                    <!-- topic of ros IMU messages -->
    
    <!-- Apply an additional transform to the cartesian pointcloud, default: "0,0,0,0,0,0" (i.e. no transform) -->
    <!-- Note: add_transform_xyz_rpy is specified by 6D pose x, y, z, roll, pitch, yaw in [m] resp. [rad] -->
    <!-- It transforms a 3D point in cloud coordinates to 3D point in user defined world coordinates: --> 
    <!-- add_transform_xyz_rpy := T[world,cloud] with parent "world" and child "cloud", i.e. P_world = T[world,cloud] * P_cloud -->
    <!-- The additional transform applies to cartesian lidar pointclouds and visualization marker (fields) -->
    <!-- It is NOT applied to polar pointclouds, radarscans, ldmrs objects or other messages -->
    <param name="add_transform_xyz_rpy" type="string" value="0.398 -0.213 0.12,0,0,-0.785398" /> 

    <!-- SOPAS settings: -->
    <param name="sopas_tcp_port" type="string" value="2111" />                          <!-- TCP port for SOPAS commands, default port: 2111 -->
    <param name="start_sopas_service" type="bool" value="True" />                       <!-- True: sopas services for CoLa-commands are started (ROS only), default: true -->
    <param name="send_sopas_start_stop_cmd" type="bool" value="True" />                 <!-- True: picoScan150 start and stop command sequence ("sWN ScanDataEnable 0/1" etc.) are sent after driver start and stop, default: true -->
    <param name="sopas_cola_binary" type="bool" value="False" />                        <!-- False: SOPAS uses CoLa-A (ascii, default, recommended), CoLa-B (true, binary) currently experimental -->
    <param name="sopas_timeout_ms" type="int" value="5000" />                           <!-- Timeout for SOPAS response in milliseconds, default: 5000 -->
    <param name="client_authorization_pw" type="string" value="F4724744" />             <!-- Default password for client authorization -->
    
    <!-- picoScan150 filter settings -->
    <param name="host_read_filtersettings" type="bool" value="True" />                                    <!-- Read picoScan150 settings for FREchoFilter, LFPangleRangeFilter and LFPlayerFilter at startup, default: true -->
    <param name="host_FREchoFilter" type="int" value="$(arg host_FREchoFilter)" />                        <!-- Optionally set FREchoFilter with 0 for FIRST_ECHO (default, EchoCount=1), 1 for ALL_ECHOS (EchoCount=3), or 2 for LAST_ECHO (EchoCount=1) -->
    <param name="host_set_FREchoFilter" type="bool" value="True" />                                       <!-- If true, FREchoFilter is set at startup -->
    
    <!-- Msgpack validation -->
    <param name="msgpack_validator_enabled" type="bool" value="False" />                                  <!-- true: check msgpack data for out of bounds and missing scan data, false: no msgpack validation (default) -->
    <param name="msgpack_validator_verbose" type="int" value="1" />                                       <!-- 0: print error messages, 1: print error and informational messages, 2: print error and all messages -->
    <param name="msgpack_validator_discard_msgpacks_out_of_bounds" type="bool" value="True" />            <!-- true: msgpacks are discarded if scan data out of bounds detected, false: error message if a msgpack is not validated -->
    <param name="msgpack_validator_check_missing_scandata_interval" type="int" value="9" />               <!-- check msgpack for missing scandata after collecting N msgpacks, default: N = 9 segments. Increase this value to tolerate udp packet drops. Use 9 to check each full scan. -->
    <param name="msgpack_validator_required_echos" type="string" value="0 1 2" />                         <!-- default: "0 1 2" for all echos (FREchoFilter=1) or "0" for one echo (FREchoFilter=0) -->
    <param name="msgpack_validator_azimuth_start" type="double" value="-138.0" />                         <!-- picoScan150: fullscan, -138 to +138 deg -->
    <param name="msgpack_validator_azimuth_end" type="double" value="+138.0" />                           <!-- picoScan150: fullscan, -138 to +138 deg -->
    <param name="msgpack_validator_elevation_start" type="double" value="0.0" />                          <!-- picoScan150: 1 layer -->
    <param name="msgpack_validator_elevation_end" type="double" value="0.0" />                            <!-- picoScan150: 1 layer -->
    <param name="msgpack_validator_valid_segments" type="string" value="0 1 2 3 4 5 6 7 8" />             <!-- indices of valid segmentes, default for full scan: 9 segments -->
    <param name="msgpack_validator_layer_filter" type="string" value="1" />                               <!-- picoScan150: 1 layer -->

    <!-- Configuration of laserscan messages (ROS only): -->
    <!-- Parameter "laserscan_layer_filter" sets a mask to create laserscan messages for configured layer (0: no laserscan message, 1: create laserscan messages for this layer) -->
    <!-- Use "1" to activate resp. "0" to deactivate laserscan messages (picoScan has just 1 layer) -->
    <param name="laserscan_layer_filter" type="string" value="1" />

    <!-- Configuration of customized pointclouds:

    Parameter "custom_pointclouds" lists all customized pointclouds to be published. Each pointcloud is given by its name and configured by the following parameters:
    "<name_of_custom_pointcloud>" type="string" value="list of key-value-pairs"
    
    The list of key-value-pairs defines the pointcloud properties. List of supported key-value-pairs for customized pointclouds:
    
    Parameter "coordinateNotation" is an enum to configure pointcloud coordinates:
        coordinateNotation=0: cartesian (default, pointcloud has fields x,y,z,i), identical to customized with fields=x,y,z,i
        coordinateNotation=1: polar (pointcloud has fields azimuth,elevation,r,i), identical to customized with fields=azimuth,elevation,range,i
        coordinateNotation=2: both cartesian and polar (pointcloud has fields x,y,z,azimuth,elevation,r,i), identical to customized with fields=x,y,z,azimuth,elevation,range,i
        coordinateNotation=3: customized pointcloud fields, i.e. the pointcloud has fields configured by parameter "fields"

    Parameter "updateMethod" is an enum to configure fullframe pointclouds versus segmented pointcloud:
        updateMethod=0: fullframe pointcloud (default)
        updateMethod=1: segmented pointcloud

    Parameter "fields" defines the fields of the pointcloud for coordinateNotation == 3 (customized pointcloud fields), e.g. 
        fields=x,y,z,i: cartesian pointcloud
        fields=range,azimuth,elevation: polar pointcloud
        or any other combination of x,y,z,i,range,azimuth,elevation,layer,echo,reflector
    
    Parameter "echos" defines which echos are included in the pointcloud, e.g.
        echos=0,1,2: all echos
        echos=2: last echo
        or any other combination of 0,1,2

    Parameter "layers" defines which layers are included in the pointcloud, e.g
        layers=1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16 for all layers
        layers=6 for the 0 degree layer
        or any other combination of 1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16
    Note: layer ids enumerate from 1 up to 16.

    Parameter "reflectors" filters the points by the reflector bit, i.e.
        reflectors=0,1 for points with reflector bit set or not set
        reflectors=0 for points with reflector bit not set
        reflectors=1 for points with reflector bit set

    Parameter "infringed" defines filters the points by infringement, i.e.
        infringed=0,1 for points with infringement bit set or not set
        infringed=0 for points with infringement bit not set
        infringed=1 for points with infringement bit set
    Parameter "infringed" is currently not supported (reserved for future use)

    Optional parameter "rangeFilter" configures how invalid measurements are filtered in the customized pointcloud.
        rangeFilter=<range_min>,<range_max>,<filter_flag>
    The range (distance) of invalid scan points is 0 and can be filtered, i.e. removed from the pointcloud or set to 0, FLT_MAX or NAN.
    If the range (distance) of a scan point is less than <range_min> or greater than <range_max>, this point is filtered depending on <filter_flag>:
        <filter_flag> = 0: RANGE_FILTER_DEACTIVATED,  do not apply range filter (default)
        <filter_flag> = 1: RANGE_FILTER_DROP,         drop point, if range is not within [range_min, range_max]
        <filter_flag> = 2: RANGE_FILTER_TO_ZERO,      set range to 0, if range is not within [range_min, range_max]
        <filter_flag> = 3: RANGE_FILTER_TO_RANGE_MAX, set range to range_max, if range is not within [range_min, range_max]
        <filter_flag> = 4: RANGE_FILTER_TO_FLT_MAX,   set range to FLT_MAX, if range is not within [range_min, range_max]
        <filter_flag> = 5: RANGE_FILTER_TO_NAN        set range to NAN, if range is not within [range_min, range_max]
    Note: Using range_filter_handling 4 or 5 requires handling of FLT_MAX and NAN values in an application.
    The working range of a picoScan is specified by 0.05 m up to 120 m. Example to drop invalid measurements:
        rangeFilter=0.05,120,1
    Note: "structured" pointclouds contain all scan points (valid and invalid), i.e. these pointclouds are not filtered. Each scan point has a fixed offset in a structured pointcloud.
    "unstructured" pointclouds contain all valid measurements, i.e. these pointclouds are filtered and contain valid scan points only. Azimuth and elevation of the n-th scan point is not constant.

    Parameter "topic" defines the ros topic, e.g. topic=/cloud_fullframe for cartesian fullframe pointclouds

    Parameter "frameid" defines the ros frame of the pointcloud, e.g. frameid=world, frameid=map or frameid=base_link

    Parameter "publish" activates or deactivates the pointcloud, e.g. publish=1 to generate and publish, or publish=0 to deactivate that pointcloud
    -->

    <!-- List of customized pointclouds: -->
    <param name="custom_pointclouds" type="string" value="$(arg custom_pointclouds)"/> <!-- Default pointclouds: segmented pointcloud and fullframe pointcloud with all layers and echos in cartesian coordinates -->
    
    <!-- A list predefined pointclouds is configured below. Use all of them or just a subset, according to your needs. Further customized pointclouds can be added in the following configuration -->
    <!-- param name="custom_pointclouds" type="string" value="cloud_unstructured_segments cloud_polar_unstructured_segments cloud_unstructured_fullframe cloud_unstructured_echo1 cloud_unstructured_echo1_segments cloud_unstructured_echo2 cloud_unstructured_echo2_segments cloud_unstructured_echo3 cloud_unstructured_echo3_segments cloud_unstructured_reflector cloud_unstructured_reflector_segments cloud_structured_hires0 cloud_structured_hires0_segments cloud_structured_hires1 cloud_structured_hires1_segments cloud_structured cloud_structured_segments cloud_all_fields_segments cloud_all_fields_fullframe"/ -->

    <!-- cloud_unstructured_segments: cartesian coordinates, segmented, all echos, all layers, range filter on, max. 2700 points, mean ca. 1000 points per cloud -->
    <param name="cloud_unstructured_segments" type="string" value="coordinateNotation=0 updateMethod=1 echos=0,1,2 layers=1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16 reflectors=0,1 infringed=0,1 rangeFilter=0.05,999,1 topic=/cloud_unstructured_segments frameid=world publish=1"/>
    
    <!-- cloud_unstructured_fullframe: cartesian coordinates, fullframe, all echos, all layers, range filter on, max. 32400 points, mean ca. 10000 points per cloud -->
    <param name="cloud_unstructured_fullframe" type="string" value="coordinateNotation=0 updateMethod=0 echos=0,1,2 layers=1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16 reflectors=0,1 infringed=0,1 rangeFilter=0.05,999,1 topic=/cloud_unstructured_fullframe frameid=world publish=1"/>

    <!-- cloud_polar_unstructured_segments: polar coordinates, segmented, all echos, all layers, range filter on, max. 2700 points, mean ca. 1000 points per cloud -->
    <param name="cloud_polar_unstructured_segments" type="string" value="coordinateNotation=1 updateMethod=1 echos=0,1,2 layers=1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16 reflectors=0,1 infringed=0,1 rangeFilter=0.05,999,1 topic=/cloud_polar_unstructured_segments frameid=world publish=1"/>

    <!-- cloud_polar_unstructured_fullframe: polar coordinates, fullframe, all echos, all layers, range filter on -->
    <param name="cloud_polar_unstructured_fullframe" type="string" value="coordinateNotation=1 updateMethod=0 echos=0,1,2 layers=1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16 reflectors=0,1 infringed=0,1 rangeFilter=0.05,999,1 topic=/cloud_polar_unstructured_fullframe frameid=world publish=1"/>

    <!-- cloud_unstructured_echo1: cartesian coordinates, fullframe, first echo, all layers, range filter on -->
    <param name="cloud_unstructured_echo1" type="string" value="coordinateNotation=0 updateMethod=0 echos=0 layers=1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16 reflectors=0,1 infringed=0,1 rangeFilter=0.05,999,1 topic=/cloud_unstructured_echo1 frameid=world publish=1"/>

    <!-- cloud_unstructured_echo1_segments: cartesian coordinates, segmented, first echo, all layers, range filter on -->
    <param name="cloud_unstructured_echo1_segments" type="string" value="coordinateNotation=0 updateMethod=1 echos=0 layers=1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16 reflectors=0,1 infringed=0,1 rangeFilter=0.05,999,1 topic=/cloud_unstructured_echo1_segments frameid=world publish=1"/>

    <!-- cloud_unstructured_echo2: cartesian coordinates, fullframe, first echo, all layers, range filter on -->
    <param name="cloud_unstructured_echo2" type="string" value="coordinateNotation=0 updateMethod=0 echos=1 layers=1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16 reflectors=0,1 infringed=0,1 rangeFilter=0.05,999,1 topic=/cloud_unstructured_echo2 frameid=world publish=1"/>

    <!-- cloud_unstructured_echo2_segments: cartesian coordinates, segmented, first echo, all layers, range filter on -->
    <param name="cloud_unstructured_echo2_segments" type="string" value="coordinateNotation=0 updateMethod=1 echos=1 layers=1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16 reflectors=0,1 infringed=0,1 rangeFilter=0.05,999,1 topic=/cloud_unstructured_echo2_segments frameid=world publish=1"/>

    <!-- cloud_unstructured_echo3: cartesian coordinates, fullframe, first echo, all layers, range filter on -->
    <param name="cloud_unstructured_echo3" type="string" value="coordinateNotation=0 updateMethod=0 echos=2 layers=1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16 reflectors=0,1 infringed=0,1 rangeFilter=0.05,999,1 topic=/cloud_unstructured_echo3 frameid=world publish=1"/>

    <!-- cloud_unstructured_echo3_segments: cartesian coordinates, segmented, first echo, all layers, range filter on -->
    <param name="cloud_unstructured_echo3_segments" type="string" value="coordinateNotation=0 updateMethod=1 echos=2 layers=1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16 reflectors=1 infringed=0,1 rangeFilter=0.05,999,1 topic=/cloud_unstructured_echo3_segments frameid=world publish=1"/>

    <!-- cloud_unstructured_reflector: cartesian coordinates, fullframe, first echo, all layers, range filter on -->
    <param name="cloud_unstructured_reflector" type="string" value="coordinateNotation=0 updateMethod=0 echos=0,1,2 layers=1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16 reflectors=1 infringed=0,1 rangeFilter=0.05,999,1 topic=/cloud_unstructured_reflector frameid=world publish=1"/>

    <!-- cloud_unstructured_reflector_segments: cartesian coordinates, segmented, first echo, all layers, range filter on -->
    <param name="cloud_unstructured_reflector_segments" type="string" value="coordinateNotation=0 updateMethod=1 echos=0,1,2 layers=1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16 reflectors=1 infringed=0,1 rangeFilter=0.05,999,1 topic=/cloud_unstructured_reflector_segments frameid=world publish=1"/>

    <!-- cloud_structured_hires0: cartesian and polar coordinates, fullframe, all echos, range filter off, high resolution layer 6, fields=x,y,z,i,range,azimuth,elevation, number of points: 2880 x NumEchos x NumSegments -->
    <param name="cloud_structured_hires0" type="string" value="coordinateNotation=3 updateMethod=0 fields=x,y,z,i,range,azimuth,elevation echos=0,1,2 layers=6 reflectors=0,1 infringed=0,1 rangeFilter=0,999,0 topic=/cloud_structured_hires0 frameid=world publish=1"/>

    <!-- cloud_structured_hires0_segments: cartesian and polar coordinates, segments, all echos, range filter off, high resolution layer 6, fields=x,y,z,i,range,azimuth,elevation -->
    <param name="cloud_structured_hires0_segments" type="string" value="coordinateNotation=3 updateMethod=1 fields=x,y,z,i,range,azimuth,elevation echos=0,1,2 layers=6 reflectors=0,1 infringed=0,1 rangeFilter=0,999,0 topic=/cloud_structured_hires0_segments frameid=world publish=1"/>

    <!-- cloud_structured_hires1: cartesian and polar coordinates, fullframe, all echos, range filter off, high resolution layer 14, fields=x,y,z,i,range,azimuth,elevation, number of points: 2880 x NumEchos x NumSegments -->
    <param name="cloud_structured_hires1" type="string" value="coordinateNotation=3 updateMethod=0 fields=x,y,z,i,range,azimuth,elevation echos=0,1,2 layers=14 reflectors=0,1 infringed=0,1 rangeFilter=0,999,0 topic=/cloud_structured_hires1 frameid=world publish=1"/>

    <!-- cloud_structured_hires1_segments: cartesian and polar coordinates, segments, all echos, range filter off, high resolution layer 14, fields=x,y,z,i,range,azimuth,elevation -->
    <param name="cloud_structured_hires1_segments" type="string" value="coordinateNotation=3 updateMethod=1 fields=x,y,z,i,range,azimuth,elevation echos=0,1,2 layers=14 reflectors=0,1 infringed=0,1 rangeFilter=0,999,0 topic=/cloud_structured_hires1_segments frameid=world publish=1"/>

    <!-- cloud_structured: cartesian and polar coordinates, fullframe, all echos, range filter off, low resolution layers 1,2,3,4,5,7,8,9,10,11,12,13,15,16, fields=x,y,z,i,range,azimuth,elevation, 12*360*14*3=181440 points per cloud -->
    <param name="cloud_structured" type="string" value="coordinateNotation=3 updateMethod=0 fields=x,y,z,i,range,azimuth,elevation echos=0,1,2 layers=1,2,3,4,5,7,8,9,10,11,12,13,15,16 reflectors=0,1 infringed=0,1 rangeFilter=0,999,0 topic=/cloud_structured frameid=world publish=1"/>

    <!-- cloud_structured_segments: cartesian and polar coordinates, segments, all echos, range filter off, low resolution layers 1,2,3,4,5,7,8,9,10,11,12,13,15,16, fields=x,y,z,i,range,azimuth,elevation, 360*14*3=15120 points per cloud -->
    <param name="cloud_structured_segments" type="string" value="coordinateNotation=3 updateMethod=1 fields=x,y,z,i,range,azimuth,elevation echos=0,1,2 layers=1,2,3,4,5,7,8,9,10,11,12,13,15,16 reflectors=0,1 infringed=0,1 rangeFilter=0,999,0 topic=/cloud_structured_segments frameid=world publish=1"/>

    <!-- cloud_all_fields_segments: all fields (x,y,z,i,range,azimuth,elevation,layer,echo,reflector), segments, all echos, all layers, range filter off -->
    <param name="cloud_all_fields_segments" type="string" value="coordinateNotation=3 updateMethod=1 fields=x,y,z,i,range,azimuth,elevation,layer,echo,reflector echos=0,1,2 layers=1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16 reflectors=0,1 infringed=0,1 rangeFilter=0,999,0 topic=/cloud_all_fields_segments frameid=world publish=1"/>

    <!-- cloud_all_fields_fullframe: all fields (x,y,z,i,range,azimuth,elevation,layer,echo,reflector), fullframe, all echos, all layers, range filter off -->
    <param name="cloud_all_fields_fullframe" type="string" value="coordinateNotation=3 updateMethod=0 fields=x,y,z,i,range,azimuth,elevation,layer,echo,reflector echos=0,1,2 layers=1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16 reflectors=0,1 infringed=0,1 rangeFilter=0,999,0 topic=/cloud_all_fields_fullframe frameid=world publish=1"/>

    <!-- 
    On ROS-1 and ROS-2, sick_scan_xd publishes TF messsages to map a given base frame (i.e. base coordinates system) to the lidar frame (i.e. lidar coordinates system) and vice versa.
    The default base frame id is "map" (which is the default frame in rviz). 
    The default 6D pose is (x,y,z,roll,pitch,yaw) = (0,0,0,0,0,0) defined by position (x,y,z) in meter and (roll,pitch,yaw) in radians.
    This 6D pose (x,y,z,roll,pitch,yaw) is the transform T[base,lidar] with parent "base" and child "lidar".
    For lidars mounted on a carrier, the lidar pose T[base,lidar] and base frame can be configured in this launchfile using the following parameter.
    The lidar frame id given by parameter "frame_id" resp. "publish_frame_id".
    Note that the transform is specified using (x,y,z,roll,pitch,yaw). In contrast, the ROS static_transform_publisher uses commandline arguments in order (x,y,z,yaw,pitch,roll).
    -->
    <param name="tf_base_frame_id" type="string" value="map" />              <!-- Frame id of base coordinates system, e.g. "map" (default frame in rviz) -->
    <param name="tf_base_lidar_xyz_rpy" type="string" value="0,0,0,0,0,0" /> <!-- T[base,lidar], 6D pose (x,y,z,roll,pitch,yaw) in meter resp. radians with parent "map" and child "cloud" -->
    <param name="tf_publish_rate" type="double" value="10" />                <!-- Rate to publish TF messages in hz, use 0 to deactivate TF messages -->

</node>
`
rostest added a commit that referenced this issue Oct 16, 2024
@rostest
Copy link
Collaborator

rostest commented Oct 16, 2024

Thank you for your feedback. Due to a configuration issue, the full frame point clouds are not published if the configured rotation is only about the z axis (i.e. roll=0, pitch=0, yaw!=0). Please use the update provided in branch https://github.com/SICKAG/sick_scan_xd/tree/feature/issue_update_2407xx (driver/src/sick_scansegment_xd/config.cpp modified), rebuild and run again.

Note that the parameter "add_transform_xyz_rpy" expects 6 comma separated values. Please replace <param name="add_transform_xyz_rpy" type="string" value="0.398 -0.213 0.12,0,0,-0.785398" /> (missing commas) with <param name="add_transform_xyz_rpy" type="string" value="0.398,-0.213,0.12,0,0,-0.785398" /> (or any other transform you want to apply) in your launch file.

@ravikiransama
Copy link
Author

Thank you for the suggestion. It works now with the update in the branch. Regarding the "add_transform_xyz_rpy" , it was typo mistake. The api now publishes the correctly. Another question, do you have any suggestion for merging 2 laser scanners? For some reason ira laser tools is not working with the sick scanners - pico100.

weinmalSICKAG added a commit that referenced this issue Oct 23, 2024
* add: Launchfiles and configuration for picoScan120
* add: Optional AngleRangeFilter and IntervalFilter for picoScan
* fix: Obsolete topic "/sick_multiscan/scan" removed
* add: IMU automatically deactivated after receiving an error code for IMU activation from picoScan w/o addons
* fix: Customization of hash values for authorization #366
* fix: Replaced builtin_addressof expressions #370
* add: Different UDP timeouts for state initial and running, improved UDP timeout handling
* fix: Picoscan range_min value in laserScan message #382
* add: Support for RMS2xxx LIDoutputstate telegrams
* fix: sick_generic_caller debug assertion #385
* add: Check of udp receiver ip at startup
* add: cmake-option to overwrite optimization level
* change: Documentation restructured
* add: Improved field evaluation TiM7xx, Tim7xxS (publish LIDinputstate messages, configuration and services for options FieldSetSelectionMethod and ActiveFieldSet)
* fix: PicoScan parameter add_transform_xyz_rpy #399
* fix: LMS4000 encoder settings #403
* fix: CMake-flag for target sick_scan_xd_api_dockertest #404
* change: Merge PR #405 (typo) and PR #406 (sick_scan_xd_api_test)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants