luckyrobots 0.1.70__tar.gz → 0.1.72__tar.gz

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.
Files changed (64) hide show
  1. {luckyrobots-0.1.70 → luckyrobots-0.1.72}/PKG-INFO +1 -1
  2. {luckyrobots-0.1.70 → luckyrobots-0.1.72}/pyproject.toml +1 -1
  3. {luckyrobots-0.1.70 → luckyrobots-0.1.72}/src/luckyrobots/__init__.py +8 -1
  4. {luckyrobots-0.1.70 → luckyrobots-0.1.72}/src/luckyrobots/client.py +201 -4
  5. luckyrobots-0.1.72/src/luckyrobots/grpc/generated/agent_pb2.py +69 -0
  6. luckyrobots-0.1.72/src/luckyrobots/grpc/generated/agent_pb2_grpc.py +283 -0
  7. luckyrobots-0.1.72/src/luckyrobots/grpc/generated/camera_pb2.py +47 -0
  8. luckyrobots-0.1.72/src/luckyrobots/grpc/generated/camera_pb2_grpc.py +144 -0
  9. luckyrobots-0.1.72/src/luckyrobots/grpc/generated/common_pb2.py +43 -0
  10. luckyrobots-0.1.72/src/luckyrobots/grpc/generated/common_pb2_grpc.py +24 -0
  11. luckyrobots-0.1.72/src/luckyrobots/grpc/generated/hazel_rpc_pb2.py +43 -0
  12. luckyrobots-0.1.72/src/luckyrobots/grpc/generated/hazel_rpc_pb2_grpc.py +24 -0
  13. luckyrobots-0.1.72/src/luckyrobots/grpc/generated/media_pb2.py +39 -0
  14. luckyrobots-0.1.72/src/luckyrobots/grpc/generated/media_pb2_grpc.py +24 -0
  15. luckyrobots-0.1.72/src/luckyrobots/grpc/generated/mujoco_pb2.py +51 -0
  16. luckyrobots-0.1.72/src/luckyrobots/grpc/generated/mujoco_pb2_grpc.py +230 -0
  17. luckyrobots-0.1.72/src/luckyrobots/grpc/generated/scene_pb2.py +66 -0
  18. luckyrobots-0.1.72/src/luckyrobots/grpc/generated/scene_pb2_grpc.py +317 -0
  19. luckyrobots-0.1.72/src/luckyrobots/grpc/generated/telemetry_pb2.py +47 -0
  20. luckyrobots-0.1.72/src/luckyrobots/grpc/generated/telemetry_pb2_grpc.py +143 -0
  21. luckyrobots-0.1.72/src/luckyrobots/grpc/generated/viewport_pb2.py +50 -0
  22. luckyrobots-0.1.72/src/luckyrobots/grpc/generated/viewport_pb2_grpc.py +144 -0
  23. {luckyrobots-0.1.70 → luckyrobots-0.1.72}/src/luckyrobots/grpc/proto/agent.proto +62 -1
  24. {luckyrobots-0.1.70 → luckyrobots-0.1.72}/src/luckyrobots/grpc/proto/camera.proto +1 -1
  25. {luckyrobots-0.1.70 → luckyrobots-0.1.72}/src/luckyrobots/grpc/proto/common.proto +1 -1
  26. {luckyrobots-0.1.70 → luckyrobots-0.1.72}/src/luckyrobots/grpc/proto/hazel_rpc.proto +1 -1
  27. {luckyrobots-0.1.70 → luckyrobots-0.1.72}/src/luckyrobots/grpc/proto/media.proto +1 -1
  28. {luckyrobots-0.1.70 → luckyrobots-0.1.72}/src/luckyrobots/grpc/proto/mujoco.proto +1 -1
  29. {luckyrobots-0.1.70 → luckyrobots-0.1.72}/src/luckyrobots/grpc/proto/scene.proto +35 -1
  30. {luckyrobots-0.1.70 → luckyrobots-0.1.72}/src/luckyrobots/grpc/proto/telemetry.proto +1 -1
  31. {luckyrobots-0.1.70 → luckyrobots-0.1.72}/src/luckyrobots/grpc/proto/viewport.proto +1 -1
  32. {luckyrobots-0.1.70 → luckyrobots-0.1.72}/src/luckyrobots/luckyrobots.py +48 -8
  33. {luckyrobots-0.1.70 → luckyrobots-0.1.72}/src/luckyrobots/models/__init__.py +2 -0
  34. luckyrobots-0.1.72/src/luckyrobots/models/randomization.py +77 -0
  35. luckyrobots-0.1.70/src/luckyrobots/grpc/generated/agent_pb2.py +0 -61
  36. luckyrobots-0.1.70/src/luckyrobots/grpc/generated/agent_pb2_grpc.py +0 -255
  37. luckyrobots-0.1.70/src/luckyrobots/grpc/generated/camera_pb2.py +0 -45
  38. luckyrobots-0.1.70/src/luckyrobots/grpc/generated/camera_pb2_grpc.py +0 -155
  39. luckyrobots-0.1.70/src/luckyrobots/grpc/generated/common_pb2.py +0 -39
  40. luckyrobots-0.1.70/src/luckyrobots/grpc/generated/common_pb2_grpc.py +0 -27
  41. luckyrobots-0.1.70/src/luckyrobots/grpc/generated/media_pb2.py +0 -35
  42. luckyrobots-0.1.70/src/luckyrobots/grpc/generated/media_pb2_grpc.py +0 -27
  43. luckyrobots-0.1.70/src/luckyrobots/grpc/generated/mujoco_pb2.py +0 -47
  44. luckyrobots-0.1.70/src/luckyrobots/grpc/generated/mujoco_pb2_grpc.py +0 -248
  45. luckyrobots-0.1.70/src/luckyrobots/grpc/generated/scene_pb2.py +0 -54
  46. luckyrobots-0.1.70/src/luckyrobots/grpc/generated/scene_pb2_grpc.py +0 -248
  47. luckyrobots-0.1.70/src/luckyrobots/grpc/generated/telemetry_pb2.py +0 -43
  48. luckyrobots-0.1.70/src/luckyrobots/grpc/generated/telemetry_pb2_grpc.py +0 -154
  49. luckyrobots-0.1.70/src/luckyrobots/grpc/generated/viewport_pb2.py +0 -48
  50. luckyrobots-0.1.70/src/luckyrobots/grpc/generated/viewport_pb2_grpc.py +0 -155
  51. {luckyrobots-0.1.70 → luckyrobots-0.1.72}/.gitignore +0 -0
  52. {luckyrobots-0.1.70 → luckyrobots-0.1.72}/LICENSE +0 -0
  53. {luckyrobots-0.1.70 → luckyrobots-0.1.72}/README.md +0 -0
  54. {luckyrobots-0.1.70 → luckyrobots-0.1.72}/src/luckyrobots/config/__init__.py +0 -0
  55. {luckyrobots-0.1.70 → luckyrobots-0.1.72}/src/luckyrobots/config/robots.yaml +0 -0
  56. {luckyrobots-0.1.70 → luckyrobots-0.1.72}/src/luckyrobots/engine/__init__.py +0 -0
  57. {luckyrobots-0.1.70 → luckyrobots-0.1.72}/src/luckyrobots/engine/check_updates.py +0 -0
  58. {luckyrobots-0.1.70 → luckyrobots-0.1.72}/src/luckyrobots/engine/download.py +0 -0
  59. {luckyrobots-0.1.70 → luckyrobots-0.1.72}/src/luckyrobots/engine/manager.py +0 -0
  60. {luckyrobots-0.1.70 → luckyrobots-0.1.72}/src/luckyrobots/grpc/__init__.py +0 -0
  61. {luckyrobots-0.1.70 → luckyrobots-0.1.72}/src/luckyrobots/grpc/generated/__init__.py +0 -0
  62. {luckyrobots-0.1.70 → luckyrobots-0.1.72}/src/luckyrobots/models/camera.py +0 -0
  63. {luckyrobots-0.1.70 → luckyrobots-0.1.72}/src/luckyrobots/models/observation.py +0 -0
  64. {luckyrobots-0.1.70 → luckyrobots-0.1.72}/src/luckyrobots/utils.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: luckyrobots
3
- Version: 0.1.70
3
+ Version: 0.1.72
4
4
  Summary: Robotics-AI Training in Hyperrealistic Game Environments
5
5
  Project-URL: Homepage, https://github.com/luckyrobots/luckyrobots
6
6
  Project-URL: Documentation, https://luckyrobots.readthedocs.io
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
4
4
 
5
5
  [project]
6
6
  name = "luckyrobots"
7
- version = "0.1.70"
7
+ version = "0.1.72"
8
8
  description = "Robotics-AI Training in Hyperrealistic Game Environments"
9
9
  readme = "README.md"
10
10
  requires-python = ">=3.10"
@@ -7,7 +7,13 @@ simulation environment via gRPC.
7
7
 
8
8
  from .luckyrobots import LuckyRobots
9
9
  from .client import LuckyEngineClient, GrpcConnectionError, BenchmarkResult
10
- from .models import ObservationResponse, StateSnapshot, CameraData, CameraShape
10
+ from .models import (
11
+ ObservationResponse,
12
+ StateSnapshot,
13
+ CameraData,
14
+ CameraShape,
15
+ DomainRandomizationConfig,
16
+ )
11
17
  from .utils import FPS
12
18
  from .engine import check_updates
13
19
 
@@ -24,6 +30,7 @@ __all__ = [
24
30
  "StateSnapshot",
25
31
  "CameraData",
26
32
  "CameraShape",
33
+ "DomainRandomizationConfig",
27
34
  # Utilities
28
35
  "FPS",
29
36
  "check_updates",
@@ -38,7 +38,7 @@ except Exception as e: # pragma: no cover
38
38
  ) from e
39
39
 
40
40
  # Import Pydantic models for type-checked responses
41
- from .models import ObservationResponse, StateSnapshot
41
+ from .models import ObservationResponse, StateSnapshot, DomainRandomizationConfig
42
42
 
43
43
 
44
44
  class GrpcConnectionError(Exception):
@@ -150,7 +150,7 @@ class LuckyEngineClient:
150
150
  self._viewport = viewport_pb2_grpc.ViewportServiceStub(self._channel)
151
151
  self._camera = camera_pb2_grpc.CameraServiceStub(self._channel)
152
152
 
153
- logger.info(f"Connected to LuckyEngine gRPC server at {target}")
153
+ logger.info(f"Channel opened to {target} (server not verified yet)")
154
154
 
155
155
  def close(self) -> None:
156
156
  """Close the gRPC channel."""
@@ -221,6 +221,7 @@ class LuckyEngineClient:
221
221
  pass
222
222
 
223
223
  if self.health_check(timeout=10.0):
224
+ logger.info(f"Connected to LuckyEngine gRPC server at {self.host}:{self.port}")
224
225
  return True
225
226
 
226
227
  time.sleep(poll_interval)
@@ -595,7 +596,12 @@ class LuckyEngineClient:
595
596
  ),
596
597
  )
597
598
 
598
- def reset_agent(self, agent_name: str = "", timeout: Optional[float] = None):
599
+ def reset_agent(
600
+ self,
601
+ agent_name: str = "",
602
+ randomization_cfg: Optional[Any] = None,
603
+ timeout: Optional[float] = None,
604
+ ):
599
605
  """
600
606
  Reset a specific agent (full reset: clear buffers, reset state, resample commands, apply MuJoCo state).
601
607
 
@@ -604,17 +610,208 @@ class LuckyEngineClient:
604
610
  Args:
605
611
  agent_name: Agent logical name. Convention is `agent_0`, `agent_1`, ...
606
612
  Empty string means "default agent" (agent_0).
613
+ randomization_cfg: Optional domain randomization config for this reset.
607
614
  timeout: Timeout in seconds (uses default if None).
608
615
 
609
616
  Returns:
610
617
  ResetAgentResponse with success and message fields.
611
618
  """
612
619
  timeout = timeout or self.timeout
620
+
621
+ # Build request with optional randomization config
622
+ request_kwargs = {"agent_name": agent_name}
623
+
624
+ if randomization_cfg is not None:
625
+ randomization_proto = self._randomization_to_proto(randomization_cfg)
626
+ request_kwargs["dr_config"] = randomization_proto
627
+
613
628
  return self.agent.ResetAgent(
614
- self.pb.agent.ResetAgentRequest(agent_name=agent_name),
629
+ self.pb.agent.ResetAgentRequest(**request_kwargs),
615
630
  timeout=timeout,
616
631
  )
617
632
 
633
+ def step(
634
+ self,
635
+ actions: list[float],
636
+ agent_name: str = "",
637
+ timeout_ms: int = 0,
638
+ timeout: Optional[float] = None,
639
+ ) -> ObservationResponse:
640
+ """
641
+ Synchronous RL step: apply action, wait for physics, return observation.
642
+
643
+ This is the recommended interface for RL training as it eliminates
644
+ one network round-trip compared to separate SendControl + GetObservation.
645
+
646
+ Args:
647
+ actions: Action vector to apply for this step.
648
+ agent_name: Agent name (empty = default agent).
649
+ timeout_ms: Server-side timeout for the step in milliseconds (0 = use default).
650
+ timeout: RPC timeout in seconds.
651
+
652
+ Returns:
653
+ ObservationResponse with observation after physics step.
654
+ """
655
+ timeout = timeout or self.timeout
656
+
657
+ resp = self.agent.Step(
658
+ self.pb.agent.StepRequest(
659
+ agent_name=agent_name,
660
+ actions=actions,
661
+ timeout_ms=timeout_ms,
662
+ ),
663
+ timeout=timeout,
664
+ )
665
+
666
+ if not resp.success:
667
+ raise RuntimeError(f"Step failed: {resp.message}")
668
+
669
+ # Extract observation from AgentFrame
670
+ agent_frame = resp.observation
671
+ observations = list(agent_frame.observations) if agent_frame.observations else []
672
+ actions_out = list(agent_frame.actions) if agent_frame.actions else []
673
+ timestamp_ms = getattr(agent_frame, "timestamp_ms", 0)
674
+ frame_number = getattr(agent_frame, "frame_number", 0)
675
+
676
+ # Look up cached schema for named access
677
+ cache_key = agent_name or "agent_0"
678
+ obs_names, action_names = self._schema_cache.get(cache_key, (None, None))
679
+
680
+ return ObservationResponse(
681
+ observation=observations,
682
+ actions=actions_out,
683
+ timestamp_ms=timestamp_ms,
684
+ frame_number=frame_number,
685
+ agent_name=cache_key,
686
+ observation_names=obs_names,
687
+ action_names=action_names,
688
+ )
689
+
690
+ def set_simulation_mode(
691
+ self,
692
+ mode: str = "fast",
693
+ timeout: Optional[float] = None,
694
+ ):
695
+ """
696
+ Set simulation timing mode.
697
+
698
+ Args:
699
+ mode: "realtime", "deterministic", or "fast"
700
+ - realtime: Physics runs at 1x wall-clock speed (for visualization)
701
+ - deterministic: Physics runs at fixed rate (for reproducibility)
702
+ - fast: Physics runs as fast as possible (for RL training)
703
+ timeout: RPC timeout in seconds.
704
+
705
+ Returns:
706
+ SetSimulationModeResponse with success and current mode.
707
+ """
708
+ timeout = timeout or self.timeout
709
+
710
+ mode_map = {
711
+ "realtime": 0,
712
+ "deterministic": 1,
713
+ "fast": 2,
714
+ }
715
+ mode_value = mode_map.get(mode.lower(), 2) # Default to fast
716
+
717
+ return self.scene.SetSimulationMode(
718
+ self.pb.scene.SetSimulationModeRequest(mode=mode_value),
719
+ timeout=timeout,
720
+ )
721
+
722
+ def get_simulation_mode(self, timeout: Optional[float] = None):
723
+ """
724
+ Get current simulation timing mode.
725
+
726
+ Returns:
727
+ GetSimulationModeResponse with mode field (0=realtime, 1=deterministic, 2=fast).
728
+ """
729
+ timeout = timeout or self.timeout
730
+
731
+ return self.scene.GetSimulationMode(
732
+ self.pb.scene.GetSimulationModeRequest(),
733
+ timeout=timeout,
734
+ )
735
+
736
+ def _randomization_to_proto(self, randomization_cfg: Any):
737
+ """Convert domain randomization config to proto message.
738
+
739
+ Accepts any object with randomization config fields (DomainRandomizationConfig,
740
+ PhysicsDRCfg from luckylab, or similar).
741
+ """
742
+ proto_kwargs = {}
743
+
744
+ # Helper to get attribute value, checking for None
745
+ def get_val(name: str, default=None):
746
+ val = getattr(randomization_cfg, name, default)
747
+ # Handle both None and empty tuples/lists
748
+ if val is None or (isinstance(val, (tuple, list)) and len(val) == 0):
749
+ return None
750
+ return val
751
+
752
+ # Initial state randomization
753
+ pose_pos = get_val("pose_position_noise")
754
+ if pose_pos is not None:
755
+ proto_kwargs["pose_position_noise"] = list(pose_pos)
756
+
757
+ pose_ori = get_val("pose_orientation_noise")
758
+ if pose_ori is not None and pose_ori != 0.0:
759
+ proto_kwargs["pose_orientation_noise"] = pose_ori
760
+
761
+ joint_pos = get_val("joint_position_noise")
762
+ if joint_pos is not None and joint_pos != 0.0:
763
+ proto_kwargs["joint_position_noise"] = joint_pos
764
+
765
+ joint_vel = get_val("joint_velocity_noise")
766
+ if joint_vel is not None and joint_vel != 0.0:
767
+ proto_kwargs["joint_velocity_noise"] = joint_vel
768
+
769
+ # Physics parameters (ranges)
770
+ friction = get_val("friction_range")
771
+ if friction is not None:
772
+ proto_kwargs["friction_range"] = list(friction)
773
+
774
+ restitution = get_val("restitution_range")
775
+ if restitution is not None:
776
+ proto_kwargs["restitution_range"] = list(restitution)
777
+
778
+ mass_scale = get_val("mass_scale_range")
779
+ if mass_scale is not None:
780
+ proto_kwargs["mass_scale_range"] = list(mass_scale)
781
+
782
+ com_offset = get_val("com_offset_range")
783
+ if com_offset is not None:
784
+ proto_kwargs["com_offset_range"] = list(com_offset)
785
+
786
+ # Motor/actuator
787
+ motor_strength = get_val("motor_strength_range")
788
+ if motor_strength is not None:
789
+ proto_kwargs["motor_strength_range"] = list(motor_strength)
790
+
791
+ motor_offset = get_val("motor_offset_range")
792
+ if motor_offset is not None:
793
+ proto_kwargs["motor_offset_range"] = list(motor_offset)
794
+
795
+ # External disturbances
796
+ push_interval = get_val("push_interval_range")
797
+ if push_interval is not None:
798
+ proto_kwargs["push_interval_range"] = list(push_interval)
799
+
800
+ push_velocity = get_val("push_velocity_range")
801
+ if push_velocity is not None:
802
+ proto_kwargs["push_velocity_range"] = list(push_velocity)
803
+
804
+ # Terrain
805
+ terrain_type = get_val("terrain_type")
806
+ if terrain_type is not None and terrain_type != "":
807
+ proto_kwargs["terrain_type"] = terrain_type
808
+
809
+ terrain_diff = get_val("terrain_difficulty")
810
+ if terrain_diff is not None and terrain_diff != 0.0:
811
+ proto_kwargs["terrain_difficulty"] = terrain_diff
812
+
813
+ return self.pb.agent.DomainRandomizationConfig(**proto_kwargs)
814
+
618
815
  def stream_telemetry(self, target_fps: int = 30):
619
816
  """
620
817
  Start streaming telemetry data. [PLACEHOLDER - not confirmed working]
@@ -0,0 +1,69 @@
1
+ # -*- coding: utf-8 -*-
2
+ # Generated by the protocol buffer compiler. DO NOT EDIT!
3
+ # NO CHECKED-IN PROTOBUF GENCODE
4
+ # source: agent.proto
5
+ # Protobuf Python Version: 6.31.1
6
+ """Generated protocol buffer code."""
7
+ from google.protobuf import descriptor as _descriptor
8
+ from google.protobuf import descriptor_pool as _descriptor_pool
9
+ from google.protobuf import runtime_version as _runtime_version
10
+ from google.protobuf import symbol_database as _symbol_database
11
+ from google.protobuf.internal import builder as _builder
12
+ _runtime_version.ValidateProtobufRuntimeVersion(
13
+ _runtime_version.Domain.PUBLIC,
14
+ 6,
15
+ 31,
16
+ 1,
17
+ '',
18
+ 'agent.proto'
19
+ )
20
+ # @@protoc_insertion_point(imports)
21
+
22
+ _sym_db = _symbol_database.Default()
23
+
24
+
25
+ from . import common_pb2 as common__pb2
26
+ from . import media_pb2 as media__pb2
27
+ from . import mujoco_pb2 as mujoco__pb2
28
+ from . import telemetry_pb2 as telemetry__pb2
29
+
30
+
31
+ DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x0b\x61gent.proto\x12\thazel.rpc\x1a\x0c\x63ommon.proto\x1a\x0bmedia.proto\x1a\x0cmujoco.proto\x1a\x0ftelemetry.proto\"\x81\x01\n\x0b\x41gentSchema\x12\x12\n\nagent_name\x18\x01 \x01(\t\x12\x19\n\x11observation_names\x18\x02 \x03(\t\x12\x14\n\x0c\x61\x63tion_names\x18\x03 \x03(\t\x12\x18\n\x10observation_size\x18\x04 \x01(\r\x12\x13\n\x0b\x61\x63tion_size\x18\x05 \x01(\r\"+\n\x15GetAgentSchemaRequest\x12\x12\n\nagent_name\x18\x01 \x01(\t\"@\n\x16GetAgentSchemaResponse\x12&\n\x06schema\x18\x01 \x01(\x0b\x32\x16.hazel.rpc.AgentSchema\"<\n\x12StreamAgentRequest\x12\x12\n\nagent_name\x18\x01 \x01(\t\x12\x12\n\ntarget_fps\x18\x02 \x01(\r\"\xa1\x03\n\x19\x44omainRandomizationConfig\x12\x1b\n\x13pose_position_noise\x18\x01 \x03(\x02\x12\x1e\n\x16pose_orientation_noise\x18\x02 \x01(\x02\x12\x1c\n\x14joint_position_noise\x18\x03 \x01(\x02\x12\x1c\n\x14joint_velocity_noise\x18\x04 \x01(\x02\x12\x16\n\x0e\x66riction_range\x18\x05 \x03(\x02\x12\x19\n\x11restitution_range\x18\x06 \x03(\x02\x12\x18\n\x10mass_scale_range\x18\x07 \x03(\x02\x12\x18\n\x10\x63om_offset_range\x18\x08 \x03(\x02\x12\x1c\n\x14motor_strength_range\x18\t \x03(\x02\x12\x1a\n\x12motor_offset_range\x18\n \x03(\x02\x12\x1b\n\x13push_interval_range\x18\x0b \x03(\x02\x12\x1b\n\x13push_velocity_range\x18\x0c \x03(\x02\x12\x14\n\x0cterrain_type\x18\r \x01(\t\x12\x1a\n\x12terrain_difficulty\x18\x0e \x01(\x02\"`\n\x11ResetAgentRequest\x12\x12\n\nagent_name\x18\x01 \x01(\t\x12\x37\n\tdr_config\x18\x02 \x01(\x0b\x32$.hazel.rpc.DomainRandomizationConfig\"6\n\x12ResetAgentResponse\x12\x0f\n\x07success\x18\x01 \x01(\x08\x12\x0f\n\x07message\x18\x02 \x01(\t\"\x87\x01\n\nAgentFrame\x12\x14\n\x0ctimestamp_ms\x18\x01 \x01(\x04\x12\x14\n\x0c\x66rame_number\x18\x02 \x01(\r\x12\x14\n\x0cobservations\x18\x03 \x03(\x02\x12\x0f\n\x07\x61\x63tions\x18\x04 \x03(\x02\x12\x12\n\nagent_name\x18\x05 \x01(\t\x12\x12\n\ntarget_fps\x18\x06 \x01(\r\"\x87\x01\n\x15GetCameraFrameRequest\x12!\n\x02id\x18\x01 \x01(\x0b\x32\x13.hazel.rpc.EntityIdH\x00\x12\x0e\n\x04name\x18\x02 \x01(\tH\x00\x12\r\n\x05width\x18\x03 \x01(\r\x12\x0e\n\x06height\x18\x04 \x01(\r\x12\x0e\n\x06\x66ormat\x18\x05 \x01(\tB\x0c\n\nidentifier\"_\n\x17GetViewportFrameRequest\x12\x15\n\rviewport_name\x18\x01 \x01(\t\x12\r\n\x05width\x18\x02 \x01(\r\x12\x0e\n\x06height\x18\x03 \x01(\r\x12\x0e\n\x06\x66ormat\x18\x04 \x01(\t\"\xfe\x01\n\x15GetObservationRequest\x12\x12\n\nrobot_name\x18\x01 \x01(\t\x12\x12\n\nagent_name\x18\x02 \x01(\t\x12\x1b\n\x13include_joint_state\x18\x03 \x01(\x08\x12\x1b\n\x13include_agent_frame\x18\x04 \x01(\x08\x12\x19\n\x11include_telemetry\x18\x05 \x01(\x08\x12\x31\n\x07\x63\x61meras\x18\x06 \x03(\x0b\x32 .hazel.rpc.GetCameraFrameRequest\x12\x35\n\tviewports\x18\x07 \x03(\x0b\x32\".hazel.rpc.GetViewportFrameRequest\"\xd4\x02\n\x16GetObservationResponse\x12\x0f\n\x07success\x18\x01 \x01(\x08\x12\x0f\n\x07message\x18\x02 \x01(\t\x12\x14\n\x0ctimestamp_ms\x18\x03 \x01(\x04\x12\x14\n\x0c\x66rame_number\x18\x04 \x01(\r\x12*\n\x0bjoint_state\x18\x05 \x01(\x0b\x32\x15.hazel.rpc.JointState\x12*\n\x0b\x61gent_frame\x18\x06 \x01(\x0b\x32\x15.hazel.rpc.AgentFrame\x12,\n\ttelemetry\x18\x07 \x01(\x0b\x32\x19.hazel.rpc.TelemetryFrame\x12\x31\n\rcamera_frames\x18\x08 \x03(\x0b\x32\x1a.hazel.rpc.NamedImageFrame\x12\x33\n\x0fviewport_frames\x18\t \x03(\x0b\x32\x1a.hazel.rpc.NamedImageFrame\"F\n\x0bStepRequest\x12\x12\n\nagent_name\x18\x01 \x01(\t\x12\x0f\n\x07\x61\x63tions\x18\x02 \x03(\x02\x12\x12\n\ntimeout_ms\x18\x03 \x01(\r\"~\n\x0cStepResponse\x12\x0f\n\x07success\x18\x01 \x01(\x08\x12\x0f\n\x07message\x18\x02 \x01(\t\x12*\n\x0bobservation\x18\x03 \x01(\x0b\x32\x15.hazel.rpc.AgentFrame\x12 \n\x18physics_step_duration_us\x18\x04 \x01(\x04\x32\x87\x03\n\x0c\x41gentService\x12U\n\x0eGetAgentSchema\x12 .hazel.rpc.GetAgentSchemaRequest\x1a!.hazel.rpc.GetAgentSchemaResponse\x12U\n\x0eGetObservation\x12 .hazel.rpc.GetObservationRequest\x1a!.hazel.rpc.GetObservationResponse\x12\x45\n\x0bStreamAgent\x12\x1d.hazel.rpc.StreamAgentRequest\x1a\x15.hazel.rpc.AgentFrame0\x01\x12I\n\nResetAgent\x12\x1c.hazel.rpc.ResetAgentRequest\x1a\x1d.hazel.rpc.ResetAgentResponse\x12\x37\n\x04Step\x12\x16.hazel.rpc.StepRequest\x1a\x17.hazel.rpc.StepResponseB\x03\xf8\x01\x01\x62\x06proto3')
32
+
33
+ _globals = globals()
34
+ _builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, _globals)
35
+ _builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, 'agent_pb2', _globals)
36
+ if not _descriptor._USE_C_DESCRIPTORS:
37
+ _globals['DESCRIPTOR']._loaded_options = None
38
+ _globals['DESCRIPTOR']._serialized_options = b'\370\001\001'
39
+ _globals['_AGENTSCHEMA']._serialized_start=85
40
+ _globals['_AGENTSCHEMA']._serialized_end=214
41
+ _globals['_GETAGENTSCHEMAREQUEST']._serialized_start=216
42
+ _globals['_GETAGENTSCHEMAREQUEST']._serialized_end=259
43
+ _globals['_GETAGENTSCHEMARESPONSE']._serialized_start=261
44
+ _globals['_GETAGENTSCHEMARESPONSE']._serialized_end=325
45
+ _globals['_STREAMAGENTREQUEST']._serialized_start=327
46
+ _globals['_STREAMAGENTREQUEST']._serialized_end=387
47
+ _globals['_DOMAINRANDOMIZATIONCONFIG']._serialized_start=390
48
+ _globals['_DOMAINRANDOMIZATIONCONFIG']._serialized_end=807
49
+ _globals['_RESETAGENTREQUEST']._serialized_start=809
50
+ _globals['_RESETAGENTREQUEST']._serialized_end=905
51
+ _globals['_RESETAGENTRESPONSE']._serialized_start=907
52
+ _globals['_RESETAGENTRESPONSE']._serialized_end=961
53
+ _globals['_AGENTFRAME']._serialized_start=964
54
+ _globals['_AGENTFRAME']._serialized_end=1099
55
+ _globals['_GETCAMERAFRAMEREQUEST']._serialized_start=1102
56
+ _globals['_GETCAMERAFRAMEREQUEST']._serialized_end=1237
57
+ _globals['_GETVIEWPORTFRAMEREQUEST']._serialized_start=1239
58
+ _globals['_GETVIEWPORTFRAMEREQUEST']._serialized_end=1334
59
+ _globals['_GETOBSERVATIONREQUEST']._serialized_start=1337
60
+ _globals['_GETOBSERVATIONREQUEST']._serialized_end=1591
61
+ _globals['_GETOBSERVATIONRESPONSE']._serialized_start=1594
62
+ _globals['_GETOBSERVATIONRESPONSE']._serialized_end=1934
63
+ _globals['_STEPREQUEST']._serialized_start=1936
64
+ _globals['_STEPREQUEST']._serialized_end=2006
65
+ _globals['_STEPRESPONSE']._serialized_start=2008
66
+ _globals['_STEPRESPONSE']._serialized_end=2134
67
+ _globals['_AGENTSERVICE']._serialized_start=2137
68
+ _globals['_AGENTSERVICE']._serialized_end=2528
69
+ # @@protoc_insertion_point(module_scope)
@@ -0,0 +1,283 @@
1
+ # Generated by the gRPC Python protocol compiler plugin. DO NOT EDIT!
2
+ """Client and server classes corresponding to protobuf-defined services."""
3
+ import grpc
4
+ import warnings
5
+
6
+ from . import agent_pb2 as agent__pb2
7
+
8
+ GRPC_GENERATED_VERSION = '1.76.0'
9
+ GRPC_VERSION = grpc.__version__
10
+ _version_not_supported = False
11
+
12
+ try:
13
+ from grpc._utilities import first_version_is_lower
14
+ _version_not_supported = first_version_is_lower(GRPC_VERSION, GRPC_GENERATED_VERSION)
15
+ except ImportError:
16
+ _version_not_supported = True
17
+
18
+ if _version_not_supported:
19
+ raise RuntimeError(
20
+ f'The grpc package installed is at version {GRPC_VERSION},'
21
+ + ' but the generated code in agent_pb2_grpc.py depends on'
22
+ + f' grpcio>={GRPC_GENERATED_VERSION}.'
23
+ + f' Please upgrade your grpc module to grpcio>={GRPC_GENERATED_VERSION}'
24
+ + f' or downgrade your generated code using grpcio-tools<={GRPC_VERSION}.'
25
+ )
26
+
27
+
28
+ class AgentServiceStub(object):
29
+ """Per-agent RL-style observation streaming (training / inference clients consume this).
30
+ """
31
+
32
+ def __init__(self, channel):
33
+ """Constructor.
34
+
35
+ Args:
36
+ channel: A grpc.Channel.
37
+ """
38
+ self.GetAgentSchema = channel.unary_unary(
39
+ '/hazel.rpc.AgentService/GetAgentSchema',
40
+ request_serializer=agent__pb2.GetAgentSchemaRequest.SerializeToString,
41
+ response_deserializer=agent__pb2.GetAgentSchemaResponse.FromString,
42
+ _registered_method=True)
43
+ self.GetObservation = channel.unary_unary(
44
+ '/hazel.rpc.AgentService/GetObservation',
45
+ request_serializer=agent__pb2.GetObservationRequest.SerializeToString,
46
+ response_deserializer=agent__pb2.GetObservationResponse.FromString,
47
+ _registered_method=True)
48
+ self.StreamAgent = channel.unary_stream(
49
+ '/hazel.rpc.AgentService/StreamAgent',
50
+ request_serializer=agent__pb2.StreamAgentRequest.SerializeToString,
51
+ response_deserializer=agent__pb2.AgentFrame.FromString,
52
+ _registered_method=True)
53
+ self.ResetAgent = channel.unary_unary(
54
+ '/hazel.rpc.AgentService/ResetAgent',
55
+ request_serializer=agent__pb2.ResetAgentRequest.SerializeToString,
56
+ response_deserializer=agent__pb2.ResetAgentResponse.FromString,
57
+ _registered_method=True)
58
+ self.Step = channel.unary_unary(
59
+ '/hazel.rpc.AgentService/Step',
60
+ request_serializer=agent__pb2.StepRequest.SerializeToString,
61
+ response_deserializer=agent__pb2.StepResponse.FromString,
62
+ _registered_method=True)
63
+
64
+
65
+ class AgentServiceServicer(object):
66
+ """Per-agent RL-style observation streaming (training / inference clients consume this).
67
+ """
68
+
69
+ def GetAgentSchema(self, request, context):
70
+ """Missing associated documentation comment in .proto file."""
71
+ context.set_code(grpc.StatusCode.UNIMPLEMENTED)
72
+ context.set_details('Method not implemented!')
73
+ raise NotImplementedError('Method not implemented!')
74
+
75
+ def GetObservation(self, request, context):
76
+ """Single-shot observation snapshot (unified observation surface).
77
+ """
78
+ context.set_code(grpc.StatusCode.UNIMPLEMENTED)
79
+ context.set_details('Method not implemented!')
80
+ raise NotImplementedError('Method not implemented!')
81
+
82
+ def StreamAgent(self, request, context):
83
+ """Server-streaming observations (and optional action echo) for a single agent.
84
+
85
+ The client specifies which agent to stream via StreamAgentRequest and may
86
+ provide a target FPS hint. Actions are currently sent via MujocoService
87
+ (SendControl); AgentFrame.actions is primarily used for telemetry.
88
+ """
89
+ context.set_code(grpc.StatusCode.UNIMPLEMENTED)
90
+ context.set_details('Method not implemented!')
91
+ raise NotImplementedError('Method not implemented!')
92
+
93
+ def ResetAgent(self, request, context):
94
+ """Reset a specific agent (full reset: clear buffers, reset state, resample commands, apply MuJoCo state).
95
+ Useful for multi-env RL where individual agents need to be reset without resetting the entire scene.
96
+ """
97
+ context.set_code(grpc.StatusCode.UNIMPLEMENTED)
98
+ context.set_details('Method not implemented!')
99
+ raise NotImplementedError('Method not implemented!')
100
+
101
+ def Step(self, request, context):
102
+ """Synchronous RL step: apply action, wait for physics, return observation.
103
+ This is the recommended interface for RL training as it eliminates
104
+ one network round-trip compared to separate SendControl + GetObservation.
105
+ """
106
+ context.set_code(grpc.StatusCode.UNIMPLEMENTED)
107
+ context.set_details('Method not implemented!')
108
+ raise NotImplementedError('Method not implemented!')
109
+
110
+
111
+ def add_AgentServiceServicer_to_server(servicer, server):
112
+ rpc_method_handlers = {
113
+ 'GetAgentSchema': grpc.unary_unary_rpc_method_handler(
114
+ servicer.GetAgentSchema,
115
+ request_deserializer=agent__pb2.GetAgentSchemaRequest.FromString,
116
+ response_serializer=agent__pb2.GetAgentSchemaResponse.SerializeToString,
117
+ ),
118
+ 'GetObservation': grpc.unary_unary_rpc_method_handler(
119
+ servicer.GetObservation,
120
+ request_deserializer=agent__pb2.GetObservationRequest.FromString,
121
+ response_serializer=agent__pb2.GetObservationResponse.SerializeToString,
122
+ ),
123
+ 'StreamAgent': grpc.unary_stream_rpc_method_handler(
124
+ servicer.StreamAgent,
125
+ request_deserializer=agent__pb2.StreamAgentRequest.FromString,
126
+ response_serializer=agent__pb2.AgentFrame.SerializeToString,
127
+ ),
128
+ 'ResetAgent': grpc.unary_unary_rpc_method_handler(
129
+ servicer.ResetAgent,
130
+ request_deserializer=agent__pb2.ResetAgentRequest.FromString,
131
+ response_serializer=agent__pb2.ResetAgentResponse.SerializeToString,
132
+ ),
133
+ 'Step': grpc.unary_unary_rpc_method_handler(
134
+ servicer.Step,
135
+ request_deserializer=agent__pb2.StepRequest.FromString,
136
+ response_serializer=agent__pb2.StepResponse.SerializeToString,
137
+ ),
138
+ }
139
+ generic_handler = grpc.method_handlers_generic_handler(
140
+ 'hazel.rpc.AgentService', rpc_method_handlers)
141
+ server.add_generic_rpc_handlers((generic_handler,))
142
+ server.add_registered_method_handlers('hazel.rpc.AgentService', rpc_method_handlers)
143
+
144
+
145
+ # This class is part of an EXPERIMENTAL API.
146
+ class AgentService(object):
147
+ """Per-agent RL-style observation streaming (training / inference clients consume this).
148
+ """
149
+
150
+ @staticmethod
151
+ def GetAgentSchema(request,
152
+ target,
153
+ options=(),
154
+ channel_credentials=None,
155
+ call_credentials=None,
156
+ insecure=False,
157
+ compression=None,
158
+ wait_for_ready=None,
159
+ timeout=None,
160
+ metadata=None):
161
+ return grpc.experimental.unary_unary(
162
+ request,
163
+ target,
164
+ '/hazel.rpc.AgentService/GetAgentSchema',
165
+ agent__pb2.GetAgentSchemaRequest.SerializeToString,
166
+ agent__pb2.GetAgentSchemaResponse.FromString,
167
+ options,
168
+ channel_credentials,
169
+ insecure,
170
+ call_credentials,
171
+ compression,
172
+ wait_for_ready,
173
+ timeout,
174
+ metadata,
175
+ _registered_method=True)
176
+
177
+ @staticmethod
178
+ def GetObservation(request,
179
+ target,
180
+ options=(),
181
+ channel_credentials=None,
182
+ call_credentials=None,
183
+ insecure=False,
184
+ compression=None,
185
+ wait_for_ready=None,
186
+ timeout=None,
187
+ metadata=None):
188
+ return grpc.experimental.unary_unary(
189
+ request,
190
+ target,
191
+ '/hazel.rpc.AgentService/GetObservation',
192
+ agent__pb2.GetObservationRequest.SerializeToString,
193
+ agent__pb2.GetObservationResponse.FromString,
194
+ options,
195
+ channel_credentials,
196
+ insecure,
197
+ call_credentials,
198
+ compression,
199
+ wait_for_ready,
200
+ timeout,
201
+ metadata,
202
+ _registered_method=True)
203
+
204
+ @staticmethod
205
+ def StreamAgent(request,
206
+ target,
207
+ options=(),
208
+ channel_credentials=None,
209
+ call_credentials=None,
210
+ insecure=False,
211
+ compression=None,
212
+ wait_for_ready=None,
213
+ timeout=None,
214
+ metadata=None):
215
+ return grpc.experimental.unary_stream(
216
+ request,
217
+ target,
218
+ '/hazel.rpc.AgentService/StreamAgent',
219
+ agent__pb2.StreamAgentRequest.SerializeToString,
220
+ agent__pb2.AgentFrame.FromString,
221
+ options,
222
+ channel_credentials,
223
+ insecure,
224
+ call_credentials,
225
+ compression,
226
+ wait_for_ready,
227
+ timeout,
228
+ metadata,
229
+ _registered_method=True)
230
+
231
+ @staticmethod
232
+ def ResetAgent(request,
233
+ target,
234
+ options=(),
235
+ channel_credentials=None,
236
+ call_credentials=None,
237
+ insecure=False,
238
+ compression=None,
239
+ wait_for_ready=None,
240
+ timeout=None,
241
+ metadata=None):
242
+ return grpc.experimental.unary_unary(
243
+ request,
244
+ target,
245
+ '/hazel.rpc.AgentService/ResetAgent',
246
+ agent__pb2.ResetAgentRequest.SerializeToString,
247
+ agent__pb2.ResetAgentResponse.FromString,
248
+ options,
249
+ channel_credentials,
250
+ insecure,
251
+ call_credentials,
252
+ compression,
253
+ wait_for_ready,
254
+ timeout,
255
+ metadata,
256
+ _registered_method=True)
257
+
258
+ @staticmethod
259
+ def Step(request,
260
+ target,
261
+ options=(),
262
+ channel_credentials=None,
263
+ call_credentials=None,
264
+ insecure=False,
265
+ compression=None,
266
+ wait_for_ready=None,
267
+ timeout=None,
268
+ metadata=None):
269
+ return grpc.experimental.unary_unary(
270
+ request,
271
+ target,
272
+ '/hazel.rpc.AgentService/Step',
273
+ agent__pb2.StepRequest.SerializeToString,
274
+ agent__pb2.StepResponse.FromString,
275
+ options,
276
+ channel_credentials,
277
+ insecure,
278
+ call_credentials,
279
+ compression,
280
+ wait_for_ready,
281
+ timeout,
282
+ metadata,
283
+ _registered_method=True)