zwx08 发表于 2024-4-21 09:26

小鸟飞飞图形化编程炫舞软件 辅助计算分析和自动编写飞行延时

前言:
我并不清楚比赛中是否运行使用自动化计算脚本,但非常希望裁判组如果看到这篇文章也允许使用它(你要是真不允许的话评论讲啊),毕竟这个脚本也是一点点写出来的。而且并不影响公平性,不是吗(
(来自上海莫区青中心不知名学生的编写,只是为了以后的人的方便于是发布于此---好吧只是因为咱自己也没人会用而大概得写个帖子或录个视频但是不想发b站于是就来这里用帖子的形式罢了)
-----------
分析
小鸟飞飞的项目保存并不复杂,它将每个动作组都单独放了一个文件夹。经过测试,只有webCodeAll.xml是真正的保存文件,py只是生成的,你不放心可以在每次手动xml之后同时删掉webCodeAll.py文件,之后打开软件导入,跳转到修改的动作组之后即可重新生成


xml文件具体算是比较复杂,至少gpt3.5加上引导也没办法理解逻辑,gpt4在引导之下还算是勉强理解了

辅助计算逻辑
简单,直接找代码,反正它没壳

这里便是辅助计算的实现代码
private void btnCal2_Click(object sender, EventArgs e)
{
    float num = 0f;
    float num2 = 0f;
    float num3 = 0f;
    float num4 = 0f;
    float num5 = 0f;
    float num6 = 0f;
    float num7 = 0f;
    float num8 = 0f;
    num = !((this.AX.Text != "") && this.IsNumbericString(this.AX.Text)) ? 0f : float.Parse(this.AX.Text);
    num2 = !((this.AY.Text != "") && this.IsNumbericString(this.AY.Text)) ? 0f : float.Parse(this.AY.Text);
    num3 = !((this.AZ.Text != "") && this.IsNumbericString(this.AZ.Text)) ? 0f : float.Parse(this.AZ.Text);
    num4 = !((this.BX.Text != "") && this.IsNumbericString(this.BX.Text)) ? 0f : float.Parse(this.BX.Text);
    num5 = !((this.BY.Text != "") && this.IsNumbericString(this.BY.Text)) ? 0f : float.Parse(this.BY.Text);
    num6 = !((this.BZ.Text != "") && this.IsNumbericString(this.BZ.Text)) ? 0f : float.Parse(this.BZ.Text);
    num7 = !((this.HSpeed.Text != "") && this.IsNumbericString(this.HSpeed.Text)) ? 0f : float.Parse(this.HSpeed.Text);
    num8 = !((this.Acc.Text != "") && this.IsNumbericString(this.Acc.Text)) ? 0f : float.Parse(this.Acc.Text);
    float num9 = (float) Math.Sqrt((double) ((((num4 - num) * (num4 - num)) + ((num5 - num2) * (num5 - num2))) + ((num6 - num3) * (num6 - num3))));
    this.Dis.Text = ((int) Math.Round((double) num9)).ToString();
    if (!(string.IsNullOrWhiteSpace(this.Acc.Text) || string.IsNullOrWhiteSpace(this.HSpeed.Text)))
    {
      float num10 = num7 / num8;
      float num11 = ((0.5f * num8) * num10) * num10;
      if (num11 > (num9 / 2f))
      {
            this.PreTime.Text = ((int) Math.Round((double) (((2f * ((float) Math.Sqrt((double) (((2f * num8) * num9) / 2f)))) / num8) * 0x3e8f))).ToString();
      }
      else
      {
            this.PreTime.Text = ((int) Math.Round((double) ((((num7 / num8) * 2f) * 0x3e8f) + (((num9 - (num11 * 2f)) / num7) * 0x3e8f)))).ToString();
      }
    }
}




350x230b10_0011private void btnCal2_Click(object sender, EventArgs e)
{
    float num = 0f;
    float num2 = 0f;
    float num3 = 0f;
    float num4 = 0f;
    float num5 = 0f;
    float num6 = 0f;
    float num7 = 0f;
    float num8 = 0f;
    num = !((this.AX.Text != "") && this.IsNumbericString(this.AX.Text)) ? 0f : float.Parse(this.AX.Text);
    num2 = !((this.AY.Text != "") && this.IsNumbericString(this.AY.Text)) ? 0f : float.Parse(this.AY.Text);
    num3 = !((this.AZ.Text != "") && this.IsNumbericString(this.AZ.Text)) ? 0f : float.Parse(this.AZ.Text);
    num4 = !((this.BX.Text != "") && this.IsNumbericString(this.BX.Text)) ? 0f : float.Parse(this.BX.Text);
    num5 = !((this.BY.Text != "") && this.IsNumbericString(this.BY.Text)) ? 0f : float.Parse(this.BY.Text);
    num6 = !((this.BZ.Text != "") && this.IsNumbericString(this.BZ.Text)) ? 0f : float.Parse(this.BZ.Text);
    num7 = !((this.HSpeed.Text != "") && this.IsNumbericString(this.HSpeed.Text)) ? 0f : float.Parse(this.HSpeed.Text);
    num8 = !((this.Acc.Text != "") && this.IsNumbericString(this.Acc.Text)) ? 0f : float.Parse(this.Acc.Text);
    float num9 = (float) Math.Sqrt((double) ((((num4 - num) * (num4 - num)) + ((num5 - num2) * (num5 - num2))) + ((num6 - num3) * (num6 - num3))));
    this.Dis.Text = ((int) Math.Round((double) num9)).ToString();
    if (!(string.IsNullOrWhiteSpace(this.Acc.Text) || string.IsNullOrWhiteSpace(this.HSpeed.Text)))
    {
      float num10 = num7 / num8;
      float num11 = ((0.5f * num8) * num10) * num10;
      if (num11 > (num9 / 2f))
      {
            this.PreTime.Text = ((int) Math.Round((double) (((2f * ((float) Math.Sqrt((double) (((2f * num8) * num9) / 2f)))) / num8) * 0x3e8f))).ToString();
      }
      else
      {
            this.PreTime.Text = ((int) Math.Round((double) ((((num7 / num8) * 2f) * 0x3e8f) + (((num9 - (num11 * 2f)) / num7) * 0x3e8f)))).ToString();
      }
    }
}






转换为python实现(gpt):
def calculate_distance(ax, ay, az, bx, by, bz):
    num4 = float(bx) if bx else 0.0
    num5 = float(by) if by else 0.0
    num6 = float(bz) if bz else 0.0
    num = float(ax) if ax else 0.0
    num2 = float(ay) if ay else 0.0
    num3 = float(az) if az else 0.0

    num9 = ((num4 - num) ** 2 + (num5 - num2) ** 2 + (num6 - num3) ** 2) ** 0.5
    return int(round(num9))

def calculate_pre_time(acc, hspeed, distance):
    num7 = float(hspeed) if hspeed else 0.0
    num8 = float(acc) if acc else 0.0

    num10 = num7 / num8
    num11 = 0.5 * num8 * num10 ** 2

    if num11 > distance / 2:
      return int(round((2 * ((2 * num8 * distance / 2) ** 0.5) / num8) * 1000))
    else:
      return int(round(((num7 / num8) * 2 * 1000) + ((distance - (num11 * 2)) / num7) * 1000))

# 示例用法
ax = input("请输入AX的值:")
ay = input("请输入AY的值:")
az = input("请输入AZ的值:")
bx = input("请输入BX的值:")
by = input("请输入BY的值:")
bz = input("请输入BZ的值:")
hspeed = input("请输入HSpeed的值:")
acc = input("请输入Acc的值:")

distance = calculate_distance(ax, ay, az, bx, by, bz)
print(f"距离为:{distance} 米")

if acc and hspeed:
    pre_time = calculate_pre_time(acc, hspeed, distance)
    print(f"预计时间为:{pre_time} 毫秒")

-----------
逻辑
在具体逻辑上,代码中读取了前两个move_to_coord_blocks块(//default_ns:block[@type="Goertek_MoveToCoord"]),再将两个坐标点填入辅助计算中,并手动输入acc和hspeed,从而得出辅助计算的time,接着进行进一的模糊处理(最后两位),从而将这个值作为delay_time(延时)的time值,接着将这个延时"插入“xml中(为什么是"插入”,主要还是xml的格式很奇怪,它是将下一个块通过<next>包裹之后作为上一个块的子元素)
脚本一定可以读的编写方式:(像这样从头直线移到尾)

脚本一定不能读的编写方式:
1、标定点
2、其他所有

此外请注意
如果在自动化脚本前就把灯写上了,那么灯会到延时之后
生成中不会生成第一个延时(也就是从无人机初始位置到第一个坐标点,第一个坐标点之后的第一个延时)
执行前请先备份(直接文件夹选上打包结束(:)
别忘了模拟
-----------
代码所有代码皆为gpt生成,没有例外(对话的都是泪)
由于发现似乎没几个人知道怎么在当前目录下打开或者转目录,于是想了下简单加上了目录切换到脚本所在目录(就这几行)
首先是处理脚本:删除所有延时(请注意是所有延时块,包括第一个延时,同时也会删去解锁后的一秒延时等)
from lxml import etree as ET
import os

# 获取当前脚本所在的目录路径
script_dir = os.path.dirname(os.path.abspath(__file__))

# 切换到脚本所在的目录
os.chdir(script_dir)

def remove_and_relocate_next_blocks(xml_document, namespace):
    """
    Remove 'block_delay' blocks and relocate their 'next' blocks (if any) to their parent element.

    Args:
    - xml_document: Path to the XML document.
    - namespace: The namespace as a dictionary, e.g., {'ns': 'http://www.w3.org/1999/xhtml'}
    """
    # Parse the XML document
    tree = ET.parse(xml_document)
    root = tree.getroot()

    # Find all 'block_delay' blocks considering the namespace
    block_delays = root.xpath('//ns:block[@type="block_delay"]', namespaces=namespace)

    for block_delay in block_delays:
      # Find 'next' block within block_delay
      next_block = block_delay.find('ns:next', namespaces=namespace)

      if next_block is not None:
            # Temporarily store the contents of the 'next' block
            temp_content = list(next_block)

            # Remove the entire 'block_delay' block
            parent = block_delay.getparent()
            parent.remove(block_delay)

            # Append temporarily stored content to the parent of 'block_delay' block
            for elem in temp_content:
                parent.append(elem)
      else:
            # If there is no 'next' block, remove the 'block_delay' block
            parent = block_delay.getparent()
            parent.remove(block_delay)

    # Return the modified XML tree
    return tree

# Specify your XML document path and namespace
# 用户输入原文件路径,默认为 'webCodeAll.xml'
input_file = input("请输入原文件路径(默认为 'webCodeAll.xml'):") or 'webCodeAll.xml'
namespace = {'ns': 'http://www.w3.org/1999/xhtml'}# Replace with the actual namespace if different

# Call the function and save the result
modified_tree = remove_and_relocate_next_blocks(input_file, namespace)



if input("是否覆盖文件?(输入'y'或'Y'覆盖,其他情况不覆盖): ").strip().lower() == 'y':
    output_file = input_file
else:
    # 用户输入输出文件名,默认为 'modified_webCodeAll.xml'
    output_file = input("请输入输出文件名(默认为 'modified_webCodeAll.xml'):") or 'modified_webCodeAll.xml'


modified_tree.write(output_file, pretty_print=True, xml_declaration=False, encoding='UTF-8')


实际延时添加脚本
(block_delay计算.py)带进一:

from lxml import etree as ET
import math
import os

# 获取当前脚本所在的目录路径
script_dir = os.path.dirname(os.path.abspath(__file__))

# 切换到脚本所在的目录
os.chdir(script_dir)

# 此函数读取 XML 文件并返回树对象
def read_xml(filename):
    with open(filename, 'rb') as file:
      return ET.parse(file)

# 此函数计算两个坐标之间的延迟
def calculate_delay(previous_coords, current_coords, hspeed, acc):
    # 获取两个坐标点的值
    ax, ay, az = previous_coords
    bx, by, bz = current_coords

    # 计算两点之间的距离
    distance = math.sqrt((float(bx) - float(ax)) ** 2 + (float(by) - float(ay)) ** 2 + (float(bz) - float(az)) ** 2)

    # 计算预计时间
    num7 = float(hspeed) if hspeed else 0.0
    num8 = float(acc) if acc else 0.0

    num10 = num7 / num8
    num11 = 0.5 * num8 * num10 ** 2

    if num11 > distance / 2:
      pre_time = int(round((2 * ((2 * num8 * distance / 2) ** 0.5) / num8) * 1000))
    else:
      pre_time = int(round(((num7 / num8) * 2 * 1000) + ((distance - (num11 * 2)) / num7) * 1000))

    pre_time = math.ceil(pre_time / 100) * 100

    return pre_time

# 此函数将格式化后的 XML 树写入到新文件
def write_xml(tree, filename):
    with open(filename, 'wb') as file:
      tree.write(file, pretty_print=True, xml_declaration=False, encoding='UTF-8')

# 用户输入水平速度(VH)和加速度(AH),默认为 200 和 400
hspeed = input("请输入水平速度(VH),默认为 200:") or '200'
acc = input("请输入加速度(AH),默认为 400:") or '400'

# 用户输入原文件路径,默认为 'webCodeAll.xml'
input_file = input("请输入原文件路径(默认为 'webCodeAll.xml'):") or 'webCodeAll.xml'

# 读取 XML 文件
tree = read_xml(input_file)

# 获取根节点,适应命名空间
root = tree.getroot()
ns = {'default_ns': root.nsmap}

# 找到所有的 Goertek_MoveToCoord 块
move_to_coord_blocks = root.xpath('//default_ns:block[@type="Goertek_MoveToCoord"]', namespaces=ns)

# 上一个坐标的坐标值初始化为空
previous_coords = None

# 遍历所有的 Goertek_MoveToCoord 块
for block in move_to_coord_blocks:
    # 读取当前块下的坐标值
    current_coords = (
      block.find('default_ns:field[@name="X"]', namespaces=ns).text,
      block.find('default_ns:field[@name="Y"]', namespaces=ns).text,
      block.find('default_ns:field[@name="Z"]', namespaces=ns).text
    )

    # 如果存在前一个坐标块,则计算延迟
    if previous_coords:
      delay = calculate_delay(previous_coords, current_coords, hspeed, acc)

      # 创建 block_delay 块
      delay_block = ET.Element('{{{}}}block'.format(ns['default_ns']), attrib={'type': 'block_delay'})
      delay_field_time = ET.SubElement(delay_block, '{{{}}}field'.format(ns['default_ns']), attrib={'name': 'time'})
      delay_field_time.text = str(delay)
      delay_field_delay = ET.SubElement(delay_block, '{{{}}}field'.format(ns['default_ns']), attrib={'name': 'delay'})
      delay_field_delay.text = '0'# 或您计算出的正确值

      # 检查当前块是否有 <next>
      next_tag = block.find('default_ns:next', namespaces=ns)
      if next_tag is not None:
            next_content = next_tag.getchildren()
            delay_next_tag = ET.SubElement(delay_block, '{{{}}}next'.format(ns['default_ns']))
            delay_next_tag.extend(next_content)# 转移 next 内容
            next_tag.clear()# 清除原有内容
            next_tag.append(delay_block)# 插入 block_delay
      else:
            # 直接创建 <next> 且不转移任何内容
            next_tag = ET.SubElement(block, '{{{}}}next'.format(ns['default_ns']))
            next_tag.append(delay_block)# 插入 block_delay
    # 更新前一个坐标值以供下次循环使用
    previous_coords = current_coords


if input("是否覆盖文件?(输入'y'或'Y'覆盖,其他情况不覆盖): ").strip().lower() == 'y':
    output_file = input_file
else:
    # 用户输入输出文件名,默认为 'modified_webCodeAll.xml'
    output_file = input("请输入输出文件名(默认为 'modified_webCodeAll.xml'):") or 'modified_webCodeAll.xml'

# 将修改后的 XML 树写入到新文件
write_xml(tree, output_file)

print(f"The modified XML has been saved to {output_file}.")



(block_delay计算 - 不带进一精确.py)

from lxml import etree as ET
import math
import os

# 获取当前脚本所在的目录路径
script_dir = os.path.dirname(os.path.abspath(__file__))

# 切换到脚本所在的目录
os.chdir(script_dir)

# 此函数读取 XML 文件并返回树对象
def read_xml(filename):
    with open(filename, 'rb') as file:
      return ET.parse(file)

# 此函数计算两个坐标之间的延迟
def calculate_delay(previous_coords, current_coords, hspeed, acc):
    # 获取两个坐标点的值
    ax, ay, az = previous_coords
    bx, by, bz = current_coords

    # 计算两点之间的距离
    distance = math.sqrt((float(bx) - float(ax)) ** 2 + (float(by) - float(ay)) ** 2 + (float(bz) - float(az)) ** 2)

    # 计算预计时间
    num7 = float(hspeed) if hspeed else 0.0
    num8 = float(acc) if acc else 0.0

    num10 = num7 / num8
    num11 = 0.5 * num8 * num10 ** 2

    if num11 > distance / 2:
      pre_time = int(round((2 * ((2 * num8 * distance / 2) ** 0.5) / num8) * 1000))
    else:
      pre_time = int(round(((num7 / num8) * 2 * 1000) + ((distance - (num11 * 2)) / num7) * 1000))

    return pre_time

# 此函数将格式化后的 XML 树写入到新文件
def write_xml(tree, filename):
    with open(filename, 'wb') as file:
      tree.write(file, pretty_print=True, xml_declaration=False, encoding='UTF-8')

# 用户输入水平速度(VH)和加速度(AH),默认为 200 和 400
hspeed = input("请输入水平速度(VH),默认为 200:") or '200'
acc = input("请输入加速度(AH),默认为 400:") or '400'

# 用户输入原文件路径,默认为 'webCodeAll.xml'
input_file = input("请输入原文件路径(默认为 'webCodeAll.xml'):") or 'webCodeAll.xml'


# 读取 XML 文件
tree = read_xml(input_file)

# 获取根节点,适应命名空间
root = tree.getroot()
ns = {'default_ns': root.nsmap}

# 找到所有的 Goertek_MoveToCoord 块
move_to_coord_blocks = root.xpath('//default_ns:block[@type="Goertek_MoveToCoord"]', namespaces=ns)

# 上一个坐标的坐标值初始化为空
previous_coords = None

# 遍历所有的 Goertek_MoveToCoord 块
for block in move_to_coord_blocks:
    # 读取当前块下的坐标值
    current_coords = (
      block.find('default_ns:field[@name="X"]', namespaces=ns).text,
      block.find('default_ns:field[@name="Y"]', namespaces=ns).text,
      block.find('default_ns:field[@name="Z"]', namespaces=ns).text
    )

    # 如果存在前一个坐标块,则计算延迟
    if previous_coords:
      delay = calculate_delay(previous_coords, current_coords, hspeed, acc)

      # 创建 block_delay 块
      delay_block = ET.Element('{{{}}}block'.format(ns['default_ns']), attrib={'type': 'block_delay'})
      delay_field_time = ET.SubElement(delay_block, '{{{}}}field'.format(ns['default_ns']), attrib={'name': 'time'})
      delay_field_time.text = str(delay)
      delay_field_delay = ET.SubElement(delay_block, '{{{}}}field'.format(ns['default_ns']), attrib={'name': 'delay'})
      delay_field_delay.text = '0'# 或您计算出的正确值

      # 检查当前块是否有 <next>
      next_tag = block.find('default_ns:next', namespaces=ns)
      if next_tag is not None:
            next_content = next_tag.getchildren()
            delay_next_tag = ET.SubElement(delay_block, '{{{}}}next'.format(ns['default_ns']))
            delay_next_tag.extend(next_content)# 转移 next 内容
            next_tag.clear()# 清除原有内容
            next_tag.append(delay_block)# 插入 block_delay
      else:
            # 直接创建 <next> 且不转移任何内容
            next_tag = ET.SubElement(block, '{{{}}}next'.format(ns['default_ns']))
            next_tag.append(delay_block)# 插入 block_delay
    # 更新前一个坐标值以供下次循环使用
    previous_coords = current_coords


if input("是否覆盖文件?(输入'y'或'Y'覆盖,其他情况不覆盖): ").strip().lower() == 'y':
    output_file = input_file
else:
    # 用户输入输出文件名,默认为 'modified_webCodeAll.xml'
    output_file = input("请输入输出文件名(默认为 'modified_webCodeAll.xml'):") or 'modified_webCodeAll.xml'
# 将修改后的 XML 树写入到新文件
write_xml(tree, output_file)

print(f"The modified XML has been saved to {output_file}.")


页: [1]
查看完整版本: 小鸟飞飞图形化编程炫舞软件 辅助计算分析和自动编写飞行延时