《坎巴拉太空计划》krpc模组|0.5.4|文档(中译版)——教程与示例:参考系

📅 2026/7/19 23:32:13 👁️ 阅读次数 📝 编程学习
《坎巴拉太空计划》krpc模组|0.5.4|文档(中译版)——教程与示例:参考系
本翻译基于 [kRPC 官方文档](https://krpc.github.io/krpc),遵循 LGPL v3 许可。 部分内容可能受 GPLv3 或 MIT 许可约束,详见原始仓库。 Copyright 2015-2023 kRPC Org.

本教程和示例脚本合集详细说明了如何使用 kRPC 的功能特性。

参考系

介绍

kRPC 中的所有位置、方向、速度和旋转都是相对于某个参考系而言的,而*参考系*定义了这些"某个参考系"是什么。

一个参考系规定了:

  • 原点 (0,0,0) 的位置
  • 坐标轴 x、y、z 的方向
  • 原点的线速度(如果参考系移动的话)
  • 坐标轴的角速度(轴旋转的速度和方向)

注意:KSP 和 kRPC 使用左手坐标系

原点位置和轴方向

下面给出了一些不同参考系的原点位置和坐标轴方向的例子。

天体参考系
天体的参考系,比如 Kerbin。赤道用蓝色表示,本初子午线用红色表示。黑色箭头表示坐标轴,原点位于行星中心。

通过调用 Kerbin 的CelestialBody.reference_frame获得的参考系具有以下属性:

  • 原点位于 Kerbin 的中心,
  • y 轴从 Kerbin 中心指向北极,
  • x 轴从 Kerbin 中心指向本初子午线与赤道的交点(0°经度、0°纬度的地表位置),
  • z 轴从 Kerbin 中心指向东经 90° 的赤道位置,
  • 坐标轴随行星旋转,即该参考系与 Kerbin 有相同的旋转/角速度。

这意味着该参考系相对于 Kerbin 是“固定的”——它随行星中心移动,也随行星旋转。因此,该参考系中的位置是相对于行星中心的。以下代码打印出了当前活动航天器在 Kerbin 参考系中的位置:

import krpc conn = krpc.connect() vessel = conn.space_center.active_vessel print('(%.1f, %.1f, %.1f)' % vessel.position(vessel.orbit.body.reference_frame))

对于停放在发射台上的航天器,该位置矢量的大小约为 600,000 米(等于 Kerbin 的半径)。位置矢量不会随时间变化,因为航天器停在 Kerbin 表面,而参考系也随 Kerbin 一起旋转。

航天器轨道参考系
航天器的轨道参考系

另一个例子是航天器的轨道参考系,通过调用Vessel.orbital_reference_frame获取。该参考系固定在航天器上(原点随航天器移动),坐标轴指向轨道顺向/法向/径向方向。

  • 原点位于航天器的质心,
  • y 轴指向航天器轨道的顺向方向,
  • x 轴指向航天器轨道的反径向方向,
  • z 轴指向航天器轨道的法向方向,
  • 坐标轴随顺向/法向/径向方向的变化而旋转,例如当航天器沿轨道继续运动时顺向方向会发生变化。
航天器参考系
飞行器的参考系

另一个例子是Vessel.reference_frame。与前一个例子一样,它也固定在航天器上(原点随航天器移动),但坐标轴的朝向不同。它们跟踪航天器的朝向:

  • 原点位于航天器的质心,
  • y 轴指向航天器所朝的方向,
  • x 轴指向航天器的右侧,
  • z 轴指向航天器底部向下,
  • 坐标轴随航天器方向的任何变化而旋转。

线速度和角速度

参考系之间会相互移动和旋转。例如,前面讨论的参考系的原点位置都固定在某些物体上(如航天器或行星)。这意味着它们会移动和旋转以跟踪该物体,因此具有与之相关的线速度和角速度。

例如,通过调用KerbinCelestialBody.reference_frame获得的参考系是相对于 Kerbin 固定的。这意味着该参考系的角速度与 Kerbin 的角速度相同,参考系的线速度与 Kerbin 当前的轨道速度一致。

可用参考系

kRPC 提供以下参考系:

Vessel.reference_frame Vessel.orbital_reference_frame Vessel.surface_reference_frame Vessel.surface_velocity_reference_frame CelestialBody.reference_frame CelestialBody.non_rotating_reference_frame CelestialBody.orbital_reference_frame Node.reference_frame Node.orbital_reference_frame Part.reference_frame Part.center_of_mass_reference_frame DockingPort.reference_frame Thruster.thrust_reference_frame

同时还可以从上述参考系构造相对和混合参考系。

自定义参考系

自定义参考系可以从上面列出的内置参考系构造而来。它们有两种类型:"相对"和"混合"。

相对参考系由一个父参考系、一个固定的位置偏移和一个固定的旋转偏移构造而成。例如,以下代码通过在Vessel.reference_frame的 z 轴上施加 10 米的位置偏移,构建了一个原点在航天器下方 10 米处的参考系。相对参考系可通过调用ReferenceFrame.create_relative()来构造。

混合参考系从其他参考系的组件(位置、旋转、速度和角速度)中继承其组件。注意这些组件不一定是固定的。例如,你可以构建一个参考系,其位置是航天器的质心(继承自 Vessel.reference_frame),旋转则是被环绕行星的旋转(继承自 CelestialBody.reference_frame)。混合参考系可通过调用 ReferenceFrame.create_hybrid() 来构造。

自定义参考系的父参考系也可以是其他自定义参考系。例如,你可以将上面两个例子结合起来:先构造一个以航天器为中心、随被环绕行星旋转的混合参考系,然后创建一个在该参考系的 z 轴上偏移 10 米位置的相对参考系。最终得到的参考系其原点在航天器下方 10 米处,并且随被环绕的行星旋转。

参考系之间的转换

kRPC 提供了用于在不同参考系之间转换位置、方向、旋转和速度的实用方法:

SpaceCenter.transform_position() SpaceCenter.transform_direction() SpaceCenter.transform_rotation() SpaceCenter.transform_velocity()

可视化调试

参考系可能会让人困惑,选择合适的参考系本身就是个挑战。为了辅助调试,kRPC 的绘图功能可用于在游戏中可视化方向向量。

Drawing.add_direction_from_com()将绘制一个方向向量,从活动航天器的质心开始。例如,以下代码绘制当前航天器相对于其所环绕天体表面的速度方向:

import krpc conn = krpc.connect(name='Visual Debugging') vessel = conn.space_center.active_vessel ref_frame = vessel.surface_velocity_reference_frame conn.drawing.add_direction_from_com((0, 1, 0), ref_frame) while True: pass

注意:

客户端必须保持连接才能持续绘制该线条,因此示例末尾使用了一个无限循环。

示例

下面的示例演示了参考系的各种用法。

导航球方向

此示例演示如何让航天器指向导航球上的各个方向:

import krpc conn = krpc.connect(name='Navball directions') vessel = conn.space_center.active_vessel ap = vessel.auto_pilot ap.reference_frame = vessel.surface_reference_frame ap.engage() # Point the vessel north on the navball, with a pitch of 0 degrees ap.target_direction = (0, 1, 0) ap.wait() # Point the vessel vertically upwards on the navball ap.target_direction = (1, 0, 0) ap.wait() # Point the vessel west (heading of 270 degrees), with a pitch of 0 degrees ap.target_direction = (0, 0, -1) ap.wait() ap.disengage()

该代码使用了航天器的表面参考系(Vessel.surface_reference_frame),如下图所示:

第一部分指示自动驾驶仪指向航天器表面参考系中的方向 (0,1,0)(即沿 y 轴)。该参考系的 y 轴指向北方,符合要求。

第二部分指示自动驾驶仪指向航天器表面参考系中的方向 (1,0,0)(沿 x 轴)。该参考系的 x 轴指向天顶(远离行星),符合要求。

最后,代码指示自动驾驶仪指向方向 (0,0,-1)(沿负 z 轴)。该参考系的 z 轴指向东方,因此请求的方向指向西方——符合要求。

轨道方向

此示例演示如何让航天器指向导航球在「轨道」模式下的各个轨道方向。它使用了Vessel.orbital_reference_frame

import krpc conn = krpc.connect(name='Orbital directions') vessel = conn.space_center.active_vessel ap = vessel.auto_pilot ap.reference_frame = vessel.orbital_reference_frame ap.engage() # Point the vessel in the prograde direction ap.target_direction = (0, 1, 0) ap.wait() # Point the vessel in the orbit normal direction ap.target_direction = (0, 0, 1) ap.wait() # Point the vessel in the orbit radial direction ap.target_direction = (-1, 0, 0) ap.wait() ap.disengage()

该代码使用了航天器的轨道参考系,如下图所示:

表面「顺向」

此示例演示如何在导航球处于「表面」模式时,让航天器指向「顺向」方向。这是航天器相对于表面的速度方向:

import krpc conn = krpc.connect(name='Surface prograde') vessel = conn.space_center.active_vessel ap = vessel.auto_pilot ap.reference_frame = vessel.surface_velocity_reference_frame ap.target_direction = (0, 1, 0) ap.engage() ap.wait() ap.disengage()

以下代码使用了 Vessel.surface_velocity_reference_frame,如下图所示:

航天器速度

本示例演示如何获取飞行器的轨道速度和表面速度,其数值等同于导航球上显示的值。

要计算飞行器的轨道速度,需要获取相对于行星非旋转参考系(CelestialBody.non_rotating_reference_frame)的速度。该参考系相对于天体固定,但不随天体旋转。

对于表面速度,则需要使用行星的参考系(CelestialBody.reference_frame),因为该参考系随天体一同旋转。

import time import krpc conn = krpc.connect(name='Vessel speed') vessel = conn.space_center.active_vessel obt_frame = vessel.orbit.body.non_rotating_reference_frame srf_frame = vessel.orbit.body.reference_frame while True: obt_speed = vessel.flight(obt_frame).speed srf_speed = vessel.flight(srf_frame).speed print('Orbital speed = %.1f m/s, Surface speed = %.1f m/s' % (obt_speed, srf_speed)) time.sleep(1)

本示例演示如何获取飞行器相对于被环绕天体表面的速度(以向量形式)。

要实现这一点,需要使用混合参考系。这是因为我们希望得到一个以飞行器为中心、但其线速度相对于地面保持固定的参考系。

因此,我们创建一个混合参考系,将其旋转设置为飞行器的表面参考系(Vessel.surface_reference_frame),而将所有其他属性(包括位置和速度)设置为天体的参考系(CelestialBody.reference_frame)——该参考系随天体一同旋转。

import time import krpc conn = krpc.connect(name='Orbital speed') vessel = conn.space_center.active_vessel ref_frame = conn.space_center.ReferenceFrame.create_hybrid( position=vessel.orbit.body.reference_frame, rotation=vessel.surface_reference_frame) while True: velocity = vessel.flight(ref_frame).velocity print('Surface velocity = (%.1f, %.1f, %.1f)' % velocity) time.sleep(1)

攻角

本示例计算飞行器指向方向与其运动方向(相对于表面)之间的夹角。

import math import time import krpc conn = krpc.connect(name='Angle of attack') vessel = conn.space_center.active_vessel while True: d = vessel.direction(vessel.orbit.body.reference_frame) v = vessel.velocity(vessel.orbit.body.reference_frame) # Compute the dot product of d and v dotprod = d[0]*v[0] + d[1]*v[1] + d[2]*v[2] # Compute the magnitude of v vmag = math.sqrt(v[0]**2 + v[1]**2 + v[2]**2) # Note: don't need to magnitude of d as it is a unit vector # Compute the angle between the vectors angle = 0 if dotprod > 0: angle = abs(math.acos(dotprod / vmag) * (180.0 / math.pi)) print('Angle of attack = %.1f degrees' % angle) time.sleep(1)

请注意,用于获取方向向量和速度向量的参考系朝向并不重要,因为两个向量之间的夹角与坐标轴的方向无关。然而,如果我们使用随飞行器移动的参考系,速度将返回(0,0,0)。因此,我们需要一个相对于飞行器不是固定的参考系。CelestialBody.reference_frame恰好满足这些要求。

着陆点

本示例计算一个位于天体表面指定高度处的参考系,该参考系可用作着陆自动驾驶仪的目标目标点。

import time from math import sin, cos, pi import krpc conn = krpc.connect(name='Landing Site') vessel = conn.space_center.active_vessel body = vessel.orbit.body create_relative = conn.space_center.ReferenceFrame.create_relative # Define the landing site as the top of the VAB landing_latitude = -(0+(5.0/60)+(48.38/60/60)) landing_longitude = -(74+(37.0/60)+(12.2/60/60)) landing_altitude = 111 # Determine landing site reference frame # (orientation: x=zenith, y=north, z=east) landing_position = body.surface_position( landing_latitude, landing_longitude, body.reference_frame) q_long = ( 0, sin(-landing_longitude * 0.5 * pi / 180), 0, cos(-landing_longitude * 0.5 * pi / 180) ) q_lat = ( 0, 0, sin(landing_latitude * 0.5 * pi / 180), cos(landing_latitude * 0.5 * pi / 180) ) landing_reference_frame = \ create_relative( create_relative( create_relative( body.reference_frame, landing_position, q_long), (0, 0, 0), q_lat), (landing_altitude, 0, 0)) # Draw axes conn.drawing.add_line((0, 0, 0), (1, 0, 0), landing_reference_frame) conn.drawing.add_line((0, 0, 0), (0, 1, 0), landing_reference_frame) conn.drawing.add_line((0, 0, 0), (0, 0, 1), landing_reference_frame) while True: time.sleep(1)