diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml
index 5f21f52f4aad5bdb8399881a0ffce9fa79578326..ba9954522c587357cc6d86586d7efd2d2e809416 100644
--- a/.gitlab-ci.yml
+++ b/.gitlab-ci.yml
@@ -14,6 +14,7 @@ stages:
 
   before_script:
     # Ccache configuration and introspection.
+    - apt-get update
     - apt-get install ccache --yes
     - ccache --set-config=cache_dir="$CI_PROJECT_DIR/.ccache"
     - ccache --max-size=5G
diff --git a/SimoxUtility/CMakeLists.txt b/SimoxUtility/CMakeLists.txt
index e08899ec3142885c5045d53a996262d2a69019a1..95bf0823199ea31f5c79e36f8cc97c7eaa80a12d 100644
--- a/SimoxUtility/CMakeLists.txt
+++ b/SimoxUtility/CMakeLists.txt
@@ -74,6 +74,8 @@ SET(INCLUDES
     algorithm/string/string_conversion_eigen.h
     algorithm/ordered_circular_buffer.h
 
+    backport/span/gcc_header.h
+
     caching/CacheMap.h
 
     color/cmaps/colormaps.h
@@ -106,7 +108,6 @@ SET(INCLUDES
     json/json.h
     json/util.h
 
-
     math/mean.h
     math/sum.h
     math/SoftMinMax.h
@@ -199,7 +200,6 @@ SET(INCLUDES
     math/statistics/Histogram1D.h
     math/statistics/measures.h
 
-
     meta/undefined_t/undefined_t.h
     meta/undefined_t/is_set.h
     meta/eigen/enable_if_compile_time_size.h
@@ -220,12 +220,9 @@ SET(INCLUDES
     meta/enum/EnumNames.hpp
     meta/key_type.h
 
-    simox/SimoxPath.h
+    random/choice.h
 
-    xml/rapidxml/rapidxml.hpp
-    xml/rapidxml/rapidxml_print.hpp
-    xml/rapidxml/RapidXMLWrapper.h
-    xml/rapidxml/RapidXMLForwardDecl.h
+    simox/SimoxPath.h
 
     shapes/AxisAlignedBoundingBox.h
     shapes/OrientedBoxBase.h
@@ -233,10 +230,13 @@ SET(INCLUDES
     shapes/XYConstrainedOrientedBox.h
     shapes/json_conversions.h
 
-    backport/span/gcc_header.h
-
     threads/system_thread_id.h
     threads/CountingSemaphore.h
+
+    xml/rapidxml/rapidxml.hpp
+    xml/rapidxml/rapidxml_print.hpp
+    xml/rapidxml/RapidXMLWrapper.h
+    xml/rapidxml/RapidXMLForwardDecl.h
 )
 
 
diff --git a/SimoxUtility/random.h b/SimoxUtility/random.h
new file mode 100644
index 0000000000000000000000000000000000000000..19a8006aa76d85a0ee1db71f1180a299d9e96f90
--- /dev/null
+++ b/SimoxUtility/random.h
@@ -0,0 +1,5 @@
+#pragma once
+
+// This file is generated!
+
+#include "random/choice.h"
diff --git a/SimoxUtility/random/choice.h b/SimoxUtility/random/choice.h
new file mode 100644
index 0000000000000000000000000000000000000000..7c7b67adc43b9f68299f97f9bc6d47ed3af05392
--- /dev/null
+++ b/SimoxUtility/random/choice.h
@@ -0,0 +1,41 @@
+#pragma once
+
+#include <random>
+#include <iterator>
+
+#include <SimoxUtility/error/SimoxError.h>
+
+
+namespace simox::random
+{
+    /**
+     * Return a random element from the non-empty iterable items.
+     *
+     * @throw `std::out_of_range` if items is empty.
+     */
+    template <class IterableT, class RandomEngineT>
+    const typename IterableT::value_type&
+    choice(const IterableT& items, RandomEngineT& gen)
+    {
+        if (items.empty())
+        {
+            throw error::SimoxError("Cannot choose an item from an empty vector.");
+        }
+
+        std::uniform_int_distribution<size_t> distrib(0, items.size() - 1);
+        std::size_t index = distrib(gen);
+        auto it = items.begin();
+        std::advance(it, index);
+        return *it;
+    }
+
+
+    template <class IterableT>
+    const typename IterableT::value_type&
+    choice(const IterableT& items)
+    {
+        std::default_random_engine gen{std::random_device{}()};
+        return choice(items, gen);
+    }
+
+} // namespace simox::random
diff --git a/SimoxUtility/tests/CMakeLists.txt b/SimoxUtility/tests/CMakeLists.txt
index b9a06183286cbbb0171b4fb31bd89420042a8707..5c09ff19f328cb58a736a1c40cd6b9870d297cb8 100644
--- a/SimoxUtility/tests/CMakeLists.txt
+++ b/SimoxUtility/tests/CMakeLists.txt
@@ -45,6 +45,7 @@ ADD_SUBDIRECTORY(filesystem)
 ADD_SUBDIRECTORY(json)
 ADD_SUBDIRECTORY(math)
 ADD_SUBDIRECTORY(meta)
+ADD_SUBDIRECTORY(random)
 ADD_SUBDIRECTORY(shapes)
 ADD_SUBDIRECTORY(simox)
 ADD_SUBDIRECTORY(backport)
diff --git a/SimoxUtility/tests/random/CMakeLists.txt b/SimoxUtility/tests/random/CMakeLists.txt
new file mode 100644
index 0000000000000000000000000000000000000000..5e4088d67f12c7e6e7f5ee51833f6a9669ee51a9
--- /dev/null
+++ b/SimoxUtility/tests/random/CMakeLists.txt
@@ -0,0 +1,3 @@
+
+ADD_SU_TEST( Choice )
+
diff --git a/SimoxUtility/tests/random/Choice.cpp b/SimoxUtility/tests/random/Choice.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..fec986df8f5f2a10989f2414adcc2fb1ca1cd9a5
--- /dev/null
+++ b/SimoxUtility/tests/random/Choice.cpp
@@ -0,0 +1,99 @@
+/*
+ * 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    RobotAPI::ArmarXObjects::FrameTracking
+ * @author     Adrian Knobloch ( adrian dot knobloch at student dot kit dot edu )
+ * @date       2019
+ * @copyright  http://www.gnu.org/licenses/gpl-2.0.txt
+ *             GNU General Public License
+ */
+
+#define BOOST_TEST_MODULE SimoxUtility/color/ColorMap
+
+#include <boost/test/included/unit_test.hpp>
+
+#include <SimoxUtility/random/choice.h>
+
+#include <iostream>
+
+#include <set>
+#include <vector>
+
+
+namespace ChoiceTest
+{
+
+struct Fixture
+{
+
+    std::vector<std::string> vector { "a", "b", "c" };
+    std::set<std::string> set {vector.begin(), vector.end()};
+
+    Fixture()
+    {
+    }
+    ~Fixture()
+    {
+    }
+};
+
+}
+
+
+BOOST_FIXTURE_TEST_SUITE(ChoiceTest, ChoiceTest::Fixture)
+
+
+BOOST_AUTO_TEST_CASE(test_choice_vector)
+{
+    std::set<std::string> allChosen;
+    for (int i = 0; i < 1e5; ++i)
+    {
+        std::string chosen = simox::random::choice(vector);
+        BOOST_CHECK(std::find(vector.begin(), vector.end(), chosen) != vector.end());
+
+        allChosen.insert(chosen);
+    }
+
+    // All items must be hit at least once ... very likely.
+    BOOST_CHECK_EQUAL(allChosen.size(), 3);
+}
+
+
+BOOST_AUTO_TEST_CASE(test_choice_set)
+{
+    std::set<std::string> allChosen;
+    for (int i = 0; i < 1e5; ++i)
+    {
+        std::string chosen = simox::random::choice(set);
+        BOOST_CHECK(std::find(set.begin(), set.end(), chosen) != set.end());
+
+        allChosen.insert(chosen);
+    }
+
+    // All items must be hit at least once ... very likely.
+    BOOST_CHECK_EQUAL(allChosen.size(), 3);
+}
+
+
+BOOST_AUTO_TEST_CASE(test_choice_empty)
+{
+    vector.clear();
+    set.clear();
+    BOOST_CHECK_THROW(simox::random::choice(vector), simox::error::SimoxError);
+    BOOST_CHECK_THROW(simox::random::choice(set), simox::error::SimoxError);
+}
+
+
+BOOST_AUTO_TEST_SUITE_END()