Loading files
This file is pinned to the selected release. Download the original to open it in your design tool.
using MavLink;
using System;
using System.Collections.Generic;
using System.Data;
using System.Linq;
using System.Windows.Forms;
namespace LidarScanningTest1
{
public struct RadarPoint
{
public double x;
public double y;
public double dist;
public double angleDeg;
public bool corr;
public bool Wrong;
public bool NotVisible;
}
public partial class Form1 : Form
{
const int UART_BAUD = 500000;
const int RADAR_ROTATION_DEG = 180;
struct ScanPoint
{
public int RawValue;
public double RealAngleDeg;
public double DistM;//meters
public bool WrongValue;
public bool DeadZone;
}
SerialWorkerClass2 SerialWorker;
Mavlink MavlinkObj;
MavlinkLongPacketClass LongPacketObj = new MavlinkLongPacketClass();
DataAnalyseClass DataAnalyseObj = new DataAnalyseClass();
HistogramForm HistogramFormObj;
public IniParser SettingsHolder;//Used for storing settings
/// <summary>
/// Rotation period in ms
/// </summary>
int RotationPeriod = 0;
DateTime PrevScanTime = DateTime.Now;
int RXPacketCnt = 0;
int CurentPointsCnt = 360;
ScanPoint[] ScanPoints = new ScanPoint[1000];
RadarPoint[] RadarPoints = new RadarPoint[1000];
/// <summary>
/// Additional rotation, deg
/// </summary>
double CurrAngularCorrection = 0.0;//degrees
int CurrStartAngle = 50;
int CurrStopAngle = (360 - 50);
//***************************************************************
public Form1()
{
InitializeComponent();
cmbPortList.Items.Clear();
SerialWorker = new SerialWorkerClass2(Application.StartupPath + @"\config.ini");
SerialWorker.AnswerReceived = SerialPortReceivedHandler;
SerialWorker.SerialFailSignal = SerialFailSignal_function;
MavlinkObj = new Mavlink();
MavlinkObj.PacketReceived += new PacketReceivedEventHandler(ProcessRxMavlinkPacket);
LongPacketObj.LongPacketReceived += ParseLongPacket;
string settingsFilePath = Application.StartupPath + @"\config.ini";
SettingsHolder = new IniParser(settingsFilePath);
string serialName = SettingsHolder.GetSetting("SERIAL_SETTINGS", "serial");
if (cmbPortList.Items.Count == 0)
{
cmbPortList.Items.Add(serialName);
cmbPortList.SelectedItem = cmbPortList.Items[0];
}
//Load calibration coefficients
string angCorrStr = SettingsHolder.GetSetting("LIDAR_SETTINGS", "angular_corr");
CurrAngularCorrection = Convert.ToDouble(angCorrStr, System.Globalization.CultureInfo.InvariantCulture);
numAngCorrection.Value = (decimal)CurrAngularCorrection;
string startAngleStr = SettingsHolder.GetSetting("LIDAR_SETTINGS", "start_angle");
CurrStartAngle = Convert.ToInt32(startAngleStr, System.Globalization.CultureInfo.InvariantCulture);
numStartAngle.Value = CurrStartAngle;
string stopAngleStr = SettingsHolder.GetSetting("LIDAR_SETTINGS", "stop_angle");
CurrStopAngle = Convert.ToInt32(stopAngleStr, System.Globalization.CultureInfo.InvariantCulture);
numStopAngle.Value = CurrStopAngle;
radarPlotComponent1.SetRadarRotation(RADAR_ROTATION_DEG);
timer1.Enabled = true;
}
private void SerialFailSignal_function(bool obj)
{
}
// Callback from "Serial Worker"
private void SerialPortReceivedHandler(byte[] received_data)
{
MavlinkObj.ParseBytes(received_data);
}
private void ProcessRxMavlinkPacket(object sender, MavlinkPacket packet)
{
RXPacketCnt++;
Invoke((MethodInvoker)delegate ()
{
lblPacketCnt.Text = $"RX Packet CNT: {RXPacketCnt}";
});
if (packet.Message.GetType() == typeof(MavLink.Msg_long_packet))
{
LongPacketObj.AddPacket(packet.Message as MavLink.Msg_long_packet);
}
else if (packet.Message.GetType() == typeof(MavLink.Msg_device_state))
{
ParseDeviceState(packet.Message as MavLink.Msg_device_state);
}
}
private void ParseLongPacket(MavlinkLongPacketClass.LongPacketStruct rxPacket)
{
if (rxPacket.dataCode == 2) //scan data
{
byte[] tmp_byte_buf = rxPacket.byteDataList.Cast<byte>().ToArray();
UInt16[] captured_buf = new UInt16[tmp_byte_buf.Length / 2];
Buffer.BlockCopy(tmp_byte_buf, 0, captured_buf, 0, tmp_byte_buf.Length);
Invoke((MethodInvoker)(() =>
{
ProcessRxData(captured_buf);
}));
}
}
private void timer1_Tick(object sender, EventArgs e)
{
CurrAngularCorrection = (double)numAngCorrection.Value;
CurrStartAngle = (int)numStartAngle.Value;
CurrStopAngle = (int)numStopAngle.Value;
if (chkSendStateRequests.Checked)
DeviceStateRequest();
}
/// <summary>
/// Process packet received from the Lidar
/// </summary>
/// <param name="dataArray"></param>
void ProcessRxData(UInt16[] dataArray)
{
int pointsCnt = dataArray.Length;
if (pointsCnt < 50)
return;
if (pointsCnt > 720)
return;
CurentPointsCnt = pointsCnt;
double angResolution = 360.0 / pointsCnt;
for (int i = 0; i < pointsCnt; i++)
{
ScanPoints[i].RealAngleDeg = i * angResolution;
ScanPoints[i].RawValue = dataArray[i];
ScanPoints[i].WrongValue = (bool)(dataArray[i] < 10);
if ((ScanPoints[i].RealAngleDeg < CurrStartAngle) ||
(ScanPoints[i].RealAngleDeg > CurrStopAngle))
{
ScanPoints[i].DistM = 0.0;
ScanPoints[i].DeadZone = true;
}
else
{
ScanPoints[i].DistM = (double)dataArray[i] / 1000.0;
ScanPoints[i].DeadZone = false;
}
}
CalculateRadarData(pointsCnt);
radarPlotComponent1.DrawRadar(RadarPoints, pointsCnt, (int)CurrAngularCorrection);
RotationPeriod = (int)(DateTime.Now - PrevScanTime).TotalMilliseconds;
PrevScanTime = DateTime.Now;
double freq = Math.Round(1.0 / (double)(RotationPeriod / 1000.0), 1);//ms -> sec
lblScanPeriod.Text = $"Scan Period: {RotationPeriod} ms";
lblScanFreq.Text = $"Scan Freq: {freq:0.0} Hz";
lblTotalPoints.Text = $"Total Scan Points: {pointsCnt}";
AnalysePointerData();
ScanDataAnalyse();
}
//Simple Data Analyse;
void ScanDataAnalyse()
{
int visiblePointsCnt = 0;
int badPointsCnt = 0;
for (int i = 0; i < CurentPointsCnt; i++)
{
if (ScanPoints[i].DeadZone == false)
{
visiblePointsCnt++;
if (ScanPoints[i].WrongValue)
badPointsCnt++;
}
}
double BadPercent = (double)badPointsCnt / visiblePointsCnt * 100;
lblWrongPointsCnt.Text = $"Wrong Points: {BadPercent:0.0} %";
}
// Simple statistic analyse of point at given direction
void AnalysePointerData()
{
int pointer_angle = radarPlotComponent1.GetPointerAngle();//deg
int pos = CurentPointsCnt * pointer_angle / 360;
int rawValue = ScanPoints[pos].RawValue;
double dist = ScanPoints[pos].DistM;
DataAnalyseObj.AddDataPoint(dist);
if (HistogramFormObj != null)
HistogramFormObj.AddNewDisatnceValue(dist);
lblRawValue.Text = "Raw Value: " + rawValue.ToString();
lblDistValue.Text = "Distance: " + dist.ToString("0.00") + " m";
lblAVRValue.Text = "Average: " + DataAnalyseObj.average.ToString("0.00") + " m";
lblMaxMIn.Text = "MaxMin: " + DataAnalyseObj.min_max.ToString("0.00") + " m";
}
void CalculateRadarData(int pointsCnt)
{
int i;
double x = 0;
double y = 0;
double angle_rad = 0;
double dist;
double offset1_deg;
double angResolution = 360.0 / pointsCnt;//deg
// Radar rotation
double ang5 = 90 + RADAR_ROTATION_DEG;
for (i = 0; i < pointsCnt; i++)
{
dist = ScanPoints[i].DistM;
offset1_deg = i * angResolution;//angle, deg
double pointAngleDeg = offset1_deg + CurrAngularCorrection + ang5;
angle_rad = pointAngleDeg / 180.0 * (Math.PI);
RadarPoints[i].angleDeg = pointAngleDeg;
RadarPoints[i].dist = dist;
RadarPoints[i].x = (Math.Cos(angle_rad) * dist);
RadarPoints[i].y = (Math.Sin(angle_rad) * dist);
if (RadarPoints[i].dist < 0.03)
RadarPoints[i].NotVisible = true;
else
RadarPoints[i].NotVisible = false;
if ((ScanPoints[i].DeadZone == false) && ScanPoints[i].WrongValue)
RadarPoints[i].Wrong = true;
else
RadarPoints[i].Wrong = false;
}
}
private void btnOpenClose_Click(object sender, EventArgs e)
{
// If we have opened port - just close it and make necessary things
if (SerialWorker.ConnectionState == true)
{
SerialWorker.ClosePort();
btnOpenClose.Text = "Open";
// Exit
return;
}
// Try to open selected COM port
string port_name = SerialWorker.GetSerialName(cmbPortList.Text);
int result = SerialWorker.OpenSerialPort(port_name, UART_BAUD);
if (result == 1)
{
btnOpenClose.Text = "Close";
}
}
void UpdatePortList()
{
cmbPortList.Items.Clear();
List<String> portNames = SerialWorker.GetSerialPortInfo();
foreach (string s in portNames)
{
cmbPortList.Items.Add(s);
}
if (portNames.Count == 0)
{
MessageBox.Show("No serial ports in system!", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
else
{
cmbPortList.SelectedItem = cmbPortList.Items[0];//нашелся хотя бы один порт
}
}
//Parsing mavlink packet
void ParseDeviceState(MavLink.Msg_device_state msg)
{
Invoke((MethodInvoker)delegate ()
{
lblLaserVolt.Text = $"Laser Volt: {msg.las_voltage:0.0} V";
lblAPDVolt.Text = $"APD Volt: {msg.apd_voltage_curr:0.0} V";
lblCompVolt.Text = $"Comp Volt: {msg.voltage_mv} mv";
lblStateMask.Text = $"State Mask: 0x{msg.state:X}";
if (msg.state != 0)
lblStateMask.BackColor = System.Drawing.Color.Yellow;
else
lblStateMask.BackColor = this.BackColor;
if (msg.pwm_state != 0)
lblAPDVoltFB.Text = "APD Volt. FB: Auto";
else
lblAPDVoltFB.Text = "APD Volt. FB: Manual";
});
}
public void DeviceStateRequest()
{
MavLink.Msg_data_request mav_msg = new MavLink.Msg_data_request();
mav_msg.data_type = (byte)MavLink.DATA_REQUEST.DATA_REQUEST_DEVICE_STATE;
var mvp = new MavlinkPacket
{
ComponentId = 1,
SystemId = 2,//PC
Message = mav_msg
};
SendMavlinkPaket(mvp);
}
public void SetAPD_TargetVoltage(float voltage_v)
{
MavLink.Msg_set_apd_voltage mav_msg = new MavLink.Msg_set_apd_voltage();
mav_msg.pwm_value = -1;//do not change
mav_msg.voltage = voltage_v;
var mvp = new MavlinkPacket
{
ComponentId = 1,
SystemId = 2,//PC
Message = mav_msg
};
SendMavlinkPaket(mvp);
}
public void SetComparatorThreshold(int voltage_mv)
{
MavLink.Msg_set_comp_threshold mav_msg = new MavLink.Msg_set_comp_threshold();
mav_msg.voltage_mv = (ushort)voltage_mv;
var mvp = new MavlinkPacket
{
ComponentId = 1,
SystemId = 2,//PC
Message = mav_msg
};
SendMavlinkPaket(mvp);
}
public void SetMotorSpeed(float speed_rps)
{
MavLink.Msg_set_motor_speed mav_msg = new MavLink.Msg_set_motor_speed();
mav_msg.speed = speed_rps;
var mvp = new MavlinkPacket
{
ComponentId = 1,
SystemId = 2,//PC
Message = mav_msg
};
SendMavlinkPaket(mvp);
}
void SendMavlinkPaket(MavlinkPacket packet)
{
byte[] dataToSend = MavlinkObj.Send(packet);
SerialWorker.send_bin_data_to_serial(dataToSend);
}
// GUI *********************************************************
void OpenHistogramForm()
{
if (HistogramFormObj == null)
HistogramFormObj = new HistogramForm();
if (HistogramFormObj.IsDisposed)
HistogramFormObj = new HistogramForm();
HistogramFormObj.Show();
}
private void btnSaveCoeff_Click(object sender, EventArgs e)
{
string ang_corr_str = CurrAngularCorrection.ToString(System.Globalization.CultureInfo.InvariantCulture);
SettingsHolder.AddSetting("LIDAR_SETTINGS", "angular_corr", ang_corr_str);
string start_angle_str = CurrStartAngle.ToString(System.Globalization.CultureInfo.InvariantCulture);
SettingsHolder.AddSetting("LIDAR_SETTINGS", "start_angle", start_angle_str);
string stop_angle_str = CurrStopAngle.ToString(System.Globalization.CultureInfo.InvariantCulture);
SettingsHolder.AddSetting("LIDAR_SETTINGS", "stop_angle", stop_angle_str);
SettingsHolder.SaveSettings();
}
private void numericUpDown1_ValueChanged(object sender, EventArgs e)
{
DataAnalyseObj.SetLength((int)nudPointsNumber.Value);
}
private void cmbPortList_DropDown(object sender, EventArgs e)
{
UpdatePortList();
}
private void numStartAngle_ValueChanged(object sender, EventArgs e)
{
radarPlotComponent1.UpdateStartStopLines(CurrStartAngle, CurrStopAngle);
}
private void numStopAngle_ValueChanged(object sender, EventArgs e)
{
radarPlotComponent1.UpdateStartStopLines(CurrStartAngle, CurrStopAngle);
}
private void btnSetAPD_TargVoltage_Click(object sender, EventArgs e)
{
float ApdTargVoltage = (float)numAPD_TargVoltage.Value;
SetAPD_TargetVoltage(ApdTargVoltage);
}
private void btnSetComparatorVoltage_Click(object sender, EventArgs e)
{
ushort voltage_mv = (ushort)numComparatorVoltage.Value;
SetComparatorThreshold(voltage_mv);
}
private void btnOpenHistogram_Click(object sender, EventArgs e)
{
OpenHistogramForm();
}
private void btnSetMotorTargetSpeed_Click(object sender, EventArgs e)
{
float speed = (float)numMotorTargetSpeed.Value;
SetMotorSpeed(speed);
}
}
}
d042bc777This file is pinned to the selected release. Download the original to open it in your design tool.