Skip to content
Snippets Groups Projects
Commit be8cd1e9 authored by Michael Jeronimo's avatar Michael Jeronimo Committed by Carl Delsey
Browse files

Port the world model lifecycle to lifecycle nodes (#654)

* Port the world model to lifecycle nodes
* Remove a couple stray printfs
* Address review feedback
parent cd96d034
No related branches found
No related tags found
No related merge requests found
...@@ -7,6 +7,7 @@ find_package(rclcpp REQUIRED) ...@@ -7,6 +7,7 @@ find_package(rclcpp REQUIRED)
find_package(nav2_util) find_package(nav2_util)
find_package(nav2_msgs) find_package(nav2_msgs)
find_package(nav2_costmap_2d REQUIRED) find_package(nav2_costmap_2d REQUIRED)
find_package(nav2_lifecycle REQUIRED)
find_package(tf2_ros REQUIRED) find_package(tf2_ros REQUIRED)
nav2_package() nav2_package()
...@@ -32,6 +33,7 @@ set(dependencies ...@@ -32,6 +33,7 @@ set(dependencies
nav2_util nav2_util
nav2_msgs nav2_msgs
nav2_costmap_2d nav2_costmap_2d
nav2_lifecycle
tf2_ros tf2_ros
) )
......
...@@ -15,37 +15,50 @@ ...@@ -15,37 +15,50 @@
#ifndef NAV2_WORLD_MODEL__WORLD_MODEL_HPP_ #ifndef NAV2_WORLD_MODEL__WORLD_MODEL_HPP_
#define NAV2_WORLD_MODEL__WORLD_MODEL_HPP_ #define NAV2_WORLD_MODEL__WORLD_MODEL_HPP_
#include <string>
#include <vector>
#include <memory> #include <memory>
#include <thread>
#include "nav2_costmap_2d/costmap_2d_ros.hpp" #include "nav2_costmap_2d/costmap_2d_ros.hpp"
#include "rclcpp/rclcpp.hpp" #include "nav2_lifecycle/lifecycle_node.hpp"
#include "nav2_util/costmap.hpp"
#include "nav2_msgs/msg/costmap.hpp" #include "nav2_msgs/msg/costmap.hpp"
#include "nav2_msgs/srv/get_costmap.hpp" #include "nav2_msgs/srv/get_costmap.hpp"
#include "tf2_ros/transform_listener.h"
namespace nav2_world_model namespace nav2_world_model
{ {
class WorldModel : public rclcpp::Node class WorldModel : public nav2_lifecycle::LifecycleNode
{ {
public: public:
WorldModel(rclcpp::executor::Executor & executor, const std::string & name); WorldModel();
explicit WorldModel(rclcpp::executor::Executor & executor); ~WorldModel();
protected:
// Implement the lifecycle interface
nav2_lifecycle::CallbackReturn on_configure(const rclcpp_lifecycle::State & state) override;
nav2_lifecycle::CallbackReturn on_activate(const rclcpp_lifecycle::State & state) override;
nav2_lifecycle::CallbackReturn on_deactivate(const rclcpp_lifecycle::State & state) override;
nav2_lifecycle::CallbackReturn on_cleanup(const rclcpp_lifecycle::State & state) override;
nav2_lifecycle::CallbackReturn on_shutdown(const rclcpp_lifecycle::State & state) override;
nav2_lifecycle::CallbackReturn on_error(const rclcpp_lifecycle::State & state) override;
// The WorldModel provides the GetCostmap service
rclcpp::Service<nav2_msgs::srv::GetCostmap>::SharedPtr costmap_service_;
private: // The callback for the GetCostmap service
void costmap_callback( void costmap_service_callback(
const std::shared_ptr<rmw_request_id_t> request_header, const std::shared_ptr<rmw_request_id_t> request_header,
const std::shared_ptr<nav2_msgs::srv::GetCostmap::Request> request, const std::shared_ptr<nav2_msgs::srv::GetCostmap::Request> request,
const std::shared_ptr<nav2_msgs::srv::GetCostmap::Response> response); const std::shared_ptr<nav2_msgs::srv::GetCostmap::Response> response);
// Server for providing a costmap // The implementation of the WorldModel uses a Costmap2DROS node
rclcpp::Service<nav2_msgs::srv::GetCostmap>::SharedPtr costmapServer_;
std::shared_ptr<nav2_costmap_2d::Costmap2DROS> costmap_ros_; std::shared_ptr<nav2_costmap_2d::Costmap2DROS> costmap_ros_;
nav2_costmap_2d::Costmap2D * costmap_;
tf2_ros::Buffer tfBuffer_; // The thread for the Costmap2DROS node
tf2_ros::TransformListener tfListener_; std::unique_ptr<std::thread> costmap_thread_;
// The frame_id and metadata layer values used in the service response message
static constexpr const char * frame_id_{"map"};
static constexpr const char * metadata_layer_{"Master"};
}; };
} // namespace nav2_world_model } // namespace nav2_world_model
......
...@@ -8,18 +8,19 @@ ...@@ -8,18 +8,19 @@
<license>Apache License 2.0</license> <license>Apache License 2.0</license>
<buildtool_depend>ament_cmake</buildtool_depend> <buildtool_depend>ament_cmake</buildtool_depend>
<build_depend>nav2_common</build_depend>
<build_depend>rclcpp</build_depend> <build_depend>rclcpp</build_depend>
<build_depend>nav2_util</build_depend> <build_depend>nav2_util</build_depend>
<build_depend>nav2_msgs</build_depend> <build_depend>nav2_msgs</build_depend>
<build_depend>nav2_costmap_2d</build_depend> <build_depend>nav2_costmap_2d</build_depend>
<build_depend>nav2_lifecycle</build_depend>
<build_depend>tf2_ros</build_depend> <build_depend>tf2_ros</build_depend>
<exec_depend>rclcpp</exec_depend> <exec_depend>rclcpp</exec_depend>
<exec_depend>nav2_util</exec_depend> <exec_depend>nav2_util</exec_depend>
<exec_depend>nav2_msgs</exec_depend> <exec_depend>nav2_msgs</exec_depend>
<exec_depend>nav2_costmap_2d</exec_depend> <exec_depend>nav2_costmap_2d</exec_depend>
<exec_depend>nav2_lifecycle</exec_depend>
<exec_depend>tf2_ros</exec_depend> <exec_depend>tf2_ros</exec_depend>
<test_depend>ament_lint_common</test_depend> <test_depend>ament_lint_common</test_depend>
......
...@@ -10,19 +10,18 @@ ...@@ -10,19 +10,18 @@
// distributed under the License is distributed on an "AS IS" BASIS, // distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and // See the License for the specific language governing permissions and
// limitations under the License. Reserved. // limitations under the License.
#include <memory> #include <memory>
#include "rclcpp/rclcpp.hpp"
#include "nav2_world_model/world_model.hpp" #include "nav2_world_model/world_model.hpp"
#include "rclcpp/rclcpp.hpp"
int main(int argc, char ** argv) int main(int argc, char ** argv)
{ {
rclcpp::init(argc, argv); rclcpp::init(argc, argv);
rclcpp::executors::SingleThreadedExecutor exec; auto node = std::make_shared<nav2_world_model::WorldModel>();
auto world_model_node = std::make_shared<nav2_world_model::WorldModel>(exec); rclcpp::spin(node->get_node_base_interface());
exec.add_node(world_model_node);
exec.spin();
rclcpp::shutdown(); rclcpp::shutdown();
return 0; return 0;
......
...@@ -12,67 +12,127 @@ ...@@ -12,67 +12,127 @@
// See the License for the specific language governing permissions and // See the License for the specific language governing permissions and
// limitations under the License. // limitations under the License.
#include <iostream>
#include <memory>
#include <vector>
#include <string>
#include "nav2_world_model/world_model.hpp" #include "nav2_world_model/world_model.hpp"
using std::vector; #include <memory>
using std::string;
namespace nav2_world_model namespace nav2_world_model
{ {
WorldModel::WorldModel(rclcpp::executor::Executor & executor, const string & name) WorldModel::WorldModel()
: Node(name), : nav2_lifecycle::LifecycleNode("world_model")
tfBuffer_(get_clock()), {
tfListener_(tfBuffer_) RCLCPP_INFO(get_logger(), "Creating");
// The costmap node is used in the implementation of the world model
costmap_ros_ = std::make_shared<nav2_costmap_2d::Costmap2DROS>("world_model_global_costmap");
// Launch a thread to run the costmap node
costmap_thread_ = std::make_unique<std::thread>(
[](rclcpp_lifecycle::LifecycleNode::SharedPtr node)
{rclcpp::spin(node->get_node_base_interface());}, costmap_ros_);
}
WorldModel::~WorldModel()
{
RCLCPP_INFO(get_logger(), "Destroying");
costmap_thread_->join();
}
nav2_lifecycle::CallbackReturn
WorldModel::on_configure(const rclcpp_lifecycle::State & state)
{ {
costmap_ros_ = std::make_shared<nav2_costmap_2d::Costmap2DROS>("global_costmap", tfBuffer_); RCLCPP_INFO(get_logger(), "Configuring");
costmap_ = costmap_ros_->getCostmap();
executor.add_node(costmap_ros_); costmap_ros_->on_configure(state);
// Create a service that will use the callback function to handle requests. // Create a service that will use the callback function to handle requests
costmapServer_ = create_service<nav2_msgs::srv::GetCostmap>("GetCostmap", costmap_service_ = create_service<nav2_msgs::srv::GetCostmap>("GetCostmap",
std::bind(&WorldModel::costmap_callback, this, std::bind(&WorldModel::costmap_service_callback, this,
std::placeholders::_1, std::placeholders::_2, std::placeholders::_3)); std::placeholders::_1, std::placeholders::_2, std::placeholders::_3));
return nav2_lifecycle::CallbackReturn::SUCCESS;
}
nav2_lifecycle::CallbackReturn
WorldModel::on_activate(const rclcpp_lifecycle::State & state)
{
RCLCPP_INFO(get_logger(), "Activating");
costmap_ros_->on_activate(state);
return nav2_lifecycle::CallbackReturn::SUCCESS;
}
nav2_lifecycle::CallbackReturn
WorldModel::on_deactivate(const rclcpp_lifecycle::State & state)
{
RCLCPP_INFO(get_logger(), "Deactivating");
costmap_ros_->on_deactivate(state);
return nav2_lifecycle::CallbackReturn::SUCCESS;
}
nav2_lifecycle::CallbackReturn
WorldModel::on_cleanup(const rclcpp_lifecycle::State & state)
{
RCLCPP_INFO(get_logger(), "Cleaning up");
costmap_ros_->on_cleanup(state);
costmap_service_.reset();
return nav2_lifecycle::CallbackReturn::SUCCESS;
}
nav2_lifecycle::CallbackReturn
WorldModel::on_error(const rclcpp_lifecycle::State & /*state*/)
{
RCLCPP_ERROR(get_logger(), "Handling error state");
return nav2_lifecycle::CallbackReturn::SUCCESS;
} }
void WorldModel::costmap_callback( nav2_lifecycle::CallbackReturn
WorldModel::on_shutdown(const rclcpp_lifecycle::State & /*state*/)
{
RCLCPP_INFO(get_logger(), "Shutting down");
return nav2_lifecycle::CallbackReturn::SUCCESS;
}
void
WorldModel::costmap_service_callback(
const std::shared_ptr<rmw_request_id_t>/*request_header*/, const std::shared_ptr<rmw_request_id_t>/*request_header*/,
const std::shared_ptr<nav2_msgs::srv::GetCostmap::Request>/*request*/, const std::shared_ptr<nav2_msgs::srv::GetCostmap::Request>/*request*/,
const std::shared_ptr<nav2_msgs::srv::GetCostmap::Response> response) const std::shared_ptr<nav2_msgs::srv::GetCostmap::Response> response)
{ {
RCLCPP_INFO(this->get_logger(), "Received costmap request"); RCLCPP_INFO(get_logger(), "Received costmap service request");
response->map.metadata.size_x = costmap_->getSizeInCellsX();
response->map.metadata.size_y = costmap_->getSizeInCellsY();
response->map.metadata.resolution = costmap_->getResolution();
response->map.metadata.layer = "Master";
response->map.metadata.map_load_time = now();
response->map.metadata.update_time = now();
tf2::Quaternion quaternion;
// TODO(bpwilcox): Grab correct orientation information // TODO(bpwilcox): Grab correct orientation information
quaternion.setRPY(0.0, 0.0, 0.0); // set roll, pitch, yaw tf2::Quaternion quaternion;
quaternion.setRPY(0.0, 0.0, 0.0);
nav2_costmap_2d::Costmap2D * costmap_ = costmap_ros_->getCostmap();
auto size_x = costmap_->getSizeInCellsX();
auto size_y = costmap_->getSizeInCellsY();
auto data_length = size_x * size_y;
unsigned char * data = costmap_->getCharMap();
auto current_time = now();
response->map.header.stamp = current_time;
response->map.header.frame_id = frame_id_;
response->map.metadata.size_x = size_x;
response->map.metadata.size_y = size_y;
response->map.metadata.resolution = costmap_->getResolution();
response->map.metadata.layer = metadata_layer_;
response->map.metadata.map_load_time = current_time;
response->map.metadata.update_time = current_time;
response->map.metadata.origin.position.x = costmap_->getOriginX(); response->map.metadata.origin.position.x = costmap_->getOriginX();
response->map.metadata.origin.position.y = costmap_->getOriginY(); response->map.metadata.origin.position.y = costmap_->getOriginY();
response->map.metadata.origin.position.z = 0.0; response->map.metadata.origin.position.z = 0.0;
response->map.metadata.origin.orientation = tf2::toMsg(quaternion); response->map.metadata.origin.orientation = tf2::toMsg(quaternion);
response->map.header.stamp = now();
response->map.header.frame_id = "map";
unsigned char * data = costmap_->getCharMap();
auto data_length = response->map.metadata.size_x * response->map.metadata.size_y;
response->map.data.resize(data_length); response->map.data.resize(data_length);
response->map.data.assign(data, data + data_length); response->map.data.assign(data, data + data_length);
} }
WorldModel::WorldModel(rclcpp::executor::Executor & executor)
: WorldModel(executor, "world_model")
{
}
} // namespace nav2_world_model } // namespace nav2_world_model
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment