洋流

本示例演示了如何在 HoloOcean 模拟中实现洋流。洋流由一个函数定义,该函数接收水下航行器的位置并返回该位置的洋流速度。在本示例中,我们定义了一个涡流场来模拟旋转的水流。该洋流场应用于仿真中的两个水下航行器,用户可以通过键盘输入控制其中一个航行器。

import holoocean
import numpy as np
from pynput import keyboard

scenario = {
    "name": "test_currents",
    "world": "SimpleUnderwater",
    "package_name": "Ocean",
    "main_agent": "auv0",
    "ticks_per_sec": 30,
    "frames_per_sec": 90,
    "current": {
        "vehicle_debugging": True
    },
    "ticks_per_sec": 60,
    "agents": [
        {
            "agent_name": "auv0",
            "agent_type": "HoveringAUV",
            "sensors": [
                {
                    "sensor_type": "LocationSensor",
                    "socket": "COM",
                    "configuration": {
                        "Sigma": 0
                    }
                }
            ],
            "control_scheme": 0,
            "location": [5, -5, -15]
        },
        {
            "agent_name": "auv1",
            "agent_type": "HoveringAUV",
            "sensors": [
                {
                    "sensor_type": "LocationSensor",
                    "socket": "COM",
                    "configuration": {
                        "Sigma": 0
                    }
                }
            ],
            "control_scheme": 0,
            "location": [-5, -5, -15]
        }
    ]
}

pressed_keys = list()
force = 10

def on_press(key):
    global pressed_keys
    if hasattr(key, 'char'):
        pressed_keys.append(key.char)
        pressed_keys = list(set(pressed_keys))

def on_release(key):
    global pressed_keys
    if hasattr(key, 'char'):
        pressed_keys.remove(key.char)

listener = keyboard.Listener(
    on_press=on_press,
    on_release=on_release)
listener.start()

def parse_keys(keys, val):
    command = np.zeros(8)
    if 'i' in keys:
        command[0:4] += val
    if 'k' in keys:
        command[0:4] -= val
    if 'j' in keys:
        command[[4,7]] += .25 * val
        command[[5,6]] -= .25 * val
    if 'l' in keys:
        command[[4,7]] -= .25 * val
        command[[5,6]] += .25 * val

    if 'w' in keys:
        command[4:8] += val
    if 's' in keys:
        command[4:8] -= val
    if 'a' in keys:
        command[[4,6]] += val
        command[[5,7]] -= val
    if 'd' in keys:
        command[[4,6]] -= val
        command[[5,7]] += val

    return command

def vortex_field(location):
    x, y, z = location
    if z > 0:
        return [0, 0, 0]
    strength = 5.0
    r_squared = x**2 + y**2 + 1e-5  # 避免除以零
    dx = -y / r_squared * strength
    dy = x / r_squared * strength
    dz = 0.2 * np.cos(0.1 * r_squared)
    return [3*dx, 3*dy, 3*dz]

vehicles = ['auv0', 'auv1']
map_dimensions = [100, 100, 35]

with holoocean.make(scenario_cfg=scenario, start_world=False) as env:
    clock = 0
    while True:
        clock += 1
        if clock == 2000:
            env.draw_debug_vector_field(vortex_field, location=[0, 0, 0], vector_field_dimensions=map_dimensions, arrow_thickness=7, arrow_size=.25, spacing=3)
        tick_info = env.tick()
        command = parse_keys(pressed_keys, force)
        env.act("auv0", command)

        # Apply currents
        for vehicle in vehicles:
            location = tick_info[vehicle]['LocationSensor']
            current_velocity = vortex_field(location)
            env.set_ocean_currents(vehicle, current_velocity)