Lerobot-Dataset-Ruby 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,95 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'test_helper'
4
+ require 'tmpdir'
5
+
6
+ class TestLeRobotDatasetReader < Minitest::Test
7
+ def setup
8
+ @root = Dir.mktmpdir('lerobot-reader-test-')
9
+ writer = LeRobotDatasetWriter.new(output_dir: @root, fps: 30)
10
+ 2.times do |episode_index|
11
+ writer.start_episode(task: "task-#{episode_index}")
12
+ 2.times do |frame_index|
13
+ writer.add_frame(
14
+ action: [frame_index.to_f],
15
+ state: [episode_index.to_f],
16
+ timestamp: frame_index.to_f / 30
17
+ )
18
+ end
19
+ writer.save_episode
20
+ end
21
+ writer.save
22
+ @reader = LeRobotDatasetReader.new(@root)
23
+ end
24
+
25
+ def teardown
26
+ FileUtils.remove_entry(@root) if @root && File.directory?(@root)
27
+ end
28
+
29
+ def test_reads_episode_frames_separately
30
+ assert_equal @reader.info['total_episodes'], @reader.episode_count
31
+ assert_equal @reader.info['total_frames'], @reader.frame_count
32
+
33
+ first = @reader.episode(0)
34
+ assert_equal 0, first[:episode_index]
35
+ assert_equal first[:length], first[:frames].length
36
+ assert_equal 0, first[:frames].first[:episode_index]
37
+ end
38
+
39
+ def test_unknown_episode_raises
40
+ assert_raises(IndexError) { @reader.episode(999_999) }
41
+ end
42
+
43
+ def test_frame_index_continues_across_episodes
44
+ assert_equal [0, 1], @reader.episode(0)[:frames].map { |frame| frame[:frame_index] }
45
+ assert_equal [2, 3], @reader.episode(1)[:frames].map { |frame| frame[:frame_index] }
46
+ end
47
+
48
+ def test_unsaved_episode_is_excluded_from_dataset
49
+ writer = LeRobotDatasetWriter.new(output_dir: @root, fps: 30)
50
+ 2.times do |episode_index|
51
+ writer.start_episode(task: "task-#{episode_index}")
52
+ 2.times do |frame_index|
53
+ writer.add_frame(
54
+ action: [frame_index.to_f],
55
+ state: [episode_index.to_f],
56
+ timestamp: frame_index.to_f / 30
57
+ )
58
+ end
59
+ writer.save_episode
60
+ end
61
+
62
+ writer.start_episode(task: 'discarded-task')
63
+ 2.times do |frame_index|
64
+ writer.add_frame(action: [frame_index.to_f], state: [2.0])
65
+ end
66
+ writer.save_episode(save: false)
67
+ writer.save
68
+ reader = LeRobotDatasetReader.new(@root)
69
+
70
+ assert_equal 2, reader.episode_count
71
+ assert_equal [0, 1], reader.episode(0)[:frames].map { |frame| frame[:frame_index] }
72
+ assert_equal [2, 3], reader.episode(1)[:frames].map { |frame| frame[:frame_index] }
73
+ assert_equal [1, 1], reader.episode(1)[:frames].map { |frame| frame[:episode_index] }
74
+ end
75
+
76
+ def test_new_episode_after_unsaved_episode_keeps_video_frame_index_unique
77
+ writer = LeRobotDatasetWriter.new(output_dir: @root, fps: 30)
78
+ 2.times do |episode_index|
79
+ writer.start_episode(task: "task-#{episode_index}")
80
+ writer.add_frame(action: [0.0], state: [episode_index.to_f])
81
+ writer.save_episode
82
+ end
83
+
84
+ writer.start_episode(task: 'discarded-task')
85
+ writer.add_frame(action: [0.0], state: [3.0])
86
+ writer.save_episode(save: false)
87
+ writer.start_episode(task: 'new-task')
88
+ writer.add_frame(action: [0.0], state: [4.0])
89
+ writer.save_episode
90
+ writer.save
91
+ reader = LeRobotDatasetReader.new(@root)
92
+
93
+ assert_equal [0, 1, 3], reader.each_frame.map { |frame| frame['frame_index'] }
94
+ end
95
+ end
@@ -0,0 +1,6 @@
1
+ # frozen_string_literal: true
2
+
3
+ $LOAD_PATH.unshift File.expand_path("../lib", __dir__)
4
+ require "Lerobot/Dataset/Ruby"
5
+
6
+ require "minitest/autorun"
@@ -0,0 +1,52 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'test_helper'
4
+ require_relative '../ext/opencv/libopencv' if File.exist?(File.expand_path('../ext/opencv/libopencv.so', __dir__))
5
+
6
+ class TestLibopencv < Minitest::Test
7
+ def test_module_defined
8
+ assert_includes Object.constants, :Libopencv
9
+ end
10
+
11
+ def test_methods_defined
12
+ assert_respond_to Libopencv, :open_mp4
13
+ assert_respond_to Libopencv, :cam_open
14
+ assert_respond_to Libopencv, :start_recording
15
+ assert_respond_to Libopencv, :take_picture
16
+ assert_respond_to Libopencv, :write_frame
17
+ assert_respond_to Libopencv, :stop_recording
18
+ assert_respond_to Libopencv, :show_movie
19
+ assert_respond_to Libopencv, :wait_key
20
+ assert_respond_to Libopencv, :destroy_window
21
+ end
22
+
23
+ def test_recording_state_errors
24
+ # 録画開始せずにフレーム書き込みを試みると例外が発生すること
25
+ assert_raises(RuntimeError) do
26
+ Libopencv.write_frame("dummy")
27
+ end
28
+ end
29
+
30
+ def test_start_recording_invalid_args
31
+ # カメラを開かずに録画開始すると例外が発生すること
32
+ assert_raises(RuntimeError) do
33
+ Libopencv.start_recording("test.mp4", 30.0)
34
+ end
35
+ # 引数が不正な場合に例外が発生すること
36
+ assert_raises(ArgumentError) do
37
+ Libopencv.start_recording(nil, 30.0)
38
+ end
39
+ assert_raises(ArgumentError) do
40
+ Libopencv.start_recording("test.mp4", -1)
41
+ end
42
+ end
43
+
44
+ def test_cam_open_invalid_args
45
+ assert_raises(ArgumentError) do
46
+ Libopencv.cam_open(0, 0, 480)
47
+ end
48
+ assert_raises(ArgumentError) do
49
+ Libopencv.cam_open(0, 640, -1)
50
+ end
51
+ end
52
+ end
metadata ADDED
@@ -0,0 +1,108 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: Lerobot-Dataset-Ruby
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Harutodesu
8
+ autorequire:
9
+ bindir: exe
10
+ cert_chain: []
11
+ date: 2026-09-29 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: parquet
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ">="
18
+ - !ruby/object:Gem::Version
19
+ version: '0.1'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ">="
25
+ - !ruby/object:Gem::Version
26
+ version: '0.1'
27
+ - !ruby/object:Gem::Dependency
28
+ name: rake
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '13.0'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '13.0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: minitest
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: '5.0'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: '5.0'
55
+ description: A Ruby gem for reading and recording robotic dataset in LeRobot v3.0
56
+ format using OpenCV and Parquet.
57
+ email:
58
+ - happyday11242019@gmail.com
59
+ executables: []
60
+ extensions:
61
+ - ext/opencv/extconf.rb
62
+ extra_rdoc_files: []
63
+ files:
64
+ - CHANGELOG.md
65
+ - CODE_OF_CONDUCT.md
66
+ - LICENSE.txt
67
+ - README.md
68
+ - Rakefile
69
+ - ext/opencv/extconf.rb
70
+ - ext/opencv/libopencv.cpp
71
+ - lib/Lerobot/Dataset/Ruby.rb
72
+ - lib/Lerobot/Dataset/Ruby/reader.rb
73
+ - lib/Lerobot/Dataset/Ruby/version.rb
74
+ - lib/Lerobot/Dataset/Ruby/writer.rb
75
+ - sig/Lerobot/Dataset/Ruby.rbs
76
+ - test/minimal_lerobot_check.rb
77
+ - test/sample.rb
78
+ - test/test_dataset.py
79
+ - test/test_dataset_reader.rb
80
+ - test/test_helper.rb
81
+ - test/test_libopencv.rb
82
+ homepage: https://github.com/paisyaluAI/lerobot-dataset-ruby
83
+ licenses:
84
+ - MIT
85
+ metadata:
86
+ homepage_uri: https://github.com/paisyaluAI/lerobot-dataset-ruby
87
+ source_code_uri: https://github.com/paisyaluAI/lerobot-dataset-ruby
88
+ changelog_uri: https://github.com/paisyaluAI/lerobot-dataset-ruby/blob/main/CHANGELOG.md
89
+ post_install_message:
90
+ rdoc_options: []
91
+ require_paths:
92
+ - lib
93
+ required_ruby_version: !ruby/object:Gem::Requirement
94
+ requirements:
95
+ - - ">="
96
+ - !ruby/object:Gem::Version
97
+ version: 3.2.0
98
+ required_rubygems_version: !ruby/object:Gem::Requirement
99
+ requirements:
100
+ - - ">="
101
+ - !ruby/object:Gem::Version
102
+ version: '0'
103
+ requirements: []
104
+ rubygems_version: 3.4.20
105
+ signing_key:
106
+ specification_version: 4
107
+ summary: LeRobot dataset v3 reader and writer library for Ruby
108
+ test_files: []