diff --git a/SimoxUtility/iterator.h b/SimoxUtility/iterator.h
new file mode 100644
index 0000000000000000000000000000000000000000..14e76f038456894270581e2346fe4c50c00c1c9e
--- /dev/null
+++ b/SimoxUtility/iterator.h
@@ -0,0 +1,5 @@
+#pragma once
+
+// This file is generated!
+
+#include "iterator/xy_index_range_iterator.h"
diff --git a/SimoxUtility/iterator/xy_index_range_iterator.h b/SimoxUtility/iterator/xy_index_range_iterator.h
new file mode 100644
index 0000000000000000000000000000000000000000..d20d5c2290410ba41cdad0822ccfe35c7fa81573
--- /dev/null
+++ b/SimoxUtility/iterator/xy_index_range_iterator.h
@@ -0,0 +1,87 @@
+#pragma once
+
+#include <iterator>
+
+namespace simox::iterator {
+
+
+struct Point {
+  int x;
+  int y;
+
+  Point(int x, int y) : x(x), y(y) {}
+  Point() = default;
+
+  bool operator==(const Point &rhs) const { return x == rhs.x && y == rhs.y; }
+
+  static Point zero() { return {0, 0}; }
+};
+
+/**
+* The XYIndexRangeIterator class.
+*
+* The aim of this class is to provide a convenient way to iterate over 2D arrays
+* This class provides a 2D iterator that returns all indices to the 2D array, e.g.
+*
+*   My2DArray arr(10, 20);
+*   for(auto [x,y] : XYIndexRangeIterator(arr)){
+*      auto val = arr.at(x,y);
+*      // do the magic
+*   }
+*
+* This is hightly inspired by cartographer::mapping::XYIndexRangeIterator
+* see: https://github.com/cartographer-project/cartographer/blob/master/cartographer/mapping/2d/xy_index.h
+*/
+template <typename IndexType = Point>
+class XYIndexRangeIterator
+    : public std::iterator<std::input_iterator_tag, IndexType> {
+public:
+  // Constructs a new iterator for the specified range.
+  XYIndexRangeIterator(const IndexType &min_xy_index,
+                       const IndexType &max_xy_index)
+      : min_xy_index(min_xy_index), max_xy_index(max_xy_index),
+        xy_index(min_xy_index) {}
+
+  // Constructs a new iterator for everything contained in 'cell_limits'.
+  explicit XYIndexRangeIterator(const IndexType &cell_limits)
+      : XYIndexRangeIterator(IndexType::zero(),
+                             IndexType(cell_limits.x - 1, cell_limits.y - 1)) {}
+
+  XYIndexRangeIterator &operator++() {
+    if (xy_index.x < max_xy_index.x) {
+      ++xy_index.x;
+    } else {
+      xy_index.x = min_xy_index.x;
+      ++xy_index.y;
+    }
+    return *this;
+  }
+
+  IndexType &operator*() { return xy_index; }
+
+  bool operator==(const XYIndexRangeIterator &other) const {
+    return xy_index == other.xy_index;
+  }
+
+  bool operator!=(const XYIndexRangeIterator &other) const {
+    return !operator==(other);
+  }
+
+  XYIndexRangeIterator begin() const {
+    return XYIndexRangeIterator(min_xy_index, max_xy_index);
+  }
+
+  XYIndexRangeIterator end() const {
+    XYIndexRangeIterator it = begin();
+    it.xy_index = IndexType(min_xy_index.x, max_xy_index.y + 1);
+    return it;
+  }
+
+private:
+  IndexType min_xy_index;
+  IndexType max_xy_index;
+  IndexType xy_index;
+};
+
+
+} // namespace simox::iterator
diff --git a/SimoxUtility/tests/CMakeLists.txt b/SimoxUtility/tests/CMakeLists.txt
index 426368c785fafa3be8733dfda996f24b14a70d82..b9a06183286cbbb0171b4fb31bd89420042a8707 100644
--- a/SimoxUtility/tests/CMakeLists.txt
+++ b/SimoxUtility/tests/CMakeLists.txt
@@ -48,3 +48,4 @@ ADD_SUBDIRECTORY(meta)
 ADD_SUBDIRECTORY(shapes)
 ADD_SUBDIRECTORY(simox)
 ADD_SUBDIRECTORY(backport)
+ADD_SUBDIRECTORY(iterator)
diff --git a/SimoxUtility/tests/iterator/CMakeLists.txt b/SimoxUtility/tests/iterator/CMakeLists.txt
new file mode 100644
index 0000000000000000000000000000000000000000..a05124858fdaae3198f0efd6bce3f58c74de39d4
--- /dev/null
+++ b/SimoxUtility/tests/iterator/CMakeLists.txt
@@ -0,0 +1,2 @@
+
+ADD_SU_TEST( XYIndexRangeIterator )
diff --git a/SimoxUtility/tests/iterator/XYIndexRangeIterator.cpp b/SimoxUtility/tests/iterator/XYIndexRangeIterator.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..bd4a58169a097e8f5ac0f51263c9adc34c2ce34d
--- /dev/null
+++ b/SimoxUtility/tests/iterator/XYIndexRangeIterator.cpp
@@ -0,0 +1,102 @@
+/*
+ * This file is part of ArmarX.
+ *
+ * ArmarX is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * ArmarX is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * @package    
+ * @author     Fabian Reister ( fabian dot reister at kit dot edu )
+ * @date       2021
+ * @copyright  http://www.gnu.org/licenses/gpl-2.0.txt
+ *             GNU General Public License
+ */
+
+#define BOOST_TEST_MODULE SimoxUtility/iterator/XYIndexRangeIterator
+
+#include <vector>
+#include <iostream>
+#include <numeric>
+#include <algorithm>
+
+#include <boost/test/included/unit_test.hpp>
+#include <boost/test/unit_test_suite.hpp>
+
+#include <SimoxUtility/iterator.h>
+
+
+// BOOST_AUTO_TEST_SUITE(XYIndexRangeIterator)
+
+
+BOOST_AUTO_TEST_CASE(test_loop)
+{
+    // dimensions
+    constexpr int N = 10;
+    constexpr int M = 20;
+
+    // create 2D vector of size N*M
+    const auto v = std::vector<std::vector<int>>(M, std::vector<int>(N, 1));
+
+    const auto range_it = simox::iterator::XYIndexRangeIterator(simox::iterator::Point{N, M});
+    
+    // max counters for test checks
+    int x_max = 0;
+    int y_max = 0;
+    int cnt = 0;
+
+    for(const auto& [x,y] : range_it){
+        x_max = std::max(x, x_max);
+        y_max = std::max(y, y_max);
+
+        // TODO(fabian.reister): access v
+
+        cnt++;
+    }
+
+    BOOST_CHECK_EQUAL(x_max, N-1);
+    BOOST_CHECK_EQUAL(y_max, M-1);
+    BOOST_CHECK_EQUAL(cnt, N*M);
+}
+
+
+BOOST_AUTO_TEST_CASE(test_foreach)
+{
+    // dimensions
+    constexpr int N = 10;
+    constexpr int M = 20;
+
+    // create 2D vector of size N*M
+    const auto v = std::vector<std::vector<int>>(M, std::vector<int>(N, 1));
+
+    const auto range_it = simox::iterator::XYIndexRangeIterator(simox::iterator::Point{N, M});
+    
+    int x_max = 0;
+    int y_max = 0;
+    int cnt = 0;
+
+    std::for_each(range_it.begin(), range_it.end(), [&](const auto& pnt){
+        const auto& [x,y] = pnt;
+
+        x_max = std::max(x, x_max);
+        y_max = std::max(y, y_max);
+
+        // TODO(fabian.reister): access v
+
+
+        cnt++;
+    });
+
+    BOOST_CHECK_EQUAL(x_max, N-1);
+    BOOST_CHECK_EQUAL(y_max, M-1);
+    BOOST_CHECK_EQUAL(cnt, N*M);
+}
+
+// BOOST_AUTO_TEST_SUITE_END()