基于卫星星历计算卫星在CGCS2000大地坐标系中的坐标

news2025/2/13 12:55:25

目录

一、北斗系统概述

1.空间星座

2.坐标系统

3.时间系统

二、实验目的

三、实验内容

四、实验过程

五、实验结果


一、北斗系统概述

1.空间星座

北斗卫星导航系统简称北斗系统,英文缩写为 BDS,其空间星座由 5 颗地球静止轨道(GEO)卫星、27 颗中圆地球轨道(MEO)卫星和 3 颗倾 斜地球同步轨道(IGSO)卫星组成。GEO 卫星轨道高度 35786 千米,分别 定点于东经 58.75 度、80 度、110.5 度、140 度和 160 度;MEO 卫星轨道高 度 21528 千米,轨道倾角 55 度;IGSO 卫星轨道高度 35786 千米,轨道倾 角 55 度。

2.坐标系统

北斗系统采用 2000 中国大地坐标系(CGCS2000)。CGCS2000 大地坐 标系的定义如下: 原点位于地球质心; Z 轴指向国际地球自转服务组织(IERS)定义的参考极(IRP)方向; X 轴为 IERS 定义的参考子午面(IRM)与通过原点且同 Z 轴正交的赤 道面的交线; Y 轴与 Z、X 轴构成右手直角坐标系。 CGCS2000 原点也用作 CGCS2000 椭球的几何中心,Z 轴用作该旋转 椭球的旋转轴。CGCS2000 参考椭球定义的基本常数为:

长半轴:a = 6378137.0 m
地球(包含大气层)引力常数:

\mu = 3.986004418\times 10^{14} m^{3}/s^{2}

扁率:f = 1/298.257222101
地球自转角速度:\Omega e = 7.2921150\times 10^{-5} rad/s

3.时间系统

北斗系统的时间基准为北斗时(BDT)。BDT 采用国际单位制(SI)秒 为基本单位连续累计,不闰秒,起始历元为 2006 年 1 月 1 日协调世界时 (UTC)00 时 00 分 00 秒,采用周和周内秒计数。BDT 通过 UTC(NTSC) 与国际 UTC 建立联系,BDT 与 UTC 的偏差保持在 100 纳秒以内(模 1 秒)。 BDT 与 UTC 之间的闰秒信息在导航电文中播报。

二、实验目的

卫星星历是描述卫星轨道运动的一组参数,根据卫星星历可计算卫星的实时位置。通过本次实验,熟悉北斗卫星星历形式、基本参数及意义,并能根据卫星星历计算卫星位置。

三、实验内容

利用给定的卫星星历数据(badata.txt ),参考《北斗卫星导 航系统空间信号接口控制文件-公开服务信号(2.1 版)》,基于编程实现卫星在 CGCS2000 大地坐标系中的坐标计算。

四、实验过程

卫星的位置是通过卫星历书数据进行计算的。卫星历书数据包含了卫星的轨道参数、时间信息和其他相关参数。通过这些数据,我们可以推算出卫星在特定时间点的准确位置。

1.首先,代码打开一个输入文件,并使用缓冲流将文件内容读取到一个字符串中。这个输入文件包含了卫星历书数据,它的格式可能是一行一组数据,或者其他形式的文本格式。

2.接下来,代码使用链表和哈希映射等数据结构来存储卫星历书数据。链表用于按顺序存储每组数据,而哈希映射则用于快速查找某个特定的卫星数据。每组数据包含了卫星的编号、时间、轨道根数等信息。

3.然后,代码使用存储的数据进行卫星位置的计算。它通过一系列的数学公式和迭代算法来计算卫星的轨道参数。这些轨道参数包括半长轴、偏心率、轨道倾角、升交点赤经等。这些参数是描述卫星轨道形状和位置的重要信息。

4.根据计算得到的轨道参数,代码进一步计算卫星在三维空间中的位置坐标。这个过程涉及到坐标系的转换、时间的计算和向量运算等。

5.最后,代码将计算得到的卫星位置结果写入一个输出文件。输出文件通常包含卫星的编号和对应的位置坐标信息。这样,用户可以通过读取输出文件来获取卫星在特定时间点的准确位置。

6.除了主要的位置计算部分,代码还包括了一些辅助函数。这些函数用于计算儒略日(Julian Day)等时间相关的计算,以及矩阵乘法等基本数学运算。

源码:

import java.io.BufferedReader;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.math.BigDecimal;
import java.util.HashMap;
import java.util.LinkedList;

public class Test_GNSS {
    public static void main(String[] args) throws IOException {

        double miu = 3.986004418e+14;           //CGCS2000 坐标系下的地球引力常数
        double OmegaEdot = 7.2921150e-5;        //CGCS2000 坐标系下的地球旋转速率
        double DayToSecond = 24.0 * 3600.0d;    //天秒数

        //创建字符输入输对象来访问文件
        FileReader fileReader = new FileReader("D:\\juechen\\badata.txt");
        FileWriter fileWriter = new FileWriter("D:\\juechen\\badata_result.txt");

        //创建输入对象的缓冲流
        BufferedReader bufferedReader = new BufferedReader(fileReader);

        //将缓冲流写入字符串
        String inputData = bufferedReader.readLine();
        //System.out.println(inputData);

        //创建字符可变的字符串用来记录计算结果
        StringBuilder outputDta = new StringBuilder("PRN\tx\ty\tz\n");

        //创建相应的数据结构用来保存原始数据
        LinkedList<HashMap<String, String>> linkedList = new LinkedList<>();

        //将卫星星历数据存储在LinkedList中的计算过程
        for (int i = 0; i < 13; i++) {
            inputData = bufferedReader.readLine();

            //将读入的字符串保存在字符串数组中,当匹配到两个及以上的空格时,分割
            String[] newLineArray = inputData.split("[ ]{2,}");

            //将列名和所对应的数据存储在HashMap中
            HashMap<String, String> newLineHashMap = new HashMap<>();
            newLineHashMap.put("Epoch", newLineArray[0]);
            newLineHashMap.put("PRN", newLineArray[1]);
            newLineHashMap.put("WN", newLineArray[2]);
            newLineHashMap.put("toe", newLineArray[3]);

            //对超过16位有效位的数用BigDecimal进行有效存储,提高精度
            BigDecimal db = new BigDecimal(newLineArray[4]);
            newLineHashMap.put("SqrtA", db.toPlainString());
            db = new BigDecimal(newLineArray[5]);
            newLineHashMap.put("e", db.toPlainString());
            db = new BigDecimal(newLineArray[6]);
            newLineHashMap.put("i", db.toPlainString());
            db = new BigDecimal(newLineArray[7]);
            newLineHashMap.put("Omega0", db.toPlainString());
            db = new BigDecimal(newLineArray[8]);
            newLineHashMap.put("w", db.toPlainString());
            db = new BigDecimal(newLineArray[9]);
            newLineHashMap.put("M", db.toPlainString());
            db = new BigDecimal(newLineArray[10]);
            newLineHashMap.put("deltaN", db.toPlainString());
            db = new BigDecimal(newLineArray[11]);
            newLineHashMap.put("OmegaDot", db.toPlainString());
            db = new BigDecimal(newLineArray[12]);
            newLineHashMap.put("idot", db.toPlainString());
            newLineHashMap.put("Crs", newLineArray[13]);
            newLineHashMap.put("Crc", newLineArray[14]);
            db = new BigDecimal(newLineArray[15]);
            newLineHashMap.put("Cus", db.toPlainString());
            db = new BigDecimal(newLineArray[16]);
            newLineHashMap.put("Cuc", db.toPlainString());
            db = new BigDecimal(newLineArray[17]);
            newLineHashMap.put("Cis", db.toPlainString());
            db = new BigDecimal(newLineArray[18]);
            newLineHashMap.put("Cic", db.toPlainString());
            newLineHashMap.put("toc", newLineArray[19]);
            db = new BigDecimal(newLineArray[20]);
            newLineHashMap.put("a0", db.toPlainString());
            db = new BigDecimal(newLineArray[21]);
            newLineHashMap.put("a1", db.toPlainString());
            db = new BigDecimal(newLineArray[22]);
            newLineHashMap.put("a3", db.toPlainString());

            //保存原始数据
            linkedList.add(newLineHashMap);
        }

        //用linkList存储的每一组卫星星历数据来计算卫星位置
        for (int i = 0; i < 13; i++) {
            HashMap<String, String> calculateHashMap = linkedList.get(i);

            //计算观测时间的儒略日
            String[] date_time = calculateHashMap.get("Epoch").split(" ");
            String date = date_time[0];
            String time = date_time[1];
            double[] timeD = new double[]{Double.parseDouble(date.split("-")[0]), Double.parseDouble(date.split("-")[1]), Double.parseDouble(date.split("-")[2])};
            double[] timeH = new double[]{Double.parseDouble(time.split(":")[0]), Double.parseDouble(time.split(":")[1]), Double.parseDouble(time.split(":")[2])};
            double EpochT = calculateJD(timeD[0], timeD[1], timeD[2], timeH[0], timeH[1], timeH[2]) - calculateJD(2006d, 1d, 1d, 0, 0, 0);

            //计算半长轴
            double A = Math.pow(Double.parseDouble(calculateHashMap.get("SqrtA")), 2);

            //计算卫星平均角速度
            double n0 = Math.sqrt(miu / Math.pow(A, 3));

            //计算观测历元到参考历元的时间差
            double tk = (EpochT - Double.parseDouble(calculateHashMap.get("WN")) * 7.0d) * DayToSecond - Double.parseDouble(calculateHashMap.get("toe"));

            //计算改正平均角速度
            double n = n0 + Double.parseDouble(calculateHashMap.get("deltaN"));

            //计算平近点角
            double Mk = Double.parseDouble(calculateHashMap.get("M")) + n * tk;

            //迭代计算偏近点角
            double delta = 1.0D;
            double Ek = Mk;
            double k = 0L;
            double e = Double.parseDouble(calculateHashMap.get("e"));
            while (Math.abs(delta) > 0.0000001D && k <= 1000l) {
                Ek = Ek - delta / (1 - e * Math.cos(Ek));
                delta = Ek - e * Math.sin(Ek) - Mk;
                k = k + 1;
            }

            //计算真近点角
            double sinvk = (Math.sqrt(1 - Math.pow(e, 2)) * Math.sin(Ek)) / (1 - e * Math.cos(Ek));
            double cosvk = (Math.cos(Ek) - e) / (1 - e * Math.cos(Ek));

            //计算vk
            double vk = 0;
            if (sinvk >= 0 && cosvk >= 0) {
                vk = Math.asin(sinvk);
            } else if (sinvk >= 0 && cosvk < 0) {
                vk = Math.PI - Math.asin(sinvk);
            } else if (sinvk < 0 && cosvk >= 0) {
                vk = Math.PI * 2 + Math.asin(sinvk);
            } else if (sinvk < 0 && cosvk < 0) {
                vk = Math.PI - Math.asin(sinvk);
            }

            //计算纬度幅角参数faik
            double faik = vk + Double.parseDouble(calculateHashMap.get("w"));

            //计算纬度幅角改正项duk、径向改正项drk、轨道倾角改正项dik
            double duk = Double.parseDouble(calculateHashMap.get("Cus")) * Math.sin(2 * faik) + Double.parseDouble(calculateHashMap.get("Cus")) * Math.cos(2 * faik);
            double drk = Double.parseDouble(calculateHashMap.get("Crs")) * Math.sin(2 * faik) + Double.parseDouble(calculateHashMap.get("Crs")) * Math.cos(2 * faik);
            double dik = Double.parseDouble(calculateHashMap.get("Cis")) * Math.sin(2 * faik) + Double.parseDouble(calculateHashMap.get("Cis")) * Math.cos(2 * faik);

            //计算改正后的纬度幅角uk
            double uk = faik + duk;

            //计算改正后的径向rk
            double rk = A * (1 - e * Math.cos(Ek)) + drk;

            //计算改正后的轨道倾角ik
            double ik = Double.parseDouble(calculateHashMap.get("i")) + Double.parseDouble(calculateHashMap.get("idot")) * tk + dik;

            //计算卫星在轨道平面内的坐标(xk,yk)
            double xk = rk * Math.cos(uk);
            double yk = rk * Math.sin(uk);

            //计算历元升交点赤经(地固系)
            //计算 MEO/IGSO 卫星在 CGCS2000 坐标系中的坐标(Xk,Yk,Zk)
            double Omegak = 0;
            double Xk = 0;
            double Yk = 0;
            double Zk = 0;
            if (Double.parseDouble(calculateHashMap.get("i")) > 0) {
                Omegak = Double.parseDouble(calculateHashMap.get("Omega0")) + (Double.parseDouble(calculateHashMap.get("OmegaDot")) - OmegaEdot) * tk - OmegaEdot * Double.parseDouble(calculateHashMap.get("toe"));
                Xk = xk * Math.cos(Omegak) - yk * Math.cos(ik) * Math.sin(Omegak);
                Yk = xk * Math.sin(Omegak) + yk * Math.cos(ik) * Math.cos(Omegak);
                Zk = yk * Math.sin(ik);
            }

            //计算历元升交点的赤经(惯性系)
            //计算 GEO 卫星在自定义坐标系系中的坐标(Xgk,Ygk,Zgk)
            //计算 GEO 卫星在 CGCS2000 坐标系中的坐标(Xk,Yk,Zk)
            double Xgk = 0;
            double Ygk = 0;
            double Zgk = 0;
            double Rxf = 0;
            double Rzf = 0;
            double[][] Rz = null;
            double[][] Rx = null;
            double[][] Rgk = null;
            double[][] XYZ = null;
            if (Double.parseDouble(calculateHashMap.get("i")) == 0) {
                Omegak = Double.parseDouble(calculateHashMap.get("Omega0")) + Double.parseDouble(calculateHashMap.get("OmegaDot")) * tk - OmegaEdot * Double.parseDouble("toe");
                Xgk = xk * Math.cos(Omegak) - yk * Math.cos(ik) * Math.sin(Omegak);
                Ygk = xk * Math.sin(Omegak) + yk * Math.cos(ik) * Math.cos(Omegak);
                Zgk = yk * Math.sin(ik);
                Rxf = -5.0 * Math.PI / 180.0D;
                Rzf = OmegaEdot * tk;
                Rx = new double[][]{{1D, 0D, 0D}, {0D, Math.cos(Rxf), Math.sin(Rxf)}, {0d, -Math.sin(Rxf), Math.cos(Rxf)}};
                Rz = new double[][]{{Math.cos(Rzf), Math.sin(Rzf), 0d}, {-Math.sin(Rzf), Math.cos(Rzf), 0d}, {0d, 0d, 1d}};
                Rgk = new double[][]{{Xgk}, {Ygk}, {Zgk}};
                XYZ = matrixMultiplication(matrixMultiplication(Rz, Rx), Rgk);
                Xk = XYZ[0][0];
                Yk = XYZ[0][1];
                Zk = XYZ[0][2];
            }

            //将计算结果添加到字符串
            outputDta.append(calculateHashMap.get("PRN") + "\t" + Xk + "\t" + Yk + "\t" + Zk + "\n");
        }

        //将字符串写入输出对象文件
        fileWriter.write(outputDta.toString());

        //回收资源
        bufferedReader.close();
        fileReader.close();
        fileWriter.close();
    }

    //计算儒略日
    static double calculateJD(double y, double mon, double d, double h, double miu, double s) {
        double day = d + (h * 3600 + miu * 60 + s) / 86400;
        double year = y + 4800;
        double m = mon;
        if (m < 2) {
            m = m + 12;
            year = year - 1;
        }
        double a = Math.floor(30.6 * (m + 1));
        double b = 0;
        if (y < 1582 || (y == 1582 && mon < 10) || (y == 1582 && mon == 10 && d < 5)) {
            b = -38;
        } else {
            b = Math.floor((y / 400) - (y / 100));
        }
        double c = Math.floor(365.25 * year);
        return (a + b + c + day);
    }

    //矩阵乘法
    static double[][] matrixMultiplication(double[][] A, double[][] B) {
        int line = A.length;        //矩阵A第一维长度(行)
        int column = B[0].length;   //矩阵B第二维长度(列)
        double[][] result = new double[line][column];   //定位结果矩阵大小
        for (int i = 0; i < A.length; i++) {            //矩阵A的行数
            for (int j = 0; j < B[0].length; j++) {     //矩阵B的列数
                double sum = 0;

                //矩阵的每一行乘以每一列
                for (int k = 0; k < B.length; k++) {
                    sum += A[i][k] * B[k][j];
                }
                result[i][j] = sum;
            }
        }
        return result;
    }
}

五、实验结果

需要注意的是:

确保程序中使用的坐标系和单位的一致性。确保在计算过程中使用了正确的时间表达方式和相关的算法,以避免时间误差引起的计算错误。确保代码的可读性,采用良好的编码规范和注释。

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

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

相关文章

​“前端已死”甚嚣尘上,全栈工程师卷到起飞

海量应届生入场&#xff0c;坑位却还是那多。具备前后端开发能力的全栈工程师兴起&#xff0c;不仅能够开发前端&#xff0c;还能够处理后端业务逻辑和数据库等技术&#xff0c;还能掌握整个软件开发的细节。企业自然会更愿意招聘全栈工程师&#xff0c;说白了&#xff0c;卷啊…

springboot整合quartz实现定时任务动态增删改查

springboot整合quartz quartz介绍Quartz 核心概念 使用依赖配置文件启动类quartz工具类job业务用到的对象类接口service实现类测试 quartz介绍 Quartz是OpenSymphony开源组织在Job scheduling领域又一个开源项目&#xff0c;它可以与J2EE与J2SE应用程序相结合也可以单独使用。…

【CMake 入门与进阶(6)】 CMakeLists.txt 部分常用变量(附使用代码)

变量也是 cmake 中的一个重头戏&#xff0c;cmake 提供了很多内置变量&#xff0c;每一个变量都有它自己的含义&#xff0c;通过这个链接地址cmake-variables(7) — CMake 3.5.2 Documentation可以查询到所有的内置变量及其相应的介绍&#xff0c;如下所示&#xff1a; 在这一份…

App移动端测试 —— Monkey的日志

Monkey的日志对于分析脚本的执行情况十分必要。 Monkey 日志由以下几部分组成&#xff1a; 测试命令信息&#xff1a;随机种子 seed、运行次数、可运行应用列表、各事件百分比。” 正文内容从这里开始&#xff08;可直接省略&#xff0c;亦可配图说明&#xff09;。 01—Mon…

使用python批量处理工作簿和工作表

案例01 批量新建并保存工作簿 将for语句与xlwings模块相结合&#xff0c;就可以轻松实现批量创建工作簿 import xlwings as xw # 导入xlwings模块 app xw.App(visibleTrue,add_bookFalse) # 启动Excel程序&#xff0c;但不新建工作簿 for i in range(6):workbook app.books…

Pyinstaller 快速找出所需库的方法

目录 【auto-py-to-exe】第三方库 使用【auto-py-to-exe】逐步尝试 1.什么文件都不添加&#xff0c;选择项目与单目录后直接打包 2.直接运行生成的exe文件 3.定位所需的包 4.--add-data 和 --hidden-import 打包为一个exe文件 【auto-py-to-exe】第三方库 其是pyinstaller操…

【头歌-Python】9.1 X射线衍射曲线绘制(project)第3~4关

第3关&#xff1a;X 射线衍射曲线峰值 任务描述 本关任务&#xff1a;读文件中的数据绘制线图形并加绘制峰值。 相关知识 为了完成本关任务&#xff0c;你需要掌握&#xff1a; python 读取文件中的数据使用 matplotlib 绘制图形 python 读取文件 python读取文件可以用以…

6.volatile与JMM

volatile与JMM 6.1 被volatile修饰的变量有两大特点 特点&#xff1a; 可见性 有序性&#xff1a;有排序要求&#xff0c;有时需要禁重排 内存语义&#xff1a; 当写一个volatile变量时&#xff0c;JMM会把该线程对应的本地内存中的共享变量值立即刷新回主内存中 当读一个vol…

Linux:ftp服务 (vsftpd)

我的ftp服务器为centos7 使用yum安装的vsftpd软件 &#xff08;如果你需要离线yum库&#xff0c;而不会搭建可以查看&#xff09; Linux&#xff1a;rpm查询安装 && yum安装_鲍海超-GNUBHCkalitarro的博客-CSDN博客 安装软件 配置环境 其次是Linux的防火墙和selinu…

写一个Orillusion编辑器(伪)

界面效果 思路 bootstrap控制界面效果jquery动态修改界面内容[Add]增加一个box[Play]导出play.html,打开play.html就可以看到程序运行效果 编辑器代码 <!DOCTYPE html> <html> <!-- TODO 1. 序列化数据,保存工程 2. 反序列化数据,打开工程 --><head>…

Python实现ACO蚁群优化算法优化随机森林回归模型(RandomForestRegressor算法)项目实战

说明&#xff1a;这是一个机器学习实战项目&#xff08;附带数据代码文档视频讲解&#xff09;&#xff0c;如需数据代码文档视频讲解可以直接到文章最后获取。 1.项目背景 蚁群优化算法(Ant Colony Optimization, ACO)是一种源于大自然生物世界的新的仿生进化算法&#xff0c…

腾讯安全SOC+荣获“鑫智奖”,助力金融业数智化转型

近日&#xff0c;由金科创新社主办&#xff0c;全球金融专业人士协会支持的“2023鑫智奖第五届金融数据智能优秀解决方案评选”榜单正式发布。腾讯安全申报的“SOC基于新一代安全日志大数据平台架构的高级威胁安全治理解决方案”获评“鑫智奖网络信息安全创新优秀解决方案”。 …

大数据分析平台释疑专用帖

大数据分析平台是大数据时代&#xff0c;企业数字化运营决策的一大关键平台&#xff0c;但初次接触大数据分析平台时&#xff0c;大家必然是问题多多的&#xff0c;本文将就几个比较常见的问题进行总结回答&#xff0c;希望对正在了解、选型大数据分析平台的大家有所帮助。 首…

Qt学习08:文本输入类与快捷键

文章首发于我的个人博客&#xff1a;欢迎大佬们来逛逛 文章目录 QLineEditQTextEditQTextCursor QPlainTextQKeySequenceEdit QLineEdit QLineEdit是最基本的输入控件&#xff0c;常用于短行的文本输入。 构造函数 QLineEdit(const QString &contents, QWidget *parent …

07_scrapy的应用——获取电影数据(通过excel保存静态页面scrapy爬虫数据的模板/通过数据库保存)

0、前言: 一般我们自己创建的一些python项目,我们都需要创建虚拟环境,其中会下载很多包,也叫做依赖。但是我们在给他人分享我们的项目时,不能把虚拟环境打包发送给别人,因为每个人电脑系统不同,我们可以把依赖导出为依赖清单,然后别人有了我们的依赖清单,就可以用一条…

[网络工程师]-网络规划与设计-网络测试运行和维护(二)

4、局域网测试 局域网测试主要是检验网络是否为应用系统提供了稳定、高效的网络平台,如果网络系统不够稳定,网络应用就不可能快速稳定。对于常规的以太网进行系统测试,主要包括系统连通性、链路传输速率、吞吐率、传输时延、丢包率及链路层健康状况测试等基本功能测试。 4.…

用那种方式安装 ThinkPHP 5.0?

简单介绍 ThinkPHP是一个免费开源的&#xff0c;快速、简单的面向对象的轻量级PHP开发框架&#xff0c;是为了敏捷WEB应用开发和简化企业应用开发而诞生的。 ThinkPHP5.0版本是一个颠覆和重构版本&#xff0c;采用全新的架构思想&#xff0c;引入了更多的PHP新特性&#xff0c…

分享几个免费 AI 生成工具 (第一期)

今天来给大家分享几个国外免费的AI视频生成工具 Artflow ai https://app.artflow.ai Artflow.ai 是一款人工智能工具&#xff0c;旨在帮助用户创建自定义头像并让他们的故事栩栩如生。主要特点和优势包括&#xff1a; 自定义创作&#xff1a;从文本中生成角色、场景和声音&…

利用C语言实现十大经典排序算法的方法

排序算法 算法分类 —— 十种常见排序算法可以分为两大类&#xff1a; 比较类排序&#xff1a;通过比较来决定元素间的相对次序&#xff0c;由于其时间复杂度不能突破O(nlogn)&#xff0c;因此也称为非线性时间比较类排序。 非比较类排序&#xff1a;不通过比较来决定元素间…

《实战AI低代码》:一场新的软件工程革命

目录 五十年前的软件危机 二十年前的软件危机 今天的软件危机 革命性的新技术 AI低代码开发宣言 AI低代码开发原则 一场新的软件工程革命 AI低代码开发不仅是继面向过程,面向对象之后的一种新的抽象方式,也是继瀑布开发,敏捷开发之后的一种新的开发方法。 五十年前的…