kscale 0.0.10__py3-none-any.whl → 0.1.0__py3-none-any.whl
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.
- kscale/__init__.py +2 -2
- kscale/api.py +3 -6
- kscale/cli.py +32 -0
- kscale/conf.py +6 -3
- kscale/requirements.txt +17 -1
- kscale/utils/checksum.py +41 -0
- kscale/utils/cli.py +28 -0
- kscale/web/api.py +14 -0
- kscale/web/cli/robot.py +100 -0
- kscale/web/cli/robot_class.py +113 -0
- kscale/web/cli/token.py +33 -0
- kscale/web/cli/user.py +33 -0
- kscale/web/clients/__init__.py +0 -0
- kscale/web/clients/base.py +314 -0
- kscale/web/clients/client.py +11 -0
- kscale/web/clients/robot.py +39 -0
- kscale/web/clients/robot_class.py +114 -0
- kscale/web/clients/user.py +10 -0
- kscale/web/gen/__init__.py +0 -0
- kscale/web/gen/api.py +73 -0
- kscale/web/utils.py +31 -0
- {kscale-0.0.10.dist-info → kscale-0.1.0.dist-info}/METADATA +29 -48
- kscale-0.1.0.dist-info/RECORD +36 -0
- {kscale-0.0.10.dist-info → kscale-0.1.0.dist-info}/WHEEL +1 -1
- kscale-0.1.0.dist-info/entry_points.txt +3 -0
- kscale/store/api.py +0 -64
- kscale/store/cli.py +0 -35
- kscale/store/client.py +0 -82
- kscale/store/gen/api.py +0 -301
- kscale/store/pybullet.py +0 -180
- kscale/store/urdf.py +0 -193
- kscale/store/utils.py +0 -33
- kscale-0.0.10.dist-info/RECORD +0 -26
- kscale-0.0.10.dist-info/entry_points.txt +0 -2
- /kscale/{store → web}/__init__.py +0 -0
- /kscale/{store/gen → web/cli}/__init__.py +0 -0
- {kscale-0.0.10.dist-info → kscale-0.1.0.dist-info}/LICENSE +0 -0
- {kscale-0.0.10.dist-info → kscale-0.1.0.dist-info}/top_level.txt +0 -0
kscale/store/pybullet.py
DELETED
@@ -1,180 +0,0 @@
|
|
1
|
-
"""Simple script to interact with a URDF in PyBullet."""
|
2
|
-
|
3
|
-
import argparse
|
4
|
-
import asyncio
|
5
|
-
import itertools
|
6
|
-
import logging
|
7
|
-
import math
|
8
|
-
import time
|
9
|
-
from typing import Sequence
|
10
|
-
|
11
|
-
from kscale.artifacts import PLANE_URDF_PATH
|
12
|
-
from kscale.store.urdf import download_urdf
|
13
|
-
|
14
|
-
logger = logging.getLogger(__name__)
|
15
|
-
|
16
|
-
|
17
|
-
async def main(args: Sequence[str] | None = None) -> None:
|
18
|
-
parser = argparse.ArgumentParser(description="Show a URDF in PyBullet")
|
19
|
-
parser.add_argument("listing_id", help="Listing ID for the URDF")
|
20
|
-
parser.add_argument("--dt", type=float, default=0.01, help="Time step")
|
21
|
-
parser.add_argument("-n", "--hide-gui", action="store_true", help="Hide the GUI")
|
22
|
-
parser.add_argument("--no-merge", action="store_true", help="Do not merge fixed links")
|
23
|
-
parser.add_argument("--hide-origin", action="store_true", help="Do not show the origin")
|
24
|
-
parser.add_argument("--show-inertia", action="store_true", help="Visualizes the inertia frames")
|
25
|
-
parser.add_argument("--see-thru", action="store_true", help="Use see-through mode")
|
26
|
-
parser.add_argument("--show-collision", action="store_true", help="Show collision meshes")
|
27
|
-
parsed_args = parser.parse_args(args)
|
28
|
-
|
29
|
-
# Gets the URDF path.
|
30
|
-
urdf_dir = await download_urdf(parsed_args.listing_id)
|
31
|
-
urdf_path = next(urdf_dir.glob("*.urdf"), None)
|
32
|
-
if urdf_path is None:
|
33
|
-
raise ValueError(f"No URDF found in {urdf_dir}")
|
34
|
-
|
35
|
-
try:
|
36
|
-
import pybullet as p # type: ignore[import-not-found]
|
37
|
-
except ImportError:
|
38
|
-
raise ImportError("pybullet is required to run this script")
|
39
|
-
|
40
|
-
# Connect to PyBullet.
|
41
|
-
p.connect(p.GUI)
|
42
|
-
p.setGravity(0, 0, -9.81)
|
43
|
-
p.setRealTimeSimulation(0)
|
44
|
-
|
45
|
-
# Turn off panels.
|
46
|
-
if parsed_args.hide_gui:
|
47
|
-
p.configureDebugVisualizer(p.COV_ENABLE_GUI, 0)
|
48
|
-
p.configureDebugVisualizer(p.COV_ENABLE_SEGMENTATION_MARK_PREVIEW, 0)
|
49
|
-
p.configureDebugVisualizer(p.COV_ENABLE_DEPTH_BUFFER_PREVIEW, 0)
|
50
|
-
p.configureDebugVisualizer(p.COV_ENABLE_RGB_BUFFER_PREVIEW, 0)
|
51
|
-
|
52
|
-
# Enable mouse picking.
|
53
|
-
p.configureDebugVisualizer(p.COV_ENABLE_MOUSE_PICKING, 1)
|
54
|
-
|
55
|
-
# Loads the floor plane.
|
56
|
-
floor = p.loadURDF(str(PLANE_URDF_PATH))
|
57
|
-
|
58
|
-
# Load the robot URDF.
|
59
|
-
start_position = [0.0, 0.0, 1.0]
|
60
|
-
start_orientation = p.getQuaternionFromEuler([0.0, 0.0, 0.0])
|
61
|
-
flags = p.URDF_USE_INERTIA_FROM_FILE
|
62
|
-
if not parsed_args.no_merge:
|
63
|
-
flags |= p.URDF_MERGE_FIXED_LINKS
|
64
|
-
robot = p.loadURDF(str(urdf_path), start_position, start_orientation, flags=flags, useFixedBase=0)
|
65
|
-
|
66
|
-
# Display collision meshes as separate object.
|
67
|
-
if parsed_args.show_collision:
|
68
|
-
collision_flags = p.URDF_USE_INERTIA_FROM_FILE | p.URDF_USE_SELF_COLLISION_EXCLUDE_ALL_PARENTS
|
69
|
-
collision = p.loadURDF(str(urdf_path), start_position, start_orientation, flags=collision_flags, useFixedBase=0)
|
70
|
-
|
71
|
-
# Make collision shapes semi-transparent.
|
72
|
-
joint_ids = [i for i in range(p.getNumJoints(collision))] + [-1]
|
73
|
-
for i in joint_ids:
|
74
|
-
p.changeVisualShape(collision, i, rgbaColor=[1, 0, 0, 0.5])
|
75
|
-
|
76
|
-
# Initializes physics parameters.
|
77
|
-
p.changeDynamics(floor, -1, lateralFriction=1, spinningFriction=-1, rollingFriction=-1)
|
78
|
-
p.setPhysicsEngineParameter(fixedTimeStep=parsed_args.dt, maxNumCmdPer1ms=1000)
|
79
|
-
|
80
|
-
# Shows the origin of the robot.
|
81
|
-
if not parsed_args.hide_origin:
|
82
|
-
p.addUserDebugLine([0, 0, 0], [0.1, 0, 0], [1, 0, 0], parentObjectUniqueId=robot, parentLinkIndex=-1)
|
83
|
-
p.addUserDebugLine([0, 0, 0], [0, 0.1, 0], [0, 1, 0], parentObjectUniqueId=robot, parentLinkIndex=-1)
|
84
|
-
p.addUserDebugLine([0, 0, 0], [0, 0, 0.1], [0, 0, 1], parentObjectUniqueId=robot, parentLinkIndex=-1)
|
85
|
-
|
86
|
-
# Make the robot see-through.
|
87
|
-
joint_ids = [i for i in range(p.getNumJoints(robot))] + [-1]
|
88
|
-
if parsed_args.see_thru:
|
89
|
-
for i in joint_ids:
|
90
|
-
p.changeVisualShape(robot, i, rgbaColor=[1, 1, 1, 0.5])
|
91
|
-
|
92
|
-
def draw_box(pt: list[list[float]], color: tuple[float, float, float], obj_id: int, link_id: int) -> None:
|
93
|
-
assert len(pt) == 8
|
94
|
-
assert all(len(p) == 3 for p in pt)
|
95
|
-
|
96
|
-
mapping = [1, 3, 0, 2]
|
97
|
-
for i in range(4):
|
98
|
-
p.addUserDebugLine(pt[i], pt[i + 4], color, 1, parentObjectUniqueId=obj_id, parentLinkIndex=link_id)
|
99
|
-
p.addUserDebugLine(pt[i], pt[mapping[i]], color, 1, parentObjectUniqueId=obj_id, parentLinkIndex=link_id)
|
100
|
-
p.addUserDebugLine(
|
101
|
-
pt[i + 4], pt[mapping[i] + 4], color, 1, parentObjectUniqueId=obj_id, parentLinkIndex=link_id
|
102
|
-
)
|
103
|
-
|
104
|
-
# Shows bounding boxes around each part of the robot representing the inertia frame.
|
105
|
-
if parsed_args.show_inertia:
|
106
|
-
for i in joint_ids:
|
107
|
-
dynamics_info = p.getDynamicsInfo(robot, i)
|
108
|
-
mass = dynamics_info[0]
|
109
|
-
if mass <= 0:
|
110
|
-
continue
|
111
|
-
inertia = dynamics_info[2]
|
112
|
-
ixx = inertia[0]
|
113
|
-
iyy = inertia[1]
|
114
|
-
izz = inertia[2]
|
115
|
-
box_scale_x = 0.5 * math.sqrt(6 * (izz + iyy - ixx) / mass)
|
116
|
-
box_scale_y = 0.5 * math.sqrt(6 * (izz + ixx - iyy) / mass)
|
117
|
-
box_scale_z = 0.5 * math.sqrt(6 * (ixx + iyy - izz) / mass)
|
118
|
-
|
119
|
-
half_extents = [box_scale_x, box_scale_y, box_scale_z]
|
120
|
-
pt = [
|
121
|
-
[x, y, z]
|
122
|
-
for x, y, z in itertools.product(
|
123
|
-
[-half_extents[0], half_extents[0]],
|
124
|
-
[-half_extents[1], half_extents[1]],
|
125
|
-
[-half_extents[2], half_extents[2]],
|
126
|
-
)
|
127
|
-
]
|
128
|
-
draw_box(pt, (1, 0, 0), robot, i)
|
129
|
-
|
130
|
-
# Show joint controller.
|
131
|
-
joints: dict[str, int] = {}
|
132
|
-
controls: dict[str, float] = {}
|
133
|
-
for i in range(p.getNumJoints(robot)):
|
134
|
-
joint_info = p.getJointInfo(robot, i)
|
135
|
-
name = joint_info[1].decode("utf-8")
|
136
|
-
joint_type = joint_info[2]
|
137
|
-
joints[name] = i
|
138
|
-
if joint_type == p.JOINT_PRISMATIC:
|
139
|
-
joint_min, joint_max = joint_info[8:10]
|
140
|
-
controls[name] = p.addUserDebugParameter(name, joint_min, joint_max, 0.0)
|
141
|
-
elif joint_type == p.JOINT_REVOLUTE:
|
142
|
-
joint_min, joint_max = joint_info[8:10]
|
143
|
-
controls[name] = p.addUserDebugParameter(name, joint_min, joint_max, 0.0)
|
144
|
-
|
145
|
-
# Run the simulation until the user closes the window.
|
146
|
-
last_time = time.time()
|
147
|
-
prev_control_values = {k: 0.0 for k in controls}
|
148
|
-
while p.isConnected():
|
149
|
-
# Reset the simulation if "r" was pressed.
|
150
|
-
keys = p.getKeyboardEvents()
|
151
|
-
if ord("r") in keys and keys[ord("r")] & p.KEY_WAS_TRIGGERED:
|
152
|
-
p.resetBasePositionAndOrientation(robot, start_position, start_orientation)
|
153
|
-
p.setJointMotorControlArray(
|
154
|
-
robot,
|
155
|
-
range(p.getNumJoints(robot)),
|
156
|
-
p.POSITION_CONTROL,
|
157
|
-
targetPositions=[0] * p.getNumJoints(robot),
|
158
|
-
)
|
159
|
-
|
160
|
-
# Set joint positions.
|
161
|
-
for k, v in controls.items():
|
162
|
-
try:
|
163
|
-
target_position = p.readUserDebugParameter(v)
|
164
|
-
if target_position != prev_control_values[k]:
|
165
|
-
prev_control_values[k] = target_position
|
166
|
-
p.setJointMotorControl2(robot, joints[k], p.POSITION_CONTROL, target_position)
|
167
|
-
except p.error:
|
168
|
-
logger.debug("Failed to set joint %s", k)
|
169
|
-
pass
|
170
|
-
|
171
|
-
# Step simulation.
|
172
|
-
p.stepSimulation()
|
173
|
-
cur_time = time.time()
|
174
|
-
time.sleep(max(0, parsed_args.dt - (cur_time - last_time)))
|
175
|
-
last_time = cur_time
|
176
|
-
|
177
|
-
|
178
|
-
if __name__ == "__main__":
|
179
|
-
# python -m kscale.store.pybullet
|
180
|
-
asyncio.run(main())
|
kscale/store/urdf.py
DELETED
@@ -1,193 +0,0 @@
|
|
1
|
-
"""Utility functions for managing artifacts in the K-Scale store."""
|
2
|
-
|
3
|
-
import argparse
|
4
|
-
import asyncio
|
5
|
-
import logging
|
6
|
-
import shutil
|
7
|
-
import sys
|
8
|
-
import tarfile
|
9
|
-
from pathlib import Path
|
10
|
-
from typing import Literal, Sequence, get_args
|
11
|
-
|
12
|
-
import httpx
|
13
|
-
import requests
|
14
|
-
|
15
|
-
from kscale.conf import Settings
|
16
|
-
from kscale.store.client import KScaleStoreClient
|
17
|
-
from kscale.store.gen.api import SingleArtifactResponse, UploadArtifactResponse
|
18
|
-
from kscale.store.utils import get_api_key
|
19
|
-
|
20
|
-
# Set up logging
|
21
|
-
logging.basicConfig(level=logging.INFO)
|
22
|
-
logger = logging.getLogger(__name__)
|
23
|
-
|
24
|
-
ALLOWED_SUFFIXES = {
|
25
|
-
".urdf",
|
26
|
-
".mjcf",
|
27
|
-
".stl",
|
28
|
-
".obj",
|
29
|
-
".dae",
|
30
|
-
".png",
|
31
|
-
".jpg",
|
32
|
-
".jpeg",
|
33
|
-
}
|
34
|
-
|
35
|
-
|
36
|
-
def get_cache_dir() -> Path:
|
37
|
-
return Path(Settings.load().store.cache_dir).expanduser().resolve()
|
38
|
-
|
39
|
-
|
40
|
-
def get_artifact_dir(artifact_id: str) -> Path:
|
41
|
-
cache_dir = get_cache_dir() / artifact_id
|
42
|
-
cache_dir.mkdir(parents=True, exist_ok=True)
|
43
|
-
return cache_dir
|
44
|
-
|
45
|
-
|
46
|
-
async def fetch_urdf_info(artifact_id: str, cache_dir: Path) -> SingleArtifactResponse:
|
47
|
-
response_path = cache_dir / "response.json"
|
48
|
-
if response_path.exists():
|
49
|
-
return SingleArtifactResponse.model_validate_json(response_path.read_text())
|
50
|
-
async with KScaleStoreClient() as client:
|
51
|
-
response = await client.get_artifact_info(artifact_id)
|
52
|
-
response_path.write_text(response.model_dump_json())
|
53
|
-
return response
|
54
|
-
|
55
|
-
|
56
|
-
async def download_artifact(artifact_url: str, cache_dir: Path) -> Path:
|
57
|
-
filename = cache_dir / Path(artifact_url).name
|
58
|
-
headers = {
|
59
|
-
"Authorization": f"Bearer {get_api_key()}",
|
60
|
-
}
|
61
|
-
|
62
|
-
if not filename.exists():
|
63
|
-
logger.info("Downloading artifact from %s", artifact_url)
|
64
|
-
|
65
|
-
async with httpx.AsyncClient() as client:
|
66
|
-
response = await client.get(artifact_url, headers=headers)
|
67
|
-
response.raise_for_status()
|
68
|
-
filename.write_bytes(response.content)
|
69
|
-
logger.info("Artifact downloaded to %s", filename)
|
70
|
-
else:
|
71
|
-
logger.info("Artifact already cached at %s", filename)
|
72
|
-
|
73
|
-
# Extract the .tgz file
|
74
|
-
extract_dir = cache_dir / filename.stem
|
75
|
-
if not extract_dir.exists():
|
76
|
-
logger.info("Extracting %s to %s", filename, extract_dir)
|
77
|
-
with tarfile.open(filename, "r:gz") as tar:
|
78
|
-
tar.extractall(path=extract_dir)
|
79
|
-
else:
|
80
|
-
logger.info("Artifact already extracted at %s", extract_dir)
|
81
|
-
|
82
|
-
return extract_dir
|
83
|
-
|
84
|
-
|
85
|
-
def create_tarball(folder_path: Path, output_filename: str, cache_dir: Path) -> Path:
|
86
|
-
tarball_path = cache_dir / output_filename
|
87
|
-
with tarfile.open(tarball_path, "w:gz") as tar:
|
88
|
-
for file_path in folder_path.rglob("*"):
|
89
|
-
if file_path.is_file() and file_path.suffix.lower() in ALLOWED_SUFFIXES:
|
90
|
-
tar.add(file_path, arcname=file_path.relative_to(folder_path))
|
91
|
-
logger.info("Added %s to tarball", file_path)
|
92
|
-
else:
|
93
|
-
logger.warning("Skipping %s", file_path)
|
94
|
-
logger.info("Created tarball %s", tarball_path)
|
95
|
-
return tarball_path
|
96
|
-
|
97
|
-
|
98
|
-
async def download_urdf(artifact_id: str) -> Path:
|
99
|
-
cache_dir = get_artifact_dir(artifact_id)
|
100
|
-
try:
|
101
|
-
urdf_info = await fetch_urdf_info(artifact_id, cache_dir)
|
102
|
-
artifact_url = urdf_info.urls.large
|
103
|
-
return await download_artifact(artifact_url, cache_dir)
|
104
|
-
|
105
|
-
except requests.RequestException:
|
106
|
-
logger.exception("Failed to fetch URDF info")
|
107
|
-
raise
|
108
|
-
|
109
|
-
|
110
|
-
async def show_urdf_info(artifact_id: str) -> None:
|
111
|
-
try:
|
112
|
-
urdf_info = await fetch_urdf_info(artifact_id, get_artifact_dir(artifact_id))
|
113
|
-
logger.info("URDF Artifact ID: %s", urdf_info.artifact_id)
|
114
|
-
logger.info("URDF URL: %s", urdf_info.urls.large)
|
115
|
-
except requests.RequestException:
|
116
|
-
logger.exception("Failed to fetch URDF info")
|
117
|
-
raise
|
118
|
-
|
119
|
-
|
120
|
-
async def remove_local_urdf(artifact_id: str) -> None:
|
121
|
-
try:
|
122
|
-
if artifact_id.lower() == "all":
|
123
|
-
cache_dir = get_cache_dir()
|
124
|
-
if cache_dir.exists():
|
125
|
-
logger.info("Removing all local caches at %s", cache_dir)
|
126
|
-
shutil.rmtree(cache_dir)
|
127
|
-
else:
|
128
|
-
logger.error("No local caches found")
|
129
|
-
else:
|
130
|
-
artifact_dir = get_artifact_dir(artifact_id)
|
131
|
-
if artifact_dir.exists():
|
132
|
-
logger.info("Removing local cache at %s", artifact_dir)
|
133
|
-
shutil.rmtree(artifact_dir)
|
134
|
-
else:
|
135
|
-
logger.error("No local cache found for artifact %s", artifact_id)
|
136
|
-
|
137
|
-
except Exception:
|
138
|
-
logger.error("Failed to remove local cache")
|
139
|
-
raise
|
140
|
-
|
141
|
-
|
142
|
-
async def upload_urdf(listing_id: str, root_dir: Path) -> UploadArtifactResponse:
|
143
|
-
tarball_path = create_tarball(root_dir, "robot.tgz", get_artifact_dir(listing_id))
|
144
|
-
|
145
|
-
async with KScaleStoreClient() as client:
|
146
|
-
response = await client.upload_artifact(listing_id, str(tarball_path))
|
147
|
-
|
148
|
-
logger.info("Uploaded artifacts: %s", [artifact.artifact_id for artifact in response.artifacts])
|
149
|
-
return response
|
150
|
-
|
151
|
-
|
152
|
-
async def upload_urdf_cli(listing_id: str, args: Sequence[str]) -> UploadArtifactResponse:
|
153
|
-
parser = argparse.ArgumentParser(description="K-Scale URDF Store", add_help=False)
|
154
|
-
parser.add_argument("root_dir", type=Path, help="The path to the root directory to upload")
|
155
|
-
parsed_args = parser.parse_args(args)
|
156
|
-
|
157
|
-
root_dir = parsed_args.root_dir
|
158
|
-
response = await upload_urdf(listing_id, root_dir)
|
159
|
-
return response
|
160
|
-
|
161
|
-
|
162
|
-
Command = Literal["download", "info", "upload", "remove-local"]
|
163
|
-
|
164
|
-
|
165
|
-
async def main(args: Sequence[str] | None = None) -> None:
|
166
|
-
parser = argparse.ArgumentParser(description="K-Scale URDF Store", add_help=False)
|
167
|
-
parser.add_argument("command", choices=get_args(Command), help="The command to run")
|
168
|
-
parser.add_argument("id", help="The ID to use (artifact when downloading, listing when uploading)")
|
169
|
-
parsed_args, remaining_args = parser.parse_known_args(args)
|
170
|
-
|
171
|
-
command: Command = parsed_args.command
|
172
|
-
id: str = parsed_args.id
|
173
|
-
|
174
|
-
match command:
|
175
|
-
case "download":
|
176
|
-
await download_urdf(id)
|
177
|
-
|
178
|
-
case "info":
|
179
|
-
await show_urdf_info(id)
|
180
|
-
|
181
|
-
case "remove-local":
|
182
|
-
await remove_local_urdf(id)
|
183
|
-
|
184
|
-
case "upload":
|
185
|
-
await upload_urdf_cli(id, remaining_args)
|
186
|
-
|
187
|
-
case _:
|
188
|
-
logger.error("Invalid command")
|
189
|
-
sys.exit(1)
|
190
|
-
|
191
|
-
|
192
|
-
if __name__ == "__main__":
|
193
|
-
asyncio.run(main())
|
kscale/store/utils.py
DELETED
@@ -1,33 +0,0 @@
|
|
1
|
-
"""Utility functions for interacting with the K-Scale Store API."""
|
2
|
-
|
3
|
-
import os
|
4
|
-
|
5
|
-
from kscale.conf import Settings
|
6
|
-
|
7
|
-
|
8
|
-
def get_api_root() -> str:
|
9
|
-
"""Returns the base URL for the K-Scale Store API.
|
10
|
-
|
11
|
-
This can be overridden when targetting a different server.
|
12
|
-
|
13
|
-
Returns:
|
14
|
-
The base URL for the K-Scale Store API.
|
15
|
-
"""
|
16
|
-
return os.getenv("KSCALE_API_ROOT", "https://api.kscale.store")
|
17
|
-
|
18
|
-
|
19
|
-
def get_api_key() -> str:
|
20
|
-
"""Returns the API key for the K-Scale Store API.
|
21
|
-
|
22
|
-
Returns:
|
23
|
-
The API key for the K-Scale Store API.
|
24
|
-
"""
|
25
|
-
api_key = Settings.load().store.api_key
|
26
|
-
if api_key is None:
|
27
|
-
api_key = os.getenv("KSCALE_API_KEY")
|
28
|
-
if not api_key:
|
29
|
-
raise ValueError(
|
30
|
-
"API key not found! Get one here and set it as the `KSCALE_API_KEY` environment variable or in your "
|
31
|
-
"config file: https://kscale.store/keys"
|
32
|
-
)
|
33
|
-
return api_key
|
kscale-0.0.10.dist-info/RECORD
DELETED
@@ -1,26 +0,0 @@
|
|
1
|
-
kscale/__init__.py,sha256=s_FPBlHyXyKecFXm57Q2kH3d0O8suiaE8FrI6n0ckXU,178
|
2
|
-
kscale/api.py,sha256=xBtKj8rgZ400r1Xx9LRY0AzSgIIttoXdejmhHhdVGS0,333
|
3
|
-
kscale/conf.py,sha256=9fShFaYTbnrm_eiGjmy8ZtC4Q4m6PQkWPyoF3eNyov8,1424
|
4
|
-
kscale/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
5
|
-
kscale/requirements-dev.txt,sha256=WI7-ea4IRJakmqVMN8QKhOsDGrghwtvk03aIsFaNSIw,130
|
6
|
-
kscale/requirements.txt,sha256=gxo_niYIHsmyxKxvIOegv45s_lvdnIzI2iFJ2TZzx_U,103
|
7
|
-
kscale/artifacts/__init__.py,sha256=RK8wdybtCJPgdLLJ8R8-YMi1Ph5ojqAKVJZowHONtgo,232
|
8
|
-
kscale/artifacts/plane.obj,sha256=x59-IIrWpLjhotChiqT2Ul6U8s0RcHkaEeUZb4KXL1c,348
|
9
|
-
kscale/artifacts/plane.urdf,sha256=LCiTk14AyTHjkZ1jvsb0hNaEaJUxDb8Z1JjsgpXu3YM,819
|
10
|
-
kscale/store/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
11
|
-
kscale/store/api.py,sha256=JBp4h6yz_ESSdB-2FpkD_1-hdI8_iEKh9svzkyy3jhs,2386
|
12
|
-
kscale/store/cli.py,sha256=8ygg_1tZzOOHJotEIgSN9pfumcriPmA31sI_FCFQiTo,859
|
13
|
-
kscale/store/client.py,sha256=R1IDnf2J4ojAcP8nmUUHfXhcHUt4zP0-mxtVI7MIC5U,2664
|
14
|
-
kscale/store/pybullet.py,sha256=zoeATQStuRWgmPhku65xjfgvE3Y8ReheUIAkZnDr2C0,7614
|
15
|
-
kscale/store/urdf.py,sha256=5x8tK2BYv901S_yYWYPWEnHv-3T0ALBQMdDwb70EZFw,6395
|
16
|
-
kscale/store/utils.py,sha256=rFXGkem2oAttAf3bhWmFEhxrqYnaVvlVJsC268IMw6Y,906
|
17
|
-
kscale/store/gen/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
18
|
-
kscale/store/gen/api.py,sha256=82D41J6pg9KWdgD0lx7NggLcNS32SpnN8DqE3Md6ON0,9559
|
19
|
-
kscale/utils/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
20
|
-
kscale/utils/api_base.py,sha256=Kk_WtRDdJHmOg6NtHmVxVrcfARSUkhfr29ypLch_pO0,112
|
21
|
-
kscale-0.0.10.dist-info/LICENSE,sha256=HCN2bImAzUOXldAZZI7JZ9PYq6OwMlDAP_PpX1HnuN0,1071
|
22
|
-
kscale-0.0.10.dist-info/METADATA,sha256=4K7YAFdI1P5PIAAw78lvbyUw1zIAZ_-ZiZr2NFx-o2Q,2505
|
23
|
-
kscale-0.0.10.dist-info/WHEEL,sha256=GV9aMThwP_4oNCtvEC2ec3qUYutgWeAzklro_0m4WJQ,91
|
24
|
-
kscale-0.0.10.dist-info/entry_points.txt,sha256=PaVs1ivqB0BBdGUsiFkxGUYjGLz05VqagxwRVwi4yV4,54
|
25
|
-
kscale-0.0.10.dist-info/top_level.txt,sha256=C2ynjYwopg6YjgttnI2dJjasyq3EKNmYp-IfQg9Xms4,7
|
26
|
-
kscale-0.0.10.dist-info/RECORD,,
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|