diff --git a/nav2_behavior_tree/plugins/condition/goal_reached_condition.cpp b/nav2_behavior_tree/plugins/condition/goal_reached_condition.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..e3c2cd02b8cdad09668ba621b1922ccdeda411a2
--- /dev/null
+++ b/nav2_behavior_tree/plugins/condition/goal_reached_condition.cpp
@@ -0,0 +1,118 @@
+// Copyright (c) 2019 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.
+
+#ifndef NAV2_BEHAVIOR_TREE__GOAL_REACHED_CONDITION_HPP_
+#define NAV2_BEHAVIOR_TREE__GOAL_REACHED_CONDITION_HPP_
+
+#include <string>
+#include <memory>
+
+#include "rclcpp/rclcpp.hpp"
+#include "behaviortree_cpp_v3/condition_node.h"
+#include "nav2_util/robot_utils.hpp"
+#include "geometry_msgs/msg/pose_stamped.hpp"
+#include "tf2_ros/buffer.h"
+
+namespace nav2_behavior_tree
+{
+
+class GoalReachedCondition : public BT::ConditionNode
+{
+public:
+  GoalReachedCondition(
+    const std::string & condition_name,
+    const BT::NodeConfiguration & conf)
+  : BT::ConditionNode(condition_name, conf), initialized_(false)
+  {
+  }
+
+  GoalReachedCondition() = delete;
+
+  ~GoalReachedCondition()
+  {
+    cleanup();
+  }
+
+  BT::NodeStatus tick() override
+  {
+    if (!initialized_) {
+      initialize();
+    }
+
+    if (isGoalReached()) {
+      return BT::NodeStatus::SUCCESS;
+    }
+    return BT::NodeStatus::FAILURE;
+  }
+
+  void initialize()
+  {
+    node_ = config().blackboard->get<rclcpp::Node::SharedPtr>("node");
+    node_->get_parameter_or<double>("goal_reached_tol", goal_reached_tol_, 0.25);
+    tf_ = config().blackboard->get<std::shared_ptr<tf2_ros::Buffer>>("tf_buffer");
+
+    initialized_ = true;
+  }
+
+  bool
+  isGoalReached()
+  {
+    geometry_msgs::msg::PoseStamped current_pose;
+
+    if (!nav2_util::getCurrentPose(current_pose, *tf_)) {
+      RCLCPP_DEBUG(node_->get_logger(), "Current robot pose is not available.");
+      return false;
+    }
+
+    geometry_msgs::msg::PoseStamped goal;
+    getInput("goal", goal);
+    double dx = goal.pose.position.x - current_pose.pose.position.x;
+    double dy = goal.pose.position.y - current_pose.pose.position.y;
+
+    if ( (dx * dx + dy * dy) <= (goal_reached_tol_ * goal_reached_tol_) ) {
+      return true;
+    } else {
+      return false;
+    }
+  }
+
+  static BT::PortsList providedPorts()
+  {
+    return {
+      BT::InputPort<geometry_msgs::msg::PoseStamped>("goal", "Destination")
+    };
+  }
+
+protected:
+  void cleanup()
+  {
+  }
+
+private:
+  rclcpp::Node::SharedPtr node_;
+  std::shared_ptr<tf2_ros::Buffer> tf_;
+
+  bool initialized_;
+  double goal_reached_tol_;
+};
+
+}  // namespace nav2_behavior_tree
+
+#include "behaviortree_cpp_v3/bt_factory.h"
+BT_REGISTER_NODES(factory)
+{
+  factory.registerNodeType<nav2_behavior_tree::GoalReachedCondition>("GoalReached");
+}
+
+#endif  // NAV2_BEHAVIOR_TREE__GOAL_REACHED_CONDITION_HPP_
diff --git a/nav2_behavior_tree/plugins/condition/initial_pose_received_condition.cpp b/nav2_behavior_tree/plugins/condition/initial_pose_received_condition.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..d3bb46989e8457c767cadeac5a59df3b7ec70938
--- /dev/null
+++ b/nav2_behavior_tree/plugins/condition/initial_pose_received_condition.cpp
@@ -0,0 +1,39 @@
+// Copyright (c) 2019 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.
+
+#ifndef NAV2_BEHAVIOR_TREE__INITIAL_POSE_RECEIVED_CONDITION_HPP_
+#define NAV2_BEHAVIOR_TREE__INITIAL_POSE_RECEIVED_CONDITION_HPP_
+
+#include "behaviortree_cpp_v3/behavior_tree.h"
+
+
+namespace nav2_behavior_tree
+{
+
+BT::NodeStatus initialPoseReceived(BT::TreeNode & tree_node)
+{
+  auto initPoseReceived = tree_node.config().blackboard->get<bool>("initial_pose_received");
+  return initPoseReceived ? BT::NodeStatus::SUCCESS : BT::NodeStatus::FAILURE;
+}
+
+}  // namespace nav2_behavior_tree
+
+#include "behaviortree_cpp_v3/bt_factory.h"
+BT_REGISTER_NODES(factory)
+{
+  factory.registerSimpleCondition("InitialPoseReceived",
+    std::bind(&nav2_behavior_tree::initialPoseReceived, std::placeholders::_1));
+}
+
+#endif  // NAV2_BEHAVIOR_TREE__INITIAL_POSE_RECEIVED_CONDITION_HPP_
diff --git a/nav2_behavior_tree/plugins/condition/is_stuck_condition.cpp b/nav2_behavior_tree/plugins/condition/is_stuck_condition.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..145dc4c8f95c49287e5b7d16c9f1c37ff7a8440b
--- /dev/null
+++ b/nav2_behavior_tree/plugins/condition/is_stuck_condition.cpp
@@ -0,0 +1,175 @@
+// 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.
+
+#ifndef NAV2_BEHAVIOR_TREE__IS_STUCK_CONDITION_HPP_
+#define NAV2_BEHAVIOR_TREE__IS_STUCK_CONDITION_HPP_
+
+#include <string>
+#include <chrono>
+#include <cmath>
+#include <atomic>
+#include <memory>
+#include <deque>
+
+#include "rclcpp/rclcpp.hpp"
+#include "behaviortree_cpp_v3/condition_node.h"
+#include "nav_msgs/msg/odometry.hpp"
+
+using namespace std::chrono_literals; // NOLINT
+
+namespace nav2_behavior_tree
+{
+
+class IsStuckCondition : public BT::ConditionNode
+{
+public:
+  IsStuckCondition(
+    const std::string & condition_name,
+    const BT::NodeConfiguration & conf)
+  : BT::ConditionNode(condition_name, conf),
+    is_stuck_(false),
+    odom_history_size_(10),
+    current_accel_(0.0),
+    brake_accel_limit_(-10.0)
+  {
+    node_ = config().blackboard->get<rclcpp::Node::SharedPtr>("node");
+
+    odom_sub_ = node_->create_subscription<nav_msgs::msg::Odometry>("odom",
+        rclcpp::SystemDefaultsQoS(),
+        std::bind(&IsStuckCondition::onOdomReceived, this, std::placeholders::_1));
+
+    RCLCPP_DEBUG(node_->get_logger(), "Initialized an IsStuckCondition BT node");
+
+    RCLCPP_INFO_ONCE(node_->get_logger(), "Waiting on odometry");
+  }
+
+  IsStuckCondition() = delete;
+
+  ~IsStuckCondition()
+  {
+    RCLCPP_DEBUG(node_->get_logger(), "Shutting down IsStuckCondition BT node");
+  }
+
+  void onOdomReceived(const typename nav_msgs::msg::Odometry::SharedPtr msg)
+  {
+    RCLCPP_INFO_ONCE(node_->get_logger(), "Got odometry");
+
+    while (odom_history_.size() >= odom_history_size_) {
+      odom_history_.pop_front();
+    }
+
+    odom_history_.push_back(*msg);
+
+    // TODO(orduno) #383 Move the state calculation and is stuck to robot class
+    updateStates();
+  }
+
+  BT::NodeStatus tick() override
+  {
+    // TODO(orduno) #383 Once check for is stuck and state calculations are moved to robot class
+    //              this becomes
+    // if (robot_state_.isStuck()) {
+
+    if (is_stuck_) {
+      logStuck("Robot got stuck!");
+      return BT::NodeStatus::SUCCESS;  // Successfully detected a stuck condition
+    }
+
+    logStuck("Robot is free");
+    return BT::NodeStatus::FAILURE;  // Failed to detected a stuck condition
+  }
+
+  void logStuck(const std::string & msg) const
+  {
+    static std::string prev_msg;
+
+    if (msg == prev_msg) {
+      return;
+    }
+
+    RCLCPP_INFO(node_->get_logger(), msg);
+    prev_msg = msg;
+  }
+
+  void updateStates()
+  {
+    // Approximate acceleration
+    // TODO(orduno) #400 Smooth out velocity history for better accel approx.
+    if (odom_history_.size() > 2) {
+      auto curr_odom = odom_history_.end()[-1];
+      double curr_time = static_cast<double>(curr_odom.header.stamp.sec);
+      curr_time += (static_cast<double>(curr_odom.header.stamp.nanosec)) * 1e-9;
+
+      auto prev_odom = odom_history_.end()[-2];
+      double prev_time = static_cast<double>(prev_odom.header.stamp.sec);
+      prev_time += (static_cast<double>(prev_odom.header.stamp.nanosec)) * 1e-9;
+
+      double dt = curr_time - prev_time;
+      double vel_diff = static_cast<double>(
+        curr_odom.twist.twist.linear.x - prev_odom.twist.twist.linear.x);
+      current_accel_ = vel_diff / dt;
+    }
+
+    is_stuck_ = isStuck();
+  }
+
+  bool isStuck()
+  {
+    // TODO(orduno) #400 The robot getting stuck can result on different types of motion
+    // depending on the state prior to getting stuck (sudden change in accel, not moving at all,
+    // random oscillations, etc). For now, we only address the case where there is a sudden
+    // harsh deceleration. A better approach to capture all situations would be to do a forward
+    // simulation of the robot motion and compare it with the actual one.
+
+    // Detect if robot bumped into something by checking for abnormal deceleration
+    if (current_accel_ < brake_accel_limit_) {
+      RCLCPP_DEBUG(node_->get_logger(), "Current deceleration is beyond brake limit."
+        " brake limit: %.2f, current accel: %.2f", brake_accel_limit_, current_accel_);
+
+      return true;
+    }
+
+    return false;
+  }
+
+  static BT::PortsList providedPorts() {return {};}
+
+private:
+  // The node that will be used for any ROS operations
+  rclcpp::Node::SharedPtr node_;
+
+  std::atomic<bool> is_stuck_;
+
+  // Listen to odometry
+  rclcpp::Subscription<nav_msgs::msg::Odometry>::SharedPtr odom_sub_;
+  // Store history of odometry measurements
+  std::deque<nav_msgs::msg::Odometry> odom_history_;
+  std::deque<nav_msgs::msg::Odometry>::size_type odom_history_size_;
+
+  // Calculated states
+  double current_accel_;
+
+  // Robot specific paramters
+  double brake_accel_limit_;
+};
+
+}  // namespace nav2_behavior_tree
+
+#include "behaviortree_cpp_v3/bt_factory.h"
+BT_REGISTER_NODES(factory)
+{
+  factory.registerNodeType<nav2_behavior_tree::IsStuckCondition>("IsStuck");
+}
+
+#endif  // NAV2_BEHAVIOR_TREE__IS_STUCK_CONDITION_HPP_