AStar寻路算法

2023-05-16

概述

AStar算法是一种图形搜索算法,常用于寻路。他是以广度优先搜索为基础,集Dijkstra算法和最佳优先(best fit)于一身的一种算法。

示例1:4向
image

示例2:8向
image

思路

image
递归的通过估值函数找到最佳路径,估值函数与距离相关,也有可能与通过代价系数相关(例如平地系数为1,坡地系数为2),有三个参数:

  • G:起点点到当前点的代价
  • H: 当前点到终点的代价
  • F: F = G + H 与最佳路径权重负相关的参数
    过程大概:
    image

代码示例

位置定义

public struct Vec2
{
    public int x;
    public int y;

    public Vec2(int x, int y)
    {
        this.x = x;
        this.y = y;
    }

    public static Vec2 Zero
    {
        get
        {
            return new Vec2(0, 0);
        }
    }

    public override bool Equals(object obj)
    {
        if (!(obj is Vec2))
            return false;

        var o = (Vec2)obj;
        return x == o.x && y == o.y;
    }

    public override int GetHashCode()
    {
        return x.GetHashCode() + y.GetHashCode();
    }

    public static Vec2 operator +(Vec2 a, Vec2 b)
    {
        return new Vec2(a.x + b.x, a.y + b.y);
    }

    public static Vec2 operator *(Vec2 a, int n)
    {
        return new Vec2(a.x * n, a.y * n);
    }

    public static Vec2 operator *(int n, Vec2 a)
    {
        return new Vec2(a.x * n, a.y * n);
    }

    public static bool operator ==(Vec2 a, Vec2 b)
    {
        return a.x == b.x && a.y == b.y;
    }

    public static bool operator !=(Vec2 a, Vec2 b)
    {
        return !(a.x == b.x && a.y == b.y);
    }
}

方向定义

public enum EDir
{
    Up = 0,
    Down = 1,
    Left = 2,
    Right = 3,
    UpLeft = 4,
    UpRight = 5,
    DownLeft = 6,
    DownRight = 7,
}

public abstract class CheckDirPol
{
    abstract public Dictionary<EDir, Vec2> GetDir();
}

public class CheckDir4Pol : CheckDirPol
{
    private Dictionary<EDir, Vec2> dirDict = new Dictionary<EDir, Vec2>
    {
        {EDir.Up, new Vec2(0, 1) },
        {EDir.Down, new Vec2(0, -1) },
        {EDir.Left, new Vec2(-1, 0) },
        {EDir.Right, new Vec2(1, 0) },
    };
    override public Dictionary<EDir, Vec2> GetDir()
    {
        return dirDict;
    }
}

public class CheckDir8Pol : CheckDirPol
{
    private Dictionary<EDir, Vec2> dirDict = new Dictionary<EDir, Vec2>
    {
        {EDir.Up, new Vec2(0, 1) },
        {EDir.Down, new Vec2(0, -1) },
        {EDir.Left, new Vec2(-1, 0) },
        {EDir.Right, new Vec2(1, 0) },
        {EDir.UpLeft, new Vec2(-1, 1) },
        {EDir.UpRight, new Vec2(1, 1) },
        {EDir.DownLeft, new Vec2(-1, -1) },
        {EDir.DownRight, new Vec2(1, -1) },

    };
    override public Dictionary<EDir, Vec2> GetDir()
    {
        return dirDict;
    }
}
  • 运用策略模式的技巧,以实现4向,8向搜索切换

估值函数

public abstract class EvaPol
{
	abstract public float Calc(Vec2 a, Vec2 b);
}

public class MANEvaPol : EvaPol
{
    override public float Calc(Vec2 a, Vec2 b)
    {
        return Mathf.Abs(a.x - b.x) + Mathf.Abs(a.y - b.y);
    }
}
  • 直接使用曼哈顿距离作为代价

节点定义

public class Node
{
    public int id;
    public Vec2 pos;
    public float g;
    public float h;
    public float f;
    public Vec2 prePos;
    public bool hasPrePos;

    public Node(Vec2 pos)
    {
        this.pos = pos;
    }

    public void SetPrePos(Vec2 pos)
    {
        prePos = pos;
        hasPrePos = true;
    }
}

算法上下文定义

Context context;
EvaPol disPol;
CheckDirPol checkDirPol;

public struct Context
{
    public Vec2 end;
    public Vec2 start;
    public Node[,] nodes;
    public List<Node> open;
    public List<Node> close;
    public int[,] map;
    public List<Vec2> result;
    public Vec2 size;
}

寻路算法

初始化

public void Init(Vec2 start, Vec2 end, int[,] map)
{
	var x = map.GetLength(0);
	var y = map.GetLength(1);
	context = new Context()
	{
		start = start,
		end = end,
		open = new List<Node>(),
		close = new List<Node>(),
		map = map,
		result = new List<Vec2>(),
		size = new Vec2(x, y),
	};

	context.nodes = new Node[x, y];
	for (int i = 0; i < x; i++)
		for (int j = 0; j < x; j++)
			context.nodes[i, j] = new Node(new Vec2(i, j));

	disPol = new MANEvaPol();
	//checkDirPol = new CheckDir4Pol();
	checkDirPol = new CheckDir8Pol();
}

获取路径

public List<Vec2> GetResult()
{
	return context.result;
}

寻路

寻路入口

public void FindPath()
{
	var s = context.start;
	var sn = context.nodes[s.x, s.y];
	sn.g = 0;
	sn.h = disPol.Calc(s, context.end);
	sn.f = sn.g + sn.h;
	context.open.Add(sn);

	FindArrangement(sn);
}

递归函数

void FindArrangement(Node node)
{
	context.close.Add(node);
	context.open.Remove(node);

	if (node.pos == context.end)
	{
		SetResult(node);
		return;
	}

	CheckRound(node);
	if (context.open.Count == 0)
		return;

	Node next = context.open[0];
	for (int i = 1; i < context.open.Count; i++)
		if (context.open[i].f < next.f)
			next = context.open[i];

	FindArrangement(next);
}

检查周围节点

void CheckRound(Node node)
{
	var dirDict = checkDirPol.GetDir();
	foreach (var pair in dirDict)
	{
		var dir = node.pos + pair.Value;

		if (IsBlock(dir))
			continue;
		var dn = context.nodes[dir.x, dir.y];

		if (context.close.Contains(dn))
			continue;

		if (context.open.Contains(dn))
			TryOverridePath(node, dn);
		else
		{
			dn.g = disPol.Calc(dn.pos, context.start);
			dn.h = disPol.Calc(dn.pos, context.end);
			dn.f = dn.g + dn.h;
			dn.SetPrePos(node.pos);
			context.open.Add(dn);
		}
	}
}

// 若是从邻节点到该节点路径更优,则替换更新
void TryOverridePath(Node a, Node b)
{
	var g = a.g + disPol.Calc(a.pos, b.pos);
	if (g < b.g)
	{
		b.g = g;
		b.SetPrePos(a.pos);
	}
}

bool IsBlock(Vec2 pos)
{
	return !InMap(pos) || context.map[pos.x, pos.y] == 1;
}

bool InMap(Vec2 pos)
{
	var x = pos.x;
	var y = pos.y;
	var size = context.size;
	return x >= 0 && x < size.x && y >= 0 && y < size.y;
}

生成路径

void SetResult(Node node)
{
	Queue<Node> q = new Queue<Node>();
	while(node.hasPrePos)
	{
		q.Enqueue(node);
		node = context.nodes[node.prePos.x, node.prePos.y];
	}
	while(q.Count > 0)
	{
		context.result.Add(q.Dequeue().pos);
	}
}

完整代码

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public struct Vec2
{
    public int x;
    public int y;

    public Vec2(int x, int y)
    {
        this.x = x;
        this.y = y;
    }

    public static Vec2 Zero
    {
        get
        {
            return new Vec2(0, 0);
        }
    }

    public override bool Equals(object obj)
    {
        if (!(obj is Vec2))
            return false;

        var o = (Vec2)obj;
        return x == o.x && y == o.y;
    }

    public override int GetHashCode()
    {
        return x.GetHashCode() + y.GetHashCode();
    }

    public static Vec2 operator +(Vec2 a, Vec2 b)
    {
        return new Vec2(a.x + b.x, a.y + b.y);
    }

    public static Vec2 operator *(Vec2 a, int n)
    {
        return new Vec2(a.x * n, a.y * n);
    }

    public static Vec2 operator *(int n, Vec2 a)
    {
        return new Vec2(a.x * n, a.y * n);
    }

    public static bool operator ==(Vec2 a, Vec2 b)
    {
        return a.x == b.x && a.y == b.y;
    }

    public static bool operator !=(Vec2 a, Vec2 b)
    {
        return !(a.x == b.x && a.y == b.y);
    }
}

public enum EDir
{
    Up = 0,
    Down = 1,
    Left = 2,
    Right = 3,
    UpLeft = 4,
    UpRight = 5,
    DownLeft = 6,
    DownRight = 7,
}

public class AstarFindPath
{
    public class Node
    {
        public int id;
        public Vec2 pos;
        public float g;
        public float h;
        public float f;
        public Vec2 prePos;
        public bool hasPrePos;

        public Node(Vec2 pos)
        {
            this.pos = pos;
        }

        public void SetPrePos(Vec2 pos)
        {
            prePos = pos;
            hasPrePos = true;
        }
    }

    public abstract class EvaPol
    {
        abstract public float Calc(Vec2 a, Vec2 b);
    }

    public class MANEvaPol : EvaPol
    {
        override public float Calc(Vec2 a, Vec2 b)
        {
            return Mathf.Abs(a.x - b.x) + Mathf.Abs(a.y - b.y);
        }
    }

    public abstract class CheckDirPol
    {
        abstract public Dictionary<EDir, Vec2> GetDir();
    }

    public class CheckDir4Pol : CheckDirPol
    {
        private Dictionary<EDir, Vec2> dirDict = new Dictionary<EDir, Vec2>
        {
            {EDir.Up, new Vec2(0, 1) },
            {EDir.Down, new Vec2(0, -1) },
            {EDir.Left, new Vec2(-1, 0) },
            {EDir.Right, new Vec2(1, 0) },
        };
        override public Dictionary<EDir, Vec2> GetDir()
        {
            return dirDict;
        }
    }

    public class CheckDir8Pol : CheckDirPol
    {
        private Dictionary<EDir, Vec2> dirDict = new Dictionary<EDir, Vec2>
        {
            {EDir.Up, new Vec2(0, 1) },
            {EDir.Down, new Vec2(0, -1) },
            {EDir.Left, new Vec2(-1, 0) },
            {EDir.Right, new Vec2(1, 0) },
            {EDir.UpLeft, new Vec2(-1, 1) },
            {EDir.UpRight, new Vec2(1, 1) },
            {EDir.DownLeft, new Vec2(-1, -1) },
            {EDir.DownRight, new Vec2(1, -1) },

        };
        override public Dictionary<EDir, Vec2> GetDir()
        {
            return dirDict;
        }
    }

    public struct Context
    {
        public Vec2 end;
        public Vec2 start;
        public Node[,] nodes;
        public List<Node> open;
        public List<Node> close;
        public int[,] map;
        public List<Vec2> result;
        public Vec2 size;
    }

    Context context;
    EvaPol disPol;
    CheckDirPol checkDirPol;

    public void Init(Vec2 start, Vec2 end, int[,] map)
    {
        var x = map.GetLength(0);
        var y = map.GetLength(1);
        context = new Context()
        {
            start = start,
            end = end,
            open = new List<Node>(),
            close = new List<Node>(),
            map = map,
            result = new List<Vec2>(),
            size = new Vec2(x, y),
        };
        
        context.nodes = new Node[x, y];
        for (int i = 0; i < x; i++)
            for (int j = 0; j < x; j++)
                context.nodes[i, j] = new Node(new Vec2(i, j));

        disPol = new MANEvaPol();
        //checkDirPol = new CheckDir4Pol();
        checkDirPol = new CheckDir8Pol();
    }

    public void FindPath()
    {
        var s = context.start;
        var sn = context.nodes[s.x, s.y];
        sn.g = 0;
        sn.h = disPol.Calc(s, context.end);
        sn.f = sn.g + sn.h;
        context.open.Add(sn);
        
        FindArrangement(sn);
    }

    public List<Vec2> GetResult()
    {
        return context.result;
    }

    void FindArrangement(Node node)
    {
        context.close.Add(node);
        context.open.Remove(node);

        if (node.pos == context.end)
        {
            SetResult(node);
            return;
        }

        CheckRound(node);
        if (context.open.Count == 0)
            return;

        Node next = context.open[0];
        for (int i = 1; i < context.open.Count; i++)
            if (context.open[i].f < next.f)
                next = context.open[i];
        
        FindArrangement(next);
    }

    void SetResult(Node node)
    {
        Queue<Node> q = new Queue<Node>();
        while(node.hasPrePos)
        {
            q.Enqueue(node);
            node = context.nodes[node.prePos.x, node.prePos.y];
        }
        while(q.Count > 0)
        {
            context.result.Add(q.Dequeue().pos);
        }
    }

    void CheckRound(Node node)
    {
        var dirDict = checkDirPol.GetDir();
        foreach (var pair in dirDict)
        {
            var dir = node.pos + pair.Value;

            if (IsBlock(dir))
                continue;
            var dn = context.nodes[dir.x, dir.y];

            if (context.close.Contains(dn))
                continue;

            if (context.open.Contains(dn))
                TryOverridePath(node, dn);
            else
            {
                dn.g = disPol.Calc(dn.pos, context.start);
                dn.h = disPol.Calc(dn.pos, context.end);
                dn.f = dn.g + dn.h;
                dn.SetPrePos(node.pos);
                context.open.Add(dn);
            }
        }
    }

    void TryOverridePath(Node a, Node b)
    {
        var g = a.g + disPol.Calc(a.pos, b.pos);
        if (g < b.g)
        {
            b.g = g;
            b.SetPrePos(a.pos);
        }
    }

    bool IsBlock(Vec2 pos)
    {
        return !InMap(pos) || context.map[pos.x, pos.y] == 1;
    }

    bool InMap(Vec2 pos)
    {
        var x = pos.x;
        var y = pos.y;
        var size = context.size;
        return x >= 0 && x < size.x && y >= 0 && y < size.y;
    }
}

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

AStar寻路算法 的相关文章

  • 【记录】python搭建openpose环境遇到的坑(不能再多了。。)

    记录 python搭建openpose环境遇到的坑 xff08 不能再多了 xff09 背景 xff1a 重装的系统 xff0c anaconda3 1 坑1 xff1a 在anaconda下创建一个新的环境时遇见如下问题 xff1a Co
  • http请求报文与响应报文

    https blog csdn net weixin 45912307 article details 109454522 1 http get请求报文 请求行 GET HTTP 1 1 61 gt 请求方法 方式 请求的资源路径 http
  • 函数执行时堆栈的详细过程

    文章目录 1 函数示例2 main函数中局部变量入栈过程3 main函数调用sum函数参数压栈4 调用sum函数的准备5 调用sum函数6 sum函数执行结束7 处理sum函数的结果返回 1 函数示例 2 main函数中局部变量入栈过程 3
  • java get方式请求url

    public String sendGet String result 61 34 34 BufferedReader in 61 null 读取响应输入流 try 创建URL对象 java net URL connURL 61 new j
  • 做自动化项目的时候自由协议通信怎么做

    工业现场 xff0c 一些扫码枪 称重传感器的通信协议 xff0c 有可能是厂家自己规定的 比如下面我给大家看一段RFID设备的通信协议 xff0c 如果你不能理解它是在干什么 xff0c 那就要好好学习plc的自由协议通信 这边举一个典型
  • vue3 element-plus el-progress 圆形circle进度条 内置文字换行

    span class token operator lt span div span class token operator gt span span class token operator lt span el span class
  • 一文彻底搞懂激光雷达原理!

    点击下方卡片 xff0c 关注 自动驾驶之心 公众号 ADAS巨卷干货 xff0c 即可获取 最近一直在搞激光雷达相关东西 xff0c 今天把了解的激光雷达知识做一个框架整理 xff0c 顺便梳理了一下行业里面激光雷达相关公司 xff0c
  • 基于深度学习网络 在可穿戴式机器人中使用IMU实现人体活动实时识别

    可穿戴式外骨骼机器人已成为支持人类运动的一种新兴高科技产品 xff0c 能够在人体康复训练 日常活动和制造任务中提供必要的运动支持 xff0c 而搭建高精度 低延迟的人体活动识别系统 xff0c 能够帮助可穿戴式机器人快速准确地识别人体活动
  • DAY19-20 PX4入坑成功

    这几天在研究科学上网 xff0c 我就不写出来了 总之 xff0c 我把PX4拉到了自己的电脑上 在入门的过程中 xff0c 我根据自己以前的学习习惯 xff0c 开始大面积地搜集教程视频 xff0c 可惜并没有 xff01 这下我瞬间没招
  • 记一次C++ std::cout未定义及大量报错处理

    原因是什么并不清楚 但无论怎么处理 xff0c cout lt lt xxxxx 都会报 cout 未定义 xff0c 并且强行编译会一直报错 我最终处理方法是把MinGW给卸载 xff0c 然后重新下载安装 结果是此方法完全可行
  • ubuntu16.04 针对rosdep init初始化报错的解决方案(一针见血版)

    Ubuntu16 04 ros安装以及出现的问题 一 更换国内源 二 添加ROS源 三 添加密钥 四 安装ROS 五 初始化ROS 一 更换国内源 先复制一份源文件 再更换源地址 sudo cp etc apt sources list e
  • Linux使用gcc编译报错对pthread_create未定义的引用

    在包含pthread h头文件后 还是报错未定义的引用 span class token operator span tmp span class token operator span cc6zqi5F span class token
  • 狂神说java java基础篇 学习笔记

    java基础的视频内容笔记都在这了前言等字数非常长的章节 xff0c 使用了AI语音识别成文字后修改的 xff0c 有错漏欢迎提出面对对象模块的按照自己的理解进行了内容修改 xff0c 可以对比原视频内容理解 xff0c 如有建议欢迎提出
  • 解决Ubuntu没有wifi图标的问题

    在配置过程中输入命令后就没有wifi图标了 xff0c 不能上网了 xff08 可能是删除了网卡驱动 xff09 后续使用命令查询网卡 hardware of Internet 状态 lshw C network 查看网卡状态发现 无线网被
  • 2022-11-15日Linux安装csitools问题及解决办法

    问题一 xff1a 执行完这三步后电脑没有wifi图标了 xff0c 不能联网了 sudo modprobe r iwldvm iwlwifi mac80211 sudo modprobe r iwlwifi mac80211 cfg802
  • win10扩展c盘容量(2022-11-17)亲测可用

    个人经验 xff1a 想要通过右键我的电脑 管理 磁盘管理 xff0c 将紧挨着C盘的E盘压缩一100G扩展给C盘 这种做法试了不行 xff0c 即使让可用空间挨着C盘 xff0c C盘的扩展卷选项也是灰色的 解决 xff1a 下载傲梅分区
  • S-V信道模型理解

    Saleh和Valenzuela提出的S V信道模型是基于大量室内信道测试构建的 xff0c 更加符合室内真实路径的传播规律 xff0c 可以用来进行信道建模与仿真 下图显示了具有多簇射线的S V信道模型 xff0c 该模型中多径以簇形式达
  • wifi收发数据包分析

    根据802 11n协议WIFI每次发送64字节数据 Intel5300网卡接收的数据包大小为213字节或者393字节或者573字节 说明接受的数据包包含多个发送的包 猜想每个数据包是由多个主体重复加上固定的标志位组成 x 61 1 2 3
  • 清华大学 | 摄像头-激光雷达的时空在线集成标定方法

    点击下方卡片 xff0c 关注 自动驾驶之心 公众号 ADAS巨卷干货 xff0c 即可获取 后台回复 多模态综述 获取论文 xff01 后台回复 ECCV2022 获取ECCV2022所有自动驾驶方向论文 xff01 后台回复 领域综述
  • 操作系统-硬件结构(小林coding笔记)

    控制和管理整个计算机系统的硬件和软件资源 xff1b 提供给用户和其他软件方便的接口和环境 xff1b 主要包括进程管理 内存管理 文件系统 设备管理和网络系统 图灵机的工作方式 基本思想就是用机器模拟人类用纸笔进行数学运算的过程 主要包含

随机推荐

  • 操作系统-三、操作系统结构(小林coding笔记)

    3 1Linux内核和Windows内核 Windows和Linux是常见的两款操作系统 xff0c 操作系统最核心的东西就是内核 内核 内核作为应用连接硬件设备的桥梁 内核的四个基本功能 xff1a 进程调度 内存管理 硬件通信 系统调用
  • 操作系统-四、内存管理(小林coding笔记)

    虚拟内存 防止内存运行多个程序时崩溃 把进程所使用的地址隔离开 xff0c 让操作系统为每个进程分配一套独立的虚拟地址 操作系统会提供一种机制 xff0c 将不同进程的虚拟地址和不同内存的物理地址映射起来 内存分段 程序时由若干逻辑分段组成
  • libcurl库

    目录 1 libcurl简介2 libcurl的使用3 libcurl的安装Libcurl库等第三方库的通用编译方法 3 调用libcurl访问百度主页4 libcurl 相关API解读1 curl global init 2 curl g
  • ERROR: cannot launch node of type: rplidar_ros

    1首先使用rospack find 命令查找该功能包 xff0c 如果输出功能包路径则该功能包存在 xff0c 如果提示没有则说明我们需要下载一个rplidar ros rospack find rplidar ros 2使用sudo ap
  • 【jetson nano】jetson nano环境配置+yolov5部署+tensorRT加速模型

    目录 jetson nano环境配置 43 yolov5部署 43 tensorRT加速模型致谢主机和jetson nano环境jetson系统开机烧录 系统设置 换源python环境配置conda环境yolov5环境matplotlib和
  • MDK仿真出现NOT IN SCOPE(不在范围内)

    这两天刚拿到一套GD32F1系列的开发板 xff0c 想着测试一下 xff0c 看和STM32的有啥不同 xff0c 自己仿真时候 xff0c 想要在窗口观察一下数值 xff0c 结果总是提示NOT IN SCOPE没办法 xff0c 就查
  • Keil调试局部变量显示“not in scope“的问题解决

    Keil调试局部变量显示 34 not in scope 34 的问题解决 参考文章 xff1a xff08 1 xff09 Keil调试局部变量显示 34 not in scope 34 的问题解决 xff08 2 xff09 https
  • MPU6050可以读取ID值,温度值和原始数据值为零问题解决

    MPU6050可以读取ID值 xff0c 温度值和原始数据值为零问题解决 参考文章 xff1a xff08 1 xff09 MPU6050可以读取ID值 xff0c 温度值和原始数据值为零问题解决 xff08 2 xff09 https w
  • 英伟达Jetson Xavier NX部署YOLO5

    1 查看JetPack版本 新到手的NX首先需要确定一下JetPack的版本 xff1a sudo apt span class token operator span cache show nvidia span class token
  • 史上最全 | BEV感知算法综述(基于图像/Lidar/多模态数据的3D检测与分割任务)...

    点击下方卡片 xff0c 关注 自动驾驶之心 公众号 ADAS巨卷干货 xff0c 即可获取 点击进入 自动驾驶之心技术交流群 后台回复 BEV综述 获取论文 xff01 后台回复 ECCV2022 获取ECCV2022所有自动驾驶方向论文
  • matlab-字符串的处理操作

    建立一个字符串向量 xff0c 然后对该向量做如下处理 xff1a 取第1 5个字符组成的子字符串 将字符串倒过来重新排列 将字符串中的小写字母变成相应的大写字母 xff0c 其余字符不变 统计字符串中小写字母的个数 代码 ch 61 39
  • curl发送带有Authorization的POST请求

    一 参数说明 格式 xff1a curl H 请求头 d 请求体 X POST 接口地址 参数内容格式 H header 请求头 Content Type application json d请求内容 remote host 10 163
  • AStar寻路算法 (C#)

    一 介绍 A星算法其实并不是最短路径算法 xff0c 它找到的路径并不是最短的 xff0c 它的目标首先是能以最快的速度找到通往目的地的路 B星实际上是A星的优化 但是B星的缺点是不能向后查找 所以会有问题 还有一种D星的可以用来找最短路径
  • 深度相机介绍(TOF、RGB双目、结构光参数对比)

    一 深度相机的介绍 随着计算机视觉与人工智能技术的飞速发展 xff0c 采用深度相机进行场景三维重建 目标检测 环境感知等应用越来越广泛 xff0c 与传统的2D相机不同 xff0c 深度相机可以通过拍摄空间来获得景深信息 xff0c 从而
  • 网络编程——UDP

    目录 UDP的服务器端 UDP的echo客户端代码 UDP的echo服务器端代码 UDP的服务器端 先运行服务器端 xff0c 再运行客户端 服务端 xff1a 开发者 xff1a Virtuous 开发版本 xff1a 1 0 开发时间
  • HTTP 完全解析

    Http 详解 HTTP 的定义 HTTP即是 xff1a Hypertext Transfer Protocol xff0c 超文本传输协议 xff0c 种 络传输协议 xff0c 位于 TCP IP 协议族的最顶层 应 层 URL 说到
  • STM32 自定义串口协议

    STM32 自定义串口协议 1 串行通信1 1 原理与优缺点1 2 分类1 2 1 按通信方向1 2 2 按通信方式 1 3 异步串行引脚连接1 3 1 串口外设之间1 3 2 ARM与PC之间 1 4 字符帧格式1 5 串口通信过程1 6
  • 无人机——电机篇(一)

    文章目录 1 电机的定义 2 电机的分类 3 电机的参数 4 电机效率 5 电机的选择 1 电机的定义 电机俗称 马达 是无人机的动力来源 无人机通过改变电机的转速来改变无人机的飞行状态 即改变每个电机的速度 使得无人机能够盘旋空中 上升或
  • HTTP请求/响应报文结构

    HTTP请求报文 一个HTTP请求报文由四个部分组成 xff1a 请求行 请求头部 空行 请求数据 1 请求行 请求行由 请求方法字段 URL字段 和 HTTP协议版本字段 3个字段组成 xff0c 它们用空格分隔 比如 GET data
  • AStar寻路算法

    概述 AStar算法是一种图形搜索算法 xff0c 常用于寻路 他是以广度优先搜索为基础 xff0c 集Dijkstra算法和最佳优先 best fit 于一身的一种算法 示例1 4向 示例2 8向 思路 递归的通过估值函数找到最佳路径 x