欢迎光临淄博市道路交通事故研究中心官方网站!

服务咨询热线

13756699636

当前位置:网站首页 >  原创作品
联系我们
服务热线

13756699636

淄博市道路交通事故研究中心

联系人:魏福禄
联系电话:13756699636
传真:0533-2786837
QQ咨询:KesionCMS官方合作洽谈QQ
邮件:weifulu@sdut.edu.cn
网址:www.shiguyanjiu.com



原创作品

打磨机器人最优路径控制代码研究

2024/9/15    来源:    作者:于亚平  浏览次数:474

为研究打磨机器人最优路径控制代码,本文使用了 A * 算法来规划最优路径,并添加了机器人运动控制和路径平滑处理的功能。代码使用 Python 实现,包含了详细的注释和可视化功能。robot-polishing-path-planning打磨机器人最优路径控制代码生成 robot_path_planning.py这个代码实现了一个完整的打磨机器人路径规划系统,具有以下特点:

使用 A * 算法进行路径规划,支持 8 方向移动,考虑了对角线移动的额外代价实现了路径平滑处理,使机器人运动更加流畅支持多个打磨区域的路径规划,按照蛇形方式填充打磨区域提供了可视化功能,可以直观地查看路径规划结果包含机器人控制器类,模拟了路径执行和打磨操作的过程

后续的研究中,可以根据实际需求调整代码中的参数,如网格大小、障碍物位置、打磨区域和机器人速度等。

如果需要适配特定的机器人平台,只需修改 RobotController 类中的相关方法即可。import numpy as np

import matplotlib.pyplot as plt

from matplotlib.patches import Rectangle

import heapq

from typing import List, Tuple, Dict, Optional

import random

 

class Node:

    """A*算法中的节点类"""

    def __init__(self, x: int, y: int, g_cost: float = float('inf'), h_cost: float = float('inf'),

                 parent: Optional['Node'] = None):

        self.x = x

        self.y = y

        self.g_cost = g_cost  # 从起点到当前节点的实际代价

        self.h_cost = h_cost  # 从当前节点到目标节点的启发式估计代价

        self.f_cost = g_cost + h_cost  # 总代价

        self.parent = parent  # 父节点,用于回溯路径

        

    def __lt__(self, other: 'Node') -> bool:

        """比较节点的总代价,用于优先队列"""

        return self.f_cost < other.f_cost

    

    def __eq__(self, other: 'Node') -> bool:

        """比较节点的坐标是否相同"""

        return self.x == other.x and self.y == other.y

    

    def __hash__(self) -> int:

        """节点的哈希值,用于集合操作"""

        return hash((self.x, self.y))

 

class RobotPathPlanner:

    """打磨机器人路径规划器"""

    def __init__(self, grid_size: Tuple[int, int], obstacles: List[Tuple[int, int]] = None):

        self.grid_size = grid_size  # 网格大小 (width, height)

        self.obstacles = obstacles if obstacles else []  # 障碍物列表

        self.grid = self._create_grid()  # 创建网格地图

        

    def _create_grid(self) -> np.ndarray:

        """创建网格地图,0表示可通行,1表示障碍物"""

        grid = np.zeros(self.grid_size, dtype=int)

        for obs in self.obstacles:

            if 0 <= obs[0] < self.grid_size[0] and 0 <= obs[1] < self.grid_size[1]:

                grid[obs[0], obs[1]] = 1

        return grid

    

    def is_valid(self, x: int, y: int) -> bool:

        """检查坐标是否在网格内且不是障碍物"""

        return 0 <= x < self.grid_size[0] and 0 <= y < self.grid_size[1] and self.grid[x, y] == 0

    

    def heuristic(self, current: Tuple[int, int], goal: Tuple[int, int]) -> float:

        """计算启发式函数值,使用曼哈顿距离"""

        return abs(current[0] - goal[0]) + abs(current[1] - goal[1])

    

    def a_star(self, start: Tuple[int, int], goal: Tuple[int, int]) -> List[Tuple[int, int]]:

        """A*算法实现"""

        start_node = Node(start[0], start[1], 0, self.heuristic(start, goal))

        goal_node = Node(goal[0], goal[1])

        

        open_set: List[Node] = []

        closed_set = set()

        

        heapq.heappush(open_set, start_node)

        

        while open_set:

            current_node = heapq.heappop(open_set)

            

            # 到达目标节点,回溯路径

            if current_node.x == goal_node.x and current_node.y == goal_node.y:

                path = []

                while current_node:

                    path.append((current_node.x, current_node.y))

                    current_node = current_node.parent

                return path[::-1]  # 反转路径,从起点到终点

            

            closed_set.add((current_node.x, current_node.y))

            

            # 8个方向的移动

            for dx in [-1, 0, 1]:

                for dy in [-1, 0, 1]:

                    if dx == 0 and dy == 0:

                        continue

                    

                    neighbor_x = current_node.x + dx

                    neighbor_y = current_node.y + dy

                    

                    # 检查是否有效

                    if not self.is_valid(neighbor_x, neighbor_y):

                        continue

                    

                    # 对角线移动的代价更高

                    movement_cost = 1.4 if dx != 0 and dy != 0 else 1.0

                    

                    # 计算新的g

                    new_g_cost = current_node.g_cost + movement_cost

                    

                    # 如果邻居节点已经在关闭列表中,跳过

                    if (neighbor_x, neighbor_y) in closed_set:

                        continue

                    

                    # 检查邻居节点是否在开放列表中

                    neighbor_node = None

                    for node in open_set:

                        if node.x == neighbor_x and node.y == neighbor_y:

                            neighbor_node = node

                            break

                    

                    if not neighbor_node:

                        # 创建新节点

                        neighbor_node = Node(neighbor_x, neighbor_y, new_g_cost,

                                           self.heuristic((neighbor_x, neighbor_y), goal))

                        neighbor_node.parent = current_node

                        heapq.heappush(open_set, neighbor_node)

                    elif new_g_cost < neighbor_node.g_cost:

                        # 更新已有节点

                        neighbor_node.g_cost = new_g_cost

                        neighbor_node.f_cost = new_g_cost + neighbor_node.h_cost

                        neighbor_node.parent = current_node

                        # 重新排序优先队列

                        open_set.sort()

        

        # 没有找到路径

        return []

    

    def smooth_path(self, path: List[Tuple[int, int]], weight_data: float = 0.5,

                   weight_smooth: float = 0.1, tolerance: float = 0.00001) -> List[Tuple[float, float]]:

        """路径平滑处理"""

        if not path or len(path) < 3:

            return path

        

        # 转换为浮点数列表以便进行平滑处理

        smoothed_path = [[float(x), float(y)] for x, y in path]

        

        change = tolerance

        while change >= tolerance:

            change = 0.0

            for i in range(1, len(path) - 1):

                for j in range(2):  # xy坐标

                    aux = smoothed_path[i][j]

                    # 数据项

                    smoothed_path[i][j] += weight_data * (path[i][j] - smoothed_path[i][j])

                    # 平滑项

                    smoothed_path[i][j] += weight_smooth * (smoothed_path[i-1][j] + smoothed_path[i+1][j] - 2.0 * smoothed_path[i][j])

                    # 检查边界条件

                    if j == 0:  # x坐标

                        if smoothed_path[i][j] < 0:

                            smoothed_path[i][j] = 0.0

                        elif smoothed_path[i][j] > self.grid_size[0] - 1:

                            smoothed_path[i][j] = float(self.grid_size[0] - 1)

                    else:  # y坐标

                        if smoothed_path[i][j] < 0:

                            smoothed_path[i][j] = 0.0

                        elif smoothed_path[i][j] > self.grid_size[1] - 1:

                            smoothed_path[i][j] = float(self.grid_size[1] - 1)

                    

                    change += abs(aux - smoothed_path[i][j])

        

        return [(x, y) for x, y in smoothed_path]

    

    def generate_polishing_waypoints(self, area: Tuple[Tuple[int, int], Tuple[int, int]],

                                    spacing: float = 1.0) -> List[Tuple[float, float]]:

        """生成打磨区域的路径点"""

        (x_min, y_min), (x_max, y_max) = area

        

        waypoints = []

        direction = 1  # 1表示向右,-1表示向左

        

        # 按行生成路径点,蛇形填充

        for y in np.arange(y_min, y_max + spacing, spacing):

            if direction == 1:

                for x in np.arange(x_min, x_max + spacing, spacing):

                    waypoints.append((x, y))

            else:

                for x in np.arange(x_max, x_min - spacing, -spacing):

                    waypoints.append((x, y))

            direction *= -1  # 切换方向

        

        return waypoints

    

    def plan_polishing_path(self, start: Tuple[int, int], polishing_areas: List[Tuple[Tuple[int, int], Tuple[int, int]]],

                           spacing: float = 1.0) -> List[Tuple[float, float]]:

        """规划完整的打磨路径"""

        # 生成所有打磨区域的路径点

        all_waypoints = []

        for area in polishing_areas:

            waypoints = self.generate_polishing_waypoints(area, spacing)

            all_waypoints.extend(waypoints)

        

        if not all_waypoints:

            return []

        

        # 规划从起点到第一个打磨点的路径

        first_waypoint = (int(all_waypoints[0][0]), int(all_waypoints[0][1]))

        path_to_first = self.a_star(start, first_waypoint)

        

        # 连接所有打磨点形成完整路径

        full_path = path_to_first[:-1]  # 去掉第一个打磨点,避免重复

        full_path.extend(all_waypoints)

        

        # 平滑路径

        smoothed_path = self.smooth_path(full_path)

        

        return smoothed_path

    

    def visualize_path(self, path: List[Tuple[float, float]], start: Tuple[int, int],

                      polishing_areas: List[Tuple[Tuple[int, int], Tuple[int, int]]]):

        """可视化路径规划结果"""

        plt.figure(figsize=(10, 8))

        

        # 绘制网格和障碍物

        plt.imshow(self.grid.T, cmap='gray_r', origin='lower', alpha=0.5)

        

        # 绘制障碍物

        for obs in self.obstacles:

            plt.gca().add_patch(Rectangle((obs[0]-0.5, obs[1]-0.5), 1, 1,

                                         linewidth=1, edgecolor='r', facecolor='r'))

        

        # 绘制打磨区域

        for area in polishing_areas:

            (x_min, y_min), (x_max, y_max) = area

            plt.gca().add_patch(Rectangle((x_min-0.5, y_min-0.5), x_max-x_min+1, y_max-y_min+1,

                                         linewidth=2, edgecolor='g', facecolor='none'))

        

        # 绘制起点和终点

        plt.plot(start[0], start[1], 'bo', markersize=10, label='Start')

        

        # 绘制路径

        if path:

            x_vals = [p[0] for p in path]

            y_vals = [p[1] for p in path]

            plt.plot(x_vals, y_vals, 'b-', linewidth=2, label='Path')

            

            # 绘制路径点

            plt.plot(x_vals, y_vals, 'ro', markersize=4)

        

        plt.grid(True)

        plt.title('Robot Polishing Path Planning')

        plt.xlabel('X Coordinate')

        plt.ylabel('Y Coordinate')

        plt.legend()

        plt.axis('equal')

        plt.tight_layout()

        plt.show()

 

class RobotController:

    """打磨机器人控制器"""

    def __init__(self, planner: RobotPathPlanner, speed: float = 1.0):

        self.planner = planner

        self.speed = speed  # 机器人移动速度 (单位/)

        self.current_position = None

        

    def execute_path(self, path: List[Tuple[float, float]], start: Tuple[int, int]):

        """执行规划好的路径"""

        self.current_position = start

        print(f"机器人从位置 {start} 开始移动")

        

        # 记录总执行时间

        total_time = 0.0

        

        for i, point in enumerate(path):

            if i == 0 and point == start:

                continue  # 已经在起点

                

            # 计算移动距离和时间

            dx = point[0] - self.current_position[0]

            dy = point[1] - self.current_position[1]

            distance = np.sqrt(dx**2 + dy**2)

            time = distance / self.speed

            

            # 更新当前位置

            self.current_position = point

            

            # 输出移动信息

            total_time += time

            print(f"步骤 {i}: 移动到点 ({point[0]:.2f}, {point[1]:.2f}),耗时 {time:.2f} ")

            

            # 模拟打磨操作

            if i > 0:  # 跳过起点

                self._simulate_polishing(point)

        

        print(f"路径执行完成,总耗时: {total_time:.2f} ")

    

    def _simulate_polishing(self, position: Tuple[float, float]):

        """模拟打磨操作"""

        # 这里可以添加实际的打磨控制代码

        print(f"  在位置 ({position[0]:.2f}, {position[1]:.2f}) 执行打磨操作...")

 

# 示例使用

def main():

    # 创建一个20x20的网格地图

    grid_size = (20, 20)

    

    # 添加一些随机障碍物

    random.seed(42)  # 设置随机种子,确保结果可重现

    obstacles = []

    for _ in range(15):

        x = random.randint(2, 18)

        y = random.randint(2, 18)

        obstacles.append((x, y))

    

    # 创建路径规划器

    planner = RobotPathPlanner(grid_size, obstacles)

    

    # 设置起点和打磨区域

    start = (2, 2)

    polishing_areas = [

        ((5, 5), (10, 8)),  # 第一个打磨区域

        ((12, 10), (17, 15))  # 第二个打磨区域

    ]

    

    # 规划打磨路径

    path = planner.plan_polishing_path(start, polishing_areas, spacing=0.8)

    

    # 可视化路径

    planner.visualize_path(path, start, polishing_areas)

    

    # 创建机器人控制器并执行路径

    controller = RobotController(planner, speed=1.5)

    controller.execute_path(path, start)

 

if __name__ == "__main__":

copyright  © 2021 淄博市道路交通事故研究中心 版权所有   技术支持:网赢信息

地址:山东理工大学交通实验楼650房间   电话:13756699636   邮编:255000