add humble-navigation2

This commit is contained in:
X-lanni
2025-05-27 19:03:40 +08:00
parent 974abb5e1e
commit e74ec539c2
1280 changed files with 204114 additions and 0 deletions
@@ -0,0 +1,30 @@
// Copyright (c) 2018 Intel Corporation
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#include <memory>
#include <stdexcept>
#include <string>
#include "nav2_map_server/map_server.hpp"
#include "rclcpp/rclcpp.hpp"
int main(int argc, char ** argv)
{
std::string node_name("map_server");
rclcpp::init(argc, argv);
auto node = std::make_shared<nav2_map_server::MapServer>();
rclcpp::spin(node->get_node_base_interface());
rclcpp::shutdown();
}
@@ -0,0 +1,257 @@
/* Copyright (c) 2018 Intel Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/* Copyright 2019 Rover Robotics
* Copyright 2010 Brian Gerkey
* Copyright (c) 2008, Willow Garage, Inc.
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* * Neither the name of the Willow Garage, Inc. nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
#include "nav2_map_server/map_server.hpp"
#include <string>
#include <memory>
#include <fstream>
#include <stdexcept>
#include <utility>
#include "yaml-cpp/yaml.h"
#include "lifecycle_msgs/msg/state.hpp"
#include "nav2_map_server/map_io.hpp"
using namespace std::chrono_literals;
using namespace std::placeholders;
namespace nav2_map_server
{
MapServer::MapServer(const rclcpp::NodeOptions & options)
: nav2_util::LifecycleNode("map_server", "", options), map_available_(false)
{
RCLCPP_INFO(get_logger(), "Creating");
// Declare the node parameters
declare_parameter("yaml_filename", rclcpp::PARAMETER_STRING);
declare_parameter("topic_name", "map");
declare_parameter("frame_id", "map");
}
MapServer::~MapServer()
{
}
nav2_util::CallbackReturn
MapServer::on_configure(const rclcpp_lifecycle::State & /*state*/)
{
RCLCPP_INFO(get_logger(), "Configuring");
// Get the name of the YAML file to use (can be empty if no initial map should be used)
std::string yaml_filename = get_parameter("yaml_filename").as_string();
std::string topic_name = get_parameter("topic_name").as_string();
frame_id_ = get_parameter("frame_id").as_string();
// only try to load map if parameter was set
if (!yaml_filename.empty()) {
// Shared pointer to LoadMap::Response is also should be initialized
// in order to avoid null-pointer dereference
std::shared_ptr<nav2_msgs::srv::LoadMap::Response> rsp =
std::make_shared<nav2_msgs::srv::LoadMap::Response>();
if (!loadMapResponseFromYaml(yaml_filename, rsp)) {
throw std::runtime_error("Failed to load map yaml file: " + yaml_filename);
}
} else {
RCLCPP_INFO(
get_logger(),
"yaml-filename parameter is empty, set map through '%s'-service",
load_map_service_name_.c_str());
}
// Make name prefix for services
const std::string service_prefix = get_name() + std::string("/");
// Create a service that provides the occupancy grid
occ_service_ = create_service<nav_msgs::srv::GetMap>(
service_prefix + std::string(service_name_),
std::bind(&MapServer::getMapCallback, this, _1, _2, _3));
// Create a publisher using the QoS settings to emulate a ROS1 latched topic
occ_pub_ = create_publisher<nav_msgs::msg::OccupancyGrid>(
topic_name,
rclcpp::QoS(rclcpp::KeepLast(1)).transient_local().reliable());
// Create a service that loads the occupancy grid from a file
load_map_service_ = create_service<nav2_msgs::srv::LoadMap>(
service_prefix + std::string(load_map_service_name_),
std::bind(&MapServer::loadMapCallback, this, _1, _2, _3));
return nav2_util::CallbackReturn::SUCCESS;
}
nav2_util::CallbackReturn
MapServer::on_activate(const rclcpp_lifecycle::State & /*state*/)
{
RCLCPP_INFO(get_logger(), "Activating");
// Publish the map using the latched topic
occ_pub_->on_activate();
if (map_available_) {
auto occ_grid = std::make_unique<nav_msgs::msg::OccupancyGrid>(msg_);
occ_pub_->publish(std::move(occ_grid));
}
// create bond connection
createBond();
return nav2_util::CallbackReturn::SUCCESS;
}
nav2_util::CallbackReturn
MapServer::on_deactivate(const rclcpp_lifecycle::State & /*state*/)
{
RCLCPP_INFO(get_logger(), "Deactivating");
occ_pub_->on_deactivate();
// destroy bond connection
destroyBond();
return nav2_util::CallbackReturn::SUCCESS;
}
nav2_util::CallbackReturn
MapServer::on_cleanup(const rclcpp_lifecycle::State & /*state*/)
{
RCLCPP_INFO(get_logger(), "Cleaning up");
occ_pub_.reset();
occ_service_.reset();
load_map_service_.reset();
map_available_ = false;
msg_ = nav_msgs::msg::OccupancyGrid();
return nav2_util::CallbackReturn::SUCCESS;
}
nav2_util::CallbackReturn
MapServer::on_shutdown(const rclcpp_lifecycle::State & /*state*/)
{
RCLCPP_INFO(get_logger(), "Shutting down");
return nav2_util::CallbackReturn::SUCCESS;
}
void MapServer::getMapCallback(
const std::shared_ptr<rmw_request_id_t>/*request_header*/,
const std::shared_ptr<nav_msgs::srv::GetMap::Request>/*request*/,
std::shared_ptr<nav_msgs::srv::GetMap::Response> response)
{
// if not in ACTIVE state, ignore request
if (get_current_state().id() != lifecycle_msgs::msg::State::PRIMARY_STATE_ACTIVE) {
RCLCPP_WARN(
get_logger(),
"Received GetMap request but not in ACTIVE state, ignoring!");
return;
}
RCLCPP_INFO(get_logger(), "Handling GetMap request");
response->map = msg_;
}
void MapServer::loadMapCallback(
const std::shared_ptr<rmw_request_id_t>/*request_header*/,
const std::shared_ptr<nav2_msgs::srv::LoadMap::Request> request,
std::shared_ptr<nav2_msgs::srv::LoadMap::Response> response)
{
// if not in ACTIVE state, ignore request
if (get_current_state().id() != lifecycle_msgs::msg::State::PRIMARY_STATE_ACTIVE) {
RCLCPP_WARN(
get_logger(),
"Received LoadMap request but not in ACTIVE state, ignoring!");
response->result = response->RESULT_UNDEFINED_FAILURE;
return;
}
RCLCPP_INFO(get_logger(), "Handling LoadMap request");
// Load from file
if (loadMapResponseFromYaml(request->map_url, response)) {
auto occ_grid = std::make_unique<nav_msgs::msg::OccupancyGrid>(msg_);
occ_pub_->publish(std::move(occ_grid)); // publish new map
}
}
bool MapServer::loadMapResponseFromYaml(
const std::string & yaml_file,
std::shared_ptr<nav2_msgs::srv::LoadMap::Response> response)
{
switch (loadMapFromYaml(yaml_file, msg_)) {
case MAP_DOES_NOT_EXIST:
response->result = nav2_msgs::srv::LoadMap::Response::RESULT_MAP_DOES_NOT_EXIST;
return false;
case INVALID_MAP_METADATA:
response->result = nav2_msgs::srv::LoadMap::Response::RESULT_INVALID_MAP_METADATA;
return false;
case INVALID_MAP_DATA:
response->result = nav2_msgs::srv::LoadMap::Response::RESULT_INVALID_MAP_DATA;
return false;
case LOAD_MAP_SUCCESS:
// Correcting msg_ header when it belongs to specific node
updateMsgHeader();
map_available_ = true;
response->map = msg_;
response->result = nav2_msgs::srv::LoadMap::Response::RESULT_SUCCESS;
}
return true;
}
void MapServer::updateMsgHeader()
{
msg_.info.map_load_time = now();
msg_.header.frame_id = frame_id_;
msg_.header.stamp = now();
}
} // namespace nav2_map_server
#include "rclcpp_components/register_node_macro.hpp"
// Register the component with class_loader.
// This acts as a sort of entry point, allowing the component to be discoverable when its library
// is being loaded into a running process.
RCLCPP_COMPONENTS_REGISTER_NODE(nav2_map_server::MapServer)