如何不使用ROS实现SLAM建图和自主导航
SLAM 技术是什么?
SLAM是Simultaneous Localization and Mapping的缩写,即同时定位与地图构建。
它是一种用于自主导航和机器人感知的技术,旨在通过在未知环境中同时进行自主定位和构建环境地图,实现机器人的导航与路径规划。
它涉及到很多复杂的算法和方法,包括特征提取与匹配、传感器融合、滤波器(如扩展卡尔曼滤波器和粒子滤波器)和优化算法等。
SLAM技术主要应用于无人驾驶汽车、无人机、机器人和增强现实等领域。在实时定位和地图构建的过程中,SLAM系统会使用各种传感器(如摄像头、激光雷达、惯性测量单元等)获取环境信息,并利用这些信息进行自主定位和地图构建。
自主定位是指机器人在未知环境中确定自身位置的过程,通过对传感器数据进行处理和分析,结合地图信息,估计机器人相对于环境的位置和姿态。
地图构建则是将机器人在移动过程中获取的传感器数据融合起来,生成环境的地图表示,包括地标、障碍物和空间结构等信息。
SLAM 技术可以分为哪几类?
(1)基于传感器类型分类
✔视觉SLAM:主要使用相机或摄像头获取图像信息进行定位和地图构建。
✔激光SLAM:使用激光雷达来感知环境并生成地图,激光测距可以提供精确的距离信息。
(2)基于地图的分类
✔基于拓扑图的SLAM:将环境表示为节点和边的拓扑结构,用于描述不同位置之间的关系。
✔基于网格地图的SLAM:使用二维或三维网格表示环境,将地图分割为离散的网格单元,每个单元表示不同的属性或占据状态。
✔基于稠密地图的SLAM:生成具有高密度信息的地图,通常使用点云或三维模型表示环境。
(3)基于算法的分类
✔滤波器方法:使用滤波器(如扩展卡尔曼滤波器或粒子滤波器)进行状态估计和数据融合。
✔优化方法:通过最小化误差函数或优化目标函数,使用图优化算法(如非线性最小二乘法)进行定位和地图优化。
✔学习方法:利用机器学习或深度学习技术,通过训练数据进行定位和地图构建。
激光SLAM,有哪些应用场景?
(1)自主导航和移动机器人:激光SLAM可用于移动机器人的自主导航和路径规划。
(2)无人驾驶和自动驾驶汽车:激光SLAM是无人驾驶和自动驾驶汽车中关键的感知技术之一。激光雷达能够提供车辆周围环境的精确地图和距离信息,用于定位车辆和障碍物检测。通过将激光SLAM与其他传感器(如相机、雷达和GPS)进行融合,实现全面的环境感知和高级驾驶决策。
(3)建筑和室内地图构建:激光雷达可以快速而准确地扫描建筑物的结构,捕捉墙壁、家具和其他物体的几何信息。
(4)无人机和航空领域:激光雷达可以提供无人机周围环境的高精度地图和距离信息,支持无人机的自主飞行、目标检测和障碍物避让。
(5)工业自动化和机器视觉:例如,用于机器人在工厂环境中的定位、零件装配和物体识别。激光雷达提供的精确距离信息可以用于精确的位置控制和目标检测。
学习激光SLAM技术需要具备的基础知识
大学本科阶段的基础数学知识,如微积分、线性代数、概率论。
大学研究生阶段的数学知识:最优化、矩阵论,一小部分李群与李代数知识。
计算机科学知识:单片机开发、嵌入式、Linux系统操作、C++语言。
EasymqOS 机器人分布式开发框架
easy_mqOS 是笔者仿照ROS 搭建的基于MQTT的简易机器人分布式开发框架,是一种轻量级并且十分容易上手的框架,支持多个节点的主题的订阅和单topic发布,节点之间独立、解耦合。没有复杂的文件配置,一定的make编程基础,像正常启动服务一样,就可以运行。甚至可以在嵌入式linux上使用,而不用安装Ubuntu没有复杂的插件,很容易上手和学习。支持c.c++ ,python,js.MQTT协议特点
使用发布/订阅消息模式,提供一对多的消息分发,解除应用程序耦合。
消息传输对有效载荷内容不可知。
使用TCP/IP提供基础网络连接。
有3个消息发布服务质量级别。
轻量传输,协议交换最小化,以降低网络网络流量。
提供一种机制,当客户端异常中断时,利用 Last Will 和 Testament 特性来通知有关各方。
对于不需要搭建太复杂的机器人,笔者认位easy_mqos就可以满足自主建图和避障导航的功能.
easyMqos诞生的目的
首先它是一个机器人的教育套件。
解决繁杂的上外网更新问题。
解决非Ubuntu不能用的问题。
避免繁杂配置出错问题。
避免非ROS无机器人的境地。
通过下面案例的应用,已经证明该框架用于机器人学习是没有问题的。
easyMqos优缺点
优点
SLAM建图和导航避障在不依赖ROS的情况下可以实现。
不需要复杂的配置;
不需要复杂的编译链;
不需要远程配置master;
没有复杂的TF坐标转换概念;
可以将精力放到深入研究算法中。
可以自己修改算法。
可以转成ros 节点;
可适用于Linux系统例如raspbian\ubuntu\centos\armbian\嵌入式Linux。单片机?
缺点
仅适合学习机器人相关的知识,不能复杂的深入学习3D坐标系统。
不支持机械臂;
没有rqt 数据流等。
编码示例
C++
int main (int argc, char * argv)
{
//创建实例
easymqos e_demo = new easymqos(CLIENT_PUB);
//发布话题的设置
e_demo->Init_Pub("/sensors/filter");
//设置代理服务器
e_demo->Set_broker("192.168.56.101");
e_demo->Set_config_Pub();
//可订阅多个主题
vector
topicStr_subscribe.push_back("/sensors/demo");//支持多个话题的订阅
topicStr_subscribe.push_back("/sensors/test");
e_demo->Init_Sub(topicStr_subscribe);
//可创建和启动多个线程
pthread_attr_t attr;
pthread_t pthread_id = 0 ;
struct sched_param param;
/*create task mqtt com queue */
pthread_attr_init (&attr);
pthread_attr_setschedpolicy (&attr, SCHED_RR);
param.sched_priority = 5;
pthread_attr_setschedparam (&attr, ¶m);
pthread_create (&pthread_id, &attr, &Mqtt_PublishTask, NULL);//可以启动线程做更多事情
pthread_attr_destroy (&attr);
/*create task mqtt client queue */
//启动订阅话题和回调函数
e_demo->Start_Sub(call_back);//启动订阅和回调处理函数
}
python示例
import adafruit_bno08x
from adafruit_bno08x_rvc import BNO08x_RVC
import serial
import time
import numpy as np
import argparse
import os
import math
import time
import sys
import datetime
from paho.mqtt import client as mqtt_client
import random
import threading
import json
添加串口
uart = serial.Serial("/dev/ttyS5", 115200)
MQTT相关
broker = '127.0.0.1'
port = 1883
添加订阅的主题
topic1 = "/sensors/topic1"
添加发布的主题
cmd_topic = "/cmd/vel"
client_id = 'python-mqtt-{}'.format(random.randint(0, 1000))
定义mqtt的client
client = mqtt_client.Client(client_id)
def getcmd(roll,pitch,yaw,ax,ay,az):
data = {"roll":"%2.2f"%(roll),"pitch":"%2.2f"%(pitch),"yaw":"%2.2f"%(yaw),"ax":"%f" %(ax),"ay":"%f" %(ay),"az":"%f" %(az)
}
return data
如果有需要可创建启动线程
def thread1():
time.sleep(0.1)
while True:
add your code here
cmd =getcmd(roll,pitch,yaw,x_accel,y_accel,z_accel)
json_data = json.dumps(cmd)
#发送数据到topic
result = client.publish(topic,json_data,0)
# result: [0, 1]
status = result[0]
if status == 0:
print(f"Send to topic `{topic}`")
else:
print(f"Failed to send message to topic {topic}")
th1 = threading.Thread(target = thread1)
th1.setDaemon(True)
th1.start()
def on_connect(client, userdata, flags, rc):
print("Connected with result code "+str(rc))
用于处理接收的多个主题
def on_message(client, userdata, msg):
global _switch
print(msg.topic+" "+msg.payload.decode("utf-8"))
_switch = ord(msg.payload.decode("utf-8"))-48
#add your code here
#any thing
print("%d"%_switch)
根据需要设计可有可无
def publish(client):
global last_time
global detect_ok
global resultImg
msg_count = 0
while True:
#add your code here
time.sleep(0.001)
if name == 'main':
print(" connected!")
client.on_connect = on_connect
client.on_message = on_message
client.connect(broker, port, 60)
#publish(client)
# 订阅主题
client.subscribe(topic1)
client.subscribe(topic2)
client.subscribe(topicn)
client.loop_forever()
js编码
var hostname = '192.168.1.2', //'',
devid =111111,
port = 8083,
clientId = 'client-mao2180',
timeout = 5,
keepAlive = 50,
cleanSession = false,
ssl = false,
topic1 = '/state/gps';
var urlPath = window.document.location.href;
var docPath = window.document.location.pathname; //文件在服务器相对地址 /ISV/demo.aspx
var index = urlPath.indexOf(docPath);
var serverPath = urlPath.substring(0, index);
var serverip = serverPath.substring(7);
console.log(serverip);
//启动链接
MQTTconnect();
function MQTTconnect(){
topic = '/s/vel';
console.log(topic);
client = new Paho.MQTT.Client(serverip, Number(port), clientId);
client.onConnectionLost = onConnectionLost;//注册连接断开处理事件
client.onMessageArrived = onMessageArrived;//注册消息接收处理事件
client.connect({onSuccess:onConnect});//连接服务器并注册连接成功处理事件
};
function onConnect() {
// Once a connection has been made, make a subscription and send a message.
console.log("onConnect:"+topic);
//订阅的主题列表
client.subscribe(topic1);
client.subscribe(topic2);
client.subscribe(topicn);
};
function onConnectionLost(responseObject) {
if (responseObject.errorCode !== 0)
console.log("onConnectionLost:"+responseObject.errorMessage);
console.log("连接已断开");
};
function onMessageArrived(message) {
//console.log("收到消息:"+message.payloadString);
//console.log("主题:"+message.destinationName);
//console.log("长度:"+strlen(message.payloadString));
//add your code here
};
//发送信息到指定主题
function send_x_y(velocity,angle){
console.log("into send message");
//add your code here
// s = "{time:"+new Date().Format("yyyy-MM-dd hh:mm:ss")+", content:"+(s)+", from: web console}";
message = new Paho.MQTT.Message("test in robot");
message.destinationName = sendtopic;
client.send(message);
}
启动程序
/easymqOs_navigation$ ./navigation
/easymqos_basecomm$ ./basecomm_node
/easymqos_imu$ python3 read_bno.py
适合的人群:
想入门学习机器人规划和导航的同学。
快速入门SLAM建图的同学。
学习自主导航的同学。
学习局部规划的同学。
学习避障算法的同学。
想快速测试效果的同学。
关注神经网络和机器人应用的同学。
机器人爱好者。
GITHUB目前开放的节点:
SLAM 建图效果
EasyMQOS简易机器人开发框架教程
www.zhihu.com/column/c_1609592563807002624
实战案例 1
室内SLAM建图与导航机器人
实验环境:室内。
建图条件:需要事先SLAM建图。
避障传感器:A1激光雷达。
测速:霍尔编码器。
驱动方式:双轮差速驱动。
IMU:9轴
主控:OPI2\旭日X3
驱动板:stm32
建图精度:+-5cm
定位精度;+-10cm 以内
框架:easymqos
github:https://github.com/horo2016/easyMQOS
避障局部规划:魔改DWA+自定义
全局规划:a* 效果差 ,需要继续优化,但不影响使用了
页面交互
页面交互设计使用HTML+JS实现通信、控制。画布用的canvas直接将接收到的地图数据画出来,同时还支持
轨迹;
雷达帧;
规划的路径;
机器人显示;
充电站显示;
A点显示;
B点显示;
设置目标点;
路径规划操作;
导航到达;
直达操作;
充电;
去指定的点操作。
轮式机器人爱好者剥离ROS,搭建非主流机器人分布式开发框架,实现slam建图和简单自主导航
mp.weixin.qq.com/s/YWueXpJ7quB0yXASQVAfNg
B站视频:
轮式机器人爱好者剥离ROS,搭建非主流机器人分布式开发框架,实现slam建图和简单自主导航测试_哔哩哔哩_bilibili
www.bilibili.com/video/BV1Hh4y1f7Fm/?spm_id_from=333.999.0.0&vd_source=2056365a3e689ccb27ee312065d1714c
导航篇
更新了,新开源无ROS,轮式机器人实现自主导航和避障
mp.weixin.qq.com/s/eAD5nlpff4UpGMQTxUFfjw
B站演示视频
进阶,在轮式机器人上实现自主导航和避障(无ROS)_哔哩哔哩_bilibili
www.bilibili.com/video/BV1R8411m7b5/?spm_id_from=333.999.0.0&vd_source=2056365a3e689ccb27ee312065d1714c
轮式机器人爱好者剥离ROS,搭建非主流机器人分布式开发框架,实现slam建图和简单自主导航测试
机器人框架:easyMQos 基于MQTT
建图:2d栅格 粒子滤波
显示:web 页面 导航:无障碍 路径跟随
全局规划算法:A* 、梯度规划
局部避障导航:dwa+puresuit
公众号:视觉动力机器人
建图精度:+-5cm
定位精度;+-10cm 以内
实战案例 2
GPS定位与导航机器人
未完待续。。。
欢迎大家尝试使用。
公众号:视觉动力机器人
核心:《轮式自主移动机器人编程实战》