Unity C#调用RPLidar的C++动态库(.dll)文件(3)

本文详细指导如何在Unity中通过C#调用RPLidar的C++动态库,包括dll配置、C#脚本编写和实际场景演示,教你轻松实现雷达数据处理。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

 

前言

Unity C#调用RPLidar的C++动态库(.dll)文件(1)

Unity C#调用RPLidar的C++动态库(.dll)文件(2)

看完了前两章博文,相信大家已经知晓了雷达的工作流程和Dll生成过程

接下来,如何在Unity中使用动态库


新建Unity工程

都知道怎么玩了就不过多叙述了

略………………


Plugins目录

  1. Assert里面新建Plugins目录, 新建x86/x86_64文件夹
  2. 把RPLidarDLL.dll放入x86_64文件夹中

创建C#调用动态库脚本

新建脚本,命名为LidarData.cs, 这里对应C++动态库里面的LidarData结构体

[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]
public struct LidarData
{
    public float theta;
    public float distant;
    public int quality;
};

新建脚本,命名为RplidarBinding.cs

public static class RplidarBinding
{
    [DllImport("RPLidarDLL")]
    public static extern int OnConnect(string opt_com_path, int opt_com_baudrate);
    [DllImport("RPLidarDLL")]
    public static extern bool OnDisconnect();

    [DllImport("RPLidarDLL")]
    public static extern bool StartMotor();
    [DllImport("RPLidarDLL")]
    public static extern bool EndMotor();

    [DllImport("RPLidarDLL")]
    public static extern bool StartScan();

    [DllImport("RPLidarDLL")]
    public static extern bool StartScanExpress(bool forcescan, int usingScanMode_);

    [DllImport("RPLidarDLL")]
    public static extern bool EndScan();

    [DllImport("RPLidarDLL")]
    public static extern bool ReleaseDrive();

    [DllImport("RPLidarDLL")]
    public static extern int GetLidarDataSize();

    [DllImport("RPLidarDLL")]
    private static extern int GrabData(IntPtr ptr);

    public static int GetData(ref LidarData[] data)
    {
        GCHandle handler = GCHandle.Alloc(data, GCHandleType.Pinned);
        IntPtr structPtr = handler.AddrOfPinnedObject();
        int count = GrabData(structPtr);
        handler.Free();
        return count;
    }
}

这里的函数和dll里面的外部调用函数统一命名

这里的知识点包含IntPtr、ref关键字、extern关键字、GCHandle、DllImport

自行百度理解,这里不过多叙说

DllImport后面跟的是动态库的名字不用加入.dll,切记!!!


创建Unity场景&C#测试脚本

场景结构如下所示:

C#测试脚本

[RequireComponent(typeof(MeshFilter))]
public class RplidarMap : MonoBehaviour
{
    private static readonly int s_MaxLength = 8192;

    public string m_COM = "COM3";
    public int m_Baudrate = 256000;
    public MeshFilter m_MeshFilter;

    private bool m_OnScan = false;
    private LidarData[] m_Data;
    private Mesh m_Mesh;
    private List<Vector3> m_Vert = new List<Vector3>();
    private List<int> m_Index = new List<int>();
    private Thread m_ThreadReceive;
    private bool m_DataChanged = false;
    private int m_DataCount = 0;

    private void Start()
    {
        m_Data = new LidarData[s_MaxLength];
        for (int i = 0; i < 720; i++)
        {
            m_Index.Add(i);
        }
        m_Mesh = new Mesh();
        m_Mesh.MarkDynamic();

        RplidarBinding.OnConnect(m_COM, m_Baudrate);
        RplidarBinding.StartMotor();
        m_OnScan = RplidarBinding.StartScan();
        if (m_OnScan)
        {
            m_ThreadReceive = new Thread(RPLidarAX)
            {
                IsBackground = true
            };
            m_ThreadReceive.Start();
        }
    }

    private void OnDestroy()
    {
        if (m_ThreadReceive != null)
        {
            //关闭线程
            m_ThreadReceive.Abort();
            m_ThreadReceive = null;
            Debug.Log("Close thread");
        }

        RplidarBinding.EndScan();
        RplidarBinding.EndMotor();
        RplidarBinding.OnDisconnect();
        RplidarBinding.ReleaseDrive();

        m_OnScan = false;
    }

    private void Update()
    {
        if (m_DataChanged)
        {
            m_Vert.Clear();

            for (int i = 0; i < m_DataCount; i++)
            {
                m_Vert.Add(Quaternion.Euler(0, 0, m_Data[i].theta) * Vector3.right * m_Data[i].distant * 0.001f);

            }
            m_Mesh.SetVertices(m_Vert);
            m_Mesh.SetIndices(m_Index.ToArray(), MeshTopology.Points, 0);

            m_Mesh.UploadMeshData(false);
            m_MeshFilter.mesh = m_Mesh;

            m_DataChanged = false;
        }
    }

    private void RPLidarAX()
    {
        while (true)
        {
            m_DataCount = RplidarBinding.GetData(ref m_Data);
            if (m_DataCount == 0)
            {
                Thread.Sleep(20);
            }
            else
            {
                m_DataChanged = true;
            }
        }
    }

}

效果如下

执行演示
//我这边提供一个如何把云点信息转为平面坐标   
public Vector2 GetPosition(double angle, float distance, float xScale = 1, float yScale = 1)
{
        double rad = (angle * Math.PI / 180f);
        float endptX = Convert.ToSingle(Math.Sin(rad) * distance * xScale);
        float endptY = Convert.ToSingle(Math.Cos(rad) * distance * yScale);
        m_Vector2.Set(-endptY, endptX);
        return m_Vector2;
}

伸手党请直接下载    资源下载

这里说明一下:

RplidarBinding.StartScan(); 这里使用的是普通扫描模式

如果要使用frame_grabber里面的所有模式

使用RplidarBinding.StartScanExpress(false,RPLidarScanMode);

扫描模式定义为:

    public enum RPLidarScanMode
    {
        Standard = 0,   
        Express = 1,    
        Boost = 2,       
        Sensitivity = 3,
        Stability = 4,  
    }

这样就不用瞎折腾解析SDK内部云点算法的实现了

开森~~~~

 

评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Jerrt-J

希望我创作能给你带来有用的帮助

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值