diff --git a/doc/parameters/param_list.md b/doc/parameters/param_list.md
index f212425ed60cb879f27eb4b722396e4a7cd8cb32..6682b20369ebffd44fce194075bb5758dc298356 100644
--- a/doc/parameters/param_list.md
+++ b/doc/parameters/param_list.md
@@ -541,13 +541,23 @@ When `planner_plugins` parameter is not overridden, the following default plugin
 | `<waypoint task executor>`.enabled | true | Whether it is enabled |
 | `<waypoint task executor>`.waypoint_pause_duration | 0 | Amount of time in milliseconds, for robot to sleep/wait after each waypoint is reached. If zero, robot will directly continue to next waypoint. |
 
-## InputAtWaypoint plugin
+## PhotoAtWaypoint plugin
 
-* `<waypoint task executor>`: Name corresponding to the `nav2_waypoint_follower::WaitAtWaypoint` plugin. 
+* `<waypoint task executor>`: Name corresponding to the `nav2_waypoint_follower::PhotoAtWaypoint` plugin. 
 
 | Parameter | Default | Description |
 | ----------| --------| ------------|
 | `<waypoint task executor>`.enabled | true | Whether it is enabled |
+| `<waypoint task executor>`.image_topic | "/camera/color/image_raw" | Camera image topic name to susbcribe |
+| `<waypoint task executor>`.save_dir | "/tmp/waypoint_images" | Path to directory to save taken photos |
+| `<waypoint task executor>`.image_format | "png" | Desired image format A few other options; "jpeg" , "jpg", "pgm", "tiff" |
+
+## InputAtWaypoint plugin
+
+* `<waypoint task executor>`: Name corresponding to the `nav2_waypoint_follower::InputAtWaypoint` plugin. 
+
+| Parameter | Default | Description |
+| ----------| --------| ------------|
 | `<waypoint task executor>`.timeout | 10.0 | Amount of time in seconds to wait for user input before moving on to the next waypoint. |
 | `<waypoint task executor>`.input_topic | "input_at_waypoint/input" | Topic input is published to to indicate to move to the next waypoint, in `std_msgs/Empty`. |
 
diff --git a/nav2_bringup/bringup/params/nav2_params.yaml b/nav2_bringup/bringup/params/nav2_params.yaml
index b6925e9f691efac01b57934937eb0683e541820d..3c60d0ae4fbc40db74a75ed269eeab3339a8ff99 100644
--- a/nav2_bringup/bringup/params/nav2_params.yaml
+++ b/nav2_bringup/bringup/params/nav2_params.yaml
@@ -289,8 +289,8 @@ waypoint_follower:
   ros__parameters:
     loop_rate: 20
     stop_on_failure: false
-    waypoint_task_executor_plugin: "waypoint_task_executor"   
-    waypoint_task_executor:
+    waypoint_task_executor_plugin: "wait_at_waypoint"   
+    wait_at_waypoint:
       plugin: "nav2_waypoint_follower::WaitAtWaypoint"
       enabled: True
-      waypoint_pause_duration: 0
+      waypoint_pause_duration: 200
diff --git a/nav2_waypoint_follower/CMakeLists.txt b/nav2_waypoint_follower/CMakeLists.txt
index a22cd4cd6cc3832fd0f017117bbe1bba09194720..3253ab3439e3fcc4df153162fff950cd53201136 100644
--- a/nav2_waypoint_follower/CMakeLists.txt
+++ b/nav2_waypoint_follower/CMakeLists.txt
@@ -1,6 +1,15 @@
 cmake_minimum_required(VERSION 3.5)
 project(nav2_waypoint_follower)
 
+# Try for OpenCV 4.X, but settle for whatever is installed
+find_package(OpenCV 4 QUIET)
+if(NOT OpenCV_FOUND)
+  find_package(OpenCV REQUIRED)
+endif()
+message(STATUS "Found OpenCV version ${OpenCV_VERSION}")
+
+find_package(image_transport REQUIRED)
+find_package(cv_bridge REQUIRED)
 find_package(ament_cmake REQUIRED)
 find_package(nav2_common REQUIRED)
 find_package(rclcpp REQUIRED)
@@ -41,6 +50,9 @@ set(dependencies
   tf2_ros
   nav2_core
   pluginlib
+  image_transport
+  cv_bridge
+  OpenCV
 )
 
 ament_target_dependencies(${executable_name}
@@ -53,16 +65,22 @@ ament_target_dependencies(${library_name}
   ${dependencies}
 )
 
-add_library(simple_waypoint_task_executor SHARED plugins/wait_at_waypoint.cpp)
-ament_target_dependencies(simple_waypoint_task_executor ${dependencies})
-# prevent pluginlib from using boost
-target_compile_definitions(simple_waypoint_task_executor PUBLIC "PLUGINLIB__DISABLE_BOOST_FUNCTIONS")
+add_library(wait_at_waypoint SHARED plugins/wait_at_waypoint.cpp)
+ament_target_dependencies(wait_at_waypoint ${dependencies})
+#prevent pluginlib from using boost
+target_compile_definitions(wait_at_waypoint PUBLIC "PLUGINLIB__DISABLE_BOOST_FUNCTIONS")
+
+add_library(photo_at_waypoint SHARED plugins/photo_at_waypoint.cpp)
+ament_target_dependencies(photo_at_waypoint ${dependencies})
+#prevent pluginlib from using boost
+target_compile_definitions(photo_at_waypoint PUBLIC "PLUGINLIB__DISABLE_BOOST_FUNCTIONS")
 
 add_library(input_at_waypoint SHARED plugins/input_at_waypoint.cpp)
 ament_target_dependencies(input_at_waypoint ${dependencies})
+#prevent pluginlib from using boost
 target_compile_definitions(input_at_waypoint PUBLIC "PLUGINLIB__DISABLE_BOOST_FUNCTIONS")
 
-install(TARGETS ${library_name} simple_waypoint_task_executor input_at_waypoint
+install(TARGETS ${library_name} wait_at_waypoint photo_at_waypoint input_at_waypoint
   ARCHIVE DESTINATION lib
   LIBRARY DESTINATION lib
   RUNTIME DESTINATION bin
@@ -82,7 +100,7 @@ if(BUILD_TESTING)
 endif()
 
 ament_export_include_directories(include)
-ament_export_libraries(simple_waypoint_task_executor input_at_waypoint)
+ament_export_libraries(wait_at_waypoint photo_at_waypoint input_at_waypoint)
 
 pluginlib_export_plugin_description_file(nav2_waypoint_follower plugins.xml)
 
diff --git a/nav2_waypoint_follower/include/nav2_waypoint_follower/plugins/photo_at_waypoint.hpp b/nav2_waypoint_follower/include/nav2_waypoint_follower/plugins/photo_at_waypoint.hpp
new file mode 100644
index 0000000000000000000000000000000000000000..7d264b7181ea2d8a49e9f6c93a6d840fd0440906
--- /dev/null
+++ b/nav2_waypoint_follower/include/nav2_waypoint_follower/plugins/photo_at_waypoint.hpp
@@ -0,0 +1,109 @@
+// Copyright (c) 2020 Fetullah Atas
+//
+// 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_WAYPOINT_FOLLOWER__PLUGINS__PHOTO_AT_WAYPOINT_HPP_
+#define NAV2_WAYPOINT_FOLLOWER__PLUGINS__PHOTO_AT_WAYPOINT_HPP_
+
+#include <experimental/filesystem>
+#include <mutex>
+#include <string>
+#include <exception>
+
+#include "rclcpp/rclcpp.hpp"
+#include "rclcpp_components/register_node_macro.hpp"
+
+#include "sensor_msgs/msg/image.hpp"
+#include "nav2_core/waypoint_task_executor.hpp"
+#include "opencv4/opencv2/core.hpp"
+#include "opencv4/opencv2/opencv.hpp"
+#include "cv_bridge/cv_bridge.h"
+#include "image_transport/image_transport.hpp"
+
+
+namespace nav2_waypoint_follower
+{
+
+class PhotoAtWaypoint : public nav2_core::WaypointTaskExecutor
+{
+public:
+  /**
+  * @brief Construct a new Photo At Waypoint object
+  *
+  */
+  PhotoAtWaypoint();
+
+  /**
+   * @brief Destroy the Photo At Waypoint object
+   *
+   */
+  ~PhotoAtWaypoint();
+
+  /**
+   * @brief declares and loads parameters used
+   *
+   * @param parent parent node that plugin will be created within
+   * @param plugin_name should be provided in nav2_params.yaml==> waypoint_follower
+   */
+  void initialize(
+    const rclcpp_lifecycle::LifecycleNode::WeakPtr & parent,
+    const std::string & plugin_name);
+
+
+  /**
+   * @brief Override this to define the body of your task that you would like to execute once the robot arrived to waypoint
+   *
+   * @param curr_pose current pose of the robot
+   * @param curr_waypoint_index current waypoint, that robot just arrived
+   * @return true if task execution was successful
+   * @return false if task execution failed
+   */
+  bool processAtWaypoint(
+    const geometry_msgs::msg::PoseStamped & curr_pose, const int & curr_waypoint_index);
+
+  /**
+   * @brief
+   *
+   * @param msg
+   */
+  void imageCallback(const sensor_msgs::msg::Image::SharedPtr msg);
+
+  /**
+   * @brief given a shared pointer to sensor::msg::Image type, make a deep copy to inputted cv Mat
+   *
+   * @param msg
+   * @param mat
+   */
+  static void deepCopyMsg2Mat(const sensor_msgs::msg::Image::SharedPtr & msg, cv::Mat & mat);
+
+protected:
+  // to ensure safety when accessing global var curr_frame_
+  std::mutex global_mutex_;
+  // the taken photos will be saved under this directory
+  std::experimental::filesystem::path save_dir_;
+  // .png ? .jpg ? or some other well known format
+  std::string image_format_;
+  // the topic to subscribe in order capture a frame
+  std::string image_topic_;
+  // whether plugin is enabled
+  bool is_enabled_;
+  // current frame;
+  sensor_msgs::msg::Image::SharedPtr curr_frame_msg_;
+  // global logger
+  rclcpp::Logger logger_{rclcpp::get_logger("nav2_waypoint_follower")};
+  // ros susbcriber to get camera image
+  rclcpp::Subscription<sensor_msgs::msg::Image>::SharedPtr camera_image_subscriber_;
+};
+}  // namespace nav2_waypoint_follower
+
+#endif  // NAV2_WAYPOINT_FOLLOWER__PLUGINS__PHOTO_AT_WAYPOINT_HPP_
diff --git a/nav2_waypoint_follower/plugins.xml b/nav2_waypoint_follower/plugins.xml
index 2c38b6c5f2ca4960ec44d70e226b4784329a76cd..ab8c01f050f6ffacbdca1d1d5b2be662accde18c 100644
--- a/nav2_waypoint_follower/plugins.xml
+++ b/nav2_waypoint_follower/plugins.xml
@@ -1,9 +1,15 @@
 <class_libraries>
-  <library path="simple_waypoint_task_executor">
+  <library path="wait_at_waypoint">
     <class type="nav2_waypoint_follower::WaitAtWaypoint" base_class_type="nav2_core::WaypointTaskExecutor">
       <description>Lets robot sleep for a specified amount of time at waypoint arrival</description>
     </class>
   </library>
+  <library path="photo_at_waypoint">
+    <class type="nav2_waypoint_follower::PhotoAtWaypoint" base_class_type="nav2_core::WaypointTaskExecutor">
+      <description>Run-time plugin that takes photos at waypoint arrivals when using waypoint follower node. 
+        Saves the taken photos to specified directory.</description>
+    </class>
+  </library>
   <library path="input_at_waypoint">
     <class type="nav2_waypoint_follower::InputAtWaypoint" base_class_type="nav2_core::WaypointTaskExecutor">
       <description>Lets robot wait for input at waypoint arrival</description>
diff --git a/nav2_waypoint_follower/plugins/photo_at_waypoint.cpp b/nav2_waypoint_follower/plugins/photo_at_waypoint.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..9939d60b680b0f53a43a0b36cd22dcded21a32f9
--- /dev/null
+++ b/nav2_waypoint_follower/plugins/photo_at_waypoint.cpp
@@ -0,0 +1,146 @@
+// Copyright (c) 2020 Fetullah Atas
+//
+// 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 "nav2_waypoint_follower/plugins/photo_at_waypoint.hpp"
+#include <pluginlib/class_list_macros.hpp>
+
+#include <string>
+#include <memory>
+
+
+namespace nav2_waypoint_follower
+{
+PhotoAtWaypoint::PhotoAtWaypoint()
+{
+}
+
+PhotoAtWaypoint::~PhotoAtWaypoint()
+{
+}
+
+void PhotoAtWaypoint::initialize(
+  const rclcpp_lifecycle::LifecycleNode::WeakPtr & parent,
+  const std::string & plugin_name)
+{
+  auto node = parent.lock();
+
+  curr_frame_msg_ = std::make_shared<sensor_msgs::msg::Image>();
+
+  node->declare_parameter(plugin_name + ".enabled", rclcpp::ParameterValue(true));
+  node->declare_parameter(
+    plugin_name + ".image_topic",
+    rclcpp::ParameterValue("/camera/color/image_raw"));
+  node->declare_parameter(
+    plugin_name + ".save_dir",
+    rclcpp::ParameterValue("/tmp/waypoint_images"));
+  node->declare_parameter(plugin_name + ".image_format", rclcpp::ParameterValue("png"));
+
+  std::string save_dir_as_string;
+  node->get_parameter(plugin_name + ".enabled", is_enabled_);
+  node->get_parameter(plugin_name + ".image_topic", image_topic_);
+  node->get_parameter(plugin_name + ".save_dir", save_dir_as_string);
+  node->get_parameter(plugin_name + ".image_format", image_format_);
+
+  // get inputted save directory and make sure it exists, if not log and create  it
+  save_dir_ = save_dir_as_string;
+  if (!std::experimental::filesystem::exists(save_dir_)) {
+    RCLCPP_WARN(
+      logger_,
+      "Provided save directory for photo at waypoint plugin does not exist,"
+      "provided directory is: %s, the directory will be created automatically.",
+      save_dir_.c_str()
+    );
+    if (!std::experimental::filesystem::create_directory(save_dir_)) {
+      RCLCPP_ERROR(
+        logger_,
+        "Failed to create directory!: %s required by photo at waypoint plugin, "
+        "exiting the plugin with failure!",
+        save_dir_.c_str()
+      );
+      is_enabled_ = false;
+    }
+  }
+
+  if (!is_enabled_) {
+    RCLCPP_INFO(
+      logger_, "Photo at waypoint plugin is disabled.");
+  } else {
+    RCLCPP_INFO(
+      logger_, "Initializing photo at waypoint plugin, subscribing to camera topic named; %s",
+      image_topic_.c_str());
+    camera_image_subscriber_ = node->create_subscription<sensor_msgs::msg::Image>(
+      image_topic_, rclcpp::SystemDefaultsQoS(),
+      std::bind(&PhotoAtWaypoint::imageCallback, this, std::placeholders::_1));
+  }
+}
+
+bool PhotoAtWaypoint::processAtWaypoint(
+  const geometry_msgs::msg::PoseStamped & curr_pose, const int & curr_waypoint_index)
+{
+  if (!is_enabled_) {
+    RCLCPP_WARN(
+      logger_,
+      "Photo at waypoint plugin is disabled. Not performing anything"
+    );
+    return true;
+  }
+  try {
+    // construct the full path to image filename
+    std::experimental::filesystem::path file_name = std::to_string(
+      curr_waypoint_index) + "_" +
+      std::to_string(curr_pose.header.stamp.sec) + "." + image_format_;
+    std::experimental::filesystem::path full_path_image_path = save_dir_ / file_name;
+
+    // save the taken photo at this waypoint to given directory
+    std::lock_guard<std::mutex> guard(global_mutex_);
+    cv::Mat curr_frame_mat;
+    deepCopyMsg2Mat(curr_frame_msg_, curr_frame_mat);
+    cv::imwrite(full_path_image_path.c_str(), curr_frame_mat);
+    RCLCPP_INFO(
+      logger_,
+      "Photo has been taken sucessfully at waypoint %i", curr_waypoint_index);
+  } catch (const std::exception & e) {
+    RCLCPP_ERROR(
+      logger_,
+      "Couldn't take photo at waypoint %i! Caught exception: %s \n"
+      "Make sure that the image topic named: %s is valid and active!",
+      curr_waypoint_index,
+      e.what(), image_topic_.c_str());
+    return false;
+  }
+  return true;
+}
+
+void PhotoAtWaypoint::imageCallback(const sensor_msgs::msg::Image::SharedPtr msg)
+{
+  std::lock_guard<std::mutex> guard(global_mutex_);
+  curr_frame_msg_ = msg;
+}
+
+void PhotoAtWaypoint::deepCopyMsg2Mat(
+  const sensor_msgs::msg::Image::SharedPtr & msg,
+  cv::Mat & mat)
+{
+  cv_bridge::CvImageConstPtr cv_bridge_ptr = cv_bridge::toCvShare(msg, msg->encoding);
+  cv::Mat frame = cv_bridge_ptr->image;
+  if (msg->encoding == "rgb8") {
+    cv::cvtColor(frame, frame, cv::COLOR_RGB2BGR);
+  }
+  frame.copyTo(mat);
+}
+
+}      // namespace nav2_waypoint_follower
+PLUGINLIB_EXPORT_CLASS(
+  nav2_waypoint_follower::PhotoAtWaypoint,
+  nav2_core::WaypointTaskExecutor)
diff --git a/nav2_waypoint_follower/src/waypoint_follower.cpp b/nav2_waypoint_follower/src/waypoint_follower.cpp
index 5c0c8955b02ca14c4edc75dad5ffba05e6608533..ff81e7666dd4da55672c7e2285328f19261c37fa 100644
--- a/nav2_waypoint_follower/src/waypoint_follower.cpp
+++ b/nav2_waypoint_follower/src/waypoint_follower.cpp
@@ -35,7 +35,7 @@ WaypointFollower::WaypointFollower()
   declare_parameter("loop_rate", 20);
   nav2_util::declare_parameter_if_not_declared(
     this, std::string("waypoint_task_executor_plugin"),
-    rclcpp::ParameterValue(std::string("waypoint_task_executor")));
+    rclcpp::ParameterValue(std::string("wait_at_waypoint")));
   nav2_util::declare_parameter_if_not_declared(
     this, std::string("waypoint_task_executor_plugin.plugin"),
     rclcpp::ParameterValue(std::string("nav2_waypoint_follower::WaitAtWaypoint")));