{"id":2932,"date":"2025-07-21T10:08:42","date_gmt":"2025-07-21T10:08:42","guid":{"rendered":"https:\/\/learnbydoing.dev\/?p=2932"},"modified":"2026-01-10T22:16:43","modified_gmt":"2026-01-10T22:16:43","slug":"smarter-path-planning-in-ros-2-implementing-a-in-python","status":"publish","type":"post","link":"https:\/\/learnbydoing.dev\/smarter-path-planning-in-ros-2-implementing-a-in-python\/","title":{"rendered":"Smarter Path Planning in ROS 2: Implementing A* in Python"},"content":{"rendered":"\t\t<div data-elementor-type=\"wp-post\" data-elementor-id=\"2932\" class=\"elementor elementor-2932\" data-elementor-post-type=\"post\">\n\t\t\t\t<div class=\"elementor-element elementor-element-e28ab35 e-flex e-con-boxed e-con e-parent\" data-id=\"e28ab35\" data-element_type=\"container\" data-e-type=\"container\" id=\"content\" data-settings=\"{&quot;background_background&quot;:&quot;classic&quot;}\">\n\t\t\t\t\t<div class=\"e-con-inner\">\n\t\t<div class=\"elementor-element elementor-element-62ab6e3 e-con-full e-flex e-con e-child\" data-id=\"62ab6e3\" data-element_type=\"container\" data-e-type=\"container\">\n\t\t\t\t<div class=\"elementor-element elementor-element-62ab203 elementor-align-center elementor-widget elementor-widget-post-info\" data-id=\"62ab203\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"post-info.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t\t\t<ul class=\"elementor-inline-items elementor-icon-list-items elementor-post-info\">\n\t\t\t\t\t\t\t\t<li class=\"elementor-icon-list-item elementor-repeater-item-2c98363 elementor-inline-item\" itemprop=\"about\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t<span class=\"elementor-icon-list-text elementor-post-info__item elementor-post-info__item--type-terms\">\n\t\t\t\t\t\t\t\t\t\t<span class=\"elementor-post-info__terms-list\">\n\t\t\t\t<span class=\"elementor-post-info__terms-list-item\">Nav2<\/span>, <span class=\"elementor-post-info__terms-list-item\">ROS 2<\/span>, <span class=\"elementor-post-info__terms-list-item\">Tutorials<\/span>\t\t\t\t<\/span>\n\t\t\t\t\t<\/span>\n\t\t\t\t\t\t\t\t<\/li>\n\t\t\t\t<\/ul>\n\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t<div class=\"elementor-element elementor-element-0650e10 e-con-full e-flex e-con e-child\" data-id=\"0650e10\" data-element_type=\"container\" data-e-type=\"container\">\n\t\t\t\t<div class=\"elementor-element elementor-element-ac19582 elementor-view-default elementor-widget elementor-widget-icon\" data-id=\"ac19582\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"icon.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t\t\t<div class=\"elementor-icon-wrapper\">\n\t\t\t<div class=\"elementor-icon\">\n\t\t\t<svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"75\" height=\"75\" viewBox=\"0 0 75 75\" fill=\"none\"><path d=\"M74.9999 75H13.1889V73.0002H71.5859L0.460938 1.87521L1.87515 0.460999L73.0001 71.586V13.1889H74.9999V75Z\" fill=\"white\"><\/path><\/svg>\t\t\t<\/div>\n\t\t<\/div>\n\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t<div class=\"elementor-element elementor-element-47aa245d e-flex e-con-boxed e-con e-parent\" data-id=\"47aa245d\" data-element_type=\"container\" data-e-type=\"container\" data-settings=\"{&quot;background_background&quot;:&quot;classic&quot;}\">\n\t\t\t\t\t<div class=\"e-con-inner\">\n\t\t\t\t<div class=\"elementor-element elementor-element-206a001 elementor-widget elementor-widget-image\" data-id=\"206a001\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"image.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t<img fetchpriority=\"high\" decoding=\"async\" width=\"1920\" height=\"1080\" src=\"https:\/\/learnbydoing.dev\/wp-content\/uploads\/2025\/07\/A-1.webp\" class=\"attachment-full size-full wp-image-2999\" alt=\"\" srcset=\"https:\/\/learnbydoing.dev\/wp-content\/uploads\/2025\/07\/A-1.webp 1920w, https:\/\/learnbydoing.dev\/wp-content\/uploads\/2025\/07\/A-1-300x169.webp 300w, https:\/\/learnbydoing.dev\/wp-content\/uploads\/2025\/07\/A-1-1024x576.webp 1024w, https:\/\/learnbydoing.dev\/wp-content\/uploads\/2025\/07\/A-1-768x432.webp 768w, https:\/\/learnbydoing.dev\/wp-content\/uploads\/2025\/07\/A-1-1536x864.webp 1536w, https:\/\/learnbydoing.dev\/wp-content\/uploads\/2025\/07\/A-1-18x10.webp 18w, https:\/\/learnbydoing.dev\/wp-content\/uploads\/2025\/07\/A-1-1320x743.webp 1320w, https:\/\/learnbydoing.dev\/wp-content\/uploads\/2025\/07\/A-1-600x338.webp 600w\" sizes=\"(max-width: 1920px) 100vw, 1920px\" \/>\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-4bc31ca3 elementor-widget elementor-widget-text-editor\" data-id=\"4bc31ca3\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"text-editor.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t\t\t\t\t<p data-start=\"419\" data-end=\"556\">In the world of robotics, planning a path from one point to another isn&#8217;t just about finding a route\u2014it&#8217;s about doing it intelligently.<\/p><p data-start=\"558\" data-end=\"819\">If you&#8217;ve ever implemented <a class=\"\" href=\"https:\/\/learnbydoing.dev\/path-planning-using-dijkstra-algorithm\/\" target=\"_new\" rel=\"noopener\" data-start=\"129\" data-end=\"221\"><strong data-start=\"130\" data-end=\"154\">Dijkstra\u2019s algorithm<\/strong><\/a>, you know how powerful it is&#8230; but also how <em data-start=\"655\" data-end=\"661\">slow<\/em> it can be when the map gets big. What if we could be smarter? What if we could guide the exploration toward the goal instead of blindly exploring everything?<\/p><p data-start=\"821\" data-end=\"854\">That\u2019s exactly what <strong data-start=\"841\" data-end=\"848\">A*<\/strong> does.<\/p><p data-start=\"856\" data-end=\"1151\">In this tutorial, we\u2019ll dive into the theory behind A*, then implement it as a <strong data-start=\"935\" data-end=\"956\">Python ROS 2 node<\/strong>, using an occupancy grid and a simulated robot. By the end, you\u2019ll be able to visualize in RViz how A* efficiently explores only the most promising cells\u2014saving time, resources, and computation.<\/p>\t\t\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-12a4ca0 elementor-widget elementor-widget-text-editor\" data-id=\"12a4ca0\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"text-editor.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t\t\t\t\t<h3 data-start=\"1857\" data-end=\"1885\">\ud83d\ude80<strong> What Makes A* So Special?<\/strong><\/h3><p data-start=\"1014\" data-end=\"1155\">Let\u2019s start with the same question we posed in the course:<\/p><p>Can we do any better than Dijkstra? Is there a faster way to reach the goal without exploring in all directions?<\/p><p data-start=\"1014\" data-end=\"1155\">Yes\u2014and it\u2019s called <strong data-start=\"1390\" data-end=\"1397\">A*<\/strong>.<\/p><p data-start=\"1400\" data-end=\"1508\">While Dijkstra explores nodes uniformly, A* evaluates each possible move with a simple yet powerful formula:<br \/>$$f(n) = g(n) + h(n)$$<\/p><ol><li>\\(g(n)\\): the actual cost to reach a node<\/li><li>\\(h(n)\\): the estimated cost to reach the goal from that node (heuristic)<\/li><\/ol><p data-start=\"1661\" data-end=\"1796\">This heuristic is what gives A* its directionality. It guesses which paths are likely to lead to the goal, and gives them <strong data-start=\"1783\" data-end=\"1795\">priority<\/strong>.<\/p>\t\t\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-821f703 elementor-widget elementor-widget-image\" data-id=\"821f703\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"image.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t<img decoding=\"async\" width=\"1920\" height=\"1080\" src=\"https:\/\/learnbydoing.dev\/wp-content\/uploads\/2025\/07\/A-GIF.gif\" class=\"attachment-full size-full wp-image-3010\" alt=\"\" \/>\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-324d52d elementor-widget elementor-widget-text-editor\" data-id=\"324d52d\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"text-editor.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t\t\t\t\t<h3 data-start=\"1946\" data-end=\"1997\"><strong>\ud83d\udccf Choosing a Heuristic: Euclidean vs Manhattan<\/strong><\/h3><p data-start=\"1999\" data-end=\"2053\">In the course, we visualized two different heuristics:<\/p><ol><li data-start=\"2057\" data-end=\"2128\"><strong data-start=\"2057\" data-end=\"2079\">Euclidean distance<\/strong>: a straight-line estimation between two points<\/li><li data-start=\"2057\" data-end=\"2128\"><strong data-start=\"2131\" data-end=\"2153\">Manhattan distance<\/strong>: the sum of absolute differences between x and y, ideal for grid-based maps<\/li><\/ol><p data-start=\"2231\" data-end=\"2388\">Since our robot operates on a 2D occupancy grid where it can only move in four directions (up, down, left, right), <strong data-start=\"2346\" data-end=\"2368\">Manhattan distance<\/strong> is the perfect fit.<\/p>\t\t\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-0d06411 elementor-widget elementor-widget-image\" data-id=\"0d06411\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"image.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t<img decoding=\"async\" width=\"1920\" height=\"1080\" src=\"https:\/\/learnbydoing.dev\/wp-content\/uploads\/2025\/07\/Titolo-_6_.webp\" class=\"attachment-full size-full wp-image-2935\" alt=\"\" srcset=\"https:\/\/learnbydoing.dev\/wp-content\/uploads\/2025\/07\/Titolo-_6_.webp 1920w, https:\/\/learnbydoing.dev\/wp-content\/uploads\/2025\/07\/Titolo-_6_-300x169.webp 300w, https:\/\/learnbydoing.dev\/wp-content\/uploads\/2025\/07\/Titolo-_6_-1024x576.webp 1024w, https:\/\/learnbydoing.dev\/wp-content\/uploads\/2025\/07\/Titolo-_6_-768x432.webp 768w, https:\/\/learnbydoing.dev\/wp-content\/uploads\/2025\/07\/Titolo-_6_-1536x864.webp 1536w, https:\/\/learnbydoing.dev\/wp-content\/uploads\/2025\/07\/Titolo-_6_-18x10.webp 18w, https:\/\/learnbydoing.dev\/wp-content\/uploads\/2025\/07\/Titolo-_6_-1320x743.webp 1320w, https:\/\/learnbydoing.dev\/wp-content\/uploads\/2025\/07\/Titolo-_6_-600x338.webp 600w\" sizes=\"(max-width: 1920px) 100vw, 1920px\" \/>\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-da593b9 elementor-widget elementor-widget-text-editor\" data-id=\"da593b9\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"text-editor.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t\t\t\t\t<p>Here\u2019s how it looks in code:<\/p>\t\t\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-0bc5e8c elementor-widget elementor-widget-code-highlight\" data-id=\"0bc5e8c\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"code-highlight.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t\t\t<div class=\"prismjs-tomorrow copy-to-clipboard \">\n\t\t\t<pre data-line=\"\" class=\"highlight-height language-python line-numbers\">\n\t\t\t\t<code readonly=\"true\" class=\"language-python\">\n\t\t\t\t\t<xmp>def manhattan_distance(self, node: GraphNode, goal_node: GraphNode):\r\n        return abs(node.x - goal_node.x) + abs(node.y - goal_node.y)\r\n<\/xmp>\n\t\t\t\t<\/code>\n\t\t\t<\/pre>\n\t\t<\/div>\n\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-d651a96 elementor-widget elementor-widget-text-editor\" data-id=\"d651a96\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"text-editor.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t\t\t\t\t<p>This distance doesn\u2019t consider walls or obstacles\u2014it\u2019s just an estimate. But it\u2019s enough to guide the algorithm intelligently.<\/p>\t\t\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-f0139c8 elementor-widget elementor-widget-text-editor\" data-id=\"f0139c8\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"text-editor.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t\t\t\t\t<h3 data-start=\"2302\" data-end=\"2336\"><img decoding=\"async\" class=\"emoji\" role=\"img\" draggable=\"false\" src=\"https:\/\/s.w.org\/images\/core\/emoji\/16.0.1\/svg\/1f3d7.svg\" alt=\"\ud83c\udfd7\ufe0f\" \/> <strong>Here&#8217;s the full code:<\/strong><\/h3>\t\t\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-2c2f678 elementor-widget elementor-widget-code-highlight\" data-id=\"2c2f678\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"code-highlight.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t\t\t<div class=\"prismjs-tomorrow copy-to-clipboard \">\n\t\t\t<pre data-line=\"\" class=\"highlight-height language-python line-numbers\">\n\t\t\t\t<code readonly=\"true\" class=\"language-python\">\n\t\t\t\t\t<xmp>#!\/usr\/bin\/env python3\r\n\r\nimport rclpy\r\nfrom rclpy.node import Node\r\nfrom nav_msgs.msg import OccupancyGrid, Path\r\nfrom geometry_msgs.msg import PoseStamped, Pose\r\nfrom rclpy.qos import QoSProfile, DurabilityPolicy\r\nfrom tf2_ros import Buffer, TransformListener, LookupException\r\nfrom queue import PriorityQueue\r\n\r\nclass GraphNode:\r\n    def __init__(self, x, y, cost=0, heuristic=0, prev=None):\r\n        self.x = x\r\n        self.y = y\r\n        self.cost = cost\r\n        self.heuristic = heuristic\r\n        self.prev = prev\r\n    \r\n    def __lt__(self, other):\r\n        return (self.cost + self.heuristic) < (other.cost + other.heuristic)\r\n\r\n    def __eq__(self, other):\r\n        return self.x == other.x and self.y == other.y\r\n    \r\n    def __hash__(self):\r\n        return hash((self.x, self.y))\r\n    \r\n    def __add__(self, other):\r\n        return GraphNode(self.x + other[0], self.y + other[1])\r\n\r\nclass AStarPlanner(Node):\r\n    def __init__(self):\r\n        super().__init__(\"a_star_node\")\r\n        self.tf_buffer = Buffer()\r\n        self.tf_listener = TransformListener(self.tf_buffer, self)\r\n\r\n        map_qos = QoSProfile(depth=10)\r\n        map_qos.durability = DurabilityPolicy.TRANSIENT_LOCAL\r\n\r\n        self.map_sub = self.create_subscription(\r\n            OccupancyGrid, \"\/map\", self.map_callback, map_qos\r\n        )\r\n        self.pose_sub = self.create_subscription(\r\n            PoseStamped, \"\/goal_pose\", self.goal_callback, 10\r\n        )\r\n        self.path_pub = self.create_publisher(Path, \"\/a_star\/path\", 10)\r\n        self.map_pub = self.create_publisher(OccupancyGrid, \"\/a_star\/visited_map\", 10)\r\n\r\n        self.map_ = None\r\n        self.visited_map_ = OccupancyGrid()\r\n\r\n    def map_callback(self, map_msg: OccupancyGrid):\r\n        self.map_ = map_msg\r\n        self.visited_map_.header.frame_id = map_msg.header.frame_id\r\n        self.visited_map_.info = map_msg.info\r\n        self.visited_map_.data = [-1] * (map_msg.info.height * map_msg.info.width)\r\n\r\n    def goal_callback(self, pose: PoseStamped):\r\n        if self.map_ is None:\r\n            self.get_logger().error(\"No map received!\")\r\n            return\r\n\r\n        self.visited_map_.data = [-1] * (self.visited_map_.info.height * self.visited_map_.info.width)\r\n\r\n        try:\r\n            map_to_base_tf = self.tf_buffer.lookup_transform(\r\n                self.map_.header.frame_id, \"base_footprint\", rclpy.time.Time()\r\n            )\r\n        except LookupException:\r\n            self.get_logger().error(\"Could not transform from map to base_footprint\")\r\n            return\r\n\r\n        map_to_base_pose = Pose()\r\n        map_to_base_pose.position.x = map_to_base_tf.transform.translation.x\r\n        map_to_base_pose.position.y = map_to_base_tf.transform.translation.y\r\n        map_to_base_pose.orientation = map_to_base_tf.transform.rotation\r\n\r\n        path = self.plan(map_to_base_pose, pose.pose)\r\n        if path.poses:\r\n            self.get_logger().info(\"Shortest path found!\")\r\n            self.path_pub.publish(path)\r\n        else:\r\n            self.get_logger().warn(\"No path found to the goal.\")\r\n\r\n    def plan(self, start: Pose, goal: Pose):\r\n        # Define possible movement directions\r\n        explore_directions = [(-1, 0), (1, 0), (0, -1), (0, 1)]\r\n\r\n        # Priority queue with custom comparison for A* based on cost + heuristic\r\n        pending_nodes = PriorityQueue()\r\n        visited_nodes = set()\r\n\r\n        start_node = self.world_to_grid(start)\r\n        goal_node = self.world_to_grid(goal)\r\n        start_node.heuristic = self.manhattan_distance(start_node, goal_node)\r\n        pending_nodes.put(start_node)\r\n\r\n        while not pending_nodes.empty() and rclpy.ok():\r\n            active_node = pending_nodes.get()\r\n\r\n            # Goal found!\r\n            if active_node == goal_node:\r\n                break\r\n            \r\n            # Explore neighbors\r\n            for dir_x, dir_y in explore_directions:\r\n                new_node: GraphNode = active_node + (dir_x, dir_y)\r\n                \r\n                if (new_node not in visited_nodes and self.pose_on_map(new_node) and \r\n                    self.map_.data[self.pose_to_cell(new_node)] == 0):\r\n                    \r\n                    new_node.cost = active_node.cost + 1\r\n                    new_node.heuristic = self.manhattan_distance(new_node, goal_node)\r\n                    new_node.prev = active_node\r\n\r\n                    pending_nodes.put(new_node)\r\n                    visited_nodes.add(new_node)\r\n\r\n            self.visited_map_.data[self.pose_to_cell(active_node)] = -106\r\n            self.map_pub.publish(self.visited_map_)\r\n\r\n        path = Path()\r\n        path.header.frame_id = self.map_.header.frame_id\r\n        while active_node and active_node.prev and rclpy.ok():\r\n            last_pose: Pose = self.grid_to_world(active_node)\r\n            last_pose_stamped = PoseStamped()\r\n            last_pose_stamped.header.frame_id = self.map_.header.frame_id\r\n            last_pose_stamped.pose = last_pose\r\n            path.poses.append(last_pose_stamped)\r\n            active_node = active_node.prev\r\n\r\n        path.poses.reverse()\r\n        return path\r\n\r\n    def manhattan_distance(self, node: GraphNode, goal_node: GraphNode):\r\n        return abs(node.x - goal_node.x) + abs(node.y - goal_node.y)\r\n\r\n    def pose_on_map(self, node: GraphNode):\r\n        return 0 <= node.x < self.map_.info.width and 0 <= node.y < self.map_.info.height\r\n\r\n    def world_to_grid(self, pose: Pose) -> GraphNode:\r\n        grid_x = int((pose.position.x - self.map_.info.origin.position.x) \/ self.map_.info.resolution)\r\n        grid_y = int((pose.position.y - self.map_.info.origin.position.y) \/ self.map_.info.resolution)\r\n        return GraphNode(grid_x, grid_y)\r\n\r\n    def grid_to_world(self, node: GraphNode) -> Pose:\r\n        pose = Pose()\r\n        pose.position.x = node.x * self.map_.info.resolution + self.map_.info.origin.position.x\r\n        pose.position.y = node.y * self.map_.info.resolution + self.map_.info.origin.position.y\r\n        return pose\r\n\r\n    def pose_to_cell(self, node: GraphNode):\r\n        return node.y * self.map_.info.width + node.x\r\n\r\n\r\ndef main(args=None):\r\n    rclpy.init(args=args)\r\n    node = AStarPlanner()\r\n    rclpy.spin(node)\r\n    rclpy.shutdown()\r\n\r\nif __name__ == '__main__':\r\n    main()<\/xmp>\n\t\t\t\t<\/code>\n\t\t\t<\/pre>\n\t\t<\/div>\n\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-e54d3fc elementor-widget elementor-widget-text-editor\" data-id=\"e54d3fc\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"text-editor.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t\t\t\t\t<h3><img decoding=\"async\" class=\"emoji\" role=\"img\" draggable=\"false\" src=\"https:\/\/s.w.org\/images\/core\/emoji\/16.0.1\/svg\/1f9f0.svg\" alt=\"\ud83e\uddf0\" \/><strong>\u00a0Hands On: The fun part of the code<\/strong><\/h3>\t\t\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-e1ef5c9 elementor-widget elementor-widget-text-editor\" data-id=\"e1ef5c9\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"text-editor.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t\t\t\t\t<h4 data-start=\"1792\" data-end=\"1824\"><strong>\ud83d\udee0\ufe0f Implementing A* in ROS 2 (Python)<\/strong><\/h4><p data-start=\"2851\" data-end=\"2886\">Now let\u2019s build the actual planner.<\/p><p data-start=\"2888\" data-end=\"3018\">Since this planner shares a lot with the Dijkstra version we already implemented, we\u2019ll <strong data-start=\"2976\" data-end=\"3017\">reuse that script as a starting point<\/strong>.<\/p>\t\t\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-c8feb2d elementor-widget elementor-widget-text-editor\" data-id=\"c8feb2d\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"text-editor.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t\t\t\t\t<h4 data-start=\"3100\" data-end=\"3142\"><strong>\ud83d\udcc4 Step 1: Clone and Rename the Script<\/strong><\/h4><p data-start=\"3144\" data-end=\"3168\">In your ROS 2 workspace:<\/p>\t\t\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-73296f4 elementor-widget elementor-widget-code-highlight\" data-id=\"73296f4\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"code-highlight.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t\t\t<div class=\"prismjs-tomorrow copy-to-clipboard \">\n\t\t\t<pre data-line=\"\" class=\"highlight-height language-bash \">\n\t\t\t\t<code readonly=\"true\" class=\"language-bash\">\n\t\t\t\t\t<xmp>cp dijkstra_planner.py a_star_planner.py\r\n<\/xmp>\n\t\t\t\t<\/code>\n\t\t\t<\/pre>\n\t\t<\/div>\n\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-5d58307 elementor-widget elementor-widget-text-editor\" data-id=\"5d58307\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"text-editor.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t\t\t\t\t<p>Open the file and rename the class:<\/p>\t\t\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-8552ec2 elementor-widget elementor-widget-code-highlight\" data-id=\"8552ec2\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"code-highlight.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t\t\t<div class=\"prismjs-tomorrow copy-to-clipboard \">\n\t\t\t<pre data-line=\"\" class=\"highlight-height language-python \">\n\t\t\t\t<code readonly=\"true\" class=\"language-python\">\n\t\t\t\t\t<xmp>class AStarPlanner(Node):\r\n    def __init__(self):\r\n        super().__init__('a_star_node')\r\n<\/xmp>\n\t\t\t\t<\/code>\n\t\t\t<\/pre>\n\t\t<\/div>\n\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-50f5ce9 elementor-widget elementor-widget-text-editor\" data-id=\"50f5ce9\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"text-editor.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t\t\t\t\t<p>Update the topics it will publish to:<\/p>\t\t\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-0941b9e elementor-widget elementor-widget-code-highlight\" data-id=\"0941b9e\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"code-highlight.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t\t\t<div class=\"prismjs-tomorrow copy-to-clipboard \">\n\t\t\t<pre data-line=\"\" class=\"highlight-height language-python \">\n\t\t\t\t<code readonly=\"true\" class=\"language-python\">\n\t\t\t\t\t<xmp>self.path_pub = self.create_publisher(Path, \"\/a_star\/path\", 10)\r\nself.map_pub = self.create_publisher(OccupancyGrid, \"\/a_star\/visited_map\", 10)\r\n<\/xmp>\n\t\t\t\t<\/code>\n\t\t\t<\/pre>\n\t\t<\/div>\n\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-6d9e08a elementor-widget elementor-widget-text-editor\" data-id=\"6d9e08a\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"text-editor.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t\t\t\t\t<h4 data-start=\"3568\" data-end=\"3627\"><strong>\ud83e\uddf1 Step 2: Add Heuristic Support to the GraphNode Class<\/strong><\/h4><p data-start=\"3629\" data-end=\"3716\">In Dijkstra, each node only tracked its cost and parent. A* adds a <strong data-start=\"3696\" data-end=\"3709\">heuristic<\/strong> value.<\/p><p data-start=\"3718\" data-end=\"3750\">So modify the <code data-start=\"3732\" data-end=\"3743\">GraphNode<\/code> class:<\/p>\t\t\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-e359b44 elementor-widget elementor-widget-code-highlight\" data-id=\"e359b44\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"code-highlight.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t\t\t<div class=\"prismjs-tomorrow copy-to-clipboard \">\n\t\t\t<pre data-line=\"\" class=\"highlight-height language-python \">\n\t\t\t\t<code readonly=\"true\" class=\"language-python\">\n\t\t\t\t\t<xmp>def __init__(self, x, y, cost=0, heuristic=0, prev=None):\r\n    self.x = x\r\n    self.y = y\r\n    self.cost = cost\r\n    self.heuristic = heuristic\r\n    self.prev = prev\r\n<\/xmp>\n\t\t\t\t<\/code>\n\t\t\t<\/pre>\n\t\t<\/div>\n\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-421b22a elementor-widget elementor-widget-text-editor\" data-id=\"421b22a\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"text-editor.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t\t\t\t\t<p>Update how nodes are compared inside the priority queue:<\/p>\t\t\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-abbca55 elementor-widget elementor-widget-code-highlight\" data-id=\"abbca55\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"code-highlight.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t\t\t<div class=\"prismjs-tomorrow copy-to-clipboard \">\n\t\t\t<pre data-line=\"\" class=\"highlight-height language-python \">\n\t\t\t\t<code readonly=\"true\" class=\"language-python\">\n\t\t\t\t\t<xmp>def __lt__(self, other):\r\n    return (self.cost + self.heuristic) < (other.cost + other.heuristic)\r\n<\/xmp>\n\t\t\t\t<\/code>\n\t\t\t<\/pre>\n\t\t<\/div>\n\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-6ee6f1c elementor-widget elementor-widget-text-editor\" data-id=\"6ee6f1c\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"text-editor.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t\t\t\t\t<p>This ensures that nodes with the <strong data-start=\"4132\" data-end=\"4169\">lowest combined cost and estimate<\/strong> are explored first.<\/p>\t\t\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-eea9ccf elementor-widget elementor-widget-text-editor\" data-id=\"eea9ccf\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"text-editor.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t\t\t\t\t<h4 data-start=\"4196\" data-end=\"4234\"><strong>\ud83e\uddee Step 3: Calculate the Heuristic<\/strong><\/h4><p data-start=\"4236\" data-end=\"4330\">In your planner, after converting the robot&#8217;s current pose and the goal into grid coordinates:<\/p>\t\t\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-4ed8b19 elementor-widget elementor-widget-code-highlight\" data-id=\"4ed8b19\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"code-highlight.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t\t\t<div class=\"prismjs-tomorrow copy-to-clipboard \">\n\t\t\t<pre data-line=\"\" class=\"highlight-height language-python \">\n\t\t\t\t<code readonly=\"true\" class=\"language-python\">\n\t\t\t\t\t<xmp>start_node = self.world_to_grid(start)\r\ngoal_node = self.world_to_grid(goal)\r\n<\/xmp>\n\t\t\t\t<\/code>\n\t\t\t<\/pre>\n\t\t<\/div>\n\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-885351b elementor-widget elementor-widget-text-editor\" data-id=\"885351b\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"text-editor.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t\t\t\t\t<p>You can now assign the heuristic to the start node:<\/p>\t\t\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-b3bef51 elementor-widget elementor-widget-code-highlight\" data-id=\"b3bef51\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"code-highlight.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t\t\t<div class=\"prismjs-tomorrow copy-to-clipboard \">\n\t\t\t<pre data-line=\"\" class=\"highlight-height language-python \">\n\t\t\t\t<code readonly=\"true\" class=\"language-python\">\n\t\t\t\t\t<xmp>start_node.heuristic = self.manhattan_distance(start_node, goal_node)\r\n<\/xmp>\n\t\t\t\t<\/code>\n\t\t\t<\/pre>\n\t\t<\/div>\n\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-7eff710 elementor-widget elementor-widget-text-editor\" data-id=\"7eff710\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"text-editor.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t\t\t\t\t<p>Then, in your main exploration loop, assign it to each neighbor node:<\/p>\t\t\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-2c8fca6 elementor-widget elementor-widget-code-highlight\" data-id=\"2c8fca6\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"code-highlight.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t\t\t<div class=\"prismjs-tomorrow copy-to-clipboard \">\n\t\t\t<pre data-line=\"\" class=\"highlight-height language-python \">\n\t\t\t\t<code readonly=\"true\" class=\"language-python\">\n\t\t\t\t\t<xmp>new_node.heuristic = self.manhattan_distance(new_node, goal_node)\r\n<\/xmp>\n\t\t\t\t<\/code>\n\t\t\t<\/pre>\n\t\t<\/div>\n\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-2728bb4 elementor-widget elementor-widget-image\" data-id=\"2728bb4\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"image.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t<img loading=\"lazy\" decoding=\"async\" width=\"800\" height=\"450\" src=\"https:\/\/learnbydoing.dev\/wp-content\/uploads\/2025\/07\/Progetto-senza-titolo-_6_-1024x576.webp\" class=\"attachment-large size-large wp-image-2959\" alt=\"\" srcset=\"https:\/\/learnbydoing.dev\/wp-content\/uploads\/2025\/07\/Progetto-senza-titolo-_6_-1024x576.webp 1024w, https:\/\/learnbydoing.dev\/wp-content\/uploads\/2025\/07\/Progetto-senza-titolo-_6_-300x169.webp 300w, https:\/\/learnbydoing.dev\/wp-content\/uploads\/2025\/07\/Progetto-senza-titolo-_6_-768x432.webp 768w, https:\/\/learnbydoing.dev\/wp-content\/uploads\/2025\/07\/Progetto-senza-titolo-_6_-1536x864.webp 1536w, https:\/\/learnbydoing.dev\/wp-content\/uploads\/2025\/07\/Progetto-senza-titolo-_6_-18x10.webp 18w, https:\/\/learnbydoing.dev\/wp-content\/uploads\/2025\/07\/Progetto-senza-titolo-_6_-1320x743.webp 1320w, https:\/\/learnbydoing.dev\/wp-content\/uploads\/2025\/07\/Progetto-senza-titolo-_6_-600x338.webp 600w, https:\/\/learnbydoing.dev\/wp-content\/uploads\/2025\/07\/Progetto-senza-titolo-_6_.webp 1920w\" sizes=\"(max-width: 800px) 100vw, 800px\" \/>\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-2978a30 elementor-widget elementor-widget-text-editor\" data-id=\"2978a30\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"text-editor.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t\t\t\t\t<h4 data-start=\"4833\" data-end=\"4875\"><strong>\ud83c\udfa8 Step 4: Visualize the Visited Cells<\/strong><\/h4><p data-start=\"4877\" data-end=\"4990\">We want to distinguish A* from Dijkstra visually. Let\u2019s mark the visited cells in orange using a different value:<\/p>\t\t\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-209d99d elementor-widget elementor-widget-code-highlight\" data-id=\"209d99d\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"code-highlight.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t\t\t<div class=\"prismjs-tomorrow copy-to-clipboard \">\n\t\t\t<pre data-line=\"\" class=\"highlight-height language-python \">\n\t\t\t\t<code readonly=\"true\" class=\"language-python\">\n\t\t\t\t\t<xmp>self.visited_map_.data[self.pose_to_cell(active_node)] = -106\r\n<\/xmp>\n\t\t\t\t<\/code>\n\t\t\t<\/pre>\n\t\t<\/div>\n\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-8bf6c51 elementor-widget elementor-widget-text-editor\" data-id=\"8bf6c51\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"text-editor.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t\t\t\t\t<p data-start=\"5069\" data-end=\"5174\">In RViz, this will appear as a bright orange overlay on the grid\u2014clearly showing the path of exploration.<\/p>\t\t\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-2e6101e elementor-widget elementor-widget-text-editor\" data-id=\"2e6101e\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"text-editor.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t\t\t\t\t<h4 data-start=\"5181\" data-end=\"5212\"><strong>\ud83e\uddf1 Step 5: Install the Node<\/strong><\/h4><p data-start=\"5214\" data-end=\"5290\">Open <code data-start=\"5219\" data-end=\"5235\">CMakeLists.txt<\/code> of your package and make sure to install the new file:<\/p>\t\t\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-192a3a6 elementor-widget elementor-widget-code-highlight\" data-id=\"192a3a6\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"code-highlight.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t\t\t<div class=\"prismjs-tomorrow copy-to-clipboard \">\n\t\t\t<pre data-line=\"\" class=\"highlight-height language-bash \">\n\t\t\t\t<code readonly=\"true\" class=\"language-bash\">\n\t\t\t\t\t<xmp>install(PROGRAMS\r\n  ${PROJECT_NAME}\/a_star_planner.py\r\n  DESTINATION lib\/${PROJECT_NAME}\r\n)\r\n<\/xmp>\n\t\t\t\t<\/code>\n\t\t\t<\/pre>\n\t\t<\/div>\n\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-d4f933a elementor-widget elementor-widget-text-editor\" data-id=\"d4f933a\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"text-editor.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t\t\t\t\t<p>Then build the workspace:<\/p>\t\t\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-0ca7ee8 elementor-widget elementor-widget-code-highlight\" data-id=\"0ca7ee8\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"code-highlight.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t\t\t<div class=\"prismjs-tomorrow copy-to-clipboard \">\n\t\t\t<pre data-line=\"\" class=\"highlight-height language-bash \">\n\t\t\t\t<code readonly=\"true\" class=\"language-bash\">\n\t\t\t\t\t<xmp>cd bumperbot_ws\r\ncolcon build\r\n<\/xmp>\n\t\t\t\t<\/code>\n\t\t\t<\/pre>\n\t\t<\/div>\n\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-6944ace elementor-widget elementor-widget-text-editor\" data-id=\"6944ace\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"text-editor.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t\t\t\t\t<h3 data-start=\"5469\" data-end=\"5502\"><strong>\ud83e\uddea Step 6: Run the Simulation<\/strong><\/h3><p data-start=\"5504\" data-end=\"5532\">Launch the robot simulation:<\/p>\t\t\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-926ee65 elementor-widget elementor-widget-code-highlight\" data-id=\"926ee65\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"code-highlight.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t\t\t<div class=\"prismjs-tomorrow copy-to-clipboard \">\n\t\t\t<pre data-line=\"\" class=\"highlight-height language-bash \">\n\t\t\t\t<code readonly=\"true\" class=\"language-bash\">\n\t\t\t\t\t<xmp>ros2 launch bumperbot_bringup simulated_robot.launch.py\r\n<\/xmp>\n\t\t\t\t<\/code>\n\t\t\t<\/pre>\n\t\t<\/div>\n\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-a638df4 elementor-widget elementor-widget-text-editor\" data-id=\"a638df4\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"text-editor.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t\t\t\t\t<p>Then launch your planner in a new terminal:<\/p>\t\t\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-78392b6 elementor-widget elementor-widget-code-highlight\" data-id=\"78392b6\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"code-highlight.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t\t\t<div class=\"prismjs-tomorrow copy-to-clipboard \">\n\t\t\t<pre data-line=\"\" class=\"highlight-height language-bash \">\n\t\t\t\t<code readonly=\"true\" class=\"language-bash\">\n\t\t\t\t\t<xmp>ros2 run bumperbot_planning a_star_planner\r\n<\/xmp>\n\t\t\t\t<\/code>\n\t\t\t<\/pre>\n\t\t<\/div>\n\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-b51de97 elementor-widget elementor-widget-image\" data-id=\"b51de97\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"image.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t<img loading=\"lazy\" decoding=\"async\" width=\"800\" height=\"450\" src=\"https:\/\/learnbydoing.dev\/wp-content\/uploads\/2025\/07\/2024-12-05-12-38-55_JnXVYjzp-1024x576.gif\" class=\"attachment-large size-large wp-image-2964\" alt=\"\" srcset=\"https:\/\/learnbydoing.dev\/wp-content\/uploads\/2025\/07\/2024-12-05-12-38-55_JnXVYjzp-1024x576.gif 1024w, https:\/\/learnbydoing.dev\/wp-content\/uploads\/2025\/07\/2024-12-05-12-38-55_JnXVYjzp-300x169.gif 300w, https:\/\/learnbydoing.dev\/wp-content\/uploads\/2025\/07\/2024-12-05-12-38-55_JnXVYjzp-768x432.gif 768w, https:\/\/learnbydoing.dev\/wp-content\/uploads\/2025\/07\/2024-12-05-12-38-55_JnXVYjzp-1536x864.gif 1536w, https:\/\/learnbydoing.dev\/wp-content\/uploads\/2025\/07\/2024-12-05-12-38-55_JnXVYjzp-18x10.gif 18w, https:\/\/learnbydoing.dev\/wp-content\/uploads\/2025\/07\/2024-12-05-12-38-55_JnXVYjzp-1320x743.gif 1320w, https:\/\/learnbydoing.dev\/wp-content\/uploads\/2025\/07\/2024-12-05-12-38-55_JnXVYjzp-600x338.gif 600w\" sizes=\"(max-width: 800px) 100vw, 800px\" \/>\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-ed819ab elementor-widget elementor-widget-text-editor\" data-id=\"ed819ab\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"text-editor.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t\t\t\t\t<p data-start=\"5802\" data-end=\"5810\">In RViz:<br \/><br \/><\/p><ol><li data-start=\"5814\" data-end=\"5865\">Add <code data-start=\"5818\" data-end=\"5832\">\/a_star\/path<\/code> to visualize the calculated path<br \/><br \/><\/li><li data-start=\"5814\" data-end=\"5865\">Add <code data-start=\"5872\" data-end=\"5893\">\/a_star\/visited_map<\/code> and set display type to <strong data-start=\"5918\" data-end=\"5929\">Costmap<br \/><br \/><\/strong><\/li><li data-start=\"5814\" data-end=\"5865\">Use the <strong data-start=\"5940\" data-end=\"5953\">Goal Pose<\/strong> tool to send a goal anywhere on the map<br \/><br \/><\/li><\/ol><p data-start=\"5995\" data-end=\"6080\">You\u2019ll immediately see A* in action\u2014moving quickly and efficiently toward the target!<\/p>\t\t\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-c6c375a elementor-widget elementor-widget-text-editor\" data-id=\"c6c375a\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"text-editor.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t\t\t\t\t<h3 data-start=\"6087\" data-end=\"6117\"><strong>\ud83e\udde0 Observing A*\u2019s Behavior<\/strong><\/h3><p data-start=\"6119\" data-end=\"6193\">Try sending goals both <strong data-start=\"6142\" data-end=\"6158\">near and far<\/strong> from the robot\u2019s current location.<\/p><p data-start=\"6195\" data-end=\"6318\">You\u2019ll notice a clear pattern: A* <strong data-start=\"6229\" data-end=\"6279\">prioritizes cells in the direction of the goal<\/strong>, skipping irrelevant parts of the map.<\/p>\t\t\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-ea8741f elementor-widget elementor-widget-image\" data-id=\"ea8741f\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"image.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t<img loading=\"lazy\" decoding=\"async\" width=\"800\" height=\"284\" src=\"https:\/\/learnbydoing.dev\/wp-content\/uploads\/2025\/07\/A-_2_-1024x363.webp\" class=\"attachment-large size-large wp-image-2973\" alt=\"\" srcset=\"https:\/\/learnbydoing.dev\/wp-content\/uploads\/2025\/07\/A-_2_-1024x363.webp 1024w, https:\/\/learnbydoing.dev\/wp-content\/uploads\/2025\/07\/A-_2_-300x106.webp 300w, https:\/\/learnbydoing.dev\/wp-content\/uploads\/2025\/07\/A-_2_-768x272.webp 768w, https:\/\/learnbydoing.dev\/wp-content\/uploads\/2025\/07\/A-_2_-1536x544.webp 1536w, https:\/\/learnbydoing.dev\/wp-content\/uploads\/2025\/07\/A-_2_-18x6.webp 18w, https:\/\/learnbydoing.dev\/wp-content\/uploads\/2025\/07\/A-_2_-1320x468.webp 1320w, https:\/\/learnbydoing.dev\/wp-content\/uploads\/2025\/07\/A-_2_-600x213.webp 600w, https:\/\/learnbydoing.dev\/wp-content\/uploads\/2025\/07\/A-_2_.webp 1920w\" sizes=\"(max-width: 800px) 100vw, 800px\" \/>\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-4166d8a elementor-widget elementor-widget-text-editor\" data-id=\"4166d8a\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"text-editor.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t\t\t\t\t<h3 data-start=\"6519\" data-end=\"6539\"><strong>\u26a0\ufe0f A Few Caveats<\/strong><\/h3><p data-start=\"6541\" data-end=\"6687\">A* is fast, but it\u2019s not perfect. If the heuristic is not <strong data-start=\"6599\" data-end=\"6613\">admissible<\/strong> (i.e. it overestimates the cost), A* might return a <strong data-start=\"6666\" data-end=\"6686\">non-optimal path<\/strong>.<\/p><p data-start=\"6689\" data-end=\"6780\">In our implementation, Manhattan distance is admissible\u2014so we\u2019re safe. But always remember:<\/p><blockquote data-start=\"6782\" data-end=\"6829\"><p data-start=\"6784\" data-end=\"6829\">The heuristic is just a guess, not the truth.<\/p><\/blockquote>\t\t\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-acd415c elementor-widget elementor-widget-text-editor\" data-id=\"acd415c\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"text-editor.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t\t\t\t\t<h3 data-start=\"6836\" data-end=\"6852\"><strong>\u2705 Conclusion<\/strong><\/h3><p data-start=\"6854\" data-end=\"6990\">By integrating a simple heuristic into our existing path planner, we made our robot smarter\u2014and much faster at navigating to its goal.<\/p><p data-start=\"6992\" data-end=\"7185\">With just a few modifications, the A* planner in Python is now ready to explore any occupancy grid efficiently, intelligently, and with a visual feedback that makes debugging and testing a joy.<\/p>\t\t\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t<div class=\"elementor-element elementor-element-c5d20e7 e-con-full e-flex e-con e-parent\" data-id=\"c5d20e7\" data-element_type=\"container\" data-e-type=\"container\">\n\t\t\t\t<div class=\"elementor-element elementor-element-0741169 elementor-bg-transform elementor-bg-transform-move-left elementor-cta--layout-image-left elementor-cta--mobile-layout-image-above elementor-cta--skin-classic elementor-animated-content elementor-widget elementor-widget-call-to-action\" data-id=\"0741169\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"call-to-action.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t\t\t<div class=\"elementor-cta\">\n\t\t\t\t\t<div class=\"elementor-cta__bg-wrapper\">\n\t\t\t\t<div class=\"elementor-cta__bg elementor-bg\" style=\"background-image: url(https:\/\/learnbydoing.dev\/wp-content\/uploads\/2025\/06\/plan_navigation.webp);\" role=\"img\" aria-label=\"plan_navigation\"><\/div>\n\t\t\t\t<div class=\"elementor-cta__bg-overlay\"><\/div>\n\t\t\t<\/div>\n\t\t\t\t\t\t\t<div class=\"elementor-cta__content\">\n\t\t\t\t\n\t\t\t\t\t\t\t\t\t<h2 class=\"elementor-cta__title elementor-cta__content-item elementor-content-item\">\n\t\t\t\t\t\tWant to learn more?\t\t\t\t\t<\/h2>\n\t\t\t\t\n\t\t\t\t\t\t\t\t\t<div class=\"elementor-cta__description elementor-cta__content-item elementor-content-item\">\n\t\t\t\t\t\tExplore a full implementation of A* and other intelligent planning algorithms in the \"Self Driving and ROS 2 - Learn by Doing! Plan &amp; Navigation\" course\t\t\t\t\t<\/div>\n\t\t\t\t\n\t\t\t\t\t\t\t\t\t<div class=\"elementor-cta__button-wrapper elementor-cta__content-item elementor-content-item \">\n\t\t\t\t\t<a class=\"elementor-cta__button elementor-button elementor-size-\" href=\"\" target=\"_blank\">\n\t\t\t\t\t\tEnroll Now\t\t\t\t\t<\/a>\n\t\t\t\t\t<\/div>\n\t\t\t\t\t\t\t<\/div>\n\t\t\t\t\t\t\t<div class=\"elementor-ribbon elementor-ribbon-right\">\n\t\t\t\t<div class=\"elementor-ribbon-inner\">\n\t\t\t\t\tDISCOUNT\t\t\t\t<\/div>\n\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-180426a elementor-widget elementor-widget-spacer\" data-id=\"180426a\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"spacer.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t\t\t<div class=\"elementor-spacer\">\n\t\t\t<div class=\"elementor-spacer-inner\"><\/div>\n\t\t<\/div>\n\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t","protected":false},"excerpt":{"rendered":"<p>In the world of robotics, planning a path from one point to another isn&#8217;t just about finding a route\u2014it&#8217;s about doing it intelligently. If you&#8217;ve ever implemented Dijkstra\u2019s algorithm, you know how powerful it is&#8230; but also how slow it can be when the map gets big. What if we could be smarter? What if [&hellip;]<\/p>\n","protected":false},"author":4,"featured_media":2999,"comment_status":"closed","ping_status":"open","sticky":false,"template":"elementor_header_footer","format":"standard","meta":{"_acf_changed":false,"footnotes":""},"categories":[49,45,43],"tags":[240,244,243,126,99,66,74,110,242,141,100,75,71,107,72,241],"class_list":["post-2932","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-nav2","category-ros-2","category-tutorials","tag-a","tag-algorithm","tag-autonomus","tag-base","tag-dijkstra","tag-learn-by-doing","tag-linux","tag-navigation","tag-plan","tag-py","tag-robot","tag-robotics","tag-ros","tag-ros-2","tag-ros2","tag-star"],"acf":[],"yoast_head":"<!-- This site is optimized with the Yoast SEO plugin v27.6 - https:\/\/yoast.com\/product\/yoast-seo-wordpress\/ -->\n<title>Smarter Path Planning in ROS 2: Implementing A* in Python - Learn by Doing!<\/title>\n<meta name=\"description\" content=\"Implement A* path planning in ROS 2 using Python. Use an occupancy grid, heuristic-driven search, and RViz visualization.\" \/>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/learnbydoing.dev\/es\/smarter-path-planning-in-ros-2-implementing-a-in-python\/\" \/>\n<meta property=\"og:locale\" content=\"es_ES\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"Smarter Path Planning in ROS 2: Implementing A* in Python\" \/>\n<meta property=\"og:description\" content=\"Learn by Doing!\" \/>\n<meta property=\"og:url\" content=\"https:\/\/learnbydoing.dev\/es\/smarter-path-planning-in-ros-2-implementing-a-in-python\/\" \/>\n<meta property=\"og:site_name\" content=\"Learn by Doing!\" \/>\n<meta property=\"article:published_time\" content=\"2025-07-21T10:08:42+00:00\" \/>\n<meta property=\"article:modified_time\" content=\"2026-01-10T22:16:43+00:00\" \/>\n<meta property=\"og:image\" content=\"https:\/\/learnbydoing.dev\/wp-content\/uploads\/2025\/07\/A-1.webp\" \/>\n\t<meta property=\"og:image:width\" content=\"1920\" \/>\n\t<meta property=\"og:image:height\" content=\"1080\" \/>\n\t<meta property=\"og:image:type\" content=\"image\/webp\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:label1\" content=\"Escrito por\" \/>\n\t<meta name=\"twitter:data1\" content=\"\" \/>\n\t<meta name=\"twitter:label2\" content=\"Tiempo de lectura\" \/>\n\t<meta name=\"twitter:data2\" content=\"8 minutos\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\\\/\\\/schema.org\",\"@graph\":[{\"@type\":\"Article\",\"@id\":\"https:\\\/\\\/learnbydoing.dev\\\/smarter-path-planning-in-ros-2-implementing-a-in-python\\\/#article\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/learnbydoing.dev\\\/smarter-path-planning-in-ros-2-implementing-a-in-python\\\/\"},\"author\":{\"name\":\"\",\"@id\":\"\"},\"headline\":\"Smarter Path Planning in ROS 2: Implementing A* in Python\",\"datePublished\":\"2025-07-21T10:08:42+00:00\",\"dateModified\":\"2026-01-10T22:16:43+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\\\/\\\/learnbydoing.dev\\\/smarter-path-planning-in-ros-2-implementing-a-in-python\\\/\"},\"wordCount\":807,\"publisher\":{\"@id\":\"https:\\\/\\\/learnbydoing.dev\\\/es\\\/#organization\"},\"image\":{\"@id\":\"https:\\\/\\\/learnbydoing.dev\\\/smarter-path-planning-in-ros-2-implementing-a-in-python\\\/#primaryimage\"},\"thumbnailUrl\":\"https:\\\/\\\/learnbydoing.dev\\\/wp-content\\\/uploads\\\/2025\\\/07\\\/A-1.webp\",\"keywords\":[\"A\",\"algorithm\",\"autonomus\",\"Base\",\"dijkstra\",\"learn by doing\",\"Linux\",\"navigation\",\"plan\",\"py\",\"robot\",\"Robotics\",\"ROS\",\"ROS 2\",\"ROS2\",\"star\"],\"articleSection\":[\"Nav2\",\"ROS 2\",\"Tutorials\"],\"inLanguage\":\"es\"},{\"@type\":\"WebPage\",\"@id\":\"https:\\\/\\\/learnbydoing.dev\\\/smarter-path-planning-in-ros-2-implementing-a-in-python\\\/\",\"url\":\"https:\\\/\\\/learnbydoing.dev\\\/smarter-path-planning-in-ros-2-implementing-a-in-python\\\/\",\"name\":\"Smarter Path Planning in ROS 2: Implementing A* in Python - Learn by Doing!\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/learnbydoing.dev\\\/es\\\/#website\"},\"primaryImageOfPage\":{\"@id\":\"https:\\\/\\\/learnbydoing.dev\\\/smarter-path-planning-in-ros-2-implementing-a-in-python\\\/#primaryimage\"},\"image\":{\"@id\":\"https:\\\/\\\/learnbydoing.dev\\\/smarter-path-planning-in-ros-2-implementing-a-in-python\\\/#primaryimage\"},\"thumbnailUrl\":\"https:\\\/\\\/learnbydoing.dev\\\/wp-content\\\/uploads\\\/2025\\\/07\\\/A-1.webp\",\"datePublished\":\"2025-07-21T10:08:42+00:00\",\"dateModified\":\"2026-01-10T22:16:43+00:00\",\"description\":\"Implement A* path planning in ROS 2 using Python. Use an occupancy grid, heuristic-driven search, and RViz visualization.\",\"breadcrumb\":{\"@id\":\"https:\\\/\\\/learnbydoing.dev\\\/smarter-path-planning-in-ros-2-implementing-a-in-python\\\/#breadcrumb\"},\"inLanguage\":\"es\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\\\/\\\/learnbydoing.dev\\\/smarter-path-planning-in-ros-2-implementing-a-in-python\\\/\"]}]},{\"@type\":\"ImageObject\",\"inLanguage\":\"es\",\"@id\":\"https:\\\/\\\/learnbydoing.dev\\\/smarter-path-planning-in-ros-2-implementing-a-in-python\\\/#primaryimage\",\"url\":\"https:\\\/\\\/learnbydoing.dev\\\/wp-content\\\/uploads\\\/2025\\\/07\\\/A-1.webp\",\"contentUrl\":\"https:\\\/\\\/learnbydoing.dev\\\/wp-content\\\/uploads\\\/2025\\\/07\\\/A-1.webp\",\"width\":1920,\"height\":1080},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\\\/\\\/learnbydoing.dev\\\/smarter-path-planning-in-ros-2-implementing-a-in-python\\\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\\\/\\\/learnbydoing.dev\\\/es\\\/learn-by-doing-es\\\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Smarter Path Planning in ROS 2: Implementing A* in Python\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\\\/\\\/learnbydoing.dev\\\/es\\\/#website\",\"url\":\"https:\\\/\\\/learnbydoing.dev\\\/es\\\/\",\"name\":\"Learn by Doing!\",\"description\":\"Learn Robotics the fun way\",\"publisher\":{\"@id\":\"https:\\\/\\\/learnbydoing.dev\\\/es\\\/#organization\"},\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\\\/\\\/learnbydoing.dev\\\/es\\\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"es\"},{\"@type\":\"Organization\",\"@id\":\"https:\\\/\\\/learnbydoing.dev\\\/es\\\/#organization\",\"name\":\"Learn by Doing!\",\"url\":\"https:\\\/\\\/learnbydoing.dev\\\/es\\\/\",\"logo\":{\"@type\":\"ImageObject\",\"inLanguage\":\"es\",\"@id\":\"https:\\\/\\\/learnbydoing.dev\\\/es\\\/#\\\/schema\\\/logo\\\/image\\\/\",\"url\":\"https:\\\/\\\/learnbydoing.dev\\\/wp-content\\\/uploads\\\/2025\\\/06\\\/cropped-cropped-cropped-Progetto-senza-titolo-6-1.png\",\"contentUrl\":\"https:\\\/\\\/learnbydoing.dev\\\/wp-content\\\/uploads\\\/2025\\\/06\\\/cropped-cropped-cropped-Progetto-senza-titolo-6-1.png\",\"width\":512,\"height\":512,\"caption\":\"Learn by Doing!\"},\"image\":{\"@id\":\"https:\\\/\\\/learnbydoing.dev\\\/es\\\/#\\\/schema\\\/logo\\\/image\\\/\"},\"sameAs\":[\"https:\\\/\\\/www.linkedin.com\\\/in\\\/antonio-brandi-512166bb\\\/\"]},{\"@type\":\"Person\",\"@id\":\"\",\"url\":\"https:\\\/\\\/learnbydoing.dev\\\/es\\\/author\\\/\"}]}<\/script>\n<!-- \/ Yoast SEO plugin. -->","yoast_head_json":{"title":"Smarter Path Planning in ROS 2: Implementing A* in Python - Learn by Doing!","description":"Implement A* path planning in ROS 2 using Python. Use an occupancy grid, heuristic-driven search, and RViz visualization.","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/learnbydoing.dev\/es\/smarter-path-planning-in-ros-2-implementing-a-in-python\/","og_locale":"es_ES","og_type":"article","og_title":"Smarter Path Planning in ROS 2: Implementing A* in Python","og_description":"Learn by Doing!","og_url":"https:\/\/learnbydoing.dev\/es\/smarter-path-planning-in-ros-2-implementing-a-in-python\/","og_site_name":"Learn by Doing!","article_published_time":"2025-07-21T10:08:42+00:00","article_modified_time":"2026-01-10T22:16:43+00:00","og_image":[{"width":1920,"height":1080,"url":"https:\/\/learnbydoing.dev\/wp-content\/uploads\/2025\/07\/A-1.webp","type":"image\/webp"}],"twitter_card":"summary_large_image","twitter_misc":{"Escrito por":"","Tiempo de lectura":"8 minutos"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"Article","@id":"https:\/\/learnbydoing.dev\/smarter-path-planning-in-ros-2-implementing-a-in-python\/#article","isPartOf":{"@id":"https:\/\/learnbydoing.dev\/smarter-path-planning-in-ros-2-implementing-a-in-python\/"},"author":{"name":"","@id":""},"headline":"Smarter Path Planning in ROS 2: Implementing A* in Python","datePublished":"2025-07-21T10:08:42+00:00","dateModified":"2026-01-10T22:16:43+00:00","mainEntityOfPage":{"@id":"https:\/\/learnbydoing.dev\/smarter-path-planning-in-ros-2-implementing-a-in-python\/"},"wordCount":807,"publisher":{"@id":"https:\/\/learnbydoing.dev\/es\/#organization"},"image":{"@id":"https:\/\/learnbydoing.dev\/smarter-path-planning-in-ros-2-implementing-a-in-python\/#primaryimage"},"thumbnailUrl":"https:\/\/learnbydoing.dev\/wp-content\/uploads\/2025\/07\/A-1.webp","keywords":["A","algorithm","autonomus","Base","dijkstra","learn by doing","Linux","navigation","plan","py","robot","Robotics","ROS","ROS 2","ROS2","star"],"articleSection":["Nav2","ROS 2","Tutorials"],"inLanguage":"es"},{"@type":"WebPage","@id":"https:\/\/learnbydoing.dev\/smarter-path-planning-in-ros-2-implementing-a-in-python\/","url":"https:\/\/learnbydoing.dev\/smarter-path-planning-in-ros-2-implementing-a-in-python\/","name":"Smarter Path Planning in ROS 2: Implementing A* in Python - Learn by Doing!","isPartOf":{"@id":"https:\/\/learnbydoing.dev\/es\/#website"},"primaryImageOfPage":{"@id":"https:\/\/learnbydoing.dev\/smarter-path-planning-in-ros-2-implementing-a-in-python\/#primaryimage"},"image":{"@id":"https:\/\/learnbydoing.dev\/smarter-path-planning-in-ros-2-implementing-a-in-python\/#primaryimage"},"thumbnailUrl":"https:\/\/learnbydoing.dev\/wp-content\/uploads\/2025\/07\/A-1.webp","datePublished":"2025-07-21T10:08:42+00:00","dateModified":"2026-01-10T22:16:43+00:00","description":"Implement A* path planning in ROS 2 using Python. Use an occupancy grid, heuristic-driven search, and RViz visualization.","breadcrumb":{"@id":"https:\/\/learnbydoing.dev\/smarter-path-planning-in-ros-2-implementing-a-in-python\/#breadcrumb"},"inLanguage":"es","potentialAction":[{"@type":"ReadAction","target":["https:\/\/learnbydoing.dev\/smarter-path-planning-in-ros-2-implementing-a-in-python\/"]}]},{"@type":"ImageObject","inLanguage":"es","@id":"https:\/\/learnbydoing.dev\/smarter-path-planning-in-ros-2-implementing-a-in-python\/#primaryimage","url":"https:\/\/learnbydoing.dev\/wp-content\/uploads\/2025\/07\/A-1.webp","contentUrl":"https:\/\/learnbydoing.dev\/wp-content\/uploads\/2025\/07\/A-1.webp","width":1920,"height":1080},{"@type":"BreadcrumbList","@id":"https:\/\/learnbydoing.dev\/smarter-path-planning-in-ros-2-implementing-a-in-python\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/learnbydoing.dev\/es\/learn-by-doing-es\/"},{"@type":"ListItem","position":2,"name":"Smarter Path Planning in ROS 2: Implementing A* in Python"}]},{"@type":"WebSite","@id":"https:\/\/learnbydoing.dev\/es\/#website","url":"https:\/\/learnbydoing.dev\/es\/","name":"Learn by Doing!","description":"Learn Robotics the fun way","publisher":{"@id":"https:\/\/learnbydoing.dev\/es\/#organization"},"potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/learnbydoing.dev\/es\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"es"},{"@type":"Organization","@id":"https:\/\/learnbydoing.dev\/es\/#organization","name":"Learn by Doing!","url":"https:\/\/learnbydoing.dev\/es\/","logo":{"@type":"ImageObject","inLanguage":"es","@id":"https:\/\/learnbydoing.dev\/es\/#\/schema\/logo\/image\/","url":"https:\/\/learnbydoing.dev\/wp-content\/uploads\/2025\/06\/cropped-cropped-cropped-Progetto-senza-titolo-6-1.png","contentUrl":"https:\/\/learnbydoing.dev\/wp-content\/uploads\/2025\/06\/cropped-cropped-cropped-Progetto-senza-titolo-6-1.png","width":512,"height":512,"caption":"Learn by Doing!"},"image":{"@id":"https:\/\/learnbydoing.dev\/es\/#\/schema\/logo\/image\/"},"sameAs":["https:\/\/www.linkedin.com\/in\/antonio-brandi-512166bb\/"]},{"@type":"Person","@id":"","url":"https:\/\/learnbydoing.dev\/es\/author\/"}]}},"_links":{"self":[{"href":"https:\/\/learnbydoing.dev\/es\/wp-json\/wp\/v2\/posts\/2932","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/learnbydoing.dev\/es\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/learnbydoing.dev\/es\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/learnbydoing.dev\/es\/wp-json\/wp\/v2\/users\/4"}],"replies":[{"embeddable":true,"href":"https:\/\/learnbydoing.dev\/es\/wp-json\/wp\/v2\/comments?post=2932"}],"version-history":[{"count":37,"href":"https:\/\/learnbydoing.dev\/es\/wp-json\/wp\/v2\/posts\/2932\/revisions"}],"predecessor-version":[{"id":5541,"href":"https:\/\/learnbydoing.dev\/es\/wp-json\/wp\/v2\/posts\/2932\/revisions\/5541"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/learnbydoing.dev\/es\/wp-json\/wp\/v2\/media\/2999"}],"wp:attachment":[{"href":"https:\/\/learnbydoing.dev\/es\/wp-json\/wp\/v2\/media?parent=2932"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/learnbydoing.dev\/es\/wp-json\/wp\/v2\/categories?post=2932"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/learnbydoing.dev\/es\/wp-json\/wp\/v2\/tags?post=2932"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}