From 601a7a03aeb9f9a26e11ea32769be4d47cee3892 Mon Sep 17 00:00:00 2001 From: Habermehl <37908699+00make@users.noreply.github.com> Date: Fri, 20 Dec 2024 15:13:16 +0800 Subject: [PATCH 01/18] docs: Add some interesting badges :) Update README_CN.md --- README.md | 47 ++++++++++++++--- README_CN.md | 145 +++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 185 insertions(+), 7 deletions(-) create mode 100644 README_CN.md diff --git a/README.md b/README.md index 36e0fbd4..c93440a1 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,5 @@
Genesis -
--- @@ -9,45 +8,73 @@ +
+ + PyPI - Version + + + PyPI - Downloads + + + GitHub Issues + + + GitHub Discussions + +
+ +

+ README in English + 简体中文版自述文件 +

# What is Genesis? + Genesis is a physics platform designed for general purpose *Robotics/Embodied AI/Physical AI* applications. It is simultaneously multiple things: + 1. A **universal physics engine** re-built from the ground up, capable of simulating a wide range of materials and physical phenomena. 2. A **lightweight**, **ultra-fast**, **pythonic**, and **user-friendly** robotics simulation platform. 3. A powerful and fast **photo-realistic rendering system**. 4. A **generative data engine** that transforms user-prompted natural language description into various modalities of data. -Powered by a universal physics engine re-designed and re-built from the ground up, Genesis integrates various physics solvers and their coupling into a unified framework. This core physics engine is further enhanced by a generative agent framework that operates at an upper level, aiming towards fully **automated data generation** for robotics and beyond. +Powered by a universal physics engine re-designed and re-built from the ground up, Genesis integrates various physics solvers and their coupling into a unified framework. This core physics engine is further enhanced by a generative agent framework that operates at an upper level, aiming towards fully **automated data generation** for robotics and beyond. Currently, we are open-sourcing the **underlying physics engine and the simulation platform**. Our generative framework is a modular system that incorporates many different generative modules, each handling a certain range of data modalities, routed by a high level agent. Some of the modules integrated existing papers and some are still under submission. Access to our generative feature will be gradually rolled out in the near future. If you are interested, feel free to explore more the [paper list](#papers-behind-genesis) below. Genesis is built and will continuously evolve with the following ***long-term missions***: + 1. **Lowering the barrier** to using physics simulations and making robotics research accessible to everyone. (See our [commitment](https://genesis-world.readthedocs.io/en/latest/user_guide/overview/mission.html)) 2. **Unifying a wide spectrum of state-of-the-art physics solvers** into a single framework, allowing re-creating the whole physical world in a virtual realm with the highest possible physical, visual and sensory fidelity, using the most advanced simulation techniques. 3. **Minimizing human effort** in collecting and generating data for robotics and other domains, letting the data flywheel spin on its own. -Project Page: https://genesis-embodied-ai.github.io/ +Project Page: ## Key Features + - **Speed**: Genesis delivers an unprecedented simulation speed -- over 43 million FPS when simulating a Franka robotic arm with a single RTX 4090 (430,000 times faster than real-time). - **Cross-platform**: Genesis runs natively across different systems (Linux, MacOS, Windows), and across different compute backend (CPU, Nvidia GPU, AMD GPU, Apple Metal). - **Unification of various physics solvers**: Genesis develops a unified simulation framework that integrates various physics solvers: Rigid body, MPM, SPH, FEM, PBD, Stable Fluid. - **Support a wide range of material models**: Genesis supports simulation (and the coupling) of rigid and articulated bodies, various types of liquids, gaseous phenomenon, deformable objects, thin-shell objects and granular materials. -- **Support for a wide range of robots**: Robot arm, legged robot, drone, _soft robot_, etc., and extensive support for loading different file types: `MJCF (.xml)`, `URDF`, `.obj`, `.glb`, `.ply`, `.stl`, etc. +- **Support for a wide range of robots**: Robot arm, legged robot, drone, *soft robot*, etc., and extensive support for loading different file types: `MJCF (.xml)`, `URDF`, `.obj`, `.glb`, `.ply`, `.stl`, etc. - **Photorealistic and high-performance ray-tracer**: Genesis supports native ray-tracing based rendering. - **Differentiability**: Genesis is designed to be fully compatible with differentiable simulation. Currently, our MPM solver and Tool Solver are differentiable, and differentiability for other solvers will be added soon (starting with rigid-body simulation). - **Physics-based Tactile Sensor**: Genesis involves a physics-based and differentiable [tactile sensor simulation module](https://github.com/Genesis-Embodied-AI/DiffTactile). This will be integrated to the public version soon (expected in version 0.3.0). - **User-friendliness**: Genesis is designed in a way to make using simulation as simple as possible. From installation to API design, if there's anything you found counter-intuitive or difficult to use, please [let us know](https://github.com/Genesis-Embodied-AI/Genesis/issues). ## Getting Started + ### Quick Installation + Genesis is available via PyPI: + ```bash pip install genesis-world # Requires Python >=3.9; ``` + You also need to install **PyTorch** following the [official instructions](https://pytorch.org/get-started/locally/). ### Documentation + Please refer to our [documentation site](https://genesis-world.readthedocs.io/en/latest/user_guide/index.html) for detailed installation steps, tutorials and API references. ## Contributing to Genesis @@ -57,12 +84,16 @@ The goal of the Genesis project is to build a fully transparent, user-friendly e We sincerely welcome *any forms of contributions* from the community to make the world a better place for robots. From **pull requests** for new features, **bug reports**, to even tiny **suggestions** that will make Genesis API more intuitive, all are wholeheartedly appreciated! ## Support -* Please use Github [Issues](https://github.com/Genesis-Embodied-AI/Genesis/issues) for bug reports and feature requests. -* Please use GitHub [Discussions](https://github.com/Genesis-Embodied-AI/Genesis/discussions) for discussing ideas, and asking questions. + +- Please use Github [Issues](https://github.com/Genesis-Embodied-AI/Genesis/issues) for bug reports and feature requests. + +- Please use GitHub [Discussions](https://github.com/Genesis-Embodied-AI/Genesis/discussions) for discussing ideas, and asking questions. ## License and Acknowledgment + The Genesis source code is licensed under Apache 2.0. The development of Genesis won't be possible without these amazing open-source projects: + - [Taichi](https://github.com/taichi-dev/taichi): for providing a high-performance cross-platform compute backend. Kudos to all the members providing technical support from taichi! - [FluidLab](https://github.com/zhouxian/FluidLab) for providing a reference MPM solver implementation - [SPH_Taichi](https://github.com/erizmr/SPH_Taichi) for providing a reference SPH solver implementation @@ -74,6 +105,7 @@ The development of Genesis won't be possible without these amazing open-source p - [trimesh](https://github.com/mikedh/trimesh), [PyMeshLab](https://github.com/cnr-isti-vclab/PyMeshLab) and [CoACD](https://github.com/SarahWeiii/CoACD) for geometry processing ## Papers behind Genesis + Genesis is a large scale effort that integrates state-of-the-art technologies of various existing and on-going research work into a single system. Here we include a non-exhaustive list of all the papers that contributed to the Genesis project in one way or another: - Xian, Zhou, et al. "Fluidlab: A differentiable environment for benchmarking complex fluid manipulation." arXiv preprint arXiv:2303.02346 (2023). @@ -99,7 +131,9 @@ Genesis is a large scale effort that integrates state-of-the-art technologies of ... and many more on-going work. ## Citation + If you used Genesis in your research, we would appreciate it if you could cite it. We are still working on a technical report, and before it's public, you could consider citing: + ``` @software{Genesis, author = {Genesis Authors}, @@ -109,4 +143,3 @@ If you used Genesis in your research, we would appreciate it if you could cite i url = {https://github.com/Genesis-Embodied-AI/Genesis} } ``` - diff --git a/README_CN.md b/README_CN.md new file mode 100644 index 00000000..4236ecbf --- /dev/null +++ b/README_CN.md @@ -0,0 +1,145 @@ +
+ Genesis +
+ +--- + +
+ +
+ +
+ + PyPI - Version + + + PyPI - Downloads + + + GitHub Issues + + + GitHub Discussions + +
+ +

+ README in English + 简体中文版自述文件 +

+ +# 概述 + +Genesis 是一个为通用 *机器人/嵌入式 AI/物理 AI* 应用设计的物理平台。它同时具备多种功能: + +1. 一个从头开始重建的 **通用物理引擎**,能够模拟各种材料和物理现象。 +2. 一个 **轻量级**、**超快**、**Python 风格** 和 **用户友好** 的机器人模拟平台。 +3. 一个强大且快速的 **照片级真实感渲染系统**。 +4. 一个 **生成数据引擎**,将用户提示的自然语言描述转换为各种数据模式。 + +Genesis 由一个重新设计和重建的通用物理引擎驱动,集成了各种物理求解器及其耦合到一个统一的框架中。这个核心物理引擎通过一个生成代理框架在上层进行增强,旨在实现机器人及其他领域的完全 **自动化数据生成**。 + +目前,我们正在开源 **底层物理引擎和模拟平台**。我们的生成框架是一个模块化系统,包含许多不同的生成模块,每个模块处理一定范围的数据模式,由一个高级代理路由。一些模块集成了现有的论文,一些仍在提交中。我们的生成功能将逐步开放。如果您感兴趣,请参阅下面的 [论文列表](#papers-behind-genesis)。 + +Genesis 的构建和持续发展基于以下 ***长期使命***: + +1. **降低使用物理模拟的门槛**,使机器人研究对所有人都可访问。(参见我们的 [承诺](https://genesis-world.readthedocs.io/en/latest/user_guide/overview/mission.html)) +2. **将各种最先进的物理求解器统一到一个框架中**,使用最先进的模拟技术在虚拟领域中重新创建整个物理世界,达到最高的物理、视觉和感官保真度。 +3. **最小化人类在收集和生成机器人及其他领域数据上的努力**,让数据飞轮自行旋转。 + +项目页面: + +## 主要特点 + +- **速度**:Genesis 提供了前所未有的模拟速度——在单个 RTX 4090 上模拟 Franka 机器人手臂时超过 4300 万 FPS(比实时快 430,000 倍)。 +- **跨平台**:Genesis 原生运行在不同系统(Linux、MacOS、Windows)和不同计算后端(CPU、Nvidia GPU、AMD GPU、Apple Metal)上。 +- **各种物理求解器的统一**:Genesis 开发了一个统一的模拟框架,集成了各种物理求解器:刚体、MPM、SPH、FEM、PBD、稳定流体。 +- **支持广泛的材料模型**:Genesis 支持刚体和关节体、各种液体、气体现象、可变形物体、薄壳物体和颗粒材料的模拟(及其耦合)。 +- **支持广泛的机器人**:机器人手臂、腿式机器人、无人机、*软体机器人*等,并广泛支持加载不同文件类型:`MJCF (.xml)`、`URDF`、`.obj`、`.glb`、`.ply`、`.stl` 等。 +- **照片级真实感和高性能光线追踪器**:Genesis 支持基于光线追踪的原生渲染。 +- **可微分性**:Genesis 设计为完全兼容可微分模拟。目前,我们的 MPM 求解器和工具求解器是可微分的,其他求解器的可微分性将很快添加(从刚体模拟开始)。 +- **基于物理的触觉传感器**:Genesis 包含一个基于物理的可微分 [触觉传感器模拟模块](https://github.com/Genesis-Embodied-AI/DiffTactile)。这将很快集成到公共版本中(预计在 0.3.0 版本中)。 +- **用户友好性**:Genesis 设计为尽可能简化模拟的使用。从安装到 API 设计,如果有任何您觉得不直观或难以使用的地方,请 [告诉我们](https://github.com/Genesis-Embodied-AI/Genesis/issues)。 + +## 入门 + +### 快速安装 + +Genesis 可通过 PyPI 获取: + +```bash +pip install genesis-world # 需要 Python >=3.9; +``` + +您还需要按照 [官方说明](https://pytorch.org/get-started/locally/) 安装 **PyTorch**。 + +### 文档 + +请参阅我们的 [文档网站](https://genesis-world.readthedocs.io/en/latest/user_guide/index.html) 以获取详细的安装步骤、教程和 API 参考。 + +## 贡献 Genesis + +Genesis 项目的目标是构建一个完全透明、用户友好的生态系统,让来自机器人和计算机图形学的贡献者 **共同创建一个高效、真实(物理和视觉上)的虚拟世界,用于机器人研究及其他领域**。 + +我们真诚地欢迎来自社区的 *任何形式的贡献*,以使世界对机器人更友好。从 **新功能的拉取请求**、**错误报告**,到甚至是使 Genesis API 更直观的微小 **建议**,我们都全心全意地感谢! + +## 支持 + +- 请使用 Github [Issues](https://github.com/Genesis-Embodied-AI/Genesis/issues) 报告错误和提出功能请求。 + +- 请使用 GitHub [Discussions](https://github.com/Genesis-Embodied-AI/Genesis/discussions) 讨论想法和提问。 + +## 许可证和致谢 + +Genesis 源代码根据 Apache 2.0 许可证授权。 +没有这些令人惊叹的开源项目,Genesis 的开发是不可能的: + +- [Taichi](https://github.com/taichi-dev/taichi):提供高性能跨平台计算后端。感谢 taichi 的所有成员提供的技术支持! +- [FluidLab](https://github.com/zhouxian/FluidLab) 提供参考 MPM 求解器实现 +- [SPH_Taichi](https://github.com/erizmr/SPH_Taichi) 提供参考 SPH 求解器实现 +- [Ten Minute Physics](https://matthias-research.github.io/pages/tenMinutePhysics/index.html) 和 [PBF3D](https://github.com/WASD4959/PBF3D) 提供参考 PBD 求解器实现 +- [MuJoCo](https://github.com/google-deepmind/mujoco) 和 [Brax](https://github.com/google/brax) 提供刚体动力学参考 +- [libccd](https://github.com/danfis/libccd) 提供碰撞检测参考 +- [PyRender](https://github.com/mmatl/pyrender) 提供基于光栅化的渲染器 +- [LuisaCompute](https://github.com/LuisaGroup/LuisaCompute) 和 [LuisaRender](https://github.com/LuisaGroup/LuisaRender) 提供其光线追踪 DSL +- [trimesh](https://github.com/mikedh/trimesh)、[PyMeshLab](https://github.com/cnr-isti-vclab/PyMeshLab) 和 [CoACD](https://github.com/SarahWeiii/CoACD) 提供几何处理 + +## Genesis 背后的论文 + +Genesis 是一个大规模的努力,将各种现有和正在进行的研究工作的最先进技术集成到一个系统中。这里我们列出了一些对 Genesis 项目有贡献的论文(非详尽列表): + +- Xian, Zhou, et al. "Fluidlab: A differentiable environment for benchmarking complex fluid manipulation." arXiv preprint arXiv:2303.02346 (2023). +- Xu, Zhenjia, et al. "Roboninja: Learning an adaptive cutting policy for multi-material objects." arXiv preprint arXiv:2302.11553 (2023). +- Wang, Yufei, et al. "Robogen: Towards unleashing infinite data for automated robot learning via generative simulation." arXiv preprint arXiv:2311.01455 (2023). +- Wang, Tsun-Hsuan, et al. "Softzoo: A soft robot co-design benchmark for locomotion in diverse environments." arXiv preprint arXiv:2303.09555 (2023). +- Wang, Tsun-Hsuan Johnson, et al. "Diffusebot: Breeding soft robots with physics-augmented generative diffusion models." Advances in Neural Information Processing Systems 36 (2023): 44398-44423. +- Katara, Pushkal, Zhou Xian, and Katerina Fragkiadaki. "Gen2sim: Scaling up robot learning in simulation with generative models." 2024 IEEE International Conference on Robotics and Automation (ICRA). IEEE, 2024. +- Si, Zilin, et al. "DiffTactile: A Physics-based Differentiable Tactile Simulator for Contact-rich Robotic Manipulation." arXiv preprint arXiv:2403.08716 (2024). +- Wang, Yian, et al. "Thin-Shell Object Manipulations With Differentiable Physics Simulations." arXiv preprint arXiv:2404.00451 (2024). +- Lin, Chunru, et al. "UBSoft: A Simulation Platform for Robotic Skill Learning in Unbounded Soft Environments." arXiv preprint arXiv:2411.12711 (2024). +- Zhou, Wenyang, et al. "EMDM: Efficient motion diffusion model for fast and high-quality motion generation." European Conference on Computer Vision. Springer, Cham, 2025. +- Qiao, Yi-Ling, Junbang Liang, Vladlen Koltun, and Ming C. Lin. "Scalable differentiable physics for learning and control." International Conference on Machine Learning. PMLR, 2020. +- Qiao, Yi-Ling, Junbang Liang, Vladlen Koltun, and Ming C. Lin. "Efficient differentiable simulation of articulated bodies." In International Conference on Machine Learning, PMLR, 2021. +- Qiao, Yi-Ling, Junbang Liang, Vladlen Koltun, and Ming Lin. "Differentiable simulation of soft multi-body systems." Advances in Neural Information Processing Systems 34 (2021). +- Wan, Weilin, et al. "Tlcontrol: Trajectory and language control for human motion synthesis." arXiv preprint arXiv:2311.17135 (2023). +- Wang, Yian, et al. "Architect: Generating Vivid and Interactive 3D Scenes with Hierarchical 2D Inpainting." arXiv preprint arXiv:2411.09823 (2024). +- Zheng, Shaokun, et al. "LuisaRender: A high-performance rendering framework with layered and unified interfaces on stream architectures." ACM Transactions on Graphics (TOG) 41.6 (2022): 1-19. +- Fan, Yingruo, et al. "Faceformer: Speech-driven 3d facial animation with transformers." Proceedings of the IEEE/CVF Conference on Computer Vision and Pattern Recognition. 2022. +- Wu, Sichun, Kazi Injamamul Haque, and Zerrin Yumak. "ProbTalk3D: Non-Deterministic Emotion Controllable Speech-Driven 3D Facial Animation Synthesis Using VQ-VAE." Proceedings of the 17th ACM SIGGRAPH Conference on Motion, Interaction, and Games. 2024. +- Dou, Zhiyang, et al. "C· ase: Learning conditional adversarial skill embeddings for physics-based characters." SIGGRAPH Asia 2023 Conference Papers. 2023. + +... 以及许多正在进行的工作。 + +## 引用 + +如果您在研究中使用了 Genesis,我们将非常感谢您引用它。我们仍在撰写技术报告,在其公开之前,您可以考虑引用: + +``` +@software{Genesis, + author = {Genesis Authors}, + title = {Genesis: A Universal and Generative Physics Engine for Robotics and Beyond}, + month = {December}, + year = {2024}, + url = {https://github.com/Genesis-Embodied-AI/Genesis} +} +``` From 7f52f40c5fa7803c97243f5ee6376fc8617f19c1 Mon Sep 17 00:00:00 2001 From: Marco Boneberger Date: Fri, 20 Dec 2024 14:12:06 +0100 Subject: [PATCH 02/18] fix cpu arg in cloth_on_rigid.py example --- examples/coupling/cloth_on_rigid.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/coupling/cloth_on_rigid.py b/examples/coupling/cloth_on_rigid.py index cdbc3475..f36dca07 100644 --- a/examples/coupling/cloth_on_rigid.py +++ b/examples/coupling/cloth_on_rigid.py @@ -12,7 +12,7 @@ def main(): args = parser.parse_args() ########################## init ########################## - gs.init(seed=0, precision="32", logging_level="debug") + gs.init(seed=0, precision="32", logging_level="debug", backend=gs.cpu if args.cpu else gs.gpu) scene = gs.Scene( sim_options=gs.options.SimOptions( From 6a36862e53f2eab9b934a18764e5434223a10175 Mon Sep 17 00:00:00 2001 From: JonnyDing <2409104790@qq.com> Date: Sat, 21 Dec 2024 14:59:57 +0800 Subject: [PATCH 03/18] Fix:Remove ANSI sequences and format issues in RBC.__repr --- genesis/datatypes.py | 12 ++++++++---- genesis/options/options.py | 8 ++++++-- genesis/repr_base.py | 12 ++++++++---- 3 files changed, 22 insertions(+), 10 deletions(-) diff --git a/genesis/datatypes.py b/genesis/datatypes.py index 48cce0d3..25f14fdf 100644 --- a/genesis/datatypes.py +++ b/genesis/datatypes.py @@ -42,10 +42,10 @@ def _repr_elem(self, elem, common_length=0): def _repr_elem_colorized(self, elem, common_length=0): content = self._repr_elem(elem, common_length) idx = content.find(">") - formatted_content = f"{colors.BLUE}{formats.ITALIC}{content[:idx+1]}{formats.RESET}{content[idx+1:]}" + formatted_content = f"{colors.BLUE}{formats.ITALIC}{content[:idx + 1]}{formats.RESET}{content[idx + 1:]}" idx = formatted_content.find(":") if idx >= 0: - formatted_content = f"{formatted_content[:idx]}{colors.GRAY}:{colors.MINT}{formatted_content[idx+1:]}" + formatted_content = f"{formatted_content[:idx]}{colors.GRAY}:{colors.MINT}{formatted_content[idx + 1:]}" formatted_content += formats.RESET return formatted_content @@ -73,6 +73,10 @@ def _repr_brief(self): return repr_str def __repr__(self): + if not __debug__: + self.__colorized__repr__() + + def __colorized__repr__(self): repr_str = f"{colors.BLUE}{self._repr_type()}(len={colors.MINT}{formats.UNDERLINE}{len(self)}{formats.RESET}{colors.BLUE}, [" if len(self) == 0: @@ -119,8 +123,8 @@ def __repr__(self): right_line_len = line_len - left_line_len repr_str = ( - f"{colors.CORN}{'─' * left_line_len} {formats.BOLD}{formats.ITALIC}{header}{formats.RESET} {colors.CORN}{'─' * right_line_len}{formats.RESET}\n" - + repr_str + f"{colors.CORN}{'─' * left_line_len} {formats.BOLD}{formats.ITALIC}{header}{formats.RESET} {colors.CORN}{'─' * right_line_len}{formats.RESET}\n" + + repr_str ) return repr_str diff --git a/genesis/options/options.py b/genesis/options/options.py index 746b4fee..cd46cfb1 100644 --- a/genesis/options/options.py +++ b/genesis/options/options.py @@ -43,11 +43,15 @@ def copy_attributes_from(self, options, override=False): def _repr_type(cls): return f"<{cls.__module__}.{cls.__qualname__}>".replace("genesis", "gs") - def __repr__(self) -> str: + def __repr__(self): + if not __debug__: + self.__colorized__repr__() + + def __colorized__repr__(self) -> str: property_attrs = self.__dict__.keys() max_attr_len = max([len(attr) for attr in property_attrs]) - repr_str = f"{colors.CORN}{'─'*(max_attr_len + 3)} {formats.BOLD}{formats.ITALIC}{self._repr_type()}{formats.RESET} {colors.CORN}{'─' * (max_attr_len + 3)}\n" + repr_str = f"{colors.CORN}{'─' * (max_attr_len + 3)} {formats.BOLD}{formats.ITALIC}{self._repr_type()}{formats.RESET} {colors.CORN}{'─' * (max_attr_len + 3)}\n" for attr in property_attrs: formatted_str = f"{colors.BLUE}'{attr}'{formats.RESET}" diff --git a/genesis/repr_base.py b/genesis/repr_base.py index 544519dc..b00e5271 100644 --- a/genesis/repr_base.py +++ b/genesis/repr_base.py @@ -31,7 +31,11 @@ def _repr_brief(self): repr_str += f", material: {self.material}" return repr_str - def __repr__(self) -> str: + def __repr__(self): + if not __debug__: + self.__colorized__repr__() + + def __colorized__repr__(self) -> str: all_attrs = self.__dir__() property_attrs = [] @@ -55,7 +59,7 @@ def __repr__(self) -> str: continue idx = content.find(">") # format with italic and color - formatted_content = f"{colors.MINT}{formats.ITALIC}{content[:idx+1]}{formats.RESET}{colors.MINT}{content[idx+1:]}{formats.RESET}" + formatted_content = f"{colors.MINT}{formats.ITALIC}{content[:idx + 1]}{formats.RESET}{colors.MINT}{content[idx + 1:]}{formats.RESET}" # in case it's multi-line if isinstance(getattr(self, attr), gs.List): # 4 = 2 x ' + : + space @@ -81,8 +85,8 @@ def __repr__(self) -> str: right_line_len = max(right_line_len, min_line_len) repr_str = ( - f"{colors.CORN}{'─'*left_line_len} {formats.BOLD}{formats.ITALIC}{self._repr_type()}{formats.RESET} {colors.CORN}{'─'*right_line_len}\n" - + repr_str + f"{colors.CORN}{'─' * left_line_len} {formats.BOLD}{formats.ITALIC}{self._repr_type()}{formats.RESET} {colors.CORN}{'─' * right_line_len}\n" + + repr_str ) return repr_str From 6c3c9389e1713e4bc4301089fa22aaf218b3c021 Mon Sep 17 00:00:00 2001 From: Zhou Xian Date: Sat, 21 Dec 2024 05:01:40 -0800 Subject: [PATCH 04/18] Update README.md --- README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/README.md b/README.md index 36e0fbd4..e5ab59a4 100644 --- a/README.md +++ b/README.md @@ -47,6 +47,8 @@ pip install genesis-world # Requires Python >=3.9; ``` You also need to install **PyTorch** following the [official instructions](https://pytorch.org/get-started/locally/). +If you would like to try out the latest version, we suggest you to git clone from the repo and do `pip install -e .` instead of via PyPI. + ### Documentation Please refer to our [documentation site](https://genesis-world.readthedocs.io/en/latest/user_guide/index.html) for detailed installation steps, tutorials and API references. From dc7d1e197234e2e0226df69e40fbd09a8807ea3f Mon Sep 17 00:00:00 2001 From: Pieter Becking Date: Sat, 21 Dec 2024 15:31:49 +0100 Subject: [PATCH 05/18] interactive drone controlled - macos --- examples/drone/README.md | 42 ++++++++ examples/drone/fly.py | 11 +- examples/drone/interactive_drone.py | 162 ++++++++++++++++++++++++++++ 3 files changed, 214 insertions(+), 1 deletion(-) create mode 100644 examples/drone/README.md create mode 100644 examples/drone/interactive_drone.py diff --git a/examples/drone/README.md b/examples/drone/README.md new file mode 100644 index 00000000..dbe65f6d --- /dev/null +++ b/examples/drone/README.md @@ -0,0 +1,42 @@ +# Drone Examples + +This directory contains examples of drone simulations using the Genesis framework. + +## Available Examples + +### 1. Interactive Drone (`interactive_drone.py`) +A real-time interactive drone simulation where you can control the drone using keyboard inputs: +- ↑ (Up Arrow): Move Forward (North) +- ↓ (Down Arrow): Move Backward (South) +- ← (Left Arrow): Move Left (West) +- → (Right Arrow): Move Right (East) +- ESC: Quit + +Run with: +```bash +python interactive_drone.py -v +``` + +### 2. Automated Flight (`fly.py`) +A pre-programmed drone flight simulation that follows a predefined trajectory stored in `fly_traj.pkl`. + +Run with: +```bash +python fly.py -v # -v flag enables visualization +``` + +## Technical Details + +- The drone model used is the Crazyflie 2.X (`urdf/drones/cf2x.urdf`) +- Base hover RPM is approximately 14468 +- Movement is achieved by varying individual rotor RPMs to create directional thrust +- The simulation uses realistic physics including gravity and aerodynamics +- Visualization is optimized for macOS using threaded rendering + +## Controls Implementation + +The interactive drone uses differential RPM control: +- Forward/Backward movement: Adjusts front/back rotor pairs +- Left/Right movement: Adjusts left/right rotor pairs +- All movements maintain a stable hover while creating directional thrust +- RPM changes are automatically clipped to safe ranges (0-25000 RPM) \ No newline at end of file diff --git a/examples/drone/fly.py b/examples/drone/fly.py index 693fd11e..3df7406e 100644 --- a/examples/drone/fly.py +++ b/examples/drone/fly.py @@ -8,7 +8,6 @@ def main(): - parser = argparse.ArgumentParser() parser.add_argument("-v", "--vis", action="store_true", default=False) args = parser.parse_args() @@ -45,11 +44,21 @@ def main(): ########################## build ########################## scene.build() + + gs.tools.run_in_another_thread(fn=run_sim, args=(scene, drone, args.vis)) + if args.vis: + scene.viewer.start() + + +def run_sim(scene, drone, enable_vis): traj = pkl.load(open(os.path.join(os.path.dirname(os.path.abspath(__file__)), "fly_traj.pkl"), "rb")) for i in range(len(traj)): # 14468 is hover rpm drone.set_propellels_rpm((1 + 0.05 * traj[i]) * 14468.429183500699) scene.step() + + if enable_vis: + scene.viewer.stop() if __name__ == "__main__": diff --git a/examples/drone/interactive_drone.py b/examples/drone/interactive_drone.py new file mode 100644 index 00000000..5d8887f1 --- /dev/null +++ b/examples/drone/interactive_drone.py @@ -0,0 +1,162 @@ +import argparse +import numpy as np +import genesis as gs +import time +import threading +from pynput import keyboard + +class DroneController: + def __init__(self): + self.thrust = 14468.429183500699 # Base hover RPM - constant hover + self.rotation_delta = 200 # Differential RPM for rotation + self.running = True + self.rpms = [self.thrust] * 4 + self.pressed_keys = set() + + def on_press(self, key): + try: + if key == keyboard.Key.esc: + self.running = False + return False + self.pressed_keys.add(key) + print(f"Key pressed: {key}") + except AttributeError: + pass + + def on_release(self, key): + try: + self.pressed_keys.discard(key) + except KeyError: + pass + + def update_thrust(self): + # Store previous RPMs for debugging + prev_rpms = self.rpms.copy() + + # Reset RPMs to hover thrust + self.rpms = [self.thrust] * 4 + + # Forward (North) - Front rotors spin faster + if keyboard.Key.up in self.pressed_keys: + self.rpms[0] += self.rotation_delta # Front left + self.rpms[1] += self.rotation_delta # Front right + self.rpms[2] -= self.rotation_delta # Back left + self.rpms[3] -= self.rotation_delta # Back right + print("Moving Forward") + + # Backward (South) - Back rotors spin faster + if keyboard.Key.down in self.pressed_keys: + self.rpms[0] -= self.rotation_delta # Front left + self.rpms[1] -= self.rotation_delta # Front right + self.rpms[2] += self.rotation_delta # Back left + self.rpms[3] += self.rotation_delta # Back right + print("Moving Backward") + + # Left (West) - Left rotors spin faster + if keyboard.Key.left in self.pressed_keys: + self.rpms[0] += self.rotation_delta # Front left + self.rpms[2] += self.rotation_delta # Back left + self.rpms[1] -= self.rotation_delta # Front right + self.rpms[3] -= self.rotation_delta # Back right + print("Moving Left") + + # Right (East) - Right rotors spin faster + if keyboard.Key.right in self.pressed_keys: + self.rpms[0] -= self.rotation_delta # Front left + self.rpms[2] -= self.rotation_delta # Back left + self.rpms[1] += self.rotation_delta # Front right + self.rpms[3] += self.rotation_delta # Back right + print("Moving Right") + + self.rpms = np.clip(self.rpms, 0, 25000) + + # Debug print if any RPMs changed + if not np.array_equal(prev_rpms, self.rpms): + print(f"RPMs changed from {prev_rpms} to {self.rpms}") + + return self.rpms + +def run_sim(scene, drone, controller): + while controller.running: + try: + # Update drone with current RPMs + rpms = controller.update_thrust() + drone.set_propellels_rpm(rpms) + # Update physics + scene.step() + time.sleep(1/60) # Limit simulation rate + except Exception as e: + print(f"Error in simulation loop: {e}") + + if scene.viewer: + scene.viewer.stop() + +def main(): + parser = argparse.ArgumentParser() + parser.add_argument("-v", "--vis", action="store_true", default=True, + help="Enable visualization (default: True)") + args = parser.parse_args() + + # Initialize Genesis + gs.init(backend=gs.cpu) + + # Create scene with enhanced camera view + viewer_options = gs.options.ViewerOptions( + camera_pos=(4.0, 0.0, 2.0), + camera_lookat=(0.0, 0.0, 0.5), + camera_fov=45, + max_FPS=60, + ) + + scene = gs.Scene( + sim_options=gs.options.SimOptions( + dt=0.01, + gravity=(0, 0, -9.81), + ), + viewer_options=viewer_options, + show_viewer=args.vis, + ) + + # Add entities + plane = scene.add_entity(gs.morphs.Plane()) + drone = scene.add_entity( + morph=gs.morphs.Drone( + file="urdf/drones/cf2x.urdf", + pos=(0.0, 0, 0.5), # Start a bit higher + ), + ) + + # Build scene + scene.build() + + # Initialize controller + controller = DroneController() + + # Print control instructions + print("\nDrone Controls:") + print("↑ - Move Forward (North)") + print("↓ - Move Backward (South)") + print("← - Move Left (West)") + print("→ - Move Right (East)") + print("ESC - Quit\n") + print("Initial hover RPM:", controller.thrust) + + # Start keyboard listener + listener = keyboard.Listener( + on_press=controller.on_press, + on_release=controller.on_release) + listener.start() + + # Run simulation in another thread + sim_thread = threading.Thread(target=run_sim, args=(scene, drone, controller)) + sim_thread.start() + + if args.vis: + scene.viewer.start() + + # Wait for threads to finish + sim_thread.join() + listener.stop() + +if __name__ == "__main__": + main() \ No newline at end of file From 3377b01493eefadcce702a374bd8f63ed2ec6bd2 Mon Sep 17 00:00:00 2001 From: GengYiran <2000012976@stu.pku.edu.cn> Date: Sun, 22 Dec 2024 01:05:35 +0800 Subject: [PATCH 06/18] support Chinese docs --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index bc423042..c62471fa 100644 --- a/README.md +++ b/README.md @@ -77,7 +77,7 @@ If you would like to try out the latest version, we suggest you to git clone fro ### Documentation -Please refer to our [documentation site](https://genesis-world.readthedocs.io/en/latest/user_guide/index.html) for detailed installation steps, tutorials and API references. +Please refer to our [documentation site (English)](https://genesis-world.readthedocs.io/en/latest/user_guide/index.html) / [(Chinese)](https://genesis-world.readthedocs.io/zh-cn/latest/user_guide/index.html)for detailed installation steps, tutorials and API references. ## Contributing to Genesis From 5f9ab75ff457b21669107f94404e926601635f06 Mon Sep 17 00:00:00 2001 From: GengYiran <2000012976@stu.pku.edu.cn> Date: Sun, 22 Dec 2024 01:08:00 +0800 Subject: [PATCH 07/18] support Chinese docs --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index c62471fa..af7856de 100644 --- a/README.md +++ b/README.md @@ -77,7 +77,7 @@ If you would like to try out the latest version, we suggest you to git clone fro ### Documentation -Please refer to our [documentation site (English)](https://genesis-world.readthedocs.io/en/latest/user_guide/index.html) / [(Chinese)](https://genesis-world.readthedocs.io/zh-cn/latest/user_guide/index.html)for detailed installation steps, tutorials and API references. +Please refer to our [documentation site (English)](https://genesis-world.readthedocs.io/en/latest/user_guide/index.html) / [(Chinese)](https://genesis-world.readthedocs.io/zh-cn/latest/user_guide/index.html) for detailed installation steps, tutorials and API references. ## Contributing to Genesis From 0fb072fa1d0ef9eda4d3661c43503f8ce5967990 Mon Sep 17 00:00:00 2001 From: GengYiran <2000012976@stu.pku.edu.cn> Date: Sun, 22 Dec 2024 01:10:59 +0800 Subject: [PATCH 08/18] support Chinese docs for CN README --- README_CN.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README_CN.md b/README_CN.md index 4236ecbf..bcc44926 100644 --- a/README_CN.md +++ b/README_CN.md @@ -75,7 +75,7 @@ pip install genesis-world # 需要 Python >=3.9; ### 文档 -请参阅我们的 [文档网站](https://genesis-world.readthedocs.io/en/latest/user_guide/index.html) 以获取详细的安装步骤、教程和 API 参考。 +请参阅我们的 [文档网站(英文)](https://genesis-world.readthedocs.io/en/latest/user_guide/index.html)/[(中文)](https://genesis-world.readthedocs.io/zh-cn/latest/user_guide/index.html)以获取详细的安装步骤、教程和 API 参考。 ## 贡献 Genesis From bf23a04e32288629c2293f17c0f4d756c349a3f9 Mon Sep 17 00:00:00 2001 From: ziyanx02 Date: Sat, 21 Dec 2024 15:15:30 -0500 Subject: [PATCH 09/18] fix set_friction_ratio, add domain randomization example --- examples/rigid/domain_randomization.py | 101 ++++++++++++++++++ .../entities/rigid_entity/rigid_entity.py | 40 ++++++- 2 files changed, 138 insertions(+), 3 deletions(-) create mode 100644 examples/rigid/domain_randomization.py diff --git a/examples/rigid/domain_randomization.py b/examples/rigid/domain_randomization.py new file mode 100644 index 00000000..e8e191b6 --- /dev/null +++ b/examples/rigid/domain_randomization.py @@ -0,0 +1,101 @@ +import argparse + +import numpy as np +import torch + +import genesis as gs + + +def main(): + parser = argparse.ArgumentParser() + parser.add_argument("-v", "--vis", action="store_true", default=False) + args = parser.parse_args() + + ########################## init ########################## + gs.init(seed=0, precision="32", logging_level="debug") + + ########################## create a scene ########################## + scene = gs.Scene( + viewer_options=gs.options.ViewerOptions( + camera_pos=(0.0, -2, 1.5), + camera_lookat=(0.0, 0.0, 0.5), + camera_fov=40, + max_FPS=200, + ), + show_viewer=args.vis, + rigid_options=gs.options.RigidOptions( + dt=0.01, + constraint_solver=gs.constraint_solver.Newton, + ), + ) + + ########################## entities ########################## + scene.add_entity( + gs.morphs.Plane(), + ) + robot = scene.add_entity( + gs.morphs.URDF( + file="urdf/go2/urdf/go2.urdf", + pos=(0, 0, 0.4), + ), + ) + ########################## build ########################## + n_envs = 8 + scene.build(n_envs=n_envs) + + ########################## domain randomization ########################## + robot.set_friction_ratio( + friction_ratio=0.5 + torch.rand(scene.n_envs, robot.n_links), + link_indices=np.arange(0, robot.n_links), + ) + robot.set_mass_shift( + mass_shift=-0.5 + torch.rand(scene.n_envs, robot.n_links), + link_indices=np.arange(0, robot.n_links), + ) + robot.set_COM_shift( + com_shift=-0.05 + 0.1 * torch.rand(scene.n_envs, robot.n_links, 3), + link_indices=np.arange(0, robot.n_links), + ) + + joint_names = [ + "FR_hip_joint", + "FR_thigh_joint", + "FR_calf_joint", + "FL_hip_joint", + "FL_thigh_joint", + "FL_calf_joint", + "RR_hip_joint", + "RR_thigh_joint", + "RR_calf_joint", + "RL_hip_joint", + "RL_thigh_joint", + "RL_calf_joint", + ] + motor_dofs = [robot.get_joint(name).dof_idx_local for name in joint_names] + + robot.set_dofs_kp(np.full(12, 20), motor_dofs) + robot.set_dofs_kv(np.full(12, 1), motor_dofs) + default_dof_pos = np.array( + [ + 0.0, + 0.8, + -1.5, + 0.0, + 0.8, + -1.5, + 0.0, + 1.0, + -1.5, + 0.0, + 1.0, + -1.5, + ] + ) + robot.control_dofs_position(default_dof_pos, motor_dofs) + + for i in range(1000): + scene.step() + + +if __name__ == "__main__": + main() diff --git a/genesis/engine/entities/rigid_entity/rigid_entity.py b/genesis/engine/entities/rigid_entity/rigid_entity.py index 83c8272f..0517c80a 100644 --- a/genesis/engine/entities/rigid_entity/rigid_entity.py +++ b/genesis/engine/entities/rigid_entity/rigid_entity.py @@ -2182,6 +2182,10 @@ def set_friction_ratio(self, friction_ratio, link_indices, envs_idx=None): envs_idx : None | array_like, optional The indices of the environments. If None, all environments will be considered. Defaults to None. """ + geom_indices = [] + for i in link_indices: + for j in range(self._links[i].n_geoms): + geom_indices.append(self._links[i]._geom_start + j) self._solver.set_geoms_friction_ratio( torch.cat( [ @@ -2190,9 +2194,7 @@ def set_friction_ratio(self, friction_ratio, link_indices, envs_idx=None): ], dim=-1, ), - torch.tensor( - [[self._links[j]._geom_start + i for i in range(self._links[j].n_geoms)] for j in link_indices] - ).view(-1), + geom_indices, envs_idx, ) @@ -2217,6 +2219,38 @@ def set_friction(self, friction): for link in self._links: link.set_friction(friction) + def set_mass_shift(self, mass_shift, link_indices, envs_idx=None): + """ + Set the mass shift of specified links. + Parameters + ---------- + mass : torch.Tensor, shape (n_envs, n_links) + The mass shift + link_indices : array_like + The indices of the links to set mass shift. + envs_idx : None | array_like, optional + The indices of the environments. If None, all environments will be considered. Defaults to None. + """ + for i in range(len(link_indices)): + link_indices[i] += self._link_start + self._solver.set_links_mass_shift(mass_shift, link_indices, envs_idx) + + def set_COM_shift(self, com_shift, link_indices, envs_idx=None): + """ + Set the center of mass (COM) shift of specified links. + Parameters + ---------- + com : torch.Tensor, shape (n_envs, n_links, 3) + The COM shift + link_indices : array_like + The indices of the links to set COM shift. + envs_idx : None | array_like, optional + The indices of the environments. If None, all environments will be considered. Defaults to None. + """ + for i in range(len(link_indices)): + link_indices[i] += self._link_start + self._solver.set_links_COM_shift(com_shift, link_indices, envs_idx) + @gs.assert_built def get_mass(self): """ From a3f2cfafbbffb15fbaca534f65ebac8816cad36c Mon Sep 17 00:00:00 2001 From: YilingQiao Date: Sat, 21 Dec 2024 17:55:09 -0500 Subject: [PATCH 10/18] add api for set global solver parameters --- .../solvers/rigid/constraint_solver_decomp.py | 12 ++------- .../rigid/constraint_solver_decomp_island.py | 11 ++------ .../solvers/rigid/rigid_solver_decomp.py | 25 ++++++++++++++++++- genesis/utils/geom.py | 4 +-- 4 files changed, 30 insertions(+), 22 deletions(-) diff --git a/genesis/engine/solvers/rigid/constraint_solver_decomp.py b/genesis/engine/solvers/rigid/constraint_solver_decomp.py index 592200e0..c680c31f 100644 --- a/genesis/engine/solvers/rigid/constraint_solver_decomp.py +++ b/genesis/engine/solvers/rigid/constraint_solver_decomp.py @@ -168,10 +168,7 @@ def add_collision_constraints(self): if ti.static(self.sparse_solve): self.jac_n_relevant_dofs[n_con, i_b] = con_n_relevant_dofs - - imp, aref = gu.imp_aref( - self._solver._sol_contact_resolve_time, impact.sol_params, -impact.penetration, jac_qvel - ) + imp, aref = gu.imp_aref(impact.sol_params, -impact.penetration, jac_qvel) diag = t + impact.friction * impact.friction * t diag *= 2 * impact.friction * impact.friction * (1 - imp) / ti.max(imp, gs.EPS) @@ -199,12 +196,7 @@ def add_joint_limit_constraints(self): jac = side jac_qvel = jac * self._solver.dofs_state[i_d, i_b].vel - imp, aref = gu.imp_aref( - self._solver._sol_contact_resolve_time, - self._solver.dofs_info[i_d].sol_params, - pos, - jac_qvel, - ) + imp, aref = gu.imp_aref(self._solver.dofs_info[i_d].sol_params, pos, jac_qvel) diag = self._solver.dofs_info[i_d].invweight * (pos < 0) * (1 - imp) / (imp + gs.EPS) aref = aref * (pos < 0) if pos < 0: diff --git a/genesis/engine/solvers/rigid/constraint_solver_decomp_island.py b/genesis/engine/solvers/rigid/constraint_solver_decomp_island.py index 1e67dc67..e33867a0 100644 --- a/genesis/engine/solvers/rigid/constraint_solver_decomp_island.py +++ b/genesis/engine/solvers/rigid/constraint_solver_decomp_island.py @@ -195,9 +195,7 @@ def add_collision_constraints(self, island, i_b): if ti.static(self.sparse_solve): self.jac_n_relevant_dofs[n_con, i_b] = con_n_relevant_dofs - imp, aref = gu.imp_aref( - self._solver._sol_contact_resolve_time, impact.sol_params, -impact.penetration, jac_qvel - ) + imp, aref = gu.imp_aref(impact.sol_params, -impact.penetration, jac_qvel) diag = t + impact.friction * impact.friction * t diag *= 2 * impact.friction * impact.friction * (1 - imp) / ti.max(imp, gs.EPS) @@ -235,12 +233,7 @@ def add_joint_limit_constraints(self, island, i_b): jac = side jac_qvel = jac * self._solver.dofs_state[i_d, i_b].vel - imp, aref = gu.imp_aref( - self._solver._sol_contact_resolve_time, - self._solver.dofs_info[i_d].sol_params, - pos, - jac_qvel, - ) + imp, aref = gu.imp_aref(self._solver.dofs_info[i_d].sol_params, pos, jac_qvel) diag = self._solver.dofs_info[i_d].invweight * (pos < 0) * (1 - imp) / (imp + gs.EPS) aref = aref * (pos < 0) if pos < 0: diff --git a/genesis/engine/solvers/rigid/rigid_solver_decomp.py b/genesis/engine/solvers/rigid/rigid_solver_decomp.py index 0e0786b3..a6abeb53 100644 --- a/genesis/engine/solvers/rigid/rigid_solver_decomp.py +++ b/genesis/engine/solvers/rigid/rigid_solver_decomp.py @@ -351,7 +351,7 @@ def _kernel_init_dof_fields( for j in ti.static(range(7)): self.dofs_info[i].sol_params[j] = dofs_sol_params[i, j] - self.dofs_info[i].sol_params[0] = self._substep_dt * 2 + self.dofs_info[i].sol_params[0] = self._sol_contact_resolve_time self.dofs_info[i].armature = dofs_armature[i] self.dofs_info[i].invweight = dofs_invweight[i] @@ -776,6 +776,7 @@ def _kernel_init_geom_fields( for j in ti.static(range(7)): self.geoms_info[i].data[j] = geoms_data[i, j] self.geoms_info[i].sol_params[j] = geoms_sol_params[i, j] + self.geoms_info[i].sol_params[0] = self._sol_contact_resolve_time self.geoms_info[i].sol_params[0] = ti.max(self.geoms_info[i].sol_params[0], self._substep_dt * 2) @@ -3319,6 +3320,28 @@ def _kernel_set_qpos( for i_q_, i_b_ in ti.ndrange(qs_idx.shape[0], envs_idx.shape[0]): self.qpos[qs_idx[i_q_], envs_idx[i_b_]] = qpos[i_b_, i_q_] + def set_global_sol_params(self, sol_params): + """ + Solver parameters (timeconst, dampratio, dmin, dmax, width, mid, power). + Reference: https://mujoco.readthedocs.io/en/latest/modeling.html#solver-parameters + """ + assert len(sol_params) == 7 + self._kernel_set_global_sol_params(sol_params) + + @ti.kernel + def _kernel_set_global_sol_params(self, sol_params: ti.types.ndarray()): + ti.loop_config(serialize=self._para_level < gs.PARA_LEVEL.PARTIAL) + for i in range(self.n_geoms): + for j in ti.static(range(7)): + self.geoms_info[i].sol_params[j] = sol_params[j] + + ti.loop_config(serialize=self._para_level < gs.PARA_LEVEL.PARTIAL) + for i, b in ti.ndrange(self.n_dofs, self._B): + for j in ti.static(range(7)): + self.dofs_info[i].sol_params[j] = sol_params[j] + + self.dofs_info[i].sol_params[0] = self._substep_dt * 2 + def set_dofs_kp(self, kp, dofs_idx): kp, dofs_idx = self._validate_1D_io_variables(kp, dofs_idx, batched=False) self._kernel_set_dofs_kp(kp, dofs_idx) diff --git a/genesis/utils/geom.py b/genesis/utils/geom.py index c272b1f1..acfd6518 100644 --- a/genesis/utils/geom.py +++ b/genesis/utils/geom.py @@ -306,9 +306,9 @@ def orthogonals2(a): @ti.func -def imp_aref(timeconst, params, pos, vel): +def imp_aref(params, pos, vel): # The first term in parms is the timeconst parsed from mjcf. However, we don't use it here but use the one passed in, which is 2*substep_dt. - _, dampratio, dmin, dmax, width, mid, power = params + timeconst, dampratio, dmin, dmax, width, mid, power = params imp_x = ti.abs(pos) / width imp_a = (1.0 / mid ** (power - 1)) * imp_x**power imp_b = 1 - (1.0 / (1 - mid) ** (power - 1)) * (1 - imp_x) ** power From 60ee0165ad681e40a8752b64d4be2ba1b43a3d8e Mon Sep 17 00:00:00 2001 From: YilingQiao Date: Sat, 21 Dec 2024 23:19:05 -0500 Subject: [PATCH 11/18] support linux and delete pickle --- examples/drone/fly.py | 176 ++++++++++++++++++++++++++-- examples/drone/fly_traj.pkl | Bin 2584 -> 0 bytes examples/drone/interactive_drone.py | 68 ++++++----- 3 files changed, 204 insertions(+), 40 deletions(-) delete mode 100644 examples/drone/fly_traj.pkl diff --git a/examples/drone/fly.py b/examples/drone/fly.py index 3df7406e..f017077f 100644 --- a/examples/drone/fly.py +++ b/examples/drone/fly.py @@ -1,7 +1,4 @@ import argparse -import os -import pickle as pkl - import numpy as np import genesis as gs @@ -10,6 +7,7 @@ def main(): parser = argparse.ArgumentParser() parser.add_argument("-v", "--vis", action="store_true", default=False) + parser.add_argument("-m", "--mac", action="store_true", default=False) args = parser.parse_args() ########################## init ########################## @@ -44,19 +42,179 @@ def main(): ########################## build ########################## scene.build() - - gs.tools.run_in_another_thread(fn=run_sim, args=(scene, drone, args.vis)) - if args.vis: - scene.viewer.start() + + if args.mac: + gs.tools.run_in_another_thread(fn=run_sim, args=(scene, drone, args.vis)) + if args.vis: + scene.viewer.start() + else: + run_sim(scene, drone, args.vis) def run_sim(scene, drone, enable_vis): - traj = pkl.load(open(os.path.join(os.path.dirname(os.path.abspath(__file__)), "fly_traj.pkl"), "rb")) + traj = np.array( + [ + [1.0, 1.0, 0.98824805, 1.0], + [0.67815816, 1.0, 1.0, 1.0], + [1.0, 0.87905186, 0.8319297, 1.0], + [1.0, 0.85295373, 0.94554883, 1.0], + [1.0, 1.0, 0.9663153, 1.0], + [1.0, 1.0, 1.0, 1.0], + [1.0, 1.0, 1.0, 1.0], + [1.0, 1.0, 1.0, 1.0], + [1.0, 1.0, 1.0, 1.0], + [1.0, 1.0, 1.0, 1.0], + [1.0, 1.0, 1.0, 1.0], + [1.0, 1.0, 1.0, 1.0], + [1.0, 1.0, 1.0, 1.0], + [1.0, 1.0, 1.0, 1.0], + [1.0, 1.0, 1.0, 1.0], + [1.0, 1.0, 1.0, 1.0], + [1.0, 1.0, 1.0, 1.0], + [1.0, 1.0, 1.0, 1.0], + [1.0, 1.0, 1.0, 1.0], + [1.0, 1.0, 1.0, 1.0], + [1.0, 1.0, 1.0, 1.0], + [1.0, 1.0, 1.0, 1.0], + [1.0, 1.0, 1.0, 1.0], + [1.0, 1.0, 1.0, 1.0], + [1.0, 1.0, 1.0, 1.0], + [1.0, 1.0, 1.0, 1.0], + [1.0, 1.0, 1.0, 1.0], + [1.0, 1.0, 1.0, 1.0], + [1.0, 1.0, 1.0, 1.0], + [1.0, 1.0, 1.0, 1.0], + [1.0, 1.0, 1.0, 1.0], + [1.0, 1.0, 1.0, 1.0], + [1.0, 1.0, 1.0, 1.0], + [1.0, 1.0, 1.0, 1.0], + [1.0, 1.0, 1.0, 1.0], + [1.0, 1.0, 1.0, 1.0], + [1.0, 1.0, 1.0, 1.0], + [1.0, 0.9954323, 1.0, 1.0], + [1.0, 0.9974212, 1.0, 1.0], + [1.0, 0.99529535, 1.0, 1.0], + [1.0, 0.9965133, 1.0, 1.0], + [1.0, 0.99495167, 1.0, 1.0], + [1.0, 0.99533206, 1.0, 1.0], + [1.0, 0.9941533, 1.0, 1.0], + [1.0, 0.9937679, 1.0, 1.0], + [1.0, 0.9926078, 1.0, 1.0], + [1.0, 0.99150425, 1.0, 1.0], + [1.0, 0.9899133, 1.0, 1.0], + [1.0, 0.9879518, 1.0, 1.0], + [1.0, 0.985401, 1.0, 0.93023926], + [1.0, 0.9757207, 1.0, 0.8165948], + [1.0, 0.94503635, 1.0, 0.47085124], + [1.0, 0.9973584, 1.0, 0.92234856], + [1.0, 0.97841257, 1.0, 0.9260282], + [1.0, 0.9749091, 1.0, 0.8766382], + [1.0, 0.9661152, 1.0, 0.8508391], + [1.0, 0.9588664, 1.0, 0.8184431], + [1.0, 0.9513355, 1.0, 0.78656846], + [1.0, 0.9438352, 1.0, 0.7555151], + [1.0, 0.9364986, 1.0, 0.7264303], + [1.0, 0.92944163, 1.0, 0.70034355], + [1.0, 0.9227477, 1.0, 0.6780561], + [1.0, 0.91646177, 1.0, 0.6601221], + [1.0, 0.91059643, 1.0, 0.6468646], + [1.0, 0.90513545, 1.0, 0.6384181], + [1.0, 0.9000414, 1.0, 0.63476765], + [1.0, 0.8952549, 1.0, 0.6357777], + [1.0, 0.89069635, 1.0, 0.64121217], + [1.0, 0.8862596, 1.0, 0.6507421], + [1.0, 0.8818036, 1.0, 0.66393715], + [1.0, 0.8771375, 1.0, 0.68025357], + [1.0, 0.8720022, 1.0, 0.6990145], + [1.0, 0.8660441, 1.0, 0.719399], + [1.0, 0.85878307, 1.0, 0.7404561], + [1.0, 0.84957653, 1.0, 0.7611621], + [1.0, 0.83757895, 1.0, 0.78056324], + [1.0, 0.8216941, 1.0, 0.7980228], + [1.0, 0.8005113, 1.0, 0.8135467], + [0.99108833, 0.77218705, 1.0, 0.828064], + [0.97618765, 0.7336579, 1.0, 0.8425417], + [0.9570234, 0.6814261, 1.0, 0.8581086], + [0.92717046, 0.6107281, 1.0, 0.8740242], + [0.87264377, 0.51361734, 1.0, 0.8831364], + [0.7667494, 0.37425363, 1.0, 0.86565703], + [0.58684665, 0.15105894, 1.0, 0.792903], + [0.40309954, -0.22192897, 1.0, 0.6778493], + [0.30307913, -0.6645406, 0.32032692, 0.5561814], + [0.1432502, -1.0, -0.7834326, 0.30731094], + [-0.05076139, -1.0, -1.0, -0.18850122], + [-0.2028995, -1.0, -1.0, -0.47833002], + [-0.33243275, -1.0, -1.0, -0.63186795], + [-0.43252927, -1.0, -0.93684345, -0.7109936], + [-0.50198543, -1.0, -0.8966909, -0.7451998], + [-0.55477273, -1.0, -0.87718576, -0.7572431], + [-0.59963316, -1.0, -0.8707306, -0.7596289], + [-0.641077, -1.0, -0.8736891, -0.7593429], + [-0.68137753, -1.0, -0.8838504, -0.76042706], + [-0.72137207, -1.0, -0.8991675, -0.7649133], + [-0.76085263, -1.0, -0.9172805, -0.77330756], + [-0.7989401, -1.0, -0.93559915, -0.78509957], + [-0.8345167, -1.0, -0.95170647, -0.799334], + [-0.86661166, -1.0, -0.963775, -0.8150858], + [-0.8946256, -1.0, -0.97078484, -0.8317086], + [-0.91837806, -1.0, -0.97249895, -0.84885603], + [-0.9380378, -1.0, -0.96929866, -0.8663847], + [-0.9540071, -1.0, -0.96197397, -0.8842322], + [-0.9668097, -1.0, -0.9515317, -0.90233094], + [-0.97700363, -1.0, -0.9390431, -0.9205734], + [-0.98512334, -1.0, -0.92553586, -0.93881696], + [-0.99164504, -1.0, -0.91191846, -0.9569116], + [-0.99697274, -1.0, -0.8989406, -0.97473806], + [-1.0, -1.0, -0.8871773, -0.99223274], + [-1.0, -1.0, -0.87696224, -1.0], + [-1.0, -1.0, -0.86855894, -1.0], + [-1.0, -1.0, -0.8622101, -1.0], + [-1.0, -1.0, -0.85795015, -1.0], + [-1.0, -1.0, -0.8557587, -1.0], + [-1.0, -1.0, -0.8555704, -1.0], + [-1.0, -1.0, -0.8572821, -1.0], + [-1.0, -1.0, -0.860755, -1.0], + [-1.0, -1.0, -0.8658133, -1.0], + [-1.0, -1.0, -0.87224096, -1.0], + [-1.0, -1.0, -0.87977535, -1.0], + [-1.0, -1.0, -0.8881058, -1.0], + [-1.0, -1.0, -0.89687437, -1.0], + [-1.0, -1.0, -0.9056818, -1.0], + [-1.0, -1.0, -0.91409653, -1.0], + [-1.0, -1.0, -0.9216669, -1.0], + [-1.0, -1.0, -0.9279278, -1.0], + [-1.0, -1.0, -0.93239695, -1.0], + [-0.9961943, -1.0, -0.9345514, -1.0], + [-0.9834586, -1.0, -0.93362767, -1.0], + [-0.9671113, -1.0, -0.9284645, -1.0], + [-0.94588476, -1.0, -0.91775376, -1.0], + [-0.91785616, -1.0, -0.8995549, -1.0], + [-0.88016766, -1.0, -0.87093955, -1.0], + [-0.8287441, -1.0, -0.82749766, -1.0], + [-0.7582472, -1.0, -0.76269644, -1.0], + [-0.66290134, -1.0, -0.66715723, -1.0], + [-0.5392508, -1.0, -0.5280629, -1.0], + [-0.39078623, -1.0, -0.3290425, -1.0], + [-0.2295668, -1.0, -0.05206226, -1.0], + [-0.06826158, -1.0, 0.30915332, -1.0], + [0.08895309, -1.0, 0.7070197, -1.0], + [0.2400503, -1.0, 1.0, -1.0], + [0.3742329, -1.0, 1.0, -1.0], + [0.48094982, -1.0, 1.0, -1.0], + [0.56609666, -1.0, 1.0, -1.0], + [0.63677347, -0.88508135, 1.0, -1.0], + [0.7058708, -0.694147, 1.0, -1.0], + [0.7992784, -0.5113944, 1.0, -1.0], + [0.9422653, -0.2919022, 1.0, -1.0], + ], + dtype=np.float32, + ) + for i in range(len(traj)): # 14468 is hover rpm drone.set_propellels_rpm((1 + 0.05 * traj[i]) * 14468.429183500699) scene.step() - + if enable_vis: scene.viewer.stop() diff --git a/examples/drone/fly_traj.pkl b/examples/drone/fly_traj.pkl deleted file mode 100644 index 1ba9e934c367a758fe48e123fc196e7ea85f4058..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2584 zcmeH}`%jZs7{@6$0|;XyxS*&*@B$G!6c;+AXB5rE5^!9F0)>{s0862iOOZ--VZx{* z3ooJ}$aFKCI);R(afzG-c5!o45gh^D4}=*8#2MTelIa-l_k?EWZ`j`C?dN=+=iJ_N zNosX&^K^H>WAiPo)R&pVv<9OtOka7xRFr2l=9vZCO0`j^HI!DEjFnoG&??wmP*Je0 zD9vY8S_P#;gAgmx2uFn^VT)3tJfU=cS9sgW=8|tRm+8btjs+1yQzOee*(5uKgoK2> zi%SoFlny3A)1@g06%2Y%BL3NFV*HoN7K{R=7fc&I9qSY9yNU93}{Tg~~u z+y7r?Yy4kXhfnSv;?BZiT0Q68H~4)08a}`I5})_I$@@Jk@2!QrH?QGcHf-U>pDX6Q zXquh<<^73{WgZ+x!MsV(OA(&$b1lJZ7fE%nEK)qB4rVKFecFu<%+!O>( zjcY)+_D$gUwLI{<`C!o3#=hHcV;H9Pw-q(>$+M-sGZ9S{uy?^Z` z-rAe;j2LadcrF@`hLTr9JLIYBL+CG(kL8njUL@?|OJZH>-m-^2Nbi(yok_eVy7*SR z#`I5ol_<7_e>V9?|A!Ih?d~@aKx<7u!x!!vXt&dAblnjL)NMMZqs3p#>2Vh?IBChH zJ!3Jn<**-o`>#3Fy;?!L)&{{}KChJt~$7?p@!a{ zPNBoAOW?h8HS}~s1|@-ItbSk()!xXaw`3;xqu46yk*%R4)@pcLdj$<%ETB{VweSF4 z8SOh?LOsIk;4_a8(8RPdTJgXFw^S6-;HM_qA*+Wkyi!07jb@a^_4Qn*rSp!5?0(Xk zYcGrW@r)eKf4rK-dDj^g=Mo>@&$;qGQpJ0DCg0!eS+;J=doNY0x&G%O^EjW()Njo-#(o6(D{giG9bzIkvv7TT&38_$e8*__Ooo^F}OuvM(4M`aT3qU+E48 zNLPRxe6Qm^C~7_hTYO5uog@|a>Wd$m!ToWk diff --git a/examples/drone/interactive_drone.py b/examples/drone/interactive_drone.py index 5d8887f1..276dff73 100644 --- a/examples/drone/interactive_drone.py +++ b/examples/drone/interactive_drone.py @@ -5,6 +5,7 @@ import threading from pynput import keyboard + class DroneController: def __init__(self): self.thrust = 14468.429183500699 # Base hover RPM - constant hover @@ -12,7 +13,7 @@ def __init__(self): self.running = True self.rpms = [self.thrust] * 4 self.pressed_keys = set() - + def on_press(self, key): try: if key == keyboard.Key.esc: @@ -32,10 +33,10 @@ def on_release(self, key): def update_thrust(self): # Store previous RPMs for debugging prev_rpms = self.rpms.copy() - + # Reset RPMs to hover thrust self.rpms = [self.thrust] * 4 - + # Forward (North) - Front rotors spin faster if keyboard.Key.up in self.pressed_keys: self.rpms[0] += self.rotation_delta # Front left @@ -43,7 +44,7 @@ def update_thrust(self): self.rpms[2] -= self.rotation_delta # Back left self.rpms[3] -= self.rotation_delta # Back right print("Moving Forward") - + # Backward (South) - Back rotors spin faster if keyboard.Key.down in self.pressed_keys: self.rpms[0] -= self.rotation_delta # Front left @@ -51,7 +52,7 @@ def update_thrust(self): self.rpms[2] += self.rotation_delta # Back left self.rpms[3] += self.rotation_delta # Back right print("Moving Backward") - + # Left (West) - Left rotors spin faster if keyboard.Key.left in self.pressed_keys: self.rpms[0] += self.rotation_delta # Front left @@ -59,7 +60,7 @@ def update_thrust(self): self.rpms[1] -= self.rotation_delta # Front right self.rpms[3] -= self.rotation_delta # Back right print("Moving Left") - + # Right (East) - Right rotors spin faster if keyboard.Key.right in self.pressed_keys: self.rpms[0] -= self.rotation_delta # Front left @@ -67,15 +68,16 @@ def update_thrust(self): self.rpms[1] += self.rotation_delta # Front right self.rpms[3] += self.rotation_delta # Back right print("Moving Right") - + self.rpms = np.clip(self.rpms, 0, 25000) - + # Debug print if any RPMs changed if not np.array_equal(prev_rpms, self.rpms): print(f"RPMs changed from {prev_rpms} to {self.rpms}") - + return self.rpms + def run_sim(scene, drone, controller): while controller.running: try: @@ -84,22 +86,23 @@ def run_sim(scene, drone, controller): drone.set_propellels_rpm(rpms) # Update physics scene.step() - time.sleep(1/60) # Limit simulation rate + time.sleep(1 / 60) # Limit simulation rate except Exception as e: print(f"Error in simulation loop: {e}") - + if scene.viewer: scene.viewer.stop() + def main(): parser = argparse.ArgumentParser() - parser.add_argument("-v", "--vis", action="store_true", default=True, - help="Enable visualization (default: True)") + parser.add_argument("-v", "--vis", action="store_true", default=True, help="Enable visualization (default: True)") + parser.add_argument("-m", "--mac", action="store_true", default=False, help="Running on MacOS (default: False)") args = parser.parse_args() # Initialize Genesis gs.init(backend=gs.cpu) - + # Create scene with enhanced camera view viewer_options = gs.options.ViewerOptions( camera_pos=(4.0, 0.0, 2.0), @@ -128,10 +131,10 @@ def main(): # Build scene scene.build() - + # Initialize controller controller = DroneController() - + # Print control instructions print("\nDrone Controls:") print("↑ - Move Forward (North)") @@ -140,23 +143,26 @@ def main(): print("→ - Move Right (East)") print("ESC - Quit\n") print("Initial hover RPM:", controller.thrust) - + # Start keyboard listener - listener = keyboard.Listener( - on_press=controller.on_press, - on_release=controller.on_release) + listener = keyboard.Listener(on_press=controller.on_press, on_release=controller.on_release) listener.start() - - # Run simulation in another thread - sim_thread = threading.Thread(target=run_sim, args=(scene, drone, controller)) - sim_thread.start() - - if args.vis: - scene.viewer.start() - - # Wait for threads to finish - sim_thread.join() + + if args.mac: + # Run simulation in another thread + sim_thread = threading.Thread(target=run_sim, args=(scene, drone, controller)) + sim_thread.start() + + if args.vis: + scene.viewer.start() + + # Wait for threads to finish + sim_thread.join() + else: + # Run simulation in main thread + run_sim(scene, drone, controller) listener.stop() + if __name__ == "__main__": - main() \ No newline at end of file + main() From 3201b238656245990cc451f40fa10d0e3ffe018f Mon Sep 17 00:00:00 2001 From: Johnson Wang Date: Sun, 22 Dec 2024 01:45:01 -0500 Subject: [PATCH 12/18] Revert "Merge pull request #186 from JonnyDing/fix/repr-ansi-issue" This reverts commit 31c074d46af142d21992c5497d7a77e46c689fc0, reversing changes made to da3d38ba0962b5b491ca54905c52f022ba19d92e. --- genesis/datatypes.py | 12 ++++-------- genesis/options/options.py | 8 ++------ genesis/repr_base.py | 12 ++++-------- 3 files changed, 10 insertions(+), 22 deletions(-) diff --git a/genesis/datatypes.py b/genesis/datatypes.py index 25f14fdf..48cce0d3 100644 --- a/genesis/datatypes.py +++ b/genesis/datatypes.py @@ -42,10 +42,10 @@ def _repr_elem(self, elem, common_length=0): def _repr_elem_colorized(self, elem, common_length=0): content = self._repr_elem(elem, common_length) idx = content.find(">") - formatted_content = f"{colors.BLUE}{formats.ITALIC}{content[:idx + 1]}{formats.RESET}{content[idx + 1:]}" + formatted_content = f"{colors.BLUE}{formats.ITALIC}{content[:idx+1]}{formats.RESET}{content[idx+1:]}" idx = formatted_content.find(":") if idx >= 0: - formatted_content = f"{formatted_content[:idx]}{colors.GRAY}:{colors.MINT}{formatted_content[idx + 1:]}" + formatted_content = f"{formatted_content[:idx]}{colors.GRAY}:{colors.MINT}{formatted_content[idx+1:]}" formatted_content += formats.RESET return formatted_content @@ -73,10 +73,6 @@ def _repr_brief(self): return repr_str def __repr__(self): - if not __debug__: - self.__colorized__repr__() - - def __colorized__repr__(self): repr_str = f"{colors.BLUE}{self._repr_type()}(len={colors.MINT}{formats.UNDERLINE}{len(self)}{formats.RESET}{colors.BLUE}, [" if len(self) == 0: @@ -123,8 +119,8 @@ def __colorized__repr__(self): right_line_len = line_len - left_line_len repr_str = ( - f"{colors.CORN}{'─' * left_line_len} {formats.BOLD}{formats.ITALIC}{header}{formats.RESET} {colors.CORN}{'─' * right_line_len}{formats.RESET}\n" - + repr_str + f"{colors.CORN}{'─' * left_line_len} {formats.BOLD}{formats.ITALIC}{header}{formats.RESET} {colors.CORN}{'─' * right_line_len}{formats.RESET}\n" + + repr_str ) return repr_str diff --git a/genesis/options/options.py b/genesis/options/options.py index cd46cfb1..746b4fee 100644 --- a/genesis/options/options.py +++ b/genesis/options/options.py @@ -43,15 +43,11 @@ def copy_attributes_from(self, options, override=False): def _repr_type(cls): return f"<{cls.__module__}.{cls.__qualname__}>".replace("genesis", "gs") - def __repr__(self): - if not __debug__: - self.__colorized__repr__() - - def __colorized__repr__(self) -> str: + def __repr__(self) -> str: property_attrs = self.__dict__.keys() max_attr_len = max([len(attr) for attr in property_attrs]) - repr_str = f"{colors.CORN}{'─' * (max_attr_len + 3)} {formats.BOLD}{formats.ITALIC}{self._repr_type()}{formats.RESET} {colors.CORN}{'─' * (max_attr_len + 3)}\n" + repr_str = f"{colors.CORN}{'─'*(max_attr_len + 3)} {formats.BOLD}{formats.ITALIC}{self._repr_type()}{formats.RESET} {colors.CORN}{'─' * (max_attr_len + 3)}\n" for attr in property_attrs: formatted_str = f"{colors.BLUE}'{attr}'{formats.RESET}" diff --git a/genesis/repr_base.py b/genesis/repr_base.py index b00e5271..544519dc 100644 --- a/genesis/repr_base.py +++ b/genesis/repr_base.py @@ -31,11 +31,7 @@ def _repr_brief(self): repr_str += f", material: {self.material}" return repr_str - def __repr__(self): - if not __debug__: - self.__colorized__repr__() - - def __colorized__repr__(self) -> str: + def __repr__(self) -> str: all_attrs = self.__dir__() property_attrs = [] @@ -59,7 +55,7 @@ def __colorized__repr__(self) -> str: continue idx = content.find(">") # format with italic and color - formatted_content = f"{colors.MINT}{formats.ITALIC}{content[:idx + 1]}{formats.RESET}{colors.MINT}{content[idx + 1:]}{formats.RESET}" + formatted_content = f"{colors.MINT}{formats.ITALIC}{content[:idx+1]}{formats.RESET}{colors.MINT}{content[idx+1:]}{formats.RESET}" # in case it's multi-line if isinstance(getattr(self, attr), gs.List): # 4 = 2 x ' + : + space @@ -85,8 +81,8 @@ def __colorized__repr__(self) -> str: right_line_len = max(right_line_len, min_line_len) repr_str = ( - f"{colors.CORN}{'─' * left_line_len} {formats.BOLD}{formats.ITALIC}{self._repr_type()}{formats.RESET} {colors.CORN}{'─' * right_line_len}\n" - + repr_str + f"{colors.CORN}{'─'*left_line_len} {formats.BOLD}{formats.ITALIC}{self._repr_type()}{formats.RESET} {colors.CORN}{'─'*right_line_len}\n" + + repr_str ) return repr_str From fc51cdea0bb7a9188c90f41d66adcc8b9e0a8cf2 Mon Sep 17 00:00:00 2001 From: Johnson Wang Date: Sun, 22 Dec 2024 02:27:24 -0500 Subject: [PATCH 13/18] fix merge for ci from pr-186 --- genesis/datatypes.py | 8 ++++++-- genesis/options/options.py | 8 ++++++-- genesis/repr_base.py | 10 +++++++--- 3 files changed, 19 insertions(+), 7 deletions(-) diff --git a/genesis/datatypes.py b/genesis/datatypes.py index 48cce0d3..83960362 100644 --- a/genesis/datatypes.py +++ b/genesis/datatypes.py @@ -42,10 +42,10 @@ def _repr_elem(self, elem, common_length=0): def _repr_elem_colorized(self, elem, common_length=0): content = self._repr_elem(elem, common_length) idx = content.find(">") - formatted_content = f"{colors.BLUE}{formats.ITALIC}{content[:idx+1]}{formats.RESET}{content[idx+1:]}" + formatted_content = f"{colors.BLUE}{formats.ITALIC}{content[:idx + 1]}{formats.RESET}{content[idx + 1:]}" idx = formatted_content.find(":") if idx >= 0: - formatted_content = f"{formatted_content[:idx]}{colors.GRAY}:{colors.MINT}{formatted_content[idx+1:]}" + formatted_content = f"{formatted_content[:idx]}{colors.GRAY}:{colors.MINT}{formatted_content[idx + 1:]}" formatted_content += formats.RESET return formatted_content @@ -73,6 +73,10 @@ def _repr_brief(self): return repr_str def __repr__(self): + if not __debug__: + self.__colorized__repr__() + + def __colorized__repr__(self): repr_str = f"{colors.BLUE}{self._repr_type()}(len={colors.MINT}{formats.UNDERLINE}{len(self)}{formats.RESET}{colors.BLUE}, [" if len(self) == 0: diff --git a/genesis/options/options.py b/genesis/options/options.py index 746b4fee..cd46cfb1 100644 --- a/genesis/options/options.py +++ b/genesis/options/options.py @@ -43,11 +43,15 @@ def copy_attributes_from(self, options, override=False): def _repr_type(cls): return f"<{cls.__module__}.{cls.__qualname__}>".replace("genesis", "gs") - def __repr__(self) -> str: + def __repr__(self): + if not __debug__: + self.__colorized__repr__() + + def __colorized__repr__(self) -> str: property_attrs = self.__dict__.keys() max_attr_len = max([len(attr) for attr in property_attrs]) - repr_str = f"{colors.CORN}{'─'*(max_attr_len + 3)} {formats.BOLD}{formats.ITALIC}{self._repr_type()}{formats.RESET} {colors.CORN}{'─' * (max_attr_len + 3)}\n" + repr_str = f"{colors.CORN}{'─' * (max_attr_len + 3)} {formats.BOLD}{formats.ITALIC}{self._repr_type()}{formats.RESET} {colors.CORN}{'─' * (max_attr_len + 3)}\n" for attr in property_attrs: formatted_str = f"{colors.BLUE}'{attr}'{formats.RESET}" diff --git a/genesis/repr_base.py b/genesis/repr_base.py index 544519dc..86f18cf0 100644 --- a/genesis/repr_base.py +++ b/genesis/repr_base.py @@ -31,7 +31,11 @@ def _repr_brief(self): repr_str += f", material: {self.material}" return repr_str - def __repr__(self) -> str: + def __repr__(self): + if not __debug__: + self.__colorized__repr__() + + def __colorized__repr__(self) -> str: all_attrs = self.__dir__() property_attrs = [] @@ -55,7 +59,7 @@ def __repr__(self) -> str: continue idx = content.find(">") # format with italic and color - formatted_content = f"{colors.MINT}{formats.ITALIC}{content[:idx+1]}{formats.RESET}{colors.MINT}{content[idx+1:]}{formats.RESET}" + formatted_content = f"{colors.MINT}{formats.ITALIC}{content[:idx + 1]}{formats.RESET}{colors.MINT}{content[idx + 1:]}{formats.RESET}" # in case it's multi-line if isinstance(getattr(self, attr), gs.List): # 4 = 2 x ' + : + space @@ -81,7 +85,7 @@ def __repr__(self) -> str: right_line_len = max(right_line_len, min_line_len) repr_str = ( - f"{colors.CORN}{'─'*left_line_len} {formats.BOLD}{formats.ITALIC}{self._repr_type()}{formats.RESET} {colors.CORN}{'─'*right_line_len}\n" + f"{colors.CORN}{'─' * left_line_len} {formats.BOLD}{formats.ITALIC}{self._repr_type()}{formats.RESET} {colors.CORN}{'─' * right_line_len}\n" + repr_str ) From 57c6d3c89cdd430be1b3f705ec4d4bdf579cabc1 Mon Sep 17 00:00:00 2001 From: Habermehl <37908699+00make@users.noreply.github.com> Date: Sun, 22 Dec 2024 16:44:42 +0800 Subject: [PATCH 14/18] docs: Update README file to comply with MD033 MD040 writing standards --- README.md | 42 ++++++++++++------------------------------ README_CN.md | 40 +++++++++++----------------------------- 2 files changed, 23 insertions(+), 59 deletions(-) diff --git a/README.md b/README.md index c93440a1..4feee6cc 100644 --- a/README.md +++ b/README.md @@ -1,32 +1,14 @@ -
- Genesis -
- ---- - -
- -
- - - -

- README in English - 简体中文版自述文件 -

+![Genesis](imgs/big_text.png) + +![Teaser](imgs/teaser.png) + +[![PyPI - Version](https://img.shields.io/pypi/v/genesis-world)](https://pypi.org/project/genesis-world/) +[![PyPI - Downloads](https://img.shields.io/pypi/dm/genesis-world)](https://pypi.org/project/genesis-world/) +[![GitHub Issues](https://img.shields.io/github/issues/Genesis-Embodied-AI/Genesis)](https://github.com/Genesis-Embodied-AI/Genesis/issues) +[![GitHub Discussions](https://img.shields.io/github/discussions/Genesis-Embodied-AI/Genesis)](https://github.com/Genesis-Embodied-AI/Genesis/discussions) + +[![README in English](https://img.shields.io/badge/English-d9d9d9)](./README.md) +[![简体中文版自述文件](https://img.shields.io/badge/简体中文-d9d9d9)](./README_CN.md) # What is Genesis? @@ -134,7 +116,7 @@ Genesis is a large scale effort that integrates state-of-the-art technologies of If you used Genesis in your research, we would appreciate it if you could cite it. We are still working on a technical report, and before it's public, you could consider citing: -``` +```bibtex @software{Genesis, author = {Genesis Authors}, title = {Genesis: A Universal and Generative Physics Engine for Robotics and Beyond}, diff --git a/README_CN.md b/README_CN.md index 4236ecbf..e7c68a1d 100644 --- a/README_CN.md +++ b/README_CN.md @@ -1,32 +1,14 @@ -
- Genesis -
- ---- - -
- -
- - - -

- README in English - 简体中文版自述文件 -

+![Genesis](imgs/big_text.png) + +![Teaser](imgs/teaser.png) + +[![PyPI - Version](https://img.shields.io/pypi/v/genesis-world)](https://pypi.org/project/genesis-world/) +[![PyPI - Downloads](https://img.shields.io/pypi/dm/genesis-world)](https://pypi.org/project/genesis-world/) +[![GitHub Issues](https://img.shields.io/github/issues/Genesis-Embodied-AI/Genesis)](https://github.com/Genesis-Embodied-AI/Genesis/issues) +[![GitHub Discussions](https://img.shields.io/github/discussions/Genesis-Embodied-AI/Genesis)](https://github.com/Genesis-Embodied-AI/Genesis/discussions) + +[![README in English](https://img.shields.io/badge/English-d9d9d9)](./README.md) +[![简体中文版自述文件](https://img.shields.io/badge/简体中文-d9d9d9)](./README_CN.md) # 概述 From 51732a9a7904a6a3c66bb7cdc091c5d26cb06bae Mon Sep 17 00:00:00 2001 From: Pieter Becking Date: Sun, 22 Dec 2024 13:07:27 +0100 Subject: [PATCH 15/18] Fixed rotation direction --- examples/drone/interactive_drone.py | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/examples/drone/interactive_drone.py b/examples/drone/interactive_drone.py index 276dff73..f074f412 100644 --- a/examples/drone/interactive_drone.py +++ b/examples/drone/interactive_drone.py @@ -55,18 +55,18 @@ def update_thrust(self): # Left (West) - Left rotors spin faster if keyboard.Key.left in self.pressed_keys: - self.rpms[0] += self.rotation_delta # Front left - self.rpms[2] += self.rotation_delta # Back left - self.rpms[1] -= self.rotation_delta # Front right - self.rpms[3] -= self.rotation_delta # Back right - print("Moving Left") - - # Right (East) - Right rotors spin faster - if keyboard.Key.right in self.pressed_keys: self.rpms[0] -= self.rotation_delta # Front left self.rpms[2] -= self.rotation_delta # Back left self.rpms[1] += self.rotation_delta # Front right self.rpms[3] += self.rotation_delta # Back right + print("Moving Left") + + # Right (East) - Right rotors spin faster + if keyboard.Key.right in self.pressed_keys: + self.rpms[0] += self.rotation_delta # Front left + self.rpms[2] += self.rotation_delta # Back left + self.rpms[1] -= self.rotation_delta # Front right + self.rpms[3] -= self.rotation_delta # Back right print("Moving Right") self.rpms = np.clip(self.rpms, 0, 25000) From f365a5c994be7d67eb1cffd9067559aaa84b4e4d Mon Sep 17 00:00:00 2001 From: Pieter Becking Date: Sun, 22 Dec 2024 13:11:39 +0100 Subject: [PATCH 16/18] Adding thrust control --- examples/drone/interactive_drone.py | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/examples/drone/interactive_drone.py b/examples/drone/interactive_drone.py index f074f412..a719c94d 100644 --- a/examples/drone/interactive_drone.py +++ b/examples/drone/interactive_drone.py @@ -10,6 +10,7 @@ class DroneController: def __init__(self): self.thrust = 14468.429183500699 # Base hover RPM - constant hover self.rotation_delta = 200 # Differential RPM for rotation + self.thrust_delta = 10 # Amount to change thrust by when accelerating/decelerating self.running = True self.rpms = [self.thrust] * 4 self.pressed_keys = set() @@ -37,6 +38,18 @@ def update_thrust(self): # Reset RPMs to hover thrust self.rpms = [self.thrust] * 4 + # Acceleration (Spacebar) - All rotors spin faster + if keyboard.Key.space in self.pressed_keys: + self.thrust += self.thrust_delta + self.rpms = [self.thrust] * 4 + print("Accelerating") + + # Deceleration (Left Shift) - All rotors spin slower + if keyboard.Key.shift in self.pressed_keys: + self.thrust -= self.thrust_delta + self.rpms = [self.thrust] * 4 + print("Decelerating") + # Forward (North) - Front rotors spin faster if keyboard.Key.up in self.pressed_keys: self.rpms[0] += self.rotation_delta # Front left From e3d8e050924bcf3724052d73cbc21e8f7ae3fe22 Mon Sep 17 00:00:00 2001 From: Pieter Becking Date: Sun, 22 Dec 2024 13:12:48 +0100 Subject: [PATCH 17/18] Updating README with thrust control --- examples/drone/README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/examples/drone/README.md b/examples/drone/README.md index dbe65f6d..e99e09bd 100644 --- a/examples/drone/README.md +++ b/examples/drone/README.md @@ -10,6 +10,8 @@ A real-time interactive drone simulation where you can control the drone using k - ↓ (Down Arrow): Move Backward (South) - ← (Left Arrow): Move Left (West) - → (Right Arrow): Move Right (East) +- Space: Increase Thrust (Accelerate) +- Left Shift: Decrease Thrust (Decelerate) - ESC: Quit Run with: From f173f61ff9409db3033238e103fc3493ca3eb675 Mon Sep 17 00:00:00 2001 From: Pieter Becking Date: Sun, 22 Dec 2024 17:43:15 +0100 Subject: [PATCH 18/18] Updating README with -m flag for macos --- examples/drone/README.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/examples/drone/README.md b/examples/drone/README.md index e99e09bd..349a8d18 100644 --- a/examples/drone/README.md +++ b/examples/drone/README.md @@ -16,7 +16,7 @@ A real-time interactive drone simulation where you can control the drone using k Run with: ```bash -python interactive_drone.py -v +python interactive_drone.py -v -m ``` ### 2. Automated Flight (`fly.py`) @@ -24,7 +24,7 @@ A pre-programmed drone flight simulation that follows a predefined trajectory st Run with: ```bash -python fly.py -v # -v flag enables visualization +python fly.py -v -m ``` ## Technical Details @@ -33,7 +33,7 @@ python fly.py -v # -v flag enables visualization - Base hover RPM is approximately 14468 - Movement is achieved by varying individual rotor RPMs to create directional thrust - The simulation uses realistic physics including gravity and aerodynamics -- Visualization is optimized for macOS using threaded rendering +- Visualization is optimized for macOS using threaded rendering when run with `-m` flag ## Controls Implementation