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.
- checksums.yaml +7 -0
- data/CHANGELOG.md +5 -0
- data/CODE_OF_CONDUCT.md +10 -0
- data/LICENSE.txt +21 -0
- data/README.md +43 -0
- data/Rakefile +21 -0
- data/ext/opencv/extconf.rb +7 -0
- data/ext/opencv/libopencv.cpp +281 -0
- data/lib/Lerobot/Dataset/Ruby/reader.rb +174 -0
- data/lib/Lerobot/Dataset/Ruby/version.rb +9 -0
- data/lib/Lerobot/Dataset/Ruby/writer.rb +362 -0
- data/lib/Lerobot/Dataset/Ruby.rb +13 -0
- data/sig/Lerobot/Dataset/Ruby.rbs +8 -0
- data/test/minimal_lerobot_check.rb +49 -0
- data/test/sample.rb +56 -0
- data/test/test_dataset.py +189 -0
- data/test/test_dataset_reader.rb +95 -0
- data/test/test_helper.rb +6 -0
- data/test/test_libopencv.rb +52 -0
- metadata +108 -0
|
@@ -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
|
data/test/test_helper.rb
ADDED
|
@@ -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: []
|