commit
d4db29f344
Binary file not shown.
@ -0,0 +1,3 @@
|
|||||||
|
{
|
||||||
|
"CurrentProjectSetting": "无配置"
|
||||||
|
}
|
@ -0,0 +1,7 @@
|
|||||||
|
{
|
||||||
|
"ExpandedNodes": [
|
||||||
|
""
|
||||||
|
],
|
||||||
|
"SelectedNode": "\\避障",
|
||||||
|
"PreviewInSolutionExplorer": false
|
||||||
|
}
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@ -0,0 +1,36 @@
|
|||||||
|
#include <QApplication>
|
||||||
|
#include <QWidget>
|
||||||
|
#include <QLabel>
|
||||||
|
#include <QPixmap>
|
||||||
|
#include <QPainter>
|
||||||
|
|
||||||
|
// 将矩形范围内绘制为指定颜色的矩形,并添加透明度
|
||||||
|
void drawRectWithTransparency(QPixmap& pixmap, const QRect& rect, const QColor& color, int transparency)
|
||||||
|
{
|
||||||
|
QPainter painter(&pixmap);
|
||||||
|
painter.setCompositionMode(QPainter::CompositionMode_Clear);
|
||||||
|
painter.fillRect(rect, QColor(0, 0, 0, 0));
|
||||||
|
painter.setCompositionMode(QPainter::CompositionMode_SourceOver);
|
||||||
|
painter.fillRect(rect, QColor(color.red(), color.green(), color.blue(), transparency));
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(int argc, char *argv[])
|
||||||
|
{
|
||||||
|
QApplication app(argc, argv);
|
||||||
|
|
||||||
|
// 创建窗口和标签
|
||||||
|
QWidget window;
|
||||||
|
QLabel label(&window);
|
||||||
|
|
||||||
|
// 加载图片
|
||||||
|
QPixmap pixmap(":1.png");
|
||||||
|
QRect rect(360, 360, 300, 250);
|
||||||
|
drawRectWithTransparency(pixmap, rect, QColor(255, 0, 0), 100);
|
||||||
|
label.setPixmap(pixmap);
|
||||||
|
|
||||||
|
// 显示窗口和标签
|
||||||
|
window.show();
|
||||||
|
label.show();
|
||||||
|
|
||||||
|
return app.exec();
|
||||||
|
}
|
@ -0,0 +1,47 @@
|
|||||||
|
#include <QApplication>
|
||||||
|
#include <QWidget>
|
||||||
|
#include <QLabel>
|
||||||
|
#include <QPixmap>
|
||||||
|
#include <QPainter>
|
||||||
|
#include <QVBoxLayout>
|
||||||
|
|
||||||
|
void drawRectOnImage(QString imagePath, QRect rect1, QRect rect2, QColor color1, QColor color2)
|
||||||
|
{
|
||||||
|
// 加载图片
|
||||||
|
QPixmap pixmap(imagePath);
|
||||||
|
|
||||||
|
// 指定范围并绘制透明红色和黑色矩形
|
||||||
|
QPainter painter(&pixmap);
|
||||||
|
painter.setCompositionMode(QPainter::CompositionMode_Clear);
|
||||||
|
painter.fillRect(rect1, QColor(0, 0, 0, 0));
|
||||||
|
painter.fillRect(rect2, color2); // 黑色矩形
|
||||||
|
painter.setCompositionMode(QPainter::CompositionMode_SourceOver);
|
||||||
|
painter.fillRect(rect1, color1);
|
||||||
|
|
||||||
|
// 显示图片
|
||||||
|
QWidget *mainWindow = new QWidget();
|
||||||
|
QVBoxLayout *layout = new QVBoxLayout(mainWindow);
|
||||||
|
QLabel *label = new QLabel(mainWindow);
|
||||||
|
layout->addWidget(label);
|
||||||
|
label->setFixedSize(pixmap.size());
|
||||||
|
label->setPixmap(pixmap);
|
||||||
|
mainWindow->show();
|
||||||
|
|
||||||
|
// 进入主事件循环
|
||||||
|
QApplication::exec();
|
||||||
|
delete mainWindow;
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(int argc, char *argv[])
|
||||||
|
{
|
||||||
|
QApplication app(argc, argv);
|
||||||
|
|
||||||
|
// 绘制矩形到图片中,并在标签上显示图片
|
||||||
|
QRect rect1(360, 360, 300, 250);
|
||||||
|
QRect rect2(400, 400, 300, 250);
|
||||||
|
QColor color1(255, 0, 0, 100);
|
||||||
|
QColor color2(0, 0, 255, 100);
|
||||||
|
drawRectOnImage(":1.png", rect1, rect2, color1, color2);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
@ -0,0 +1,191 @@
|
|||||||
|
#ifndef _ASTAR_H
|
||||||
|
#define _ASTAR_H
|
||||||
|
|
||||||
|
#include <ros/ros.h>
|
||||||
|
#include <Eigen/Eigen>
|
||||||
|
#include <iostream>
|
||||||
|
#include <queue>
|
||||||
|
#include <string>
|
||||||
|
#include <unordered_map>
|
||||||
|
#include <sstream>
|
||||||
|
// #include <boost/functional/hash.hpp>
|
||||||
|
// #include <map>
|
||||||
|
|
||||||
|
#include <sensor_msgs/PointCloud2.h>
|
||||||
|
#include <nav_msgs/Path.h>
|
||||||
|
|
||||||
|
#include "occupy_map.h"
|
||||||
|
#include "tools.h"
|
||||||
|
#include "message_utils.h"
|
||||||
|
|
||||||
|
#define NODE_NAME "Swarm_Planner [Astar]"
|
||||||
|
|
||||||
|
|
||||||
|
namespace Swarm_Planning
|
||||||
|
{
|
||||||
|
|
||||||
|
#define IN_CLOSE_SET 'a'
|
||||||
|
#define IN_OPEN_SET 'b'
|
||||||
|
#define NOT_EXPAND 'c'
|
||||||
|
#define inf 1 >> 30
|
||||||
|
|
||||||
|
extern ros::Publisher message_pub;
|
||||||
|
|
||||||
|
class Node
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
/* -------------------- */
|
||||||
|
Eigen::Vector3i index;
|
||||||
|
Eigen::Vector3d position;
|
||||||
|
double g_score, f_score;
|
||||||
|
Node* parent;
|
||||||
|
char node_state;
|
||||||
|
|
||||||
|
double time; // dyn
|
||||||
|
int time_idx;
|
||||||
|
|
||||||
|
Node()
|
||||||
|
{
|
||||||
|
parent = NULL;
|
||||||
|
node_state = NOT_EXPAND;
|
||||||
|
}
|
||||||
|
~Node(){};
|
||||||
|
};
|
||||||
|
typedef Node* NodePtr;
|
||||||
|
|
||||||
|
// 为什么不直接比较?
|
||||||
|
class NodeComparator0
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
bool operator()(NodePtr node1, NodePtr node2)
|
||||||
|
{
|
||||||
|
return node1->f_score > node2->f_score;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
struct matrix_hash0 : std::unary_function<T, size_t>
|
||||||
|
{
|
||||||
|
std::size_t operator()(T const& matrix) const
|
||||||
|
{
|
||||||
|
size_t seed = 0;
|
||||||
|
for (size_t i = 0; i < matrix.size(); ++i)
|
||||||
|
{
|
||||||
|
auto elem = *(matrix.data() + i);
|
||||||
|
seed ^= std::hash<typename T::Scalar>()(elem) + 0x9e3779b9 + (seed << 6) + (seed >> 2);
|
||||||
|
}
|
||||||
|
return seed;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
class NodeHashTable0
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
/* data */
|
||||||
|
std::unordered_map<Eigen::Vector3i, NodePtr, matrix_hash0<Eigen::Vector3i>> data_3d_;
|
||||||
|
|
||||||
|
public:
|
||||||
|
NodeHashTable0(/* args */)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
~NodeHashTable0()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
void insert(Eigen::Vector3i idx, NodePtr node)
|
||||||
|
{
|
||||||
|
data_3d_.insert(std::make_pair(idx, node));
|
||||||
|
}
|
||||||
|
|
||||||
|
NodePtr find(Eigen::Vector3i idx)
|
||||||
|
{
|
||||||
|
auto iter = data_3d_.find(idx);
|
||||||
|
return iter == data_3d_.end() ? NULL : iter->second;
|
||||||
|
}
|
||||||
|
|
||||||
|
void clear()
|
||||||
|
{
|
||||||
|
data_3d_.clear();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
class Astar
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
// 备选路径点指针容器
|
||||||
|
std::vector<NodePtr> path_node_pool_;
|
||||||
|
// 使用节点计数器、迭代次数计数器
|
||||||
|
int use_node_num_, iter_num_;
|
||||||
|
// 扩展的节点?
|
||||||
|
NodeHashTable0 expanded_nodes_;
|
||||||
|
// open set (根据规则已排序好)
|
||||||
|
std::priority_queue<NodePtr, std::vector<NodePtr>, NodeComparator0> open_set_;
|
||||||
|
// 最终路径点容器
|
||||||
|
std::vector<NodePtr> path_nodes_;
|
||||||
|
|
||||||
|
// 参数
|
||||||
|
// 启发式参数
|
||||||
|
double lambda_heu_;
|
||||||
|
// 最大搜索次数
|
||||||
|
int max_search_num;
|
||||||
|
// tie breaker
|
||||||
|
double tie_breaker_;
|
||||||
|
int is_2D;
|
||||||
|
double fly_height;
|
||||||
|
|
||||||
|
/* ---------- record data ---------- */
|
||||||
|
// 目标点
|
||||||
|
Eigen::Vector3d goal_pos;
|
||||||
|
|
||||||
|
// 地图相关
|
||||||
|
std::vector<int> occupancy_buffer_;
|
||||||
|
double resolution_, inv_resolution_;
|
||||||
|
Eigen::Vector3d origin_, map_size_3d_;
|
||||||
|
bool has_global_point;
|
||||||
|
|
||||||
|
// 辅助函数
|
||||||
|
Eigen::Vector3i posToIndex(Eigen::Vector3d pt);
|
||||||
|
void indexToPos(Eigen::Vector3i id, Eigen::Vector3d &pos);
|
||||||
|
void retrievePath(NodePtr end_node);
|
||||||
|
|
||||||
|
// 搜索启发函数,三种形式,选用其中一种即可
|
||||||
|
double getDiagHeu(Eigen::Vector3d x1, Eigen::Vector3d x2);
|
||||||
|
double getManhHeu(Eigen::Vector3d x1, Eigen::Vector3d x2);
|
||||||
|
double getEuclHeu(Eigen::Vector3d x1, Eigen::Vector3d x2);
|
||||||
|
|
||||||
|
public:
|
||||||
|
Astar(){}
|
||||||
|
~Astar();
|
||||||
|
|
||||||
|
enum
|
||||||
|
{
|
||||||
|
REACH_END = 1,
|
||||||
|
NO_PATH = 2
|
||||||
|
};
|
||||||
|
|
||||||
|
// 占据图类
|
||||||
|
Occupy_map::Ptr Occupy_map_ptr;
|
||||||
|
|
||||||
|
// 重置
|
||||||
|
void reset();
|
||||||
|
// 初始化
|
||||||
|
void init(ros::NodeHandle& nh);
|
||||||
|
// 检查安全性
|
||||||
|
bool check_safety(Eigen::Vector3d &cur_pos, double safe_distance);
|
||||||
|
// 搜索
|
||||||
|
int search(Eigen::Vector3d start_pt, Eigen::Vector3d end_pt);
|
||||||
|
// 返回路径
|
||||||
|
std::vector<Eigen::Vector3d> getPath();
|
||||||
|
// 返回ros消息格式的路径
|
||||||
|
nav_msgs::Path get_ros_path();
|
||||||
|
// 返回访问过的节点
|
||||||
|
std::vector<NodePtr> getVisitedNodes();
|
||||||
|
|
||||||
|
typedef std::shared_ptr<Astar> Ptr;
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
@ -0,0 +1,100 @@
|
|||||||
|
#ifndef _OCCUPY_MAP_H
|
||||||
|
#define _OCCUPY_MAP_H
|
||||||
|
|
||||||
|
#include <iostream>
|
||||||
|
#include <algorithm>
|
||||||
|
|
||||||
|
#include <ros/ros.h>
|
||||||
|
#include <Eigen/Eigen>
|
||||||
|
|
||||||
|
#include <pcl_ros/point_cloud.h>
|
||||||
|
#include <pcl_ros/transforms.h>
|
||||||
|
#include <pcl/point_cloud.h>
|
||||||
|
#include <pcl/point_types.h>
|
||||||
|
#include <pcl/kdtree/kdtree_flann.h>
|
||||||
|
#include <pcl_conversions/pcl_conversions.h>
|
||||||
|
#include <tf/transform_listener.h>
|
||||||
|
#include <nav_msgs/OccupancyGrid.h>
|
||||||
|
#include <nav_msgs/Odometry.h>
|
||||||
|
#include <visualization_msgs/Marker.h>
|
||||||
|
#include <sensor_msgs/LaserScan.h>
|
||||||
|
|
||||||
|
#include "tools.h"
|
||||||
|
#include "message_utils.h"
|
||||||
|
|
||||||
|
#define NODE_NAME "Swarm_Planner [map]"
|
||||||
|
|
||||||
|
namespace Swarm_Planning
|
||||||
|
{
|
||||||
|
|
||||||
|
extern ros::Publisher message_pub;
|
||||||
|
|
||||||
|
class Occupy_map
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
Occupy_map(){}
|
||||||
|
|
||||||
|
// 全局点云指针
|
||||||
|
sensor_msgs::PointCloud2ConstPtr global_env_;
|
||||||
|
// 地图是否占据容器, 从编程角度来讲,这就是地图变为单一序列化后的索引
|
||||||
|
std::vector<int> occupancy_buffer_; // 0 is free, 1 is occupied
|
||||||
|
string uav_name;
|
||||||
|
// 地图分辨率
|
||||||
|
double resolution_, inv_resolution_;
|
||||||
|
// 膨胀参数
|
||||||
|
double inflate_;
|
||||||
|
//是否2D规划
|
||||||
|
bool is_2D;
|
||||||
|
double fly_height_2D;
|
||||||
|
bool debug_mode;
|
||||||
|
// 地图原点,地图尺寸
|
||||||
|
Eigen::Vector3d origin_, map_size_3d_, min_range_, max_range_;
|
||||||
|
// 占据图尺寸 = 地图尺寸 / 分辨率
|
||||||
|
Eigen::Vector3i grid_size_;
|
||||||
|
|
||||||
|
bool has_global_point;
|
||||||
|
|
||||||
|
pcl::PointXYZ nei_pos1;
|
||||||
|
pcl::PointXYZ nei_pos2;
|
||||||
|
|
||||||
|
// 显示相关
|
||||||
|
void show_gpcl_marker(visualization_msgs::Marker &m, int id, Eigen::Vector4d color);
|
||||||
|
|
||||||
|
// 发布点云用于rviz显示
|
||||||
|
ros::Publisher global_pcl_pub, inflate_pcl_pub;
|
||||||
|
|
||||||
|
//初始化
|
||||||
|
void init(ros::NodeHandle& nh);
|
||||||
|
// 地图更新函数 - 输入:全局点云
|
||||||
|
void map_update_gpcl(const sensor_msgs::PointCloud2ConstPtr & global_point);
|
||||||
|
// 地图更新函数 - 输入:局部点云
|
||||||
|
void map_update_lpcl(const sensor_msgs::PointCloud2ConstPtr & local_point, const nav_msgs::Odometry & odom);
|
||||||
|
// 地图更新函数 - 输入:二维激光雷达
|
||||||
|
void map_update_laser(const sensor_msgs::LaserScanConstPtr & local_point, const nav_msgs::Odometry & odom);
|
||||||
|
// 设置邻居位置
|
||||||
|
void setNeiPos(Eigen::Vector3d pos, int uav_id);
|
||||||
|
// 地图膨胀
|
||||||
|
void inflate_point_cloud(void);
|
||||||
|
// 判断当前点是否在地图内
|
||||||
|
bool isInMap(Eigen::Vector3d pos);
|
||||||
|
// 设置占据
|
||||||
|
void setOccupancy(Eigen::Vector3d pos, int occ);
|
||||||
|
// 由位置计算索引
|
||||||
|
void posToIndex(Eigen::Vector3d pos, Eigen::Vector3i &id);
|
||||||
|
// 由索引计算位置
|
||||||
|
void indexToPos(Eigen::Vector3i id, Eigen::Vector3d &pos);
|
||||||
|
// 根据位置返回占据状态
|
||||||
|
int getOccupancy(Eigen::Vector3d pos);
|
||||||
|
// 根据索引返回占据状态
|
||||||
|
int getOccupancy(Eigen::Vector3i id);
|
||||||
|
// 检查安全
|
||||||
|
bool check_safety(Eigen::Vector3d& pos, double check_distance/*, Eigen::Vector3d& map_point*/);
|
||||||
|
// 定义该类的指针
|
||||||
|
typedef std::shared_ptr<Occupy_map> Ptr;
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#endif
|
Loading…
Reference in new issue