I think there is really only one factor that is easily selectable:
[YDLIDAR3]:Fixed Size: 1020
[YDLIDAR3]:Sample Rate: 5K <--- Can be 5-12k
[YDLIDAR INFO] Current Sampling Rate : 5K <--- my current configured sample rate
[YDLIDAR INFO] Now YDLIDAR is scanning ......
Scan received[1624198712776831000]: 567 ranges is [8.833922]Hz
Scan received[1624198712898864000]: 572 ranges is [8.756567]Hz
Scan received[1624198713013605000]: 571 ranges is [8.771930]Hz
and then there is the fixed board transfer Baud Rate: 128k
Although these are the selectable parameters for the ROS node:
ydlidar_ros2_driver_node:
ros__parameters:
port: /dev/ttyUSB0
frame_id: laser_frame
ignore_array: ""
baudrate: 128000
lidar_type: 1
device_type: 6
sample_rate: 5
abnormal_check_count: 4
resolution_fixed: true
reversion: false
inverted: true
auto_reconnect: true
isSingleChannel: false
intensity: false
support_motor_dtr: true
angle_max: 180.0
angle_min: -180.0
range_max: 10.0
range_min: 0.12 <-- any range less than this is turned into zero in the publisher
frequency: 5.0
invalid_range_is_inf: false
Scan received[1624198712776831000]: 567 ranges is [8.833922]Hz <-- ~64 ranges per rev
The “bursty” nature of the data is interesting, as this output would have led me to believe it is taking one measurement approximately every six degrees, not a bunch at half degree intervals, then a pause before another bunch at half degree intervals. Some part of the pipe must be bottleneckin’ the dataflow.
@KeithW I can’t find a ydlidar.yaml file with your configuration parameters in your github. Are you using some defaults?
Also interesting that the ROS ydlidar node you are using in your “KFW-patch-1” branch has some message header value changes. The ROS2 node does not have those changes.
I was under the that he was executing the standard “and the next value IS! . . .” system/ROS call that anyone else would do.
. . . and that part of his problem was the amount of garbage data he received. (i.e. Why collect and view all that data if it’s not relevant and is never seen/used anyway?)
Good question - I haven’t had time to look. But when I make maps and even when I’ve done SLAM outside of my ‘roboland’ things seem to work fine. So I was surprised by the result. And I looked at the documentation - forward is towards the motors supposedly. Edit - I now see that you had already looked at that as well. Yeah - I’m still confused.
That was my thought as well - the onboard firmware doesn’t seem to capture quickly enough, or something.
I thought about running the stats, but didn’t. If you factor in all of the 0 values the SD may actually be pretty high. For the actual readings, yes, the results seem pretty good.
I was surprised by how many 0’s I got, but based on that I had somewhat assumed that the software was treating the zeros as essentially null values - I hadn’t seen that confirmed anywhere.
ooh - I’ll have to look at that. Maybe that’s my problem.
Right now I’m not using the IMU at all, so I’m sure nothing is depending on the IMU.
I hadn’t thought about that - I was assuming that ROS would rely more on the accelerometers, but I realize I have no basis for this assumption. @jimrh 's concern about the motor on the lidar throwing things off seems reasonable.
Not at all. I’m sure we’ll have an IMU thread at some point. At the pace you’re going I suspect you’ll start it
The ydlidar node publishes a zero distance for any distance less than the min_value, and if no data is received.
All actual laser ranges are published relative to the center of rotation.
It is impossible for a range from the center of rotation to be 0, since the LIDAR has a 35mm minimum radius.
Thus 0 is a good “invalid” value. (The node does allow configuring NAN/infinity for “invalid” if desired.)
Probably to save message length in queuing and dequeuing time in industrial systems. Rather than publishing a variable size list of angles and a list of ranges, the structure allows for start/stop/increment angle (three values) and the list of ranges (1 to a max of 719 for our 360 by half degree LIDAR). In the never misses a beat case this would save 716 floats.
Since ROS is primarily targeted for industrial robots with costly sensors, perhaps the waste, in my case only 65 good values, of 589 to 654 floats transmitted is of no concern to anyone?
sensor_msgs/LaserScan (/scan)
# Single scan from a planar laser range-finder
#
# If you have another ranging device with different behavior (e.g. a sonar
# array), please find or create a different message, since applications
# will make fairly laser-specific assumptions about this data
Header header # timestamp in the header is the acquisition time of
# the first ray in the scan.
#
# in frame frame_id, angles are measured around
# the positive Z axis (counterclockwise, if Z is up)
# with zero angle being forward along the x axis
float32 angle_min # start angle of the scan [rad]
float32 angle_max # end angle of the scan [rad]
float32 angle_increment # angular distance between measurements [rad]
float32 time_increment # time between measurements [seconds] - if your scanner
# is moving, this will be used in interpolating position
# of 3d points
float32 scan_time # time between scans [seconds]
float32 range_min # minimum range value [m]
float32 range_max # maximum range value [m]
float32[] ranges # range data [m] (Note: values < range_min or > range_max should be discarded)
float32[] intensities # intensity data [device-specific units]. If your
# device does not provide intensities, please leave
# the array empty.
Compact Message Definition
std_msgs/Header header
float32 angle_min
float32 angle_max
float32 angle_increment
float32 time_increment
float32 scan_time
float32 range_min
float32 range_max
float32[] ranges
float32[] intensities
Looking at this clears up one mystery I think. Note the min angle is -180, and max is 180. it’s not 0 to 360. That would explain why my zeroth distance value is straight behind me I think.
When the robot starts it has a message
[YDLidar]: [YDLIDAR INFO] Current Sampling Rate : 4K
[YDLidar]: [YDLIDAR INFO] Now YDLIDAR is scanning ......
But I think that’s coming from the firmware - when I check the rosparameters the values are the ones set in the launch file. Next thing to check is what happens if I fool with those. But they’re the ones that came from the book’s examples, so I assume they’re not entirely arbitrary.
I don’t know how to see all the values of a scan. I did an echo to the console and it prints the first 128 ranges. I am getting 105 to 109 non-zero ranges in the 128 values displayed for about 84% non-zero. Is that approximately what you are seeing - 84% non-zero out of 719 ranges?
The datasheet for my lidar says frequency 5K. Is yours 7K like your config param?
My time_increment in the header of each scan is 0.00200000000 or 0.000019999999 which corresponds to 5k.
The change you did in the code sets the scan_time to 1/freq or 1/7 in your launch config. When you look at the scan data does the scan_time value change or is it constant at 1/7?
My code is the unchanged version, and my scan_time value is steady at 0.0112199… = 1/8.9285 and varies sometimes slightly 0.0112400 = 1/8.896 is the value for the fourth of four scans I looked at.
My little script is on my GitHub test branch for now. I’ve attached it for convenience. laser_logger.py (633 Bytes)
Not that high - I just looked at my spreadsheet (thank god for the COUNTIF function). Looking at the first 50 rows I’m averaging only 366 values (range 357 - 371), so just a hair under 51%.
right now I’ve only captured the ranges. I’ll take a look at the headers to see.
I found a way to generate csv files. I start a bag play in one shell, and then a topic echo in another (must start the play before the echo)
For ROS2:
$ ros2 bag info rosbag2_2021_08_28-18_43_25/
Files: rosbag2_2021_08_28-18_43_25_0.db3
Bag size: 460.8 KiB
Storage id: sqlite3
Duration: 10.69s
Start: Aug 28 2021 18:43:27.995 (1630190607.995)
End: Aug 28 2021 18:43:38.64 (1630190618.64)
Messages: 91
Topic information: Topic: /scan | Type: sensor_msgs/msg/LaserScan | Count: 91 | Serialization Format: cdr
$ ros2 bag play rosbag2_2021_08_28-18_43_25/
[INFO] [1630252505.294131771] [rosbag2_storage]: Opened database 'rosbag2_2021_08_28-18_43_25//rosbag2_2021_08_28-18_43_25_0.db3' for READ_ONLY.
----- And in second shell ----
$ ros2 topic echo --csv --full-length /scan > scan.csv
That method strips off the field identifiers. To keep the field identifiers:
$ ros2 topic echo --full-length /scan > scan.txt
I’m wondering if the discrepancy between the scan time and the rate of spin is contributing to all of the null values? I haven’t had much free time so I haven’t been able to investigate as much as I’d like. But I’ll keep plugging along. I need to think through a structured plan to changing the parameters and seeing what happens.
Rerun your “rosrun tf2_tools view_frames.py” to be sure everything is linked up correct
Redo your “Rviz with AMCL Nav” to see if the localization is still twitchy
Restart your “preparation for nav tests” now that you have changed:
base_link xy is now at the center of rotation between the wheels
LIDAR is using the parameters listed by the manufacturer
ydlidar node is again the manufacturer’s version
URDF uses the same frame_id as the ydlidar node publishes in the joint definition (and link def)
I didn’t look very deep into the ydlidar pull-request - perhaps that is still needed. I just think it is good to let the node set those two values in the header for this round of testing, and then if the original AMCL Nav problem shows up, make the change.