<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>Forem: Gracija</title>
    <description>The latest articles on Forem by Gracija (@gracija).</description>
    <link>https://forem.com/gracija</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F2491129%2F07a87eb8-adcf-42bf-bd8d-cc70bb3471c6.jpg</url>
      <title>Forem: Gracija</title>
      <link>https://forem.com/gracija</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/gracija"/>
    <language>en</language>
    <item>
      <title>Comparing Data Management Tools for Robotics</title>
      <dc:creator>Gracija</dc:creator>
      <pubDate>Mon, 14 Apr 2025 00:00:00 +0000</pubDate>
      <link>https://forem.com/reductstore/comparing-data-management-tools-for-robotics-36kj</link>
      <guid>https://forem.com/reductstore/comparing-data-management-tools-for-robotics-36kj</guid>
      <description>&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F9rgfef9ayiphhnw7thfp.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F9rgfef9ayiphhnw7thfp.png" alt="Data Management Tools for Robotics" width="800" height="537"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Data management is a very important element in modern robotics systems. As robots become more advanced, they generate massive amounts of information from various sources, such as sensor readings, system logs, and video feeds, and being able to manage this data effectively can mean the difference between a robot that performs well and one that fails to meet expectations.&lt;/p&gt;

&lt;p&gt;In this article, we will compare different data management tools for robotics by looking into their key features, strengths, and the types of use cases they are best suited for. Understanding these differences will help robotics engineers and developers choose the right tool for their specific needs.&lt;/p&gt;

&lt;h2&gt;
  
  
  Key Criteria for Comparison&lt;a href="https://www.reduct.store/blog/data-management-tools#key-criteria-for-comparison" rel="noopener noreferrer"&gt;​&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;When evaluating data management tools for robotics, several critical factors must be considered to ensure the selected solution meets the unique demands of robotic systems:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Data Type Support:&lt;/strong&gt; Different robotics applications generate and require various types of data, each with its own storage and processing needs:&amp;lt;!-- --&amp;gt;

&lt;ul&gt;
&lt;li&gt;
&lt;em&gt;Lightweight telemetry data&lt;/em&gt;: Includes GPS coordinates, IMU readings, joint positions, and system status. This data requires low bandwidth and offers near real-time access, making it valuable for analytics and monitoring robot performance over time.&lt;/li&gt;
&lt;li&gt;
&lt;em&gt;Downsampled sensor data&lt;/em&gt; represents a middle ground when it comes to the volume. It consists of reduced framerate camera feeds and lower-resolution lidar scans, making it particularly useful for monitoring robot operations and investigating incidents without consuming excessive storage.&lt;/li&gt;
&lt;li&gt;
&lt;em&gt;Full-resolution data&lt;/em&gt; comprises the complete, uncompressed outputs from sensors - raw camera frames at maximum framerate, high-frequency LiDAR point clouds, and detailed depth maps. Even though this data requires a larger storage capacity, it's essential for in-depth debugging and retraining machine learning models to improve robot performance and capturing specific events for incident triage.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;

&lt;strong&gt;Integration &amp;amp; Ecosystem:&lt;/strong&gt; Data management tools must integrate well with other systems and tools, such as ROS (Robot Operating System), cloud platforms, and development environments. Good integration leads to smoother data flow, which leads to reduced time and effort needed to synchronize components of the system. Compatibility with cloud platforms is also important, as it offers scalability and the flexibility to store large amounts of data without needing on-premise infrastructure.&lt;/li&gt;

&lt;li&gt;

&lt;strong&gt;Performance &amp;amp; Scalability:&lt;/strong&gt; Fast data processing in robotics is essential, especially for tasks like autonomous navigation and robotic manipulation where even small delays can cause errors or safety concerns. Additionally, as data volumes grow, systems must scale effectively without performance loss. Storing large files, such as ROS bags, on edge devices can overwhelm resources, leading to overheating and slower performance, and transferring these files to the cloud may also cause delays. Efficient data management helps avoid these issues, ensuring efficient performance and scalability as the system grows.&lt;/li&gt;

&lt;li&gt;

&lt;strong&gt;Ease of Use &amp;amp; API Support:&lt;/strong&gt; The data management tool's ease of use and API support can make a big difference in how easily it fits into day-to-day development. A clean, intuitive interface helps engineers and data scientists to quickly familiarize themselves with the tool and therefore increase productivity, while having reliable, well-documented API support makes it easier to automate tasks, connect with other tools, and adapt the system to match specific needs.&lt;/li&gt;

&lt;/ul&gt;

&lt;h2&gt;
  
  
  In-Depth Comparison of Tools&lt;a href="https://www.reduct.store/blog/data-management-tools#in-depth-comparison-of-tools" rel="noopener noreferrer"&gt;​&lt;/a&gt;
&lt;/h2&gt;

&lt;h3&gt;
  
  
  ReductStore&lt;a href="https://www.reduct.store/blog/data-management-tools#reductstore" rel="noopener noreferrer"&gt;​&lt;/a&gt;
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F99cch5clb9mnxw2up8sn.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F99cch5clb9mnxw2up8sn.png" alt="ReductStore Dashboard" width="800" height="376"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;ReductStore is a high-performance storage and streaming solution for robotics and industrial IoT applications optimized for managing and storing large volumes of unstructured data. Its design makes it especially suitable for high-frequency sensor data, telemetry, and full-resolution sensor data like raw camera images and lidar frames coming from autonomous vehicles, industrial robots, drones, and other robotic applications.&lt;/p&gt;

&lt;p&gt;One key aspect of ReductStore is its ability to effectively manage data both locally on edge and in a central storage (either on-prem or in the cloud). It enables efficient storage of large files, such as rosbag files, by allowing users to &lt;a href="https://www.reduct.store/blog/store-ros-topics" rel="noopener noreferrer"&gt;&lt;strong&gt;split them by topic and save each topic as a separate record&lt;/strong&gt;&lt;/a&gt; or entry, rather than storing the entire rosbag file. This approach provides greater flexibility in managing the data, enabling different storage, replication, and retention strategies for different data types.&lt;/p&gt;

&lt;p&gt;As edge devices often have limited storage capacity, ReductStore offers volume-based retention policies based on the First In, First Out (FIFO) principle. This approach ensures that older data is deleted only when the storage reaches full capacity. These retention policies are customizable and can be adjusted separately for each data bucket, allowing users to make different data management strategies according to their specific needs and thus avoid storage overrun on the robot.&lt;/p&gt;

&lt;p&gt;When it comes to syncing the robot's data to a cloud or central storage, ReductStore uses conditional replication, which basically means that users can set filters in order to replicate only specific entries or a subset of records that satisfy a given set of rules. This is achieved through a JSON-like query language in the ReductStore HTTP API, enabling efficient data transfer based on customized conditions. The API also supports batch operations, reducing the number of requests and improving overall performance when transferring large datasets.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.reduct.store/solutions/cloud" rel="noopener noreferrer"&gt;&lt;strong&gt;ReductStore integrates with Google Cloud Storage&lt;/strong&gt;&lt;/a&gt;, offering the fastest and most cost-effective cloud storage for time series objects. It cuts data storage costs by storing infrequently accessed data in lower-cost tiers, such as Cool or Cold. Additionally, it uses the pay-as-you-go model, allowing users to pay only for the storage they use.&lt;/p&gt;

&lt;h3&gt;
  
  
  Foxglove &amp;amp; MCAP&lt;a href="https://www.reduct.store/blog/data-management-tools#foxglove--mcap" rel="noopener noreferrer"&gt;​&lt;/a&gt;
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fllop1bzbpoihchjgu3ek.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fllop1bzbpoihchjgu3ek.png" alt="Foxglove Dashboard" width="800" height="344"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Foxglove is a web-based visualization and observability platform for robotics data, with tight support for ROS 1, ROS 2, and MCAP logs. It supports a wide range of data types that robotics teams commonly work with, like telemetry, camera feeds, lidar point clouds, and depth maps.&lt;/p&gt;

&lt;p&gt;For large, high-resolution data, Foxglove relies on &lt;em&gt;MCAP&lt;/em&gt;, its open-source log format built for robotics and optimized for both speed and storage. The tool provides an efficient way to explore and visualize these MCAP files, allowing users to stream only the specific data they need.&lt;/p&gt;

&lt;p&gt;To facilitate real-time monitoring, Foxglove provides a simple agent that automatically detects new MCAP files on the robot and sends them to the Foxglove platform. To use the Foxglove agent effectively, robots must continuously record data with &lt;em&gt;rosbag&lt;/em&gt;, creating small, rotating files (typically 1-5 minutes each). Once a file reaches its set limit, it's closed, and a new one is created. While this works, it is highly inefficient because the robots only store data in the file system in separate files. All in all, Foxglove is a good solution for managing bag files and data visualization, but it definitely has its limitations.&lt;/p&gt;

&lt;p&gt;Foxglove integrates with key systems and platforms commonly used in robotics development. It works great with ROS, allowing direct ingestion of data from ROS topics, services, and actions. It also supports integration with external systems via APIs, such as WebSocket and REST APIs. For cloud integration, Foxglove can connect to platforms like AWS, Azure, or Google Cloud for scalable storage solutions, ensuring that your data is accessible without local storage limitations.&lt;/p&gt;

&lt;p&gt;Foxglove offers a clean, intuitive interface with a strong emphasis on handling large sensor and time-series data commonly found in robotics. It focuses heavily on data streaming, with interactive visualizations such as graphs, plots, and camera feeds. It also supports a "drag-and-drop" interface for easy interaction with data.&lt;/p&gt;

&lt;h3&gt;
  
  
  Rerun&lt;a href="https://www.reduct.store/blog/data-management-tools#rerun" rel="noopener noreferrer"&gt;​&lt;/a&gt;
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fyy6ycskft2mxroo1ubsz.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fyy6ycskft2mxroo1ubsz.png" alt="Rerun Dashboard" width="800" height="414"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Rerun is an open-source visualization toolbox and data platform for multimodal and temporal data. It is designed to handle a wide variety of data types such as images, point clouds, tensors, LiDAR scans, depth maps, and sensor data. Its main strength is in its ability to combine easy log handling with a fast, built-in visualizer designed for robotics and XR applications.&lt;/p&gt;

&lt;p&gt;When working with large-scale time-series data, Rerun provides a special, &lt;em&gt;Column-Oriented API&lt;/em&gt; (apart from its row-based API), which optimizes both data ingestion speed and memory usage. Rerun also leverages efficient data structures, like the &lt;em&gt;Chunk&lt;/em&gt; structure, to minimize memory allocations and boost data manipulation efficiency. Furthermore, the platform allows for selective logging, enabling the capture of only necessary data.&lt;/p&gt;

&lt;p&gt;When it comes to integration, it's important to note that Rerun currently does not have native support for ROS. However, users can still use it with ROS by implementing custom logging within their ROS nodes.&lt;/p&gt;

&lt;p&gt;Rerun supports embedding within Jupyter notebooks and web pages and it offers integrations with native loggers in languages like Python, Rust, and C++, allowing you to stream logs directly into the Rerun Viewer.&lt;/p&gt;

&lt;p&gt;Rerun's UI is more focused on real-time 3D visualization, with an interactive approach that allows users to explore robot environments in depth. It features easy-to-use 3D overlays and it supports live streaming and tracking, letting users explore their data in real-time and view different data types in a unified 3D space.&lt;/p&gt;

&lt;h3&gt;
  
  
  Heex&lt;a href="https://www.reduct.store/blog/data-management-tools#heex" rel="noopener noreferrer"&gt;​&lt;/a&gt;
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fzms0bh9q6040hopbqono.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fzms0bh9q6040hopbqono.png" alt="Heex Dashboard" width="800" height="482"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The biggest difference between Heex and the other platforms is that, instead of recording everything all the time, Heex focuses on capturing only what's important — like when an error happens or a specific event is triggered. This tool is built to efficiently handle large amounts of different data, such as logs, images, and sensor data, without overwhelming the users' system.&lt;/p&gt;

&lt;p&gt;A key feature of Heex is its RDA (Resource and Data Automation) for ROS 2, which automates data capture, processing, and management in real time. It works in the following way: the robot runs a small software agent that monitors its activity and knows when to start recording based on specific rules or scenarios set by the user. These rules can be updated remotely in real-time, without the need to plug anything in or restart the robot.&lt;/p&gt;

&lt;p&gt;The platform manages recorded data using the MCAP format—similar to Foxglove—and even embeds Foxglove's visualization tools directly into its platform, allowing users to explore data in context. Once relevant data is captured, it's sent to the cloud, where teams can review it through the Heex dashboard. This setup makes it easy to manage and analyze data across an entire fleet of robots, even if they're in different locations. Since only important moments are logged, the system runs faster, uses less bandwidth, and keeps storage manageable.&lt;/p&gt;

&lt;p&gt;Heex integrates easily with your systems using SDK Agents for real-time data collection, APIs to connect with other tools and workflows, and a Command Line Interface (CLI) for advanced users who prefer direct control. It also integrates with ROS 1 and ROS 2, offering native logging and data streaming.&lt;/p&gt;

&lt;p&gt;Heex's UI offers interactive dashboards where users can view and analyze data from connected robots in real time. The platform allows users to customize their dashboards to highlight specific events or metrics that are important for their workflows, such as errors, system status, and sensor readings. It also provides detailed insights into the robot's state, with easy navigation through timelines and data streams.&lt;/p&gt;

&lt;h2&gt;
  
  
  Comparative Analysis Table&lt;a href="https://www.reduct.store/blog/data-management-tools#comparative-analysis-table" rel="noopener noreferrer"&gt;​&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;To help visualize the differences between the various data management tools discussed, here's a comparison table that summarizes their key differences:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&lt;strong&gt;Tool&lt;/strong&gt;&lt;/th&gt;
&lt;th&gt;&lt;strong&gt;ReductStore&lt;/strong&gt;&lt;/th&gt;
&lt;th&gt;&lt;strong&gt;Foxglove&lt;/strong&gt;&lt;/th&gt;
&lt;th&gt;&lt;strong&gt;Rerun&lt;/strong&gt;&lt;/th&gt;
&lt;th&gt;&lt;strong&gt;Heex&lt;/strong&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Primary Focus&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;High-frequency unstructured time-series robotics data, large-scale storage&lt;/td&gt;
&lt;td&gt;Real-time data streaming and visualization&lt;/td&gt;
&lt;td&gt;Real-time 3D multimodal data visualization and XR applications&lt;/td&gt;
&lt;td&gt;Real-time, event-driven data capture and fleet management&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Data Types&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;High-frequency sensor data, telemetry, complex data streams&lt;/td&gt;
&lt;td&gt;Telemetry, camera feeds, lidar, depth maps, ROS data&lt;/td&gt;
&lt;td&gt;Images, point clouds, tensors, text, multimodal data&lt;/td&gt;
&lt;td&gt;Logs, images, sensor data&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Performance Advantages&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;High-throughput ingestion, time-series queries, and optimized for edge-to-cloud workloads&lt;/td&gt;
&lt;td&gt;Web-based visualization of MCAP files with timeline syncing and stream filtering&lt;/td&gt;
&lt;td&gt;Data model enabling efficient in-memory storage, fast access, and real-time rendering of multimodal data&lt;/td&gt;
&lt;td&gt;Event-driven data offloading system that captures only relevant moments from continuous streams into MCAP&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;ROS Integration&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Supports ROS (via custom setups)&lt;/td&gt;
&lt;td&gt;Native ROS1 and ROS2 support&lt;/td&gt;
&lt;td&gt;No native ROS support (custom integration possible)&lt;/td&gt;
&lt;td&gt;Native ROS1 and ROS2 support&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;UI&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Web-based UI and CLI tools&lt;/td&gt;
&lt;td&gt;Web-based (browser UI with timeline, 2D/3D viewers)&lt;/td&gt;
&lt;td&gt;App-based (cross-platform native app; browser UI in dev)&lt;/td&gt;
&lt;td&gt;Web-based dashboard with filters, events, alerts&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h2&gt;
  
  
  Conclusion&lt;a href="https://www.reduct.store/blog/data-management-tools#conclusion" rel="noopener noreferrer"&gt;​&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;In this article, we covered the key challenges of managing robotics data, such as data type support, performance and scalability, integration with other systems, and ease of use. We also examined several data management platforms like ReductStore, Foxglove, Rerun, and Heex, each with its own set of strengths and disadvantages. Understanding these differences can help you make informed decisions about which solution best fits your specific needs.&lt;/p&gt;




&lt;p&gt;Thanks for reading, I hope this article will help you choose the right storage strategy for your vibration data. If you have any questions or comments, feel free to use the &lt;a href="https://community.reduct.store/signup" rel="noopener noreferrer"&gt;&lt;strong&gt;ReductStore Community Forum&lt;/strong&gt;&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>robotics</category>
      <category>ros</category>
      <category>comparison</category>
    </item>
    <item>
      <title>3 Ways to Store ROS Topics</title>
      <dc:creator>Gracija</dc:creator>
      <pubDate>Tue, 21 Jan 2025 00:00:00 +0000</pubDate>
      <link>https://forem.com/reductstore/3-ways-to-store-ros-topics-2ikl</link>
      <guid>https://forem.com/reductstore/3-ways-to-store-ros-topics-2ikl</guid>
      <description>&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fzp31x28uo4i2g9bkss9a.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fzp31x28uo4i2g9bkss9a.png" alt="Introduction Diagram" width="800" height="322"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The &lt;strong&gt;Robot Operating System (ROS)&lt;/strong&gt; is a powerful framework for developing and managing robotic systems. It simplifies integration, communication, and development through various tools and libraries. ROS is built around a communication system that uses a &lt;em&gt;publish-subscribe model&lt;/em&gt; to connect components, where some, like sensors or cameras, act as &lt;em&gt;publishers&lt;/em&gt;, and others, like motors or processors, are &lt;em&gt;subscribers&lt;/em&gt;. The data shared between these components is organized into &lt;em&gt;topics&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;To make the most of this data, especially when it's needed later for analysis, debugging, or sharing, it's crucial to store it efficiently. In this article, we'll dive into three methods for storing ROS topics, comparing their benefits and limitations to help you choose the best one for your needs. In case you need to gain a broader understanding of how to handle robotics data effectively, make sure to check out our &lt;a href="https://dev.to/atimin/how-to-store-and-manage-robotic-data-2f4b-temp-slug-723768"&gt;&lt;strong&gt;article on storing and managing robotics data&lt;/strong&gt;&lt;/a&gt; first.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why Storing ROS Topics is Important&lt;a href="https://www.reduct.store/blog/store-ros-topics#why-storing-ros-topics-is-important" rel="noopener noreferrer"&gt;​&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;Storing ROS topics enables robotic engineers to better manage their data for various purposes, such as:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Post-Processing&lt;/strong&gt; : After collecting data, engineers can use the data to analyze the robot's behavior, performance, and decision-making in detail, helping identify patterns or issues. They can also use the analyzed information for algorithm optimizations or for training machine learning models.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Debugging&lt;/strong&gt; : When something goes wrong in a robot's operation, having a stored history of ROS topics can be useful for reviewing past data and pinpointing exactly when and where the problem occurred.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Reproducibility&lt;/strong&gt; : Storing topics makes it possible to recreate the same scenario over and over again, which is useful for troubleshooting or testing with different configurations.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Documentation&lt;/strong&gt; : Having the data that the robot produced stored somewhere can be useful for reporting, training, or improving systems based on previous results.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Each method of storing ROS topics has its strengths, so let’s dive into the three main approaches.&lt;/p&gt;

&lt;h2&gt;
  
  
  Method 1: Store ROS Topics to File System Using Rosbag&lt;a href="https://www.reduct.store/blog/store-ros-topics#method-1-store-ros-topics-to-file-system-using-rosbag" rel="noopener noreferrer"&gt;​&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F8j94scqu3s5yrltnnibw.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F8j94scqu3s5yrltnnibw.png" alt="Method 1 Diagram" width="800" height="260"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Rosbag&lt;/strong&gt; is the default and most commonly used tool in ROS for handling recorded data. It works by capturing the messages being published on ROS topics and saving them into a &lt;em&gt;.bag file&lt;/em&gt;. Since rosbag supports recording multiple topics at once, it is a great tool for scenarios where you need to capture many different data streams, such as sensor readings, images, or even logs. However, in case you don’t need the data from all the topics that exist on the system, there is an option to record only a subset of them.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Advantages&lt;/strong&gt; :&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Easy to set up&lt;/strong&gt; : Rosbag is a built-in ROS tool, so no additional software installation is required.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Offline analysis&lt;/strong&gt; : There is no need to connect to the live robot in order to analyze the recorded data.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Drawbacks&lt;/strong&gt; :&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Limited scalability&lt;/strong&gt; : Since Rosbag is made for debugging but not for storing data continuously, managing and storing large Rosbag files can become very difficult as the amount of data grows.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;No advanced filtering&lt;/strong&gt; : Rosbag doesn’t provide advanced tools for filtering or querying data efficiently.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;No built-in User Interface&lt;/strong&gt; : Rosbag is a command line tool and as such, it has no built-in UI, meaning engineers have to interact with Rosbag through terminal commands.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://github.com/swri-robotics/bag-database" rel="noopener noreferrer"&gt;&lt;strong&gt;The Bag Database&lt;/strong&gt;&lt;/a&gt;, an open-source tool, addresses the challenges of working with Rosbag files by offering a user-friendly, web-based user interface for managing bag files. This tool makes it easier to search for specific bags, download them, or run post-processing scripts. Additionally, the Bag Database provides a REST API, allowing engineers to automate tasks like indexing or organizing bag files.&lt;/p&gt;

&lt;h2&gt;
  
  
  Method 2: Store Rosbag Data in Time-Series Object Storage&lt;a href="https://www.reduct.store/blog/store-ros-topics#method-2-store-rosbag-data-in-time-series-object-storage" rel="noopener noreferrer"&gt;​&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fj1omeqpnovftu8hk4uq9.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fj1omeqpnovftu8hk4uq9.png" alt="Method 2 Diagram" width="800" height="282"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Another option is to store compressed Rosbag files in a &lt;em&gt;time-series object storage solution&lt;/em&gt; like &lt;a href="https://www.reduct.store/" rel="noopener noreferrer"&gt;&lt;strong&gt;ReductStore&lt;/strong&gt;&lt;/a&gt;. Time-series storage works really well for ROS data because it sorts and retrieves information by time, which fits naturally with how robots process and use data. This approach also lets you add helpful labels to the files, like AI labels, sensor types, or recording locations, making it easier to manage and access your data.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Advantages&lt;/strong&gt; :&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Advanced filtering&lt;/strong&gt; : Labels make it easier to search and filter large datasets based on specific criteria.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Scalable&lt;/strong&gt; : ReductStore can easily handle large amounts of data, making it suitable for long-term storage of robotics data.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Drawbacks&lt;/strong&gt; :&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Learning curve&lt;/strong&gt; : Engineers new to time-series storage may need some time to set up and learn how to use them effectively.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Costs&lt;/strong&gt; : Using cloud-based object storage can cost more than simply storing the files on your system.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Method 3: Store Topics in Separate ReductStore Records for Granular Control&lt;a href="https://www.reduct.store/blog/store-ros-topics#method-3-store-topics-in-separate-reductstore-records-for-granular-control" rel="noopener noreferrer"&gt;​&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fb2czj40dec792h2q237x.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fb2czj40dec792h2q237x.png" alt="Method 3 Diagram" width="800" height="243"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This method involves &lt;em&gt;storing each ROS topic as a separate record in ReductStore&lt;/em&gt;, giving you great flexibility over how your data is managed. By grouping data by topic, you gain way better control over filtering, searching, and replicating the data. Each record can be configured with its own compression settings depending on the type of the data that’s being sent over that topic. Moreover, having specific metadata labels for each topic makes it easier to create useful and efficient queries.&lt;/p&gt;

&lt;p&gt;This approach also makes it easier to replicate data to the cloud. For example, you can make a rule to replicate only the most important topics - such as camera data or specific events - while excluding less relevant information.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Advantages&lt;/strong&gt; :&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Better control over your data&lt;/strong&gt; : You can customize how each topic is stored, compressed, and labeled.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Conditional filtering and replication&lt;/strong&gt; : With the ability to filter records based on label, you can quickly find what you need. You can also have granular replication by replicating only the important topics to the cloud.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Drawbacks&lt;/strong&gt; :&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Requires careful management&lt;/strong&gt; : Storing topics as separate records means you'll need to plan ahead to keep track of the data and its metadata, ensuring everything stays well-organized and manageable.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Examples&lt;/strong&gt; :&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Vibration Data&lt;/strong&gt; : Vibration sensors generate a large volume of data, which can quickly become challenging to manage. To handle this efficiently, data is often chunked and stored as objects. Keeping these chunks in separate records makes filtering and analysis much easier, especially for tracking machinery or robots where vibration patterns reveal potential issues. For more tips on managing vibration sensor data, check out this &lt;a href="https://dev.to/atimin/how-to-store-vibration-sensor-data-43gl-temp-slug-9825445"&gt;&lt;strong&gt;blog article on storing vibration sensor data&lt;/strong&gt;&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;LiDAR Data&lt;/strong&gt; : LiDAR data can be quite large, so applying compression is key to reducing storage needs. There are special compression formats designed specifically for LiDAR, which help shrink the size without losing the quality of the 3D point clouds. By storing LiDAR data as a separate record in ReductStore, you can apply these specialized compression techniques to that particular topic without affecting other types of data.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Logs and JSON Data&lt;/strong&gt; : Storing logs and JSON data in separate records allows you to organize and query them easily based on metadata labels. Logs may include useful details like timestamps, event types, or sensor statuses, while JSON is great for storing structured information. Keeping them as individual topics allows you to quickly filter and retrieve only the data you need, making analysis or debugging simpler.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Images&lt;/strong&gt; : Imagine that the robotic system has two separate topics, one for sharing image data, and the other for position data (like X, Y coordinates). Now, what you can do is sync these two topics by storing them together - in this scenario, the images would be the data itself, while the coordinates would be the labels of the record. This allows you to link the image to specific location data, enabling you to query images based on the robot’s position. For a step-by-step guide with code examples on how to store images in ROS using ReductStore, take a look at this &lt;a href="https://dev.to/anthonycvn/how-to-store-images-in-ros-2-af6-temp-slug-4675494"&gt;&lt;strong&gt;blog article on storing images in ROS&lt;/strong&gt;&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Best Practices for Storing ROS Topics&lt;a href="https://www.reduct.store/blog/store-ros-topics#best-practices-for-storing-ros-topics" rel="noopener noreferrer"&gt;​&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;When choosing how to store ROS topics, consider the following:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Data Size and Scalability&lt;/strong&gt; : For large datasets like LiDAR or images, ReductStore's time-series storage is ideal. Simpler solutions like Rosbag are enough for smaller data, but become difficult to manage as the project grows.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Query and Filtering Needs&lt;/strong&gt; : Storing each topic separately in ReductStore allows you to query data based on labels, enabling you to retrieve only the specific data you need. So, in case you need more granular filtering of the data, the best option would be storing each topic in its own record.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Cost and Complexity&lt;/strong&gt; : Storing topics separately offers great flexibility, but it takes more planning and management. If you're on a budget, simpler solutions like Rosbag or storing entire bag files in a time-series storage like ReductStore can work well for smaller projects.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Conclusion&lt;a href="https://www.reduct.store/blog/store-ros-topics#conclusion" rel="noopener noreferrer"&gt;​&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;In conclusion, there are various ways to store ROS data, each with its own set of advantages and disadvantages. Choosing the right storage method for your ROS topics depends on data size, query needs, and scalability. For larger datasets and advanced filtering, &lt;a href="https://www.reduct.store/" rel="noopener noreferrer"&gt;&lt;strong&gt;ReductStore&lt;/strong&gt;&lt;/a&gt;'s time-series storage is a great fit. Smaller projects may find simpler options like Rosbag more suitable. Therefore, it's important to consider the specific requirement of your project and plan accordingly.&lt;/p&gt;




&lt;p&gt;If you have any questions or comments, feel free to use the &lt;a href="https://community.reduct.store/" rel="noopener noreferrer"&gt;&lt;strong&gt;ReductStore Community Forum&lt;/strong&gt;&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>robotics</category>
    </item>
    <item>
      <title>How to Store and Manage Robotic Data</title>
      <dc:creator>Gracija</dc:creator>
      <pubDate>Tue, 07 Jan 2025 00:00:00 +0000</pubDate>
      <link>https://forem.com/reductstore/how-to-store-and-manage-robotic-data-3ojp</link>
      <guid>https://forem.com/reductstore/how-to-store-and-manage-robotic-data-3ojp</guid>
      <description>&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fobai5mciztjcfk2rrdms.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fobai5mciztjcfk2rrdms.png" alt="Introduction Diagram" width="800" height="706"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Robots generate massive amounts of data that must be managed effectively. Challenges like limited on-device storage, the need for real-time processing, and high cloud storage costs make it essential to find efficient solutions. Balancing edge and cloud storage while keeping data synchronized is a key part of effective management.&lt;/p&gt;

&lt;p&gt;This article begins by outlining these challenges and offering practical strategies, such as using time-series databases and implementing retention policies. We will then introduce &lt;a href="https://www.reduct.store/" rel="noopener noreferrer"&gt;&lt;strong&gt;ReductStore&lt;/strong&gt;&lt;/a&gt;, a specialized database designed to meet the unique needs of robotic systems. With features like real-time ingestion, efficient querying with batching, smart retention policies, and edge-to-cloud replication, &lt;em&gt;ReductStore offers a cost-effective and high-performance solution for storing and managing robotic data.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;We’ll also explore a hand-on example where we’ll show how you can set up ReductStore and use it for storing and managing data. Finally, we will compare ReductStore with MongoDB, explaining why ReductStore is the better choice for robotics. This comprehensive guide is designed to help engineers and developers overcome the challenges of robotic data management and optimize their systems.&lt;/p&gt;

&lt;p&gt;What we’ll cover:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://www.reduct.store/blog/store-robotic-data#challenges-in-robotic-data-management" rel="noopener noreferrer"&gt;&lt;strong&gt;Challenges in Robotic Data Management&lt;/strong&gt;&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.reduct.store/blog/store-robotic-data#general-strategies-for-managing-robotic-data" rel="noopener noreferrer"&gt;&lt;strong&gt;General Strategies for Managing Robotic Data&lt;/strong&gt;&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.reduct.store/blog/store-robotic-data#reductstore-a-purpose-built-solution-for-robotic-data" rel="noopener noreferrer"&gt;&lt;strong&gt;ReductStore: A Purpose-Built Solution for Robotic Data&lt;/strong&gt;&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.reduct.store/blog/store-robotic-data#mongodb-vs-reductstore-for-robotics" rel="noopener noreferrer"&gt;&lt;strong&gt;MongoDB vs. ReductStore for Robotics&lt;/strong&gt;&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.reduct.store/blog/store-robotic-data#hands-on-example-storing-and-handling-robotic-data-in-reductstore" rel="noopener noreferrer"&gt;&lt;strong&gt;Hands-On Example: Storing and Handling Robotic Data in ReductStore&lt;/strong&gt;&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Challenges in Robotic Data Management&lt;a href="https://www.reduct.store/blog/store-robotic-data#challenges-in-robotic-data-management" rel="noopener noreferrer"&gt;​&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;Robots often operate in dynamic and unpredictable environments and are continuously generating large amounts of data. Therefore, finding an efficient way to store and manage this data can at times be challenging, mainly due to the following factors:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;High Frequency and Real-Time Requirements&lt;/strong&gt; : Robots often operate in real-time environments; for example, a drone navigating through a city must process camera and sensor data in milliseconds to avoid potential obstacles and stay on track. Data storage solutions must be able to manage these high-frequency streams and make them easily and quickly accessible in order to ensure fast analysis and good decision-making.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Limited On-Device Storage&lt;/strong&gt; : Most robots cannot store all the data they generate because they have limited edge storage capacity due to size, weight, and power limitations. That’s why it’s important for engineers to make effective data management strategies and ensure that important data is maintained without exceeding storage limits.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;High Volume of Data&lt;/strong&gt; : An autonomous vehicle can produce up to &lt;a href="https://www.datacenterfrontier.com/connected-cars/article/11429212/rolling-zettabytes-quantifying-the-data-impact-of-connected-cars" rel="noopener noreferrer"&gt;&lt;strong&gt;5 terabytes of data every hour&lt;/strong&gt;&lt;/a&gt;, including camera feeds, LiDAR scans, radar data, GPS logs, and sensor readings. Processing, storing, and managing such large datasets requires storage systems designed for scalability, which is something traditional relational databases often lack.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Cloud Storage Costs&lt;/strong&gt; : Sending all robotic data to the cloud is impractical and costly. Cloud services charge for storage and data transfer, and since robots generate many terabytes of data, the costs can grow quickly. Balancing what to store locally and what to offload to the cloud is an important part of cost-effective data management.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Reduction Challenges&lt;/strong&gt; : Implementing good reduction strategies can be tricky, as it requires balancing storage efficiency with maintaining important information. Without clear strategies, valuable data might be lost, or storage could fill up with unnecessary details.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  General Strategies for Managing Robotic Data&lt;a href="https://www.reduct.store/blog/store-robotic-data#general-strategies-for-managing-robotic-data" rel="noopener noreferrer"&gt;​&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;In order to have an effective data management system for handling robotic data, engineers must have a clear strategy and use various specialized tools. The key is to implement solutions that can handle high-frequency data streams while at the same time optimizing storage space and costs.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Time-Series Object Stores&lt;/strong&gt; : Time-series object stores, such as ReductStore, are designed to handle high-frequency, time-stamped unstructured data streams, which makes them ideal for managing robotic data. They offer efficient storage, real-time querying, and high-performance data writing, ensuring that robots can operate effectively while keeping costs manageable.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Balance Edge and Cloud Storage&lt;/strong&gt; : To optimize storage, keep critical data - such as the latest logs or details of high-priority events - on edge devices for immediate access, while moving less time-sensitive data to the cloud for long-term analysis and archiving. With such hybrid model, you can definitely reduce cloud storage, while also making sure that there will be a minimal delay when accessing decision-making data.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Implement Retention Policies&lt;/strong&gt; : Retention policies are automated rules for data lifecycle management, and they help manage storage by automatically deleting or archiving outdated or non-essential data. Robot's Edge devices are quite space-constrained, and often we just want to keep as much history as possible. The best retention policy in this case is a FIFO quota based on storage volume. For example, an entry with a 1TB FIFO quota would not delete older records until the quota was full.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Compress and Optimize Data&lt;/strong&gt; : Another way to reduce storage but still maintain usability is to compress large datasets, such as images or videos. Advanced compression formats like H.265 for video and JPEG for images allow robotics teams to save loads of storage space.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Prioritize Data Relevance&lt;/strong&gt; : Not all robotic data holds the same value, so it’s important for engineers to know how to make the distinction between what’s considered critical data and should be kept, and what data is not important and can be discarded.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  ReductStore: A Purpose-Built Solution for Robotic Data&lt;a href="https://www.reduct.store/blog/store-robotic-data#reductstore-a-purpose-built-solution-for-robotic-data" rel="noopener noreferrer"&gt;​&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;In this section, we’ll get into more detail about what ReductStore actually is and why it is such a good solution when it comes to storing and managing high volumes of robotic data.&lt;/p&gt;

&lt;h3&gt;
  
  
  Key Features and Benefits&lt;a href="https://www.reduct.store/blog/store-robotic-data#key-features-and-benefits" rel="noopener noreferrer"&gt;​&lt;/a&gt;
&lt;/h3&gt;

&lt;p&gt;ReductStore is a high-performance, time-series database specifically designed to handle the complex data needs of robotics systems and the challenges that we’ve discussed about in the previous sections. It is designed to handle unstructured data and is optimized for real-time data ingestion, allowing it to process high-frequency sensor readings and large data streams generated by autonomous vehicles, drones, industrial robots, and more.&lt;/p&gt;

&lt;h3&gt;
  
  
  Cost-Efficiency&lt;a href="https://www.reduct.store/blog/store-robotic-data#cost-efficiency" rel="noopener noreferrer"&gt;​&lt;/a&gt;
&lt;/h3&gt;

&lt;p&gt;ReductStore can actually achieve 10-100x better performance for 1/10th of the cost compared to traditional time-series object stores when working with records of around 100KB. But how exactly does it do it? Well, firstly, it can integrate with blob storages like &lt;a href="https://www.reduct.store/docs/guides/integration/azure-vm" rel="noopener noreferrer"&gt;&lt;strong&gt;Azure Blob Storage&lt;/strong&gt;&lt;/a&gt; or &lt;a href="https://www.reduct.store/solutions/cloud" rel="noopener noreferrer"&gt;&lt;strong&gt;Google Cloud Storage&lt;/strong&gt;&lt;/a&gt; with a &lt;em&gt;Fuse driver&lt;/em&gt;. In the example below, we’ll be using Azure Blob Storage.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Azure Blob Storage&lt;/strong&gt; : A scalable object storage service optimized for large amounts of unstructured data.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;BlobFuse&lt;/strong&gt; : An open-source virtual file system driver for Azure Blob Storage.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;ReductStore leverages Azure's storage tiers and stores infrequently accessed data in lower-cost tiers like Cool or Cold, and it also utilizes a &lt;em&gt;pay-as-you-go model&lt;/em&gt;. Moreover, traditional databases require high IOPS (Input/Output Operations per Second) and often rely on expensive storage options like SSDs to maintain performance. ReductStore can store data in blob storage using FUSE drivers, eliminating the need for redundant, costly storage setups. BlobFuse allows ReductStore to treat blob storage like a local file system, meaning that data can be quickly accessed without having duplicate data in other layers like caches or local databases. Plus, unlike traditional databases, &lt;em&gt;Blob Storage can scale virtually infinitely&lt;/em&gt;. ReductStore takes advantage of this scalability without additional costs for maintaining database indexes or clusters.&lt;/p&gt;

&lt;p&gt;When it comes to data replication, ReductStore allows &lt;em&gt;replication at the bucket level&lt;/em&gt;, not the entire dataset, meaning we may only replicate high-priority sensor data or logs while leaving unimportant data untouched. This minimizes storage and network costs compared to traditional databases that replicate entire datasets. In addition, &lt;em&gt;ReductStore replicates data incrementally&lt;/em&gt;, which ensures that only changes or new data will be replicated and in this way avoids extra costs for potential duplicate files. Additionally, ReductStore supports storing &lt;em&gt;summary metrics as labels&lt;/em&gt; alongside each record. These labels act as metadata, making it easier to filter important records and design efficient replication strategies for selectively replicating only the most critical data to the cloud.&lt;/p&gt;

&lt;h3&gt;
  
  
  Query Language and Batching Capabilities&lt;a href="https://www.reduct.store/blog/store-robotic-data#query-language-and-batching-capabilities" rel="noopener noreferrer"&gt;​&lt;/a&gt;
&lt;/h3&gt;

&lt;p&gt;ReductStore uses a flexible and powerful &lt;a href="https://www.reduct.store/docs/next/conditional-query#query-syntax" rel="noopener noreferrer"&gt;&lt;strong&gt;query language that is based on JSON syntax&lt;/strong&gt;&lt;/a&gt; and is optimized for robotics data. The query language allows for real-time and historical analysis of data, as well as powerful filtering, aggregation, and joining of datasets. For robotics applications, where performance and precision are critical, the ability to run complex queries in real-time is essential.&lt;/p&gt;

&lt;p&gt;The query language also supports time-series operations, which allow engineers to analyze sensor data over specified time windows. For example, you can query for vibration data from a specific robot within a defined timeframe or compare sensor data from different robots in parallel.&lt;/p&gt;

&lt;p&gt;Additionally, ReductStore provides APIs and SDKs for integration with popular programming languages, making it easy to interface with robotic systems and third-party software applications. Whether you're working in &lt;em&gt;Python, C++, JavaScript&lt;/em&gt;, or &lt;em&gt;Rust&lt;/em&gt;, ReductStore ensures that you can access and manipulate data with minimal overhead.&lt;/p&gt;

&lt;p&gt;ReductStore optimizes data retrieval through &lt;em&gt;batching&lt;/em&gt;, allowing multiple records to be grouped into a single query based on a time range. This reduces the number of requests, improving performance and reducing delays. Queries are processed iteratively, returning batches of records per iteration, which is beneficial for managing large datasets. For more details, visit the &lt;a href="https://www.reduct.store/docs/guides/data-querying" rel="noopener noreferrer"&gt;&lt;strong&gt;official guide on data querying&lt;/strong&gt;&lt;/a&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Replication Strategies and Edge-To-Cloud Syncing&lt;a href="https://www.reduct.store/blog/store-robotic-data#replication-strategies-and-edge-to-cloud-syncing" rel="noopener noreferrer"&gt;​&lt;/a&gt;
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F98888e91btvqvfpher0j.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F98888e91btvqvfpher0j.png" alt="Replication Diagram" width="800" height="896"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In this example, there are a couple of industrial robots that produce a large amount of data which then gets ingested by Kafka and then distributed to a local storage on the edge. This is where the replication comes into play - in order to optimize costs, only a part of the data that’s stored locally is actually going to be stored on the cloud. For example, if we ingest and store sensor data every second, only 1 in 10 seconds are actually going to be stored on the cloud, as well as some common metrics which may be useful for analysis later on. Due to the fact that we can create custom policies for the replication strategy, ReductStore offers a great solution to the edge-to-cloud syncing problem and shows that it is possible to have great performance while still significantly cutting on costs.&lt;/p&gt;

&lt;h3&gt;
  
  
  Retention Strategies&lt;a href="https://www.reduct.store/blog/store-robotic-data#retention-strategies" rel="noopener noreferrer"&gt;​&lt;/a&gt;
&lt;/h3&gt;

&lt;p&gt;As mentioned in the previous section, implementing effective retention policies is crucial for ensuring that the local storage doesn’t fill up and lead to potential bottlenecks, but we also must make sure that all the data that we need quick access to is actually stored at the edge.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.reduct.store/docs/guides/buckets#quota-type" rel="noopener noreferrer"&gt;&lt;strong&gt;ReductStore implements volume-based retention policies&lt;/strong&gt;&lt;/a&gt; that follow the &lt;em&gt;FIFO&lt;/em&gt; (first-In, First-Out) principle. That means that old data will be deleted only when the storage is at full capacity in order for new data to be stored. These retention policies are customizable and can be adjusted separately for each data bucket.&lt;/p&gt;

&lt;p&gt;This is different from how most of the other databases are handling retention – they’re implementing them based on &lt;em&gt;time periods&lt;/em&gt;. This can be problematic because even if the system was not working for some time due to an outage or any other problem and the storage is not filled up, the database will delete data that it mustn’t have deleted, only because the predefined timeframe has passed.&lt;/p&gt;

&lt;h3&gt;
  
  
  Example Applications&lt;a href="https://www.reduct.store/blog/store-robotic-data#example-applications" rel="noopener noreferrer"&gt;​&lt;/a&gt;
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Autonomous Vehicles&lt;/strong&gt; : Autonomous vehicles generate massive amounts of sensor data that need to be processed and analyzed in real-time. ReductStore’s ability to handle time-series data and support high-throughput ingestion makes it an excellent solution for managing this data.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Industrial Robots&lt;/strong&gt; : In manufacturing, robots rely on real-time sensor data to adjust operations and monitor performance. ReductStore is ideal for storing and analyzing diagnostic data, enabling predictive maintenance and continuous optimization.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Drones and UAVs&lt;/strong&gt; : Drones often operate in remote areas with limited connectivity. ReductStore’s offline data synchronization and edge storage capabilities allow for reliable operation, even in environments with poor network coverage.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  MongoDB vs. ReductStore for Robotics&lt;a href="https://www.reduct.store/blog/store-robotic-data#mongodb-vs-reductstore-for-robotics" rel="noopener noreferrer"&gt;​&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;MongoDB and ReductStore are both robust databases, but they are built for different purposes. ReductStore is great at handling high-speed time-series data, making it perfect for storing unstructured “blob” data. It uses buckets to organize data by time, which helps with fast real-time processing. MongoDB, on the other hand, is a flexible database for semi-structured data, but it struggles with big files unless you use GridFS, which can slow things down.&lt;/p&gt;

&lt;p&gt;With features like batch querying, smart edge-to-cloud syncing, and simple retention policies to avoid storage issues, ReductStore is a perfect solution for robotics applications, where data is processed locally and only important pieces are sent to the cloud. MongoDB has good features like replication and time-based data deletion, but it’s not as well-suited for these specific needs. Moreover, in performance tests, ReductStore was up to 900% faster for writing data and 2300% faster for reading compared to MongoDB.&lt;/p&gt;

&lt;p&gt;For a deeper analysis, explore the full comparison here: &lt;a href="https://dev.to/atimin/mongodb-vs-reductstore-choosing-the-right-database-for-robotics-applications-4o05-temp-slug-1871626"&gt;&lt;strong&gt;MongoDB vs ReductStore: Choosing the Right Database for Robotics Applications&lt;/strong&gt;&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Hands-On Example: Storing and Handling Robotic Data in ReductStore&lt;a href="https://www.reduct.store/blog/store-robotic-data#hands-on-example-storing-and-handling-robotic-data-in-reductstore" rel="noopener noreferrer"&gt;​&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;In this section, we’ll walk through a &lt;a href="https://github.com/reductstore/reduct-robotics-example/blob/main/StoreQueryData.py" rel="noopener noreferrer"&gt;&lt;strong&gt;practical example of how to store and handle robotic data using ReductStore&lt;/strong&gt;&lt;/a&gt;. ReductStore is very efficient for storing “episodes” - for example, 10-second raw data with all the logs generated by robots that would be around 100KB. For simplicity reasons, we’ll show how to store trajectory data, but in reality, engineers will most probably work with bigger and more diverse data.&lt;/p&gt;

&lt;p&gt;For this example, we’ll use Python, so make sure you have &lt;em&gt;Python 3.8+&lt;/em&gt; installed in your environment.&lt;/p&gt;

&lt;h3&gt;
  
  
  Setting Up ReductStore&lt;a href="https://www.reduct.store/blog/store-robotic-data#setting-up-reductstore" rel="noopener noreferrer"&gt;​&lt;/a&gt;
&lt;/h3&gt;

&lt;p&gt;We’ll start by using Docker to set up ReductStore in a containerized environment. Docker ensures that our setup is isolated, reproducible, and easy to manage. To get started, create a folder on your system, and inside of it, create a &lt;em&gt;docker-compose.yaml&lt;/em&gt; file with the necessary configuration to run ReductStore:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;version&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;3.8"&lt;/span&gt;

&lt;span class="na"&gt;services&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;reductstore&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;image&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;reduct/store:latest&lt;/span&gt;
    &lt;span class="na"&gt;ports&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;8383:8383"&lt;/span&gt;
    &lt;span class="na"&gt;volumes&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;data:/data&lt;/span&gt;
    &lt;span class="na"&gt;environment&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;RS_API_TOKEN=my-token&lt;/span&gt;

&lt;span class="na"&gt;volumes&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;data&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;driver&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;local&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;span&gt;&lt;/span&gt;&lt;/p&gt;

&lt;p&gt;Then, to start the ReductStore container, simply run:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker compose up &lt;span class="nt"&gt;-d&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;span&gt;&lt;/span&gt;&lt;/p&gt;

&lt;p&gt;This command will pull the latest ReductStore image and start the container. Once the container is up, ReductStore will be available on port &lt;a href="http://127.0.0.1:8383/" rel="noopener noreferrer"&gt;http://127.0.01:8383&lt;/a&gt; and can be accessed by your robotic system.&lt;/p&gt;

&lt;p&gt;You can check the status of your container by running:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker ps
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;span&gt;&lt;/span&gt;&lt;/p&gt;

&lt;p&gt;One last thing you need to do before we begin is make sure you have the necessary libraries installed by running:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;pip &lt;span class="nb"&gt;install &lt;/span&gt;reduct-py numpy
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;span&gt;&lt;/span&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Store and Manage Data&lt;a href="https://www.reduct.store/blog/store-robotic-data#store-and-manage-data" rel="noopener noreferrer"&gt;​&lt;/a&gt;
&lt;/h3&gt;

&lt;p&gt;Now that ReductStore is running and we have everything that we need installed, let's look at how we can store robotic data. In our example, we’ll work with trajectory data like coordinates, speed, and orientation.&lt;/p&gt;

&lt;h4&gt;
  
  
  Create (or Get) a Bucket&lt;a href="https://www.reduct.store/blog/store-robotic-data#create-or-get-a-bucket" rel="noopener noreferrer"&gt;​&lt;/a&gt;
&lt;/h4&gt;

&lt;p&gt;Let us first create a new bucket for storing the robot trajectory data named &lt;em&gt;trajectory_data&lt;/em&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;create_trajectory_bucket&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
 &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="k"&gt;with&lt;/span&gt; &lt;span class="nc"&gt;Client&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;http://localhost:8383&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;api_token&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;my-token&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;client&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
  &lt;span class="n"&gt;settings&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;BucketSettings&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
     &lt;span class="n"&gt;quota_type&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;QuotaType&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;FIFO&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
     &lt;span class="n"&gt;quota_size&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;1000_000_000&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;client&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;create_bucket&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;trajectory_data&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;settings&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;exist_ok&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;span&gt;&lt;/span&gt;&lt;/p&gt;

&lt;p&gt;The quota type of this bucket will be FIFO and its size will be 1 GB. In case we don’t define this as a setting, the bucket will be created with a default quota type of &lt;em&gt;NONE&lt;/em&gt;.&lt;/p&gt;

&lt;h4&gt;
  
  
  Generate Trajectory Data&lt;a href="https://www.reduct.store/blog/store-robotic-data#generate-trajectory-data" rel="noopener noreferrer"&gt;​&lt;/a&gt;
&lt;/h4&gt;

&lt;p&gt;Now, let’s create a &lt;em&gt;generate_trajectory_data&lt;/em&gt; function that simulates the generation of trajectory data points for a robot moving in a 2D space.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;generate_trajectory_data&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;frequency&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;int&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;duration&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;int&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
 &lt;span class="n"&gt;interval&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="n"&gt;frequency&lt;/span&gt;
 &lt;span class="n"&gt;start_time&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;datetime&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;now&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

  &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="nf"&gt;range&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;frequency&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;duration&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;time_step&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;interval&lt;/span&gt;
    &lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;np&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;sin&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;np&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;pi&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;time_step&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mf"&gt;0.2&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;np&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;random&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;randn&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="n"&gt;y&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;np&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;cos&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;np&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;pi&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;time_step&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mf"&gt;0.2&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;np&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;random&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;randn&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="n"&gt;yaw&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;np&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;degrees&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;np&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;arctan2&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;y&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;np&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;random&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;uniform&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;speed&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;abs&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;np&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;sin&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;np&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;pi&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;time_step&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mf"&gt;0.1&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;np&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;random&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;randn&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="n"&gt;timestamp&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;start_time&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nf"&gt;timedelta&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;seconds&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;time_step&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="k"&gt;yield&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;timestamp&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;timestamp&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;isoformat&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
      &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;position&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;x&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;round&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;y&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;round&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;y&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;)},&lt;/span&gt;
      &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;orientation&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;yaw&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;round&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;yaw&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;)},&lt;/span&gt;
      &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;speed&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;round&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;speed&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;asyncio&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;sleep&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;interval&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;span&gt;&lt;/span&gt;&lt;/p&gt;

&lt;p&gt;The frequency is the number of data points generated per second (default is 10 Hz), while the duration is the total time, in seconds, for which the data generation will run (the default is 1 second). &lt;em&gt;X&lt;/em&gt; and &lt;em&gt;y&lt;/em&gt; are the coordinates and they dictate the position of the robot, &lt;em&gt;yaw&lt;/em&gt; is its orientation, &lt;em&gt;speed&lt;/em&gt; is its approximate speed based on position changes, while &lt;em&gt;timestamp&lt;/em&gt; is the current timestamp for the current data point.&lt;/p&gt;

&lt;h4&gt;
  
  
  Calculate Metrics&lt;a href="https://www.reduct.store/blog/store-robotic-data#calculate-metrics" rel="noopener noreferrer"&gt;​&lt;/a&gt;
&lt;/h4&gt;

&lt;p&gt;Now, we would like to calculate some important metrics that can be useful for further analysis of our robots. In this example, we will calculate the average speed and total distance of the robot by analyzing the data that we generated in the previous section:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;calculate_trajectory_metrics&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;trajectory&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;list&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;tuple&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
  &lt;span class="n"&gt;positions&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;np&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;array&lt;/span&gt;&lt;span class="p"&gt;([[&lt;/span&gt;&lt;span class="n"&gt;point&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;position&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;][&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;x&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="n"&gt;point&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;position&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;][&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;y&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]]&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt;   &lt;span class="n"&gt;point&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;trajectory&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
  &lt;span class="n"&gt;speeds&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;np&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;array&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="n"&gt;point&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;speed&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;point&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;trajectory&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;

  &lt;span class="n"&gt;deltas&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;np&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;diff&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;positions&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;axis&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="n"&gt;distances&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;np&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;sqrt&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;np&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;sum&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;deltas&lt;/span&gt;&lt;span class="o"&gt;**&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;axis&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
  &lt;span class="n"&gt;total_distance&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;np&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;sum&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;distances&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

  &lt;span class="n"&gt;average_speed&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;np&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;mean&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;speeds&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;total_distance&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;average_speed&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;span&gt;&lt;/span&gt;&lt;/p&gt;

&lt;h4&gt;
  
  
  Storing data in ReductStore&lt;a href="https://www.reduct.store/blog/store-robotic-data#storing-data-in-reductstore" rel="noopener noreferrer"&gt;​&lt;/a&gt;
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;store_trajectory_data&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
  &lt;span class="n"&gt;trajectory_data&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;
  &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;data_point&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="nf"&gt;generate_trajectory_data&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;frequency&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;duration&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;trajectory_data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;append&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;data_point&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

  &lt;span class="n"&gt;total_distance&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;average_speed&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;calculate_trajectory_metrics&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;trajectory_data&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

  &lt;span class="n"&gt;labels&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;total_distance&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;total_distance&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;average_speed&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;average_speed&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="n"&gt;packed_data&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;pack_trajectory_data&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;trajectory_data&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

  &lt;span class="n"&gt;timestamp&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;datetime&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;now&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

  &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="k"&gt;with&lt;/span&gt; &lt;span class="nc"&gt;Client&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;http://localhost:8383&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;api_token&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;my-token&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;client&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="n"&gt;bucket&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;client&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get_bucket&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;trajectory_data&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;bucket&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;write&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;trajectory_data&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;packed_data&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;timestamp&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;labels&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;labels&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;


&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;pack_trajectory_data&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;trajectory&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;list&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;bytes&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
  &lt;span class="sh"&gt;"""&lt;/span&gt;&lt;span class="s"&gt;Pack trajectory data json format&lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;json&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;dumps&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;trajectory&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;encode&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;utf-8&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;span&gt;&lt;/span&gt;&lt;/p&gt;

&lt;p&gt;In the &lt;em&gt;store_trajectory_data&lt;/em&gt; function, we’re making use of the functions we previously created to generate the data and calculate the metrics. Then, we need to somehow pack the data, therefore we create the &lt;em&gt;pack_trajectory_data&lt;/em&gt; function where, as an example, we convert the trajectory list output to a json dump. Next step is to store that data in the bucket we have already created. The fact that we’re calling the functions for generating the data and calculating the metrics inside of the &lt;em&gt;store_trajectory_data&lt;/em&gt; function is due to simplicity reasons, but in general, these functions should be called from the outside and then simply fed to this function.&lt;/p&gt;

&lt;p&gt;Now, if we take a look at the &lt;strong&gt;Buckets&lt;/strong&gt; section in ReductStore, we’ll see that our bucket now has data inside.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ftrdlhvz7x1qm4sj9bsqy.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ftrdlhvz7x1qm4sj9bsqy.png" alt="ReductStore Bucket" width="800" height="342"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h4&gt;
  
  
  Retrieving Data&lt;a href="https://www.reduct.store/blog/store-robotic-data#retrieving-data" rel="noopener noreferrer"&gt;​&lt;/a&gt;
&lt;/h4&gt;

&lt;p&gt;The next step would be to retrieve the data we just stored queried by a specific label. Here’s the query:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;query_by_label&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;bucket_name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;entry_name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;label_key&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;label_value&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
  &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="k"&gt;with&lt;/span&gt; &lt;span class="nc"&gt;Client&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;http://localhost:8383&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;api_token&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;my-token&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;client&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="n"&gt;bucket&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;client&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get_bucket&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;bucket_name&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;record&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;bucket&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;query&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
      &lt;span class="n"&gt;entry_name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="n"&gt;when&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;label_key&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;$gt&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;label_value&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
      &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="p"&gt;):&lt;/span&gt;
      &lt;span class="c1"&gt;# Do something with the record
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;span&gt;&lt;/span&gt;&lt;/p&gt;

&lt;p&gt;Note that in order to get all records with no filtering at all, you just have to remove the &lt;em&gt;‘when’&lt;/em&gt; condition.&lt;/p&gt;

&lt;h4&gt;
  
  
  Running Everything&lt;a href="https://www.reduct.store/blog/store-robotic-data#running-everything" rel="noopener noreferrer"&gt;​&lt;/a&gt;
&lt;/h4&gt;

&lt;p&gt;This is our main function in which we’re calling the functions for creating the bucket, storing the trajectory data (which inside includes functions for generating the data and its labels), and retrieving records filtered by a specific label.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
  &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;create_trajectory_bucket&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;store_trajectory_data&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="n"&gt;label_query_result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;query_by_label&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;trajectory_data&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;trajectory_data&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;&amp;amp;total_distance&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;HIGH_DISTANCE&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;label_query_result&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
      &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Data queried by label: &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;label_query_result&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="n"&gt;asyncio&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;run&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;span&gt;&lt;/span&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion&lt;a href="https://www.reduct.store/blog/store-robotic-data#conclusion" rel="noopener noreferrer"&gt;​&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;Managing robotic data doesn't have to be complicated. With the right tools and strategies, you can handle large amounts of data efficiently while keeping costs low. ReductStore offers a practical solution that meets the unique needs of robotics systems, from real-time processing to smart storage management. By implementing these approaches, robotics teams can focus less on data management and more on building better robots.&lt;/p&gt;

&lt;p&gt;Ready to improve your robotic data management? Try ReductStore today at &lt;a href="https://www.reduct.store/" rel="noopener noreferrer"&gt;&lt;strong&gt;reduct.store&lt;/strong&gt;&lt;/a&gt; or check out our &lt;a href="https://www.reduct.store/docs/how-does-it-work" rel="noopener noreferrer"&gt;&lt;strong&gt;documentation&lt;/strong&gt;&lt;/a&gt; to get started.&lt;/p&gt;

&lt;p&gt;Thanks for reading. If you have any questions or comments, feel free to use the &lt;a href="https://community.reduct.store/" rel="noopener noreferrer"&gt;&lt;strong&gt;ReductStore Community Forum&lt;/strong&gt;&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>robotics</category>
    </item>
    <item>
      <title>MongoDB vs ReductStore: Choosing the Right Database for Robotics Applications</title>
      <dc:creator>Gracija</dc:creator>
      <pubDate>Tue, 26 Nov 2024 00:00:00 +0000</pubDate>
      <link>https://forem.com/reductstore/mongodb-vs-reductstore-choosing-the-right-database-for-robotics-applications-539b</link>
      <guid>https://forem.com/reductstore/mongodb-vs-reductstore-choosing-the-right-database-for-robotics-applications-539b</guid>
      <description>&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fwo486d8a1amiuajby5oh.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fwo486d8a1amiuajby5oh.png" alt="Introduction Diagram" width="800" height="666"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Robotics applications generate and process a wide variety of data, such as sensor readings, video streams, logs, and AI model outputs. Managing this data efficiently is crucial because it affects the performance, scalability, and reliability of the entire system.&lt;/p&gt;

&lt;p&gt;In this article, we'll compare &lt;a href="https://www.reduct.store/" rel="noopener noreferrer"&gt;&lt;strong&gt;ReductStore&lt;/strong&gt;&lt;/a&gt; and &lt;strong&gt;MongoDB&lt;/strong&gt; , two databases designed to handle different aspects of data management. ReductStore is a time-series blob storage solution optimized for managing large amounts of data coming from continuous streams. MongoDB, on the other hand, is a popular NoSQL database known for its flexibility, scalability, and support for unstructured and semi-structured data.&lt;/p&gt;

&lt;p&gt;By understanding the strengths and limitations of each, you can make an informed decision to meet your project's specific data needs.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;TL;DR;&lt;/strong&gt;&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&lt;strong&gt;Feature&lt;/strong&gt;&lt;/th&gt;
&lt;th&gt;&lt;strong&gt;ReductStore&lt;/strong&gt;&lt;/th&gt;
&lt;th&gt;&lt;strong&gt;MongoDB&lt;/strong&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Architecture&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Time-series string messages with metadata stored as key-value pairs&lt;/td&gt;
&lt;td&gt;Collections of JSON-like documents&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Data Querying&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Query requests via time ranges with filters&lt;/td&gt;
&lt;td&gt;MongoDB Query Language (MQL)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Communication Protocol&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Uses HTTP/HTTPS&lt;/td&gt;
&lt;td&gt;MongoDB Wire Protocol (binary, BSON-based)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Data Batching Capabilities&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Supports data batching&lt;/td&gt;
&lt;td&gt;Supports data batching, but it’s not optimized for time-series data&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Replication&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Granular data filtering support&lt;/td&gt;
&lt;td&gt;Replicates the entire dataset; no native support for filtering during replication.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Retention&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Retention policy based on data volume with ‘First-in, First-out’ (FIFO) deletions&lt;/td&gt;
&lt;td&gt;Uses TTL (Time to Live) indexes for time-based data deletion&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Performance&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Optimized for unstructured data; up to 900% faster for writes and 2300% faster for reads.&lt;/td&gt;
&lt;td&gt;General-purpose; slower with large blobs.&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h2&gt;
  
  
  Understanding the General Architectural Differences&lt;a href="https://www.reduct.store/blog/robotics-mongodb-vs-reductstore#understanding-the-general-architectural-differences" rel="noopener noreferrer"&gt;​&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;First, let's look at MongoDB and ReductStore's differences in terms of their general architectural principles.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;ReductStore&lt;/strong&gt; has a specialized approach to managing unstructured, “blob” data organized by time. Its architecture revolves around buckets, entries, and records—concepts comparable to databases, tables, and rows in SQL systems. This structure, combined with fixed-size blocks for chronological data storage, makes ReductStore highly efficient for real-time processing and retrieval of data coming from continuous streams. It's also important to be mentioned that ReductStore has no limits to the size or the type of the data you can store.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;MongoDB&lt;/strong&gt; , in contrast, uses a document-oriented model based on collections of JSON-like documents. This flexible structure supports complex hierarchies and adapts well to applications with dynamic or loosely structured data, such as e-commerce platforms or content management systems. While MongoDB has a 16MB document size limit, it can handle larger files using GridFS, a feature designed to store and retrieve large binary files by splitting them into smaller chunks. However, storing data with GridFS is slower compared to working with standard JSON documents, which can affect performance in applications requiring frequent or rapid access to large files.&lt;/p&gt;

&lt;h2&gt;
  
  
  Development Experience&lt;a href="https://www.reduct.store/blog/robotics-mongodb-vs-reductstore#development-experience" rel="noopener noreferrer"&gt;​&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;In this section, we will compare the development experience of MongoDB and ReductStore, focusing on their query languages, communication protocols, and integration capabilities.&lt;/p&gt;

&lt;h3&gt;
  
  
  Query languages and SDK support&lt;a href="https://www.reduct.store/blog/robotics-mongodb-vs-reductstore#query-languages-and-sdk-support" rel="noopener noreferrer"&gt;​&lt;/a&gt;
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://www.reduct.store/docs/guides/data-querying" rel="noopener noreferrer"&gt;&lt;strong&gt;ReductStore supports querying data in several different ways&lt;/strong&gt;&lt;/a&gt; – either by using its &lt;em&gt;CLI, SDKs&lt;/em&gt;, or &lt;em&gt;HTTP API&lt;/em&gt;. This database solution improves data retrieval by batching records within a time range, minimizing requests and delays. Apart from querying by a time range, there is a possibility to retrieve a record by its timestamp, but you have to keep in mind that such querying is less efficient due to the lack of batching. ReductStore provides client SDKs for Python, JavaScript, C++, and Rust.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;MongoDB&lt;/strong&gt; uses its own query language, &lt;em&gt;MongoDB Query Language (MQL),&lt;/em&gt; which allows for flexible and powerful data querying. MQL supports complex filtering, aggregation, and indexing, making it a great choice for applications that need to work with semi-structured data. MongoDB also provides official SDKs for various languages, such as Java, Python, and C#, making it easy to integrate with various development environments.&lt;/p&gt;

&lt;h3&gt;
  
  
  Communication protocols&lt;a href="https://www.reduct.store/blog/robotics-mongodb-vs-reductstore#communication-protocols" rel="noopener noreferrer"&gt;​&lt;/a&gt;
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;ReductStore&lt;/strong&gt; uses &lt;em&gt;HTTP/HTTPS protocols&lt;/em&gt; to handle data, focusing on reducing network load in environments with high latency. It processes large datasets by batching requests and delivering data in segments, making it efficient for both real-time and historical data access.&lt;/p&gt;

&lt;p&gt;On the other hand, &lt;strong&gt;MongoDB&lt;/strong&gt; uses its native &lt;em&gt;MongoDB Wire Protocol&lt;/em&gt;, a lightweight, binary protocol optimized for fast communication between clients and servers. This protocol encodes data in BSON (Binary JSON), which supports efficient transmission and storage of JSON-like documents. These design choices make MongoDB a great choice for web-based applications, offering both flexibility and scalability.&lt;/p&gt;

&lt;h2&gt;
  
  
  Data Management Features&lt;a href="https://www.reduct.store/blog/robotics-mongodb-vs-reductstore#data-management-features" rel="noopener noreferrer"&gt;​&lt;/a&gt;
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Data batching capabilities&lt;a href="https://www.reduct.store/blog/robotics-mongodb-vs-reductstore#data-batching-capabilities" rel="noopener noreferrer"&gt;​&lt;/a&gt;
&lt;/h3&gt;

&lt;p&gt;Robots often generate high-frequency data from sensors and cameras, which requires efficient data transfer to avoid bottlenecks.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;ReductStore&lt;/strong&gt; enables efficient &lt;em&gt;data batching&lt;/em&gt; by grouping multiple records into a single HTTP request, minimizing delays and reducing the number of queries needed. ReductStore optimizes data retrieval by batching multiple records into a single HTTP request, reducing network overhead and delays. The storage system ensures data records are batched optimally for the HTTP protocol, supporting use cases such as real-time monitoring and historical data analysis with minimal query overhead.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;MongoDB&lt;/strong&gt; , provides &lt;em&gt;bulk&lt;/em&gt; &lt;em&gt;write operations&lt;/em&gt; that enable inserting, updating, or deleting multiple documents in a single transaction. This is particularly useful for applications that need to modify large datasets without compromising performance. MongoDB's aggregation pipelines also support batch data processing, but this batching is more general and not a good option for time-series data.&lt;/p&gt;

&lt;h3&gt;
  
  
  Edge-to-Cloud Replication&lt;a href="https://www.reduct.store/blog/robotics-mongodb-vs-reductstore#edge-to-cloud-replication" rel="noopener noreferrer"&gt;​&lt;/a&gt;
&lt;/h3&gt;

&lt;p&gt;In robotics, data is often processed locally (on edge devices) to reduce latency and dependence on cloud connectivity. However, important data still needs to be replicated to the cloud for centralized analysis, long-term storage, or to train machine learning models.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.reduct.store/docs/guides/data-replication" rel="noopener noreferrer"&gt;&lt;strong&gt;ReductStore offers granular control over data filtering during replication&lt;/strong&gt;&lt;/a&gt;, making it easy to move specific subsets of data between edge devices and the cloud. This feature allows efficient syncing, ensuring only necessary data is transferred to reduce bandwidth usage. This makes ReductStore particularly well-suited for applications like robotics where data is processed in real-time at the edge, and only relevant or high-priority data needs to be replicated to the cloud for analysis or storage.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;MongoDB's&lt;/strong&gt; replication system mainly focuses on maintaining data consistency and fault tolerance across multiple replica sets. While it is very reliable and flexible for general-purpose applications, it is not specifically suited for edge-to-cloud workflows since it does not natively allow data filtering during the replication process.&lt;/p&gt;

&lt;h3&gt;
  
  
  Retention policies&lt;a href="https://www.reduct.store/blog/robotics-mongodb-vs-reductstore#retention-policies" rel="noopener noreferrer"&gt;​&lt;/a&gt;
&lt;/h3&gt;

&lt;p&gt;Robotic systems generate large amounts of data, much of which quickly becomes irrelevant. Efficient retention policies are a must to maintain performance and avoid disk space issues on edge devices.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;ReductStore's&lt;/strong&gt; retention policies are based on &lt;em&gt;volume thresholds&lt;/em&gt;, meaning that older entries are automatically removed as new ones are added. The platform follows a &lt;em&gt;FIFO (first-in, first-out)&lt;/em&gt; rule, making it a perfect solution for applications where only recent data needs to be kept, such as sensor readings or telemetry logs. These retention policies can be customized for each data bucket, which ensures efficient data management.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;MongoDB&lt;/strong&gt; uses &lt;em&gt;TTL (Time to Live)&lt;/em&gt; indexes to delete documents once they reach a certain age. This feature isn't automatic and requires setup, but it lets developers manage expiration policies for individual collections. TTL indexes are especially useful for applications like session storage, temporary logs, or data with defined lifespans.&lt;/p&gt;

&lt;h2&gt;
  
  
  Performance Analysis&lt;a href="https://www.reduct.store/blog/robotics-mongodb-vs-reductstore#performance-analysis" rel="noopener noreferrer"&gt;​&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;MongoDB&lt;/strong&gt; is often better suited for structured numerical data but requires a more complex setup with GridFS for handling blob storage. On the other hand, &lt;strong&gt;ReductStore&lt;/strong&gt; simplifies the process by storing binary data directly into buckets, which makes it easier to manage time-series data.&lt;/p&gt;

&lt;p&gt;In terms of performance, our analysis shows that &lt;a href="https://dev.to/anthonycvn/alternative-to-mongodb-for-blob-data-1l45-temp-slug-2170766"&gt;&lt;strong&gt;ReductStore greatly outperforms MongoDB&lt;/strong&gt;&lt;/a&gt; when handling large blobs of unstructured data. In write tests, ReductStore is up to &lt;strong&gt;900% faster&lt;/strong&gt; than MongoDB, while for read operations, it delivers up to &lt;strong&gt;2300% faster&lt;/strong&gt; results. In the table below, you can find the results of the tests conducted by measuring the speed of writing and reading of binary data of varying sizes on an NVMe drive.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Chunk Size&lt;/th&gt;
&lt;th&gt;Operation&lt;/th&gt;
&lt;th&gt;MongoDB, blob/s&lt;/th&gt;
&lt;th&gt;ReductStore, blob/s&lt;/th&gt;
&lt;th&gt;ReductStore, %&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;1 KB&lt;/td&gt;
&lt;td&gt;Write&lt;/td&gt;
&lt;td&gt;799&lt;/td&gt;
&lt;td&gt;7994&lt;/td&gt;
&lt;td&gt;+900%&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;Read&lt;/td&gt;
&lt;td&gt;2008&lt;/td&gt;
&lt;td&gt;47979&lt;/td&gt;
&lt;td&gt;+2300%&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;10 KB&lt;/td&gt;
&lt;td&gt;Write&lt;/td&gt;
&lt;td&gt;783&lt;/td&gt;
&lt;td&gt;7431&lt;/td&gt;
&lt;td&gt;+850%&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;Read&lt;/td&gt;
&lt;td&gt;1918&lt;/td&gt;
&lt;td&gt;32888&lt;/td&gt;
&lt;td&gt;+1600%&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;100 KB&lt;/td&gt;
&lt;td&gt;Write&lt;/td&gt;
&lt;td&gt;694&lt;/td&gt;
&lt;td&gt;3612&lt;/td&gt;
&lt;td&gt;+420%&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;Read&lt;/td&gt;
&lt;td&gt;1730&lt;/td&gt;
&lt;td&gt;6250&lt;/td&gt;
&lt;td&gt;+260%&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;1 MB&lt;/td&gt;
&lt;td&gt;Write&lt;/td&gt;
&lt;td&gt;246&lt;/td&gt;
&lt;td&gt;663&lt;/td&gt;
&lt;td&gt;+170%&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;Read&lt;/td&gt;
&lt;td&gt;776&lt;/td&gt;
&lt;td&gt;540&lt;/td&gt;
&lt;td&gt;-30%&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h2&gt;
  
  
  Real-World Example&lt;a href="https://www.reduct.store/blog/robotics-mongodb-vs-reductstore#real-world-example" rel="noopener noreferrer"&gt;​&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;For a real-world robotics system, consider a scenario where numerous robots are operating on a manufacturing shop floor. These robots are continuously generating data, such as sensor readings, status updates, and environmental information. Kafka is used for ingesting this data in real-time and directing it into a local storage system for temporary retention and processing.&lt;/p&gt;

&lt;p&gt;As the amount of data accumulates, it is very important to efficiently replicate this data to the cloud for further analysis and long-term storage. This is where ReductStore comes into play. The data replication strategy involves decreasing the volume of data by filtering out less important information automatically. By using ReductStore's edge-to-cloud replication and data filtering capabilities, only the most relevant time-series data is transmitted to the cloud, making sure that resources are used efficiently and bandwidth is optimized. This reduction strategy can be applied by using predefined rules or dynamic triggers, such as certain events or changes in sensor readings, helping improve performance and save on cloud costs.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fd197lsn4yhgnj9yhvu26.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fd197lsn4yhgnj9yhvu26.png" alt="ReductStore in Robotics Application" width="800" height="267"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion&lt;a href="https://www.reduct.store/blog/robotics-mongodb-vs-reductstore#conclusion" rel="noopener noreferrer"&gt;​&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;ReductStore&lt;/strong&gt; and &lt;strong&gt;MongoDB&lt;/strong&gt; each have their own strengths, making them a good fit for different needs and use cases. MongoDB is great for flexible, general-purpose storage, especially with structured data, but when it comes to handling large-scale, time-sensitive data—like the kind found in robotics—ReductStore really shines. With optimized performance, fast read/write speeds, and features like edge-to-cloud replication, ReductStore is better suited for managing large, unstructured data sets. So, while MongoDB is a solid choice for many use cases, ReductStore stands out for robotics applications that need efficient, real-time data management.&lt;/p&gt;




&lt;p&gt;I hope this tutorial has been helpful. If you have any questions or feedback, don't hesitate to use the &lt;a href="https://community.reduct.store/" rel="noopener noreferrer"&gt;&lt;strong&gt;ReductStore Community&lt;/strong&gt;&lt;/a&gt; forum.&lt;/p&gt;

</description>
      <category>comparison</category>
      <category>mongodb</category>
      <category>robotics</category>
    </item>
  </channel>
</rss>
