scienceasdf


  • 首页

  • 分类

  • 归档

  • 标签

Qt for Android实现与webview的交互

发表于 2018-04-23 | 分类于 Programming

在Qt的程序里搭建一个localhost,实现前端webview+html+js和后端C++的交互,该解决方案能够跨平台。


Qt要在移动端写浏览器只能用一些比较牵强的方案(如果不自己造轮子的话),就是QtWebView.然而QtWebView提供的接口太少,不方便C++与html交互,如果是写web应用就比较劣势,毕竟cordova,react native等的方案非常流行,如果无法前后端交互,纯一个静态页面实在不好玩,还不如把网页挂在互联网上用浏览器直接访问网页。在安卓上有一种可行的方案:C++通过jni与java交互,再与js对象交互。这个也有弊端,一个是不是跨平台的方案,第二个是我不会java,只会c++和js.在网上查到的另一种解决方法是搭建一个local server,通过http请求进行交互。

在GitHub上找到了一些用Qt搭建http server的代码(当然用boost也可以),例如QtWEbApp,QtWebApp。我最终用的是qhttpserver,star数目很多,比较可惜的是有一阵没有更新了,但是还是很好的一个东西。

这个程序按照GitHub直接下载下来的项目把代码编译,例子可以直接运行在安卓机上。例如运行例子Helloworld,那么在手机浏览器上打开http://localhost:8080,可以看到helloworld字样。按照release模式编译得到libqhttpserver.so,然后按照文档在自己的项目里面添加头文件包含和需要链接的库就可以了。

在Qt构建移动web应用有两种方案:网页资源放在qrc文件里面,运行时把qrc里面的内容全部复制到存储中,或者直接放在assets目录下(安卓的url格式为:file:///android_asset/site/groundTrackPlot.html,不能直接用assets目录访问,这个需要注意)。由于QtWebView只是一个原生浏览器的wrapper,因此不能直接访问qrc里面的文件。现在一种可行的解决方案是后端直接用QFile读取qrc文件,作为http请求的响应返回给前端:

class HelloWorld : public QObject
{
    Q_OBJECT

public:
    HelloWorld();

private slots:
    void handleRequest(QHttpRequest *req, QHttpResponse *resp);
};

HelloWorld::HelloWorld()
{
    QHttpServer *server = new QHttpServer(this);
    connect(server, SIGNAL(newRequest(QHttpRequest*, QHttpResponse*)),
            this, SLOT(handleRequest(QHttpRequest*, QHttpResponse*)));

    server->listen(QHostAddress::Any, 8080);
}

void HelloWorld::handleRequest(QHttpRequest *req, QHttpResponse *resp)
{
    Q_UNUSED(req);

    QByteArray body = req->path().toLocal8Bit();
    qDebug() << req->path();
    QFile file(":" + req->path());
    if (!file.open(QIODevice::ReadOnly)) {
        //return;
    }
    QByteArray data = QByteArray(file.readAll());
    qDebug() << data;
    resp->setHeader("Content-Length", QString::number(data.size()));
    resp->writeHead(200);
    resp->end(data);
    file.close();
}

在main主函数里直接调用在QApplication对象创建后就创建HelloWorld(这个http server),就可以实现想要的效果了。速度非常快,返回的数据量如果特别大那一定是渲染会花更多的时间而不是http请求的过程耗时间。用qrc的一个好处是编译成obj文件后占空间更小,而且不会被用户直接得到,但是编译会很花时间。

另外有时我们会需要Qt的http request是同步的,比如我们的localhost需要先访问一个外部的资源,再用得到的结果响应请求,那么代码如下

class HelloWorld : public QObject
{
    Q_OBJECT

public:
    HelloWorld();
    QByteArray get(const QString&);
    QNetworkAccessManager m_qnam;
private slots:
    void handleRequest(QHttpRequest *req, QHttpResponse *resp);
};

HelloWorld::HelloWorld() : m_qnam()
{
    QHttpServer *server = new QHttpServer(this);
    connect(server, SIGNAL(newRequest(QHttpRequest*, QHttpResponse*)),
            this, SLOT(handleRequest(QHttpRequest*, QHttpResponse*)));

    server->listen(QHostAddress::Any, 8080);
}

QByteArray HelloWorld::get(const QString &strUrl)
{
    assert(!strUrl.isEmpty());

    const QUrl url = QUrl::fromUserInput(strUrl);
    assert(url.isValid());

    QNetworkRequest qnr(url);
    qnr.setRawHeader("Origin","a");
    QNetworkReply* reply = m_qnam.get(qnr); //m_qnam是QNetworkAccessManager对象

    QEventLoop eventLoop;
    connect(reply, &QNetworkReply::finished, &eventLoop, &QEventLoop::quit);
    eventLoop.exec(QEventLoop::ExcludeUserInputEvents);

    QByteArray replyData = reply->readAll();
    reply->deleteLater();
    reply = nullptr;

    return replyData;
}

void HelloWorld::handleRequest(QHttpRequest *req, QHttpResponse *resp)
{
    QByteArray body = req->path().toLocal8Bit();
    qDebug() << req->path();

    QByteArray data = get("some domain" + req->path());
    qDebug() << data;
    resp->setHeader("Content-Length", QString::number(data.size()));
    resp->writeHead(200);
    resp->end(data);
}

这样我们就能够综合js,qml,c++的好处,得到一个十分优化的web应用程序。一个神奇的现象是安卓的后台机制,如果我在这个程序里面开了host,自己访问会很快,但是别的浏览器访问就会很慢,如果我们此时切回server的那个程序,再切出到外部浏览器,那么会发现资源又加载好了,这个的原因应该是Android的后台程序只会得到很少的性能的分配。

阅读全文 »

最近写程序遇到的一些坑的总结

发表于 2018-04-21 | 分类于 Programming

总结一些最近编程遇到的坑(C++)


使用Eigen时的一个报错:

在使用Eigen库时,有时会报错:

my_program: path/to/eigen/Eigen/src/Core/DenseStorage.h:44: Eigen::internal::matrix_array<T, Size, MatrixOptions, Align>::internal::matrix_array() [with T = double, int Size = 2, int MatrixOptions = 2, bool Align = true]: Assertion `(reinterpret_cast(array) & (sizemask)) == 0 && "this assertion is explained here: http://eigen.tuxfamily.org/dox-devel/group__TopicUnalignedArrayAssert.html READ THIS WEB PAGE !!! ****"' failed.

这里Eigen已经把解决问题的网页贴出来了。进去一看,给出了可能的原因,我这里遇到的是因为一个类里面的成员为Eigen的类,比如

class Foo
{
  //...
  Eigen::Vector2d v;
  //...
};
//...
Foo *foo = new Foo;

需要加上一个宏EIGEN_MAKE_ALIGNED_OPERATOR_NEW,如下

class Foo
{
  //...
  Eigen::Vector2d v;
  //...
public:
  EIGEN_MAKE_ALIGNED_OPERATOR_NEW
};
//...
Foo *foo = new Foo;

就不会报错了。这个是对于固定维数的矩阵(向量)会出现的错误,动态维数的矩阵(向量)不存在这样的问题。其它的情况包括按值传递矩阵(向量、或者带矩阵成员的类),需要改成按引用传递。这个问题的根本原因是Eigen为了提高运算速度,采取了128位内存对齐,以让编译器进行向量化优化。而如果自己的new就不会有内存对已,因此需要加上一个宏,重新实现内存对齐的new.

一个在析构函数中需要注意的问题

为了减少头文件包含,我们有时会这样写

class bar;
class foo{
public:
    foo();
    ~foo()
    {
        delete m_bar;
    }
private:
    bar* m_bar
}

这个时候编译器会给出警告,因为没有bar的析构函数。正确的还是应该把析构函数放进cpp文件里面。

Eigen的矩阵判断相等

Eigen库有一个用于判断矩阵是否大致相等的函数,可以这样用

typedef typename Eigen::Matrix<T, Eigen::Dynamic, Eigen::Dynamic> EigenMatrix;
 
EigenMatrix a, b;
 
// True if equal
bool r = a.isApprox(b, 1e-5);

原理是两个矩阵相减并求Frobenius范数。

阅读全文 »

一个三角恒等式的证明

发表于 2018-04-18 | 分类于 Math

一道神奇的三角恒等式的证明(非原创)


本文公式较多,在浏览器中将会花较长时间用于渲染公式。


在柯斯特利金的《代数学引论》里面居然看到了这样的一个恒等式: \begin{equation} \sum_{k=1}^n \cot^2(\frac{k\pi}{2n+1}) = \frac{n(2n-1)}{3} \end{equation} 自己想了想,用数学归纳法没有证明出来,于是谷歌查解法(谷歌的匹配还是很强大的),查到证明如下,书上的留白太小,所以把它记录在这里: 首先是一个引理,也是一个恒等式 \begin{equation} \tan rx=\frac{\binom r1\tan x-\binom r3\tan^3x+\cdots}{1-\binom r2\tan^2x+\cdots} \end{equation} 证明如下: 根据复变函数欧拉公式和二项式展开定理可以得到
相除得到 \begin{equation} \tan rx=\frac{\binom r1\tan x-\binom r3\tan^3x+\binom r5\tan^5x-\cdots}{1-\binom r2\tan^2x+\binom r4\tan^4x-\cdots} \end{equation} 接下来,如果$\tan(2n+1)x=0$,即$(2n+1)x=n\pi,n\in N$,那么$\tan x$将满足方程 \begin{equation} \binom{2n+1}1\tan x-\binom{2n+1}3\tan^3x+\cdots+(-1)^{n}\tan^{2n+1}x=0 \end{equation} 令$\tan^2 x = \frac{1}{y}$,那么$y$会是下面的多项式的根: \begin{equation} \binom{2n+1}1y^n-\binom{2n+1}3y^{n-1}+\cdots+(-1)^n=0 \end{equation} 方程的根为$\cot^2x = y$,当$x=0,\pm\dfrac{\pi}{2n+1},\pm\dfrac{2\pi}{2n+1},\pm\dfrac{k\pi}{2n+1}$
最后,由韦达定理可以得到 \begin{equation} \implies \sum_{k=1}^n \cot^2(\frac{k\pi}{2n+1}) = \frac{n(2n-1)}{3} \end{equation}

阅读全文 »

在Windows下编译deal.ii

发表于 2018-04-17 | 分类于 Programming

在Windows下用MSVC2017编译deal.ii


最近由于一些原因需要学习开源有限元的程序。在Github上找了一下,C++的还算有三位数stars的有deal.ii,libMesh和mFem(按照stars数目由多到少排列)。libMesh的代码下载下来居然不支持cmake,编译只能用msys来make,似乎也不能用MSVC编译。而deal.ii只能支持MSVC而不支持mingw.权衡了一下,选择deal.ii来学习,一个是它stars数多,知名度更高,另一个是mingw的编译器编译出来的程序通常比MSVC编译出来的更慢,这个在科学计算中比较头疼。

CMake里面configure的过程要设置一大堆flag,我都没有管,毕竟windows什么都特别不方便。像LAPACK库,GSL库我觉得还是有必要去链接的。希望这个东西的矩阵运算效率至少能够达到Eigen的水平。Configure第一次不对劲,原因竟然是我设置的build目录里面有’-‘减号。重新设置了build目录以后,生成了sln文件,感觉似乎有点希望了。不过不敢乐观,以前cmake成功但是sln最后还是编译不了的例子也有。

打开MSVC后,开始编译。很神奇的是,编译到一半出错了,说cmd停止运行,然后打开目录里面却发现已经deal_II.g.lib和deal_II.lib生成了。这个时候我相信它是编译成功了,但是打开别的test目录里却发现没有编译,examples也没有。有些失落,直接试试这个库到底能不能用。

直接把官网的第一个例子复制过来,用QMake编译:

/* ---------------------------------------------------------------------
 *
 * Copyright (C) 1999 - 2016 by the deal.II authors
 *
 * This file is part of the deal.II library.
 *
 * The deal.II library is free software; you can use it, redistribute
 * it, and/or modify it under the terms of the GNU Lesser General
 * Public License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 * The full text of the license can be found in the file LICENSE at
 * the top level of the deal.II distribution.
 *
 * ---------------------------------------------------------------------

 */


#include <deal.II/grid/tria.h>
#include <deal.II/grid/tria_accessor.h>
#include <deal.II/grid/tria_iterator.h>
#include <deal.II/grid/grid_generator.h>
#include <deal.II/grid/manifold_lib.h>
#include <deal.II/grid/grid_out.h>

#include <iostream>
#include <fstream>
#include <cmath>

using namespace dealii;


void first_grid ()
{
  Triangulation<2> triangulation;

  GridGenerator::hyper_cube (triangulation);
  triangulation.refine_global (4);

  std::ofstream out ("grid-1.eps");
  GridOut grid_out;
  grid_out.write_eps (triangulation, out);
  std::cout << "Grid written to grid-1.eps" << std::endl;
}




void second_grid ()
{
  Triangulation<2> triangulation;

  const Point<2> center (1,0);
  const double inner_radius = 0.5,
               outer_radius = 1.0;
  GridGenerator::hyper_shell (triangulation,
                              center, inner_radius, outer_radius,
                              10);
  const SphericalManifold<2> manifold_description(center);
  triangulation.set_manifold (0, manifold_description);
  triangulation.set_all_manifold_ids(0);

  for (unsigned int step=0; step<5; ++step)
    {
      Triangulation<2>::active_cell_iterator cell = triangulation.begin_active();
      Triangulation<2>::active_cell_iterator endc = triangulation.end();
      for (; cell!=endc; ++cell)
        {
          for (unsigned int v=0;
               v < GeometryInfo<2>::vertices_per_cell;
               ++v)
            {
              const double distance_from_center
                = center.distance (cell->vertex(v));

              if (std::fabs(distance_from_center - inner_radius) < 1e-10)
                {
                  cell->set_refine_flag ();
                  break;
                }
            }
        }

      triangulation.execute_coarsening_and_refinement ();
    }


  std::ofstream out ("grid-2.eps");
  GridOut grid_out;
  grid_out.write_eps (triangulation, out);

  std::cout << "Grid written to grid-2.eps" << std::endl;

  triangulation.set_manifold (0);
}




int main ()
{
  first_grid ();
  second_grid ();
}

编译的时候也是坑,又提示需要include boost,我在QMAKE加了boost目录,还是没有包含,干脆把所有的boost文件全部复制到deal.ii的include路径下。而且deal.iibuild目录下的include和deal.ii源代码下的include还要合并。然后又说不对,还需要链接boost::serialization库,接着又是链接这个库。还是不对,说triangulation.set_manifold (0);没有这个方法。把这一行注释掉,运行又有问题,不过倒是输出了eps图片。到底编译成功没有还是个未知数。

接着是第二个例子,用刚才的QMAKE配置一次成功。第三个例子的一句话是Functions::ZeroFunction<2>,又不对了,需要自己包含#include <deal.II/base/function.h>,然后还不对,进头文件一看,ZeroFunction继承于Functions类,这个官网的例子实在有点扯。最后编译成功了。但是出的gpl图居然又不能在GNU PLOT里面打开,说有语法错误。

用release又编译了第四个例子,一次成功了,但是又费劲地用three.js渲染vtk文件,没有显示出来,不知道是什么毛病。只能说姑且认为这个编译成功了,但是坑还很大。


第二个例子生成了svg图片,不小心发现了我的win10电脑上居然还有IE,版本是11,果断试试我的网站在IE11上的兼容性,好像很差(主要是sql.js和echarts)。非常无奈,中国还有许多人用IE,现在移动端对html5的支持居然都比IE好。不过edge长得太像IE了,微软改名部啊:Grin:

阅读全文 »

初窥含太阳系动力系统在内的几类动力系统

发表于 2018-04-12 | 分类于 Dynamics

初步认识一些动力系统,如太阳系系统,混沌系统等,并研究其数值解法


本文公式较多,在浏览器中将会花较长时间用于渲染公式。


最近看boost::numeric::odeint的文档,发现了一些很有趣的动力系统。

太阳系系统

这个看起来简单,无非就是万有引力的动力学,但是深入探究并不简单。这里我们想考虑太阳、木星、土星、天王星、海王星等天体的运动以及他们的相互作用。


NOTE

一个简单的物理史:二体问题是可积的,可以理论分析得到解析解,而三体问题则不存在解析解。在19世纪末,庞加莱发现了这个问题,并成为混沌理论的始祖。


理想的天体运动都是保守场,因此可以列出哈密顿方程。首先是动量的表达式(当然这里的动量的量纲是速度的量纲,但是物理含义是动量) \begin{equation} \frac{dq_i}{dt}=p_i \end{equation} \begin{equation} \frac{dp_i}{dt}=\frac{1}{m_i} \sum_{i\neq j}F_{ij} \end{equation} 那么哈密顿函数的表达式为 \begin{equation} H=\sum_i \frac{p_i^2}{2m_i}+\sum_j V(q_i,q_j) \end{equation} $V(q_i,q_j)$是$i,j$相互的势能。哈密顿方程的动力学方程为 在boost库中求解这个动力系统,有专门的辛算法:Runge-Kutta-Nystroem算法,在boost库中是一个叫symplectic_rkn_sb3a_mclachlan的步进器。事实上,对于很多实际生活中的动力系统,只要它有惯性,不耗散,就能够写出哈密顿函数,从而写出正则方程组,用这个算法求解。三体问题就是混沌的了,因此在这个世纪太阳系问题的求解中,必须要选择符合实际的初始条件,否则得不到想要的结果。
而对于一个实际的航天器,考虑的动力学方程通常如下: 这里某几个项的含义是(不一一赘述了):

  • $\nabla \phi_{sj}^o$ 中心天体非圆带来的扰动项
  • 其它天体的引力扰动项
  • $\frac{\dot m_s}{m}\frac{d\mathbf{r}}{dt}$发动机推力
  • 大气阻力
  • $\frac{P_{SR}C_RA_{sun}}{m_s}\hat{\mathbf{r}}_{sun}$是太阳辐射光压
  • $\frac{\mu}{c^2r^3}((4\frac{\mu}{r}-v^2)\mathbf{r}+4(\mathbf{r\cdot v})\mathbf{v})$为史瓦西解(Schwarzsehild solution)
  • $2(\mathbf{\Omega}\times\mathbf{v})$是测地线精度(广义相对论造成的空间扭曲形成的误差)
  • $2\frac{\mu}{c^2r^3}(\frac{3}{r^2}(\mathbf{r\times v})(\mathbf{r \cdot J})+(\mathbf{v\times J}))$是兰斯-蒂林效应(Lens-Thirring Precession)

广义相对论对受力的修正作用就是式(\ref{eqs_force})的最后三项,即[1] 如果在J2000坐标系下,那么

  • 是一个近似
  • $c$是光速
  • $\mathbf{r}$是在J2000坐标系下的位置矢量
  • $\mathbf{v}$是在J2000坐标系下的速度矢量
  • $\mathbf{r}_{B/S}$是中心天体相对于太阳的位置矢量
  • $\mathbf{v}_{B/S}$是中心天体相对于太阳的速度矢量
  • $\mathbf{J}$是中心天体的单位质量角动量,有$\mathbf{J}=\mathbf{R}^{I/F}_B[0\quad 0\quad \frac{2}{5}R_B^2\omega_B]^T$,而$\mathbf{R}^{I/F}_B$是中心天体的体坐标系到惯性系的旋转矩阵,$R_B$是中心天体的平均赤道半径,$\omega_B$是中心天体的自旋速度。

式(\ref{eqs_force})数值求解通常的方法是广义的龙格库塔法,见我之前的讨论。

混沌系统与李雅普诺夫指数

这个系统我是没怎么看懂。。。设$x$是自变量,$\delta x$是扰动量。扰动量满足线性微分方程,但是是时间相关的: \begin{equation} \frac{d\delta x}{dt}=J(x)\delta x \end{equation} 李雅普诺夫指数被定义为扰动随指数形式增长的那个对数。如果存在一个李雅普诺夫指数大于0那么扰动会发散,形成混沌。如果所有李雅普诺夫指数都小于0,那么扰动将收敛至一个点。
为了计算李雅普诺夫指数,需要首先求解扰动动力学方程,每过k步后将结果正交化,李雅普诺夫指数可以用取对数的方法得到,再多次计算取平均值。boost::numeric::odeint的test有相关代码。这个东西我是真的没搞明白是什么……

刚性方程

在数学领域中,刚性方程是指一个微分方程,其数值分析的解只有在时间间隔很小时才会稳定,只要时间间隔略大,其解就会不稳定。特点是特征值的实部均为负数并且实部最大的的特征值的实部与实部最小的的特征值的实部的比值远大于1。化学反应的动力学方程可能会是这样的方程,如果各个子反应的速率相差非常大。 刚性系统需要用Rosenbrock method来求解。boost::numeric::odeint提供了这个算法,然而坑的是必须和boost::ublas一起用。。。odeint的文档提供了一个对比,如果用Rosenbrock算法,只需要71步迭代,而龙格库塔算法,准确说是Dormand-Prince 5算法需要1531次迭代。

Stuart-Landau振子

微分方程也可以是复数的形式,如下面这个例子,Stuart-Landau oscillator: \begin{equation} \frac{d\Psi}{dt}=(1=i\eta)\Psi+(1+i\alpha)|\Psi|^2\Psi \end{equation} 这个系统表示了什么,我也不知道。从数值求解来说,这个系统虽然数域是复数域,不过依然可以用4阶龙格库塔算法求解。

网格动力系统

一个突出的例子是Fermi-Pasta-Ulam系统,这是一个非线性的哈密顿系统,哈密顿函数为 \begin{equation} H=\sum_i \frac{p_i^2}{2}+\frac{1}{2}(q_{i+1}-q_i)^2+\frac{\beta}{4}(q_{i+1}-q_i)^4 \end{equation} 和太阳系动力系统一样,这个系统也适合用辛求解算法,但是更为简单,因为$\frac{dq_i}{dt}=p_i$.
有纪念意义的是,FPU系统的求解是世界上最早的计算机上的数值实验。在1953年,洛斯阿拉莫斯,在世界上最早的计算机之一(MANIAC I)进行了这项研究,并触发了一个数学物理学的新领域。

振子集合

N-N耦合相位振子(N all-to all coupled phase oscillator)定义为 \begin{equation} \frac{d\phi_k}{dt}=\omega_k+\frac{\epsilon}{N}\sin(\phi_i-\phi_k) \end{equation} 各个振子的自然频率满足某种分布,$\epsilon$是耦合强度。如果我们取$\omega_i$的分布为洛伦兹分布(其实就是柯西分布,物理学上一般叫做洛伦兹分布),那么我们会观察到一个有趣的现象:当耦合强度超过某个临界值后,振子间会发生相位转移,伺候振子会以共同的频率运动。这种转移被称为Kuramoto transition。这个动力学系统本身的数值求解直接用4阶龙格库塔就行。


参考文献

[1]Huang C, Ries J C, Tapley B D, et al. Relativistic effects for near-earth satellite orbit determination[J]. Celestial Mechanics & Dynamical Astronomy, 1990, 48(2):167-185.

阅读全文 »

初窥牛顿平方反比定律和胡克定律的对偶性

发表于 2018-04-12 | 分类于 Dynamics
阅读全文 »

在线绘制星下点轨迹

发表于 2018-04-06 | 分类于 Programming

自己写了写网页绘制星下点轨迹的代码。


算法

这个算是原创算法了吧,身边没有轨道动力学和弹道导弹学的教材,都是自己瞎琢磨的算法。之前我们分析了轨道动力学中常用的计算机算法,轨道动力学中常用的计算机算法(二),这些很有用,可以让我们把轨道六根数转化为笛卡尔坐标系的坐标,以及进行轨道外推。

星下点轨迹的具体计算过程如下:每隔时间$dt$后,外推此时的轨道六根数,并得到相应的笛卡尔坐标系坐标。然后经度 \begin{equation} \lambda = \mathrm{atan2}(y,x) \end{equation} 纬度 \begin{equation} \phi = \mathrm{asin}(\frac{z}{r}) \end{equation} 其中 \begin{equation} r=\sqrt{x^2+y^2+z^2} \end{equation} 这里就基本完成了。不过还要考虑地球自转的影响,这个很让人头疼,因为atan2函数本身值域没问题,$[-\pi,\pi]$,但是考虑地球自转后需要 \begin{equation} \lambda = \lambda - t * \omega \end{equation} 这样$\lambda$的值域就会变化。想了挺长时间,得到这样的一种解决方法

geo.prototype.adjust = function (){
    if(this.long > 180 || this.long < 180){
        var theta = this.long * radPerDeg;
        var s = Math.sin(theta);
        var c = Math.cos(theta);
        var res = Math.atan2(s,c);
        this.long = res * degPerRad;
    }
};

具体实现

我是javascript的门外汉,把我以前写的C++代码全部移植到javascript很是费劲。不过运算速度比我想象中快多了。这里直接用的是开普勒运动的轨道外推,如果考虑摄动项那就需要用龙格库塔算法了。整个javascript的代码在orbitState.js,代码是可读的。

UI还是以前的东西,用jQuery Mobile+ECharts做的。最后,绘图的连接在这里。


更新(2018-4-8)

另外自己还做了一个在线解析TLE数据绘制星下点轨迹的网页,这个的算法就不是我写的了,而是用的开源的satellite.js的SGP4算法,他的代码也写得非常好。网页里面还有试一试功能,就是在NORAD的网站里面按编号随机抓取一个TLE数据,不过再度遇到了跨域访问的问题,这一次的解决方法则是protocol:

$.ajax({ 
  type: 'GET', 
  url: 'https://crossorigin.me/https://celestrak.com/cgi-bin/TLE.pl?CATNR=' + rndSat + '&callback=?' , 
  cache:false, 
  dataType: "text", 
  crossDomain: true, 
  headers : {'Origin':'http://foo.example'}, 
  success : function(data){ 
    var el = document.createElement( 'html' );
    el.innerHTML = data;
    var p = el.getElementsByTagName( 'BODY' )[0].getElementsByTagName('PRE')[0].textContent;
    var eachLine = p.split(/[\n]/);
    if(eachLine[0] == 'No TLE found'){
      $( "#myPopup3" ).popup( "open" );   
    }else{
      var titleStr = eachLine[0].replace(/[\s]deb/ig, "的碎片");
      window.alert("随机得到的卫星名字是" + titleStr);
      $('#areaTLE').val(eachLine[1] + '\n' + eachLine[2]);
      boolNotGet = false;
    }
  }
});

没错,通过一个crossorigin.me的网站来抓数据,这样就可以实现跨域访问了。但是需要注意的是一定要加上Origin的访问头,否则得不到数据。

2018-4-14更新

https://crossorigin.me访问不了了,只能登陆http://crossorigin,又是费了很大劲找解决方案。最终找到了一个替代的网站:https://cors-anywhere.herokuapp.com,和crossorigin的使用没什么区别。还有一些不支持https的站点,以及一些用不了的站点,我就不列举在这里了。

航天类开源代码一览

  • GMAT:这个是对我帮助最大的一个软件,C++的代码,软件设计非常好,无论是数学类算法还是从软件工程上说大量设计模式的运用,能够在一定程度上取代STK,不过遗憾的是GUI是用wxWidgets写的,如果是Qt就好了;
  • satellite.js:就是我网页里用到的开源代码,写得也很好,可以实现在网页中的计算(如果结合three.js这些3D渲染框架,在网页上还能进行动画演示);
  • Vallado的代码:这个Vallodo是天体动力学的祖师级大神,他的代码我虽然没有看过,但是他的代码和学术出版都是对我有很大帮助的,satellite.js的代码就是参考了Vallado的代码的;

下面的这些我不太了解了,仅供参考:

  • PreviSat:还在更新,C++写的,Qt做GUI;
  • JSatTrak:Java写的,更新很慢;
  • JAT:Java写的,没更新了;
  • ODTBX:Java写的,更新很慢;
  • Orekit:Java写的,更新很慢;
  • PyEphem:Python库,很久没更新了;
  • SGP4:Python库,很久没更新了

这些开源的不知道为什么有不少托管在SourceForge上面,按理说GitHub生态更好啊。不更新也可以理解,毕竟航天这个东西生态圈太小了。
另外再给两个在网页上渲染轨道运行的网页的例子,托管在GitHub上的:SOT spacemission

阅读全文 »
1 … 3 4 5 … 7
scienceasdf

scienceasdf

We will bury them !

45 日志
10 分类
RSS
GitHub ZhiHu 404公益@宝贝回家 神奇的网页
© 2017 - 2020 scienceasdf
由 Jekyll 强力驱动
主题 - NexT.Pisces