Closed rossihwang closed 4 years ago
I first used a logic analyzer to find out the baud rate. this is 115200 baud
After examining the protocol I found the following structure:
packages are 36 bytes.
<0x55><0xAA><0x03><0x08> (always the same start) \An tool that was very usefull for reverse engineering the protocol is lorris toolbox
thanks a lot, i'm gonna put the lidar in a static environment, plot the distance data to see the period underhood, and try to figure out the angle index
Yea, have tried the same but until now without success.
After visualizing the data, I found that every (about) 50 frames will be a complete package(360-degree data). so that the degree gap between the data will be 0.9 degree. But I still not figure out how the data index, currently I only start collecting data after the counter(unknown1) reset. Please check the code https://gist.github.com/rossihwang/0b3f76164bf454cda5d62ad18b6538b7
Looks good,
I found this repository today: https://github.com/anhui1995/Camsense_X1
According to that, it gives back a start and end angle:
float startAngle = (data [7] << 8 | data [6]) / 64.0 - 640.0;
float endAngle = (data [33] << 8 | data [32]) / 64.0 - 640.0;
float step = 0.0;
if(endAngle > startAngle)
{
step = (endAngle-startAngle);
}
else
{
step = (endAngle - (startAngle - 360));
}
step /= 8;
it looks promising but the angle values are jumping around. That makes it difficult to put them in a normal array.
We can use a static array data[360] to store the data. Firstly we initialize all the value to the maximum measurement "00 80". Then use the index rule above but round the angle to int and fill them in the array. I may try this later
In addition, post-processing may help. say, median filter to remove some of the maximum measurement and subsample to shrink the data size
update the gist https://gist.github.com/rossihwang/0b3f76164bf454cda5d62ad18b6538b7 and port to ros2 https://github.com/rossihwang/ros2_camsense_x1
36 Bytes, 115200 baud. 00-03 Always 0x55 0xAA 0x03 0x08 04-05 Rotational Speed 06 unknown 07 Start angle/2 + 160 08-09 Reading 0 (Low, High) 0a Strength 0 (0-255 reflected power, 0=no reading, higher=better) 0b-0c Reading 1 0d Strength 1 0e-0f Reading 2 10 Strength 2 11-12 Reading 3 13 Strength 3 14-15 Reading 4 16 Strength 4 17-18 Reading 5 19 Strength 5 1a-1b Reading 6 1c Strength 6 1d-1e Reading 7 1f Strength 7 20 Unknown 21 Finish angle/2 + 160 22 Unknown 23 Unknown e.g. 55 AA 03 08 3E 4E 1C B3 C8 02 91 CB 02 1A C9 02 3D CB 02 13 C5 02 4C C4 02 33 C0 02 A3 BE 02 07 AE B4 88 5E 07: B3 = 179. (179-160)2 = 38. Readings start at 38 degrees. 08-09: C802 = 712mm to target (Reading 0) 0a: 0x91 = 145, a good strength signal. 14-15: C502 = 709mm to target (Reading 4) 16: 4C = 76, good signal, but not as shiny as reading 0. 21: B4 = 180. (180-160)2 = 40. Readings end at 40 degrees.
Does this help you?
Thanks, @fabiogua. For the start/stop angle, I think the solution above(the code than @Vidicon provided) is more reasonable, for other parts, it's almost the same as we have known.
@rossihwang After looking more into the data I did notice that the angle resets after 50 or 51 packages this would mean that on average there are about 50*8= 400 measurements per resolution.
What I'm currently use in the ros1 node I'm writing:
const float anglePerIndex = 400 / 360.0;
const float angleOffset = 180.0;
float measurementAngle = (startAngle + step * i)+angleOffset;
float fIndex = measurementAngle * IndexMultiplier;
int index = round(fIndex);
index = index % 400; // limit index between 0 and 399
index = 399-index; // invert to match ROS
rotation speed is as follows:
uint16_t rawRotationValue = ((uint16_t) (raw_bytes[5] << 8) | raw_bytes[4]);
float rotationRPM = rawRotationValue / 64.0;
float rotationHz = rotationRPM / 60.0;
ROS1 driver:
@rossihwang After looking more into the data I did notice that the angle resets after 50 or 51 packages this would mean that on average there are about 50*8= 400 measurements per resolution.
What I'm currently use in the ros1 node I'm writing:
const float anglePerIndex = 400 / 360.0; const float angleOffset = 180.0; float measurementAngle = (startAngle + step * i)+angleOffset; float fIndex = measurementAngle * IndexMultiplier; int index = round(fIndex); index = index % 400; // limit index between 0 and 399 index = 399-index; // invert to match ROS
great idea! previously I just quantize the data to 360 degree. I wonder what the "angleOffset" for?
ROS1 driver:
some suggestions
About to buy this on AliExpress. Is the code/driver able to read acceptable reads to setup SLAM and start prototyping a navigation robot?
About to buy this on AliExpress. Is the code/driver able to read acceptable reads to setup SLAM and start prototyping a navigation robot?
yes it can, you can use @Vidicon 's ros1 package or my ros2 package directly
@RuairiSpain I have successfully made a (crappy) map by walking around with the LiDAR and running Hector_mapping. navigation will most likely work as well.
ROS1 driver: https://github.com/Vidicon/camsense_driver
some suggestions
- when sync failed, it should be reset to the first sync state
- the invalid range data should be the maximum value. it seems the convention in the SLAM system(such as amcl)
yes, both are good ideas to add. will do that very soon
@rossihwang angleOffset is used to rotate the forward direction. So the motor is to the back (-X) this seems to be the convention for similar lidars (RP lidar A1, YDlidar, XV-11, etc)
thanks, i will update it soon!😁
Bram Fenijn notifications@github.com 于2020年7月24日周五 上午1:35写道:
@rossihwang https://github.com/rossihwang angleOffset is used to rotate the forward direction. So the motor is to the back (-X) this seems to be the convention for similar lidars (RP lidar A1, YDlidar, XV-11, etc)
— You are receiving this because you were mentioned. Reply to this email directly, view it on GitHub https://github.com/Vidicon/camsense-X1/issues/1#issuecomment-663137770, or unsubscribe https://github.com/notifications/unsubscribe-auth/ABOTZUPEHPC7W3PXJ6RO5NLR5BYGFANCNFSM4NWBW5XQ .
-- regards
HUANG RUOXI
Hey guys I dont know if you still need my Information, but I found this.
@fabiogua No I think the protocol is fully known (with exception of the CRC).
I think it used this repository to get it to work as they link to me in that repository:
Credit: Bram Fenijn (https://github.com/vidicon)
I will close this issue.
especially this part