【Nomoto 船舶模型】

【Nomoto 船舶模型】

  • 1. Nomoto 船舶模型简介
  • 2. 来源及发展历程
  • 3. 构建 一阶模型Nomoto 船舶模型
    • 3.1 C++ 实现
    • 3.2 Python 实现
    • 3.3 说明
  • 5. 参数辨识方法
    • 5.1 基于最小二乘法的参数辨识
    • 5.2 数学推导
    • 5.3 Python 实现
    • 5.4 说明
  • 4. 结论
  • 参考文献

1. Nomoto 船舶模型简介

Nomoto 模型是由日本学者 T. Nomoto 于上世纪50年代提出的一种用于描述船舶操纵运动的数学模型。它最初是为了解决船舶在操舵时的动态响应问题,并且因其简单性和实用性而被广泛应用于航海工程和船舶自动控制领域。Nomoto 模型通过简化实际的水动力特性来预测船舶在舵角输入下的响应,适用于初步分析和控制系统设计。
参考学习:https://github.com/martinlarsalbert/blog/blob/master/_notebooks/2020-08-25-nomoto_model.ipynb

在这里插入图片描述

2. 来源及发展历程

Nomoto 模型的发展经历了多个阶段,从最初的一阶模型扩展到二阶甚至更高阶模型,以更准确地描述船舶的动态行为。尽管存在更复杂的模型(如 Abkowitz 整体模型、MMG 分离型模型、Fossen 的矩阵向量形式模型),Nomoto 模型由于其简洁性仍然在许多应用中具有重要地位。

3. 构建 一阶模型Nomoto 船舶模型

Nomoto 模型通常用以下微分方程表示:

τ 1 d ψ d t + ψ = K δ \tau_1 \frac{d\psi}{dt} + \psi = K \delta τ1dtdψ+ψ=

其中:

  • ψ \psi ψ 是船舶的航向角(偏航角),单位为弧度。
  • δ \delta δ是舵角,单位为弧度。
  • K K K 是比例增益,表征舵角对航向角变化的影响程度。
  • τ 1 \tau_1 τ1 是时间常数,代表系统的时间响应特性。

3.1 C++ 实现

下面是一个简单的C++代码示例,用于模拟Nomoto模型的行为:

#include <iostream>
#include <cmath>class NomotoModel {
public:NomotoModel(double tau, double K) : tau_(tau), K_(K), psi_(0.0), dpsi_dt_(0.0) {}// 更新状态void update(double delta, double dt) {// 计算导数double d2psi_dt2 = (-1.0 / tau_) * dpsi_dt_ + (K_ / tau_) * delta;// 使用欧拉法更新状态dpsi_dt_ += d2psi_dt2 * dt;psi_ += dpsi_dt_ * dt;// 确保航向角在 [-pi, pi] 范围内while (psi_ > M_PI) psi_ -= 2 * M_PI;while (psi_ < -M_PI) psi_ += 2 * M_PI;}// 获取当前航向角double getHeading() const { return psi_; }private:double tau_, K_;  // 模型参数double psi_;      // 当前航向角double dpsi_dt_;  // 当前航向角速度
};int main() {// 定义模型参数double tau = 5.0;  // 时间常数double K = 0.05;   // 比例增益// 创建 Nomoto 模型实例NomotoModel model(tau, K);// 模拟时间步长和总时间double dt = 0.1;  // 时间步长 (秒)double totalTime = 30.0;  // 总模拟时间 (秒)// 设置初始舵角double delta = M_PI / 6;  // 初始舵角为 30 度for (double t = 0; t <= totalTime; t += dt) {// 更新模型状态model.update(delta, dt);// 输出当前时间和航向角std::cout << "Time: " << t << "s, Heading: " << model.getHeading() * 180.0 / M_PI << " degrees" << std::endl;}return 0;
}

3.2 Python 实现

下面是等效的Python代码实现:

import mathclass NomotoModel:def __init__(self, tau, K):self.tau_ = tauself.K_ = Kself.psi_ = 0.0self.dpsi_dt_ = 0.0# 更新状态def update(self, delta, dt):# 计算导数d2psi_dt2 = (-1.0 / self.tau_) * self.dpsi_dt_ + (self.K_ / self.tau_) * delta# 使用欧拉法更新状态self.dpsi_dt_ += d2psi_dt2 * dtself.psi_ += self.dpsi_dt_ * dt# 确保航向角在 [-pi, pi] 范围内while self.psi_ > math.pi:self.psi_ -= 2 * math.piwhile self.psi_ < -math.pi:self.psi_ += 2 * math.pi# 获取当前航向角def get_heading(self):return self.psi_if __name__ == "__main__":# 定义模型参数tau = 5.0  # 时间常数K = 0.05   # 比例增益# 创建 Nomoto 模型实例model = NomotoModel(tau, K)# 模拟时间步长和总时间dt = 0.1  # 时间步长 (秒)total_time = 30.0  # 总模拟时间 (秒)# 设置初始舵角delta = math.pi / 6  # 初始舵角为 30 度for t in range(int(total_time / dt)):current_time = t * dt# 更新模型状态model.update(delta, dt)# 输出当前时间和航向角print(f"Time: {current_time:.1f}s, Heading: {math.degrees(model.get_heading()):.2f} degrees")

3.3 说明

  • 参数解释

    • tau:时间常数,反映了系统的惯性特性。
    • K:比例增益,决定了舵角对航向角变化的影响程度。
  • 数值积分方法

    • 在上述实现中,使用了简单的欧拉法进行数值积分。对于更精确的仿真,可以考虑使用更高阶的数值积分方法,如龙格-库塔法(Runge-Kutta method)。
  • 角度范围限制

    • 为了确保航向角保持在合理的范围内,使用了 while 循环将角度限制在 ([-π, π]) 之间。
      Nomoto 模型参数辨识是指通过实验数据或仿真结果来确定模型中的未知参数,如时间常数 (\tau) 和比例增益 (K)。对于 Nomoto 一阶模型:

τ d ψ d t + ψ = K δ \tau \frac{d\psi}{dt} + \psi = K \delta τdtdψ+ψ=

其中:

  • KaTeX parse error: Undefined control sequence: \ps at position 1: \̲p̲s̲是船舶的航向角(偏航角)。
  • δ \delta δ是舵角。
  • KaTeX parse error: Undefined control sequence: \K at position 1: \̲K̲是比例增益,表征舵角对航向角变化的影响程度。
  • τ \tau τ 是时间常数,代表系统的时间响应特性。

5. 参数辨识方法

实现参数辨识通常需要以下步骤:

  1. 实验设计:进行操舵实验,记录船舶在不同舵角下的航向角随时间的变化情况。
  2. 数据预处理:清洗和整理实验数据,确保其适用于后续分析。
  3. 选择辨识方法:根据问题的具体情况选择合适的参数辨识方法,常用的有最小二乘法、递推最小二乘法、极大似然估计等。
  4. 参数优化:利用选定的方法估计模型参数,使模型预测值与实际观测值之间的误差最小化。

下面介绍一种基于最小二乘法的简单参数辨识方法,并提供相应的 Python 实现示例。

5.1 基于最小二乘法的参数辨识

假设我们已经有一组实验数据,包含时间序列 t、舵角序列 delta 和航向角序列 psi。我们的目标是找到最优的 (\tau) 和 (K),使得模型预测值与实际观测值之间的误差平方和最小。

5.2 数学推导

首先将 Nomoto 模型重写为离散形式:

ψ k + 1 = ( 1 − Δ t τ ) ψ k + Δ t τ K δ k \psi_{k+1} = (1 - \frac{\Delta t}{\tau}) \psi_k + \frac{\Delta t}{\tau} K \delta_k ψk+1=(1τΔt)ψk+τΔtKδk

其中 Δ t \Delta t Δt 是采样间隔, k k k 表示第 k k k 个采样点。

定义误差函数 E E E 为:

E ( τ , K ) = ∑ k = 1 N ( ψ k model − ψ k data ) 2 E(\tau, K) = \sum_{k=1}^{N} (\psi_k^{\text{model}} - \psi_k^{\text{data}})^2 E(τ,K)=k=1N(ψkmodelψkdata)2

其中 ψ k model \psi_k^{\text{model}} ψkmodel是模型预测的航向角, ψ k data \psi_k^{\text{data}} ψkdata 是实验数据中的航向角。

我们的目标是最小化 E ( τ , K ) E(\tau, K) E(τ,K)

5.3 Python 实现

以下是使用 Python 和 SciPy 库进行参数辨识的示例代码:

import numpy as np
from scipy.optimize import minimize
import matplotlib.pyplot as plt# 定义模型函数
def nomoto_model(params, delta, dt):tau, K = paramspsi_model = [0]  # 初始航向角设为0for k in range(1, len(delta)):psi_next = (1 - dt / tau) * psi_model[-1] + (dt / tau) * K * delta[k]psi_model.append(psi_next)return np.array(psi_model)# 定义误差函数
def error_function(params, delta, dt, psi_data):psi_model = nomoto_model(params, delta, dt)return np.sum((psi_model - psi_data) ** 2)# 生成模拟数据(用于测试)
np.random.seed(0)
time = np.linspace(0, 30, 300)
dt = time[1] - time[0]
delta = np.zeros_like(time)
delta[50:100] = np.radians(10)  # 设置舵角为10度
delta[150:200] = np.radians(-10)  # 设置舵角为-10度# 真实参数
true_tau = 5.0
true_K = 0.05# 使用真实参数生成模拟的航向角数据
psi_true = nomoto_model([true_tau, true_K], delta, dt)
psi_data = psi_true + np.random.normal(0, 0.01, size=psi_true.shape)  # 添加噪声# 参数辨识
initial_guess = [1.0, 0.1]  # 初始猜测值
result = minimize(error_function, initial_guess, args=(delta, dt, psi_data), method='L-BFGS-B')estimated_tau, estimated_K = result.x
print(f"Estimated parameters: tau = {estimated_tau:.3f}, K = {estimated_K:.3f}")# 绘制结果
plt.figure(figsize=(10, 6))
plt.plot(time, np.degrees(psi_data), label="Noisy Data", linestyle='--')
plt.plot(time, np.degrees(nomoto_model([true_tau, true_K], delta, dt)), label="True Model")
plt.plot(time, np.degrees(nomoto_model(result.x, delta, dt)), label="Estimated Model")
plt.xlabel("Time (s)")
plt.ylabel("Heading Angle (degrees)")
plt.legend()
plt.show()

5.4 说明

  1. 数据生成:为了测试辨识算法的效果,我们首先生成了一组带有噪声的模拟数据。这里使用了真实的参数 (\tau) 和 (K) 来生成模拟的航向角数据,并添加了一些随机噪声以模拟实际情况。

  2. 误差函数:定义了一个误差函数 error_function,它计算模型预测值与实验数据之间的误差平方和。

  3. 参数辨识:使用 SciPy 的 minimize 函数来最小化误差函数,从而估计出最佳的 (\tau) 和 (K) 值。这里选择了 L-BFGS-B 方法作为优化算法,因为它适合处理有界的参数空间。

  4. 结果展示:最后,绘制了原始数据、真实模型输出以及辨识得到的模型输出,以便直观地比较它们之间的差异。

上述方法是一个简单的实现,适用于初步的参数辨识任务。在实际应用中,可能需要考虑以下几个方面进行改进:

  • 更复杂的模型:如果需要更高的精度,可以考虑使用更高阶的 Nomoto 模型或其他更为复杂的船舶操纵模型。
  • 鲁棒性:针对不同的噪声水平和数据质量,优化算法的选择和参数初始化可能会有所不同。
  • 实时辨识:在某些应用场景下,可能需要在线实时地更新模型参数,这时可以考虑使用递推最小二乘法等在线学习算法。

4. 结论

Nomoto 模型提供了一种简便的方法来描述船舶的操纵行为,适用于初步分析和控制系统设计。尽管它有一定的局限性,但在很多情况下已经足够有效。对于更精确的模拟和控制需求,可以考虑使用更复杂的模型,如 MMG 分离型模型或 Fossen 的矩阵向量形式模型。

通过【Nomoto 船舶模型C++与python实现】学习,您应该能够用Nomoto 船舶模型描述船舶的操纵行为。从而实现对外部世界进行感知,充分认识这个有机与无机的环境,科学地合理地进行创作和发挥效益,然后为人类社会发展贡献一点微薄之力。🤣🤣🤣

  1. 我会持续更新对应专栏博客,非常期待你的三连!!!🎉🎉🎉
  2. 如果鹏鹏有哪里说的不妥,还请大佬多多评论指教!!!👍👍👍
  3. 下面有我的🐧🐧🐧群推广,欢迎志同道合的朋友们加入,期待与你的思维碰撞😘😘😘

参考文献

  • Nomoto, K., Taguchi, K., Honda, K., & Hirano, S. (1957). On the Steering Qualities of Ships. International Shipbuilding Progress, 4(35), 354-370.
  • Fossen, T. I. (2011). Handbook of Marine Craft Hydrodynamics and Motion Control. John Wiley & Sons.

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/web/66942.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

差分进化算法 (Differential Evolution) 算法详解及案例分析

差分进化算法 (Differential Evolution) 算法详解及案例分析 目录 差分进化算法 (Differential Evolution) 算法详解及案例分析1. 引言2. 差分进化算法 (DE) 算法原理2.1 基本概念2.2 算法步骤3. 差分进化算法的优势与局限性3.1 优势3.2 局限性4. 案例分析4.1 案例1: 单目标优化…

深入理解GPT底层原理--从n-gram到RNN到LSTM/GRU到Transformer/GPT的进化

从简单的RNN到复杂的LSTM/GRU,再到引入注意力机制,研究者们一直在努力解决序列建模的核心问题。每一步的进展都为下一步的突破奠定了基础,最终孕育出了革命性的Transformer架构和GPT大模型。 1. 从n-gram到循环神经网络(RNN)的诞生 1.1 N-gram 模型 在深度学习兴起之前,处理…

【JWT】jwt实现HS、RS、ES、ED签名与验签

JWT 实现 HS、RS、ES 和 ED 签名与验签 签名方式算法密钥类型签名要点验签要点HSHMAC-SHA256对称密钥- 使用 crypto/hmac 和对称密钥生成 HMAC 签名- 将 header.payload 作为数据输入- 使用同一密钥重新计算 HMAC 签名- 比较计算结果与接收到的签名是否一致RSRSA-SHA256公钥 …

地址栏信息location

获取信息 页面跳转 location.href当前地址栏信息 location.assign()设置跳转新的页面 location.replace() location.reload()刷新页面

程序员转型测试:解锁漏洞挖掘新旅程

前言&#xff1a;哈喽&#xff0c;大家好&#xff0c;今天给大家分享一篇文章&#xff01;并提供具体代码帮助大家深入理解&#xff0c;彻底掌握&#xff01;创作不易&#xff0c;如果能帮助到大家或者给大家一些灵感和启发&#xff0c;欢迎收藏关注哦 &#x1f495; 目录 程序…

StarRocks常用命令

目录 1、StarRocks 集群管理&配置命令 2、StarRocks 常用操作命令 3、StarRocks 数据导入和导出 1、StarRocks 集群管理&配置命令 查询 FE 节点信息 SHOW frontends; SHOW PROC /frontends; mysql -h192.168.1.250 -P9030 -uroot -p -e "SHOW PROC /dbs;"…

08-ArcGIS For JavaScript-通过Mesh绘制几何体(Cylinder,Circle,Box,Pyramid)

目录 概述代码实现1、Mesh.createBox2、createPyramid3、Mesh.createSphere4、Mesh.createCylinder 完整代码 概述 对于三维场景而言&#xff0c;二位的点、线、面&#xff0c;三维的圆、立方体、圆柱等都是比较常见的三维对象&#xff0c;在ArcGIS For JavaScript中我们知道点…

Linux中page、buffer_head、bio的关系

在Linux中&#xff0c;page、buffer_head、bio这三个概念紧密相关&#xff0c;共同构成了块设备I/O和内存管理的重要部分&#xff0c;它们的联系主要体现在以下方面&#xff1a; page与buffer_head 基于page构建&#xff1a;buffer_head通常是基于page来构建的&#xff0c;一…

直线拟合例子 ,岭回归拟合直线

目录 直线拟合,算出离群点 岭回归拟合直线&#xff1a; 直线拟合,算出离群点 import cv2 import numpy as np# 输入的点 points np.array([[51, 149],[122, 374],[225, 376],[340, 382],[463, 391],[535, 298],[596, 400],[689, 406],[821, 407] ], dtypenp.float32)# 使用…

SpringCloud两种注册中心

SpringCloud 基本概念 系统架构 我们之前做的所有的项目都属于单体架构&#xff0c;下面我们将要学习更适合大型项目的分布式架构 单体架构&#xff1a; 将业务的所有功能几种在一个项目中开发&#xff0c;打成一个包部署。 优点&#xff1a;架构简单、部署成本低 缺点&am…

SpringAI 搭建智能体(二):搭建客服系统智能体

在现代人工智能应用中&#xff0c;智能体&#xff08;Agent&#xff09; 是一个重要的概念&#xff0c;它的核心能力是自主性与灵活性。一个智能体不仅能够理解用户的需求&#xff0c;还能拆解任务、调用工具完成具体操作&#xff0c;并在复杂场景中高效运行。在本篇博客中&…

SVN客户端使用手册

目录 一、简介 二、SVN的安装与卸载 1. 安装&#xff08;公司内部一般会提供安装包和汉化包&#xff0c;直接到公司内部网盘下载即可&#xff0c;如果找不到可以看下面的教程&#xff09; 2. 查看SVN版本 ​编辑 3. SVN卸载 三、SVN的基本操作 1. 检出 2. 清除认证数据 3. 提交…

HTML 文本格式化详解

在网页开发中&#xff0c;文本内容的呈现方式直接影响用户的阅读体验。HTML 提供了多种文本格式化元素&#xff0c;可以帮助我们更好地控制文本的显示效果。本文将详细介绍 HTML 中的文本格式化元素及其使用方法&#xff0c;帮助你轻松实现网页文本的美化。 什么是 HTML 文本格…

衡量算法性能的量级标准:算法复杂度

今天开始数据结构的学习&#xff01;作为一大重点&#xff0c;拿出态度很重要&#xff0c;想要真实掌握&#xff0c;博客笔记自然少不了&#xff01;重点全部上色&#xff01;避免疏忽 下面我们从0基础开始学习今天的第一节&#xff01;不用担心看不懂&#xff0c;拒绝枯燥的理…

Spring Boot Starter介绍

前言 大概10来年以前&#xff0c;当时springboot刚刚出现并没有流行&#xff0c;当时的Java开发者们开发Web应用主要是使用spring整合springmvc或者struts、iBatis、hibernate等开发框架来进行开发。项目里一般有许多xml文件配置&#xff0c;其中配置了很多项目中需要用到的Be…

Java面试题2025-Spring

讲师&#xff1a;邓澎波 Spring面试专题 1.Spring应该很熟悉吧&#xff1f;来介绍下你的Spring的理解 1.1 Spring的发展历程 先介绍Spring是怎么来的&#xff0c;发展中有哪些核心的节点&#xff0c;当前的最新版本是什么等 通过上图可以比较清晰的看到Spring的各个时间版本对…

Linux 切换到 Root 用户的方式及差异详解

在 Linux 系统中&#xff0c;切换到 root 用户进行管理和操作是常见需求。不同的切换方法会影响环境变量、工作目录以及加载的配置文件。本文将介绍几种常用的切换方式及它们的特点。 切换到 Root 用户的主要方式 1. sudo su 这是通过 sudo 提权后调用 su 切换到 root 用户的…

虹科分享 | 汽车NVH小课堂之听音辨故障

随着车主开始关注汽车抖动异响问题&#xff0c;如何根据故障现象快速诊断异响来源&#xff0c;成了汽修人的必修课。 一个比较常用的方法就是靠“听”——“听音辨故障”。那今天&#xff0c;虹科Pico也整理了几个不同类型的异响声音&#xff0c;一起来听听看你能答对几个吧 汽…

浅谈Redis

2007 年&#xff0c;一位程序员和朋友一起创建了一个网站。为了解决这个网站的负载问题&#xff0c;他自己定制了一个数据库。于2009 年开发&#xff0c;称之为Redis。这位意大利程序员是萨尔瓦托勒桑菲利波(Salvatore Sanfilippo)&#xff0c;他被称为Redis之父&#xff0c;更…

element tbas增加下拉框

使用Tabs 标签页的label插槽&#xff0c;嵌入Dropdown 下拉菜单&#xff0c;实现Tabs 标签页增加下拉切换功能 Tabs 标签页 tab-click"事件"&#xff08;这个事件当中到拥有下拉框的tab里时&#xff0c;可以存一下Dropdown 第一个菜单的id&#xff0c;实现点击到拥有…