Pymunk 伺服关节

2023-12-08

如何在 Pymunk 中实现“伺服”关节?

我正在尝试创建一个简单的模型,其中一个盒子在其下方的一条细“腿”上保持平衡。我已经能够创建一个盒子并使用PinJoint,但似乎没有任何方法可以控制连接连接到盒子的角度。我希望能够指定附着角度。其他关节似乎都不支持这一点。除了 SimpleMotor 关节之外,它们似乎都是被动关节,但即便如此,这也只是一个您无法控制的持续旋转关节。

我已经成功地将一些东西拼凑在一起,通过使用 PinJoint 将两个薄盒子在其末端连接在一起,以及 SimpleMotor,使它们相对于彼此旋转,以响应用户按下“向上”和“向下” “ 方向键。下面是代码:

import sys

import pygame
from pygame.locals import USEREVENT, QUIT, KEYDOWN, KEYUP, K_s, K_r, K_q, K_ESCAPE, K_UP, K_DOWN
from pygame.color import THECOLORS

import pymunk
from pymunk import Vec2d
import pymunk.pygame_util

class Simulator(object):

    def __init__(self):
        self.display_flags = 0
        self.display_size = (600, 600)

        self.space = pymunk.Space()
        self.space.gravity = (0.0, -1900.0)
        self.space.damping = 0.999 # to prevent it from blowing up.

        # Pymunk physics coordinates start from the lower right-hand corner of the screen.
        self.ground_y = 100
        ground = pymunk.Segment(self.space.static_body, (5, self.ground_y), (595, self.ground_y), 1.0)
        ground.friction = 1.0
        self.space.add(ground)

        self.screen = None

        self.draw_options = None

    def reset_bodies(self):
        for body in self.space.bodies:
            if not hasattr(body, 'start_position'):
                continue
            body.position = Vec2d(body.start_position)
            body.force = 0, 0
            body.torque = 0
            body.velocity = 0, 0
            body.angular_velocity = 0
            body.angle = body.start_angle

    def draw(self):
        ### Clear the screen
        self.screen.fill(THECOLORS["white"])

        ### Draw space
        self.space.debug_draw(self.draw_options)

        ### All done, lets flip the display
        pygame.display.flip()

    def main(self):

        pygame.init()
        self.screen = pygame.display.set_mode(self.display_size, self.display_flags)
        width, height = self.screen.get_size()
        self.draw_options = pymunk.pygame_util.DrawOptions(self.screen)

        def to_pygame(p):
            """Small hack to convert pymunk to pygame coordinates"""
            return int(p.x), int(-p.y+height)
        def from_pygame(p):
            return to_pygame(p)

        clock = pygame.time.Clock()
        running = True
        font = pygame.font.Font(None, 16)

        # Create the torso box.
        box_width = 50
        box_height = 100
        leg_length = 100

        mass = 1
        points = [(-100, -1), (0, -1), (0, 1), (-100, 1)]
        moment = pymunk.moment_for_poly(mass, points)
        body1 = pymunk.Body(mass, moment)
        # body1.position = (0, 0)
        body1.position = (self.display_size[0]/2, self.ground_y+100)
        body1.start_position = Vec2d(body1.position)
        body1.start_angle = body1.angle
        shape1 = pymunk.Poly(body1, points)
        shape1.friction = 0.8
        self.space.add(body1, shape1)

        # Create bar 2 extending from the right to the origin.
        mass = 1
        points = [(100, -1), (0, -1), (0, 1), (100, 1)]
        moment = pymunk.moment_for_poly(mass, points)
        body2 = pymunk.Body(mass, moment)
        # body2.position = (0, 0)
        body2.position = (self.display_size[0]/2, self.ground_y+100)
        body2.start_position = Vec2d(body2.position)
        body2.start_angle = body2.angle
        shape2 = pymunk.Poly(body2, points)
        shape2.friction = 0.8
        self.space.add(body2, shape2)

        # Link bars together at end.
        pj = pymunk.PinJoint(body1, body2, (0, 0), (0, 0))
        self.space.add(pj)

        motor_joint = pymunk.SimpleMotor(body1, body2, 0)
        self.space.add(motor_joint)

        pygame.time.set_timer(USEREVENT+1, 70000) # apply force
        pygame.time.set_timer(USEREVENT+2, 120000) # reset
        pygame.event.post(pygame.event.Event(USEREVENT+1))
        pygame.mouse.set_visible(False)

        simulate = False
        while running:
            for event in pygame.event.get():
                if event.type == QUIT or (event.type == KEYDOWN and event.key in (K_q, K_ESCAPE)):
                    #running = False
                    sys.exit(0)
                elif event.type == KEYDOWN and event.key == K_s:
                    # Start/stop simulation.
                    simulate = not simulate
                elif event.type == KEYDOWN and event.key == K_r:
                    # Reset.
                    # simulate = False
                    self.reset_bodies()
                elif event.type == KEYDOWN and event.key == K_UP:
                    motor_joint.rate = 1
                elif event.type == KEYDOWN and event.key == K_DOWN:
                    motor_joint.rate = -1
                elif event.type == KEYUP:
                    motor_joint.rate = 0

            self.draw()

            ### Update physics
            fps = 50
            iterations = 25
            dt = 1.0/float(fps)/float(iterations)
            if simulate:
                for x in range(iterations): # 10 iterations to get a more stable simulation
                    self.space.step(dt)

            pygame.display.flip()
            clock.tick(fps)

if __name__ == '__main__':
    sim = Simulator()
    sim.main()

然而,这种行为有些奇怪。当您按下向上/向下按钮时,会动态设置 SimpleMotor 关节上的速率,导致两个盒子在其共同的“伺服关节”处旋转,例如:

enter image description here

除非随着时间的推移,这两个条会翻转到一端,否则就会反抗重力,看起来像:

enter image description here

为什么是这样?我对 Pymunk/Chipmunk 物理模拟器还很陌生,所以我不确定我是否正确使用了这些关节。


有几件事可能会导致问题:

  1. 忽略两个形状之间的碰撞。由于电机和销钉接头迫使它们在一起,但碰撞解决方案将它们推开,可能会发生奇怪的事情。您可以通过将两个形状设置为同一组来做到这一点: shape_filter = pymunk.ShapeFilter(group=1) shape1.filter = shape_filter shape2.filter = shape_filter

  2. 这两个形状的重心位于其两端,而不是中心。尝试将其移至中心([(-50, -1), (50, -1), (50, 1), (-50, 1)]).

(在这种情况下,我认为 1 足以解决问题,但我添加了 2 以防万一您注意到其他奇怪的事情)

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Pymunk 伺服关节 的相关文章

随机推荐

  • 服务器端的 SQLAlchemy 日期时间操作

    我有一个包含计划付款和过去付款的表 我需要查找同一周内是否对同一用户 合同进行了两次收费 select count from charge as c1 charge as c2 where c1 id contract c2 id cont
  • 使用 python scipy 正确插值 3D 矢量场

    GOAL 我的目标是使用 python 插值 3D 矢量场 CODE 原始向量场 import numpy as np import matplotlib pyplot as plt For interpolation from scipy
  • 如何将包含月份名称的日期字符串转换为日期时间?

    我确信这一定很简单 但是搜索引擎引导我的文章回答了除此之外的所有问题 我有一个字符串 13 February 2023 13 45 40 我需要将其转换为日期时间 以便我可以进行比较 你是如何安排这样的约会的 它是否需要一个比我更聪明的专业
  • 如何将文件从沙盒应用程序正确复制到应用程序脚本文件夹?

    我真的很困惑如何正确复制文件并授予执行权限 例如来自沙盒应用程序的 AppleScript 文件 我读过几篇文章和主题 但读得越多 我就越困惑 The Task 我的应用程序需要运行一个非常简单的AppleScript从一个 scpt文件
  • jboss6中log4j设置在哪里配置

    jboss 6 0 0 Final 似乎没有用于在 jboss5 中配置 log4j 设置的 jboss log4j xml 即在 server default conf jboss log4j xml 下 显然 自版本 6 以来 名称和位
  • 如何在Android操作栏开关中获取/设置操作事件

    我找到了这个帖子如何给android操作栏添加开关 这对我有用 但我无法获取它的事件 我正在使用 appcompat 并且我对 actionLayout 和 showAsAction 使用了应用程序命名空间 但我无法处理其对 onOptio
  • 根据模式将文件拆分为多个文件,并通过 Unix 中的搜索模式命名新文件?

    如何根据搜索模式拆分文件 并且将生成的新文件的文件名将等于用于拆分文件的搜索模式 目前 我正在使用以下命令来分割文件 awk GROUP x F i print gt x cdw all jobs reduced3 txt 它生成的文件名称
  • 使用 jQuery 和 Drupal6 自动更新宽度/长度/面积

    我正在使用 Drupal 创建测量表 Drupal 6 中的测量表 并且现在所有字段都已就位 我只需要编写一些 jQuery 在用户输入数据时自动更新相应的字段 代码如下 jQuery document ready function inp
  • 如何将列表分配为子列表,同时保持元素的原始顺序?

    如何将列表拆分为给定数量的列表 按顺序获取元素并将它们分配到子列表 因此不对列表进行分区 我想尽可能 好 地做到这一点 使用 Java 8 功能或 Guava 或类似的东西 示例列表 1 2 3 4 5 6 7 应分为 3 部分 1 4 7
  • 在 HTML 选择下拉选项中设置下拉元素的宽度

    我正在开发一个网站 该网站涉及使用 PHP 脚本自动填充选择框 这一切都工作正常 除了问题是我用来填充文本框的标题很长 它们是期刊文章和演示文稿标题 下拉框延伸到最长元素的宽度 该元素延伸到屏幕边缘 因此使滚动条无法到达 我尝试过各种方法尝
  • 使用 Postman 访问 OAuth 2.0 Google API

    我正在尝试访问邻近谷歌API using 邮递员 Chrome 应用程序 我已按照邮递员和谷歌开发网站上的教程进行操作 但仍然收到 401 错误消息 我在做什么 第 1 步 启用 Proximity API 为了使用 Proximity A
  • :app:processDebugResources 的executeTaskAction 失败

    我收到此错误消息 构建 构建失败 gt 运行构建 gt 运行任务 gt app processDebugResources gt executeTaskAction 下面显示的代码顺序为 错误消息 然后 build gradle Proje
  • 为什么Python中主进程退出时子进程(daemon=True)不退出?

    这是官方的解释daemonpython 多处理中的标志 当进程退出时 它会尝试终止其所有守护子进程 据我了解 父进程退出时会杀死其守护进程标志设置为 True 的子进程 下面是我用来证明我的猜测的代码 但结果不同 import multip
  • 打字稿条件:backend_layout(带幻灯片)

    我用这个条件 globalVar GP colPos 0 page backend layout pagets MainTemplate 我的问题是我的 子页面 没有选择 backend layout 因为设置了父页面 后端布局 此页面的子
  • C函数内存分配

    在 C 语言中 函数何时分配以及它在内存中的何处 函数的内存是在第一次编译程序时分配的 还是在第一次看到函数调用时分配的 它是分配在堆栈上还是在代码段中 你的问题问得很好 但是要做好应对一些额外复杂性的准备 因为其中一些东西会接触到运行代码
  • 使用 AutoHotKey 查找并填写输入字段

    对所有 AutoHotKey 大师的挑战 给我们一个函数查找并移动光标到输入字段 例如登录名 或者发送输入文本 对于像我这样又老又懒的黑客来说 只是摆弄 AHK 它看起来像这样 FindFillField elementid sendtex
  • Javascript Array.some() 和 Array.every() 相当于 Set?

    在 JavaScript 中 是否有等价的Array some and Array every 为了Set内置对象 不 唯一的内置方法Set prototype are Set prototype add Set prototype cle
  • 从 &str 数组获取 Iterator

    我正在尝试抽象一个函数来获取两个实例std str Lines以及用于测试目的的模拟版本 由一系列创建 str 我的代码 确实有效 看起来像这样 use std fs test fn test day 1 let v 3 3 4 2 4 i
  • 如何解决“Newtonsoft.Json.JsonSerializationException无法找到用于类型的构造函数”Android错误?

    我正在使用 Unity3D 开发应用程序 我将我自己的实用程序 DLL 与一些类一起使用 我已经工作了几个月了 并且毫无问题地进行了很多构建 编译 上周向 DLL 添加了一个新类 它在我的 PC 中运行良好 但当我构建该项目并在我的 And
  • Pymunk 伺服关节

    如何在 Pymunk 中实现 伺服 关节 我正在尝试创建一个简单的模型 其中一个盒子在其下方的一条细 腿 上保持平衡 我已经能够创建一个盒子并使用PinJoint 但似乎没有任何方法可以控制连接连接到盒子的角度 我希望能够指定附着角度 其他