风云四号卫星运行的周期方向

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了风云四号卫星运行的周期方向相关的知识,希望对你有一定的参考价值。

风云四号卫星运行周期是24小时。
风云四号卫星是由中国航天科技集团公司第八研究院(上海航天技术研究院)抓总研制的第二代地球静止轨道(GEO)定量遥感气象卫星,采用三轴稳定控制方案。将接替自旋稳定的风云二号卫星,其连续、稳定运行将大幅提升我国静止轨道气象卫星探测水平。
作为新一代静止轨道定量遥感气象卫星,风云四号卫星的功能和性能实现了跨越式发展。卫星的辐射成像通道由FY-2G星的5个增加为14个,覆盖了可见光、短波红外、中波红外和长波红外等波段,接近欧美第三代静止轨道气象卫星的16个通道。星上辐射定标精度0.5K、灵敏度0.2K、可见光空间分辨率0.5km,与欧美第三代静止轨道气象卫星水平相当。
参考技术A

风云四号卫星运行方向、周期与地球自转相同。

风云四号卫星(FY-4)卫星是由中国航天科技集团公司第八研究院(上海航天技术研究院)抓总研制的第二代地球静止轨道(GEO)定量遥感气象卫星。

采用三轴稳定控制方案,将接替自旋稳定的风云二号(FY-2)卫星,其连续、稳定运行将大幅提升我国静止轨道气象卫星探测水平。

尽管三轴稳定卫星平台扫描成像辐射计相对于自旋稳定卫星平台扫描成像辐射计有较多突出的优点,但也有其特有的问题。

主要有以下几点:

(1)由于扫描成像辐射计采用机械扫描实现二维扫描成像,当扫描镜运动时,将会对卫星平台产生一定的扰动。这种扰动将会影响图像的定位和配准,严重时将会漏扫图像。并且扫描镜惯量越大、扫描速度越高、扫描镜运动行程越大,这种影响越大。

(2)由于三轴稳定卫星平台上的扫描成像辐射计凝视地球且随地球一起自转,在每天子夜时分,太阳直射进扫描成像辐射计遮光罩的时间约有6小时。在每天的其余时间,扫描成像辐射计将不被太阳照射,接受地球辐射和太空冷背景辐射。

(3)三轴稳定卫星平台上的扫描成像辐射计扫描镜的东西向连续往复扫描运动对气象卫星的长寿命将构成主要障碍。对扫描电机进行备份,将是应该考虑的选择。

Android GNSS 可视卫星星空图/卫星天顶图 原理及画法介绍

效果图:

首先介绍一下相关的概念:


方位角:是从某点的指北(地理北极)方向线起,依顺时针方向到目标方向线之间的水平夹角。

高度角:从一点至观测目标的方向线与水平面间的夹角。

卫星天顶图:即是根据每一颗卫星的方位角和高度角将其画在以观测位置为中心的天顶图上。

天顶图其底图为由外向内的三个圆和四条直线。三个圆由外向内依次代表高度角0°、30°、60°,中心点代表90°;四条直线分别表示正北-正南、东北-西南、正东-正西、东南-西北的方位角方向。

下面逐一介绍绘制的步骤

1 获取卫星信息


要想画出卫星图,必须先有卫星的方位角和高度角等基本信息。在Android中,可以通过向LocationManager类注册GnssStatus监听器获取卫星PRN、方位角、高度角、星座类型、卫星载噪比等与卫星本身有关的信息。


关于如何注册GNSS监听器,Android GNSS伪距计算 中有注册测量监听器的详细步骤,卫星状态监听器的注册方式完全类似。


不同的是在回调方法中的行为,在这里,我们需要使用数组将卫星信息保存起来,如下:

private float[] mElevations, mAzimuths, mSnrs;

private int[] mPrns, mConstellationTypes;

public void setGnssStatus(GnssStatus status) {
    if (mPrns == null) {
        final int MAX_LENGTH = 255;
        mPrns = new int[MAX_LENGTH];
        mElevations = new float[MAX_LENGTH];
        mAzimuths = new float[MAX_LENGTH];
        mConstellationTypes = new int[MAX_LENGTH];
        mSnrs = new float[MAX_LENGTH];
    }
    int length = status.getSatelliteCount();
    mSvCount = 0;
    while (mSvCount < length) {
        mPrns[mSvCount] = status.getSvid(mSvCount);
        mElevations[mSvCount] = status.getElevationDegrees(mSvCount);
        mAzimuths[mSvCount] = status.getAzimuthDegrees(mSvCount);
        mConstellationTypes[mSvCount] = status.getConstellationType(mSvCount);
        mSnrs[mSvCount] = status.getCn0DbHz(mSvCount);

        mSvCount++;
    }

    invalidate();
}

通过GnssStatus的参数对象status的 getSatelliteCount() 方法获取卫星数量,然后使用 getSvid()、getElevationDegrees()、getAzimuthDegrees()、getConstellationType()、getCn0DbHz() 方法分别获取卫星的 PRN、高度角、方位角、星座、载噪比


然后调用View对象的invalidate()方法重绘星空图,即更新。


2 自定义视图


由于Android中并没有一种系统控件可以让我们方便的展示卫星图,因此我们需要自定义一个天空图视图

public class GnssSkyView extends View { }


我们在碎片Fragment中加载这个视图,通过在碎片上注册监听器获得不断更新的信息,并在碎片的回调方法中调用 GnssSkyView 对象的 setGnssStatus 方法将信息传给它,从而使其获得数据来源,进而进行多样化地展示

3 绘制底图


底图包括三个圆、四条直线和外圈圆上的方位角刻度。

onDraw() 方法会在视图绘制的过程中系统自动调用,我们需要在这个方法中自定义绘制内容。

protected void onDraw(Canvas canvas) {
    super.onDraw(canvas);

    int minScreenDimen = Math.min(mWidth, mHeight);
    float radius = minScreenDimen / 2.0f;

    drawCircle(canvas, radius);
    drawLine(canvas, minScreenDimen, radius);
    drawDegree(canvas, radius);
}


因为我们要画的是一个圆,所以一定有一个外切正方形,上面的代码中,minScreenDimen 为视图长和宽的最小值,这个值就作为正方形的边长,也是外圈圆的直径


然后我们分别调用三个函数drawCircle()、drawLine()、drawDegree(),这三个函数是我们自己定义的,分别画圆、直线、刻度。


3.1 圆的画法


onDraw() 方法会给我们一个参数canvas,这个参数是视图画布Canvas的对象,通过调用canvas的 drawCircle() 方法,就能实现圆的绘制。


该方法的函数原型如下:

public void drawCircle(float cx, float cy, float radius, Paint paint) {
    super.drawCircle(cx, cy, radius, paint);
}


可见,我们需要给出圆心的 x,y 坐标和圆的半径 r,还有画笔 paint


这里需要注意的是,画布的坐标系是以左上角为坐标原点,水平向右为X轴正向,竖直向下为Y轴正向


我们在前面已经获取了外圆的半径,而外圈圆代表的是高度角0°,因此还需要计算出30°、60°的高度角代表的圆的半径。


然后这里给了一个 Y_TRANSLATION ,这是预定义的Y轴偏移量,方向向下为正,目的是使最上方的卫星能够完整的显示出来

private void drawCircle(Canvas c, float radius) {
    c.drawCircle(radius, radius + Y_TRANSLATION, elevationToRadius(radius, 60.0f), mPaintCircleAndLine);
    c.drawCircle(radius, radius + Y_TRANSLATION, elevationToRadius(radius, 30.0f), mPaintCircleAndLine);
    c.drawCircle(radius, radius + Y_TRANSLATION, elevationToRadius(radius, 0.0f), mPaintCircleAndLine);
}

private float elevationToRadius(float s, float elev) {
    return s * (1.0f - (elev / 90.0f));
}

3.2 直线的画法


直线的画法与圆类似,画直线的系统函数如下,其属于canvas画布对象:

public void drawLine(float startX, float startY, float stopX, float stopY, Paint paint) {
    super.drawLine(startX, startY, stopX, stopY, paint);
}


可知我们需要给出线段的起点坐标和终点坐标,还有画笔对象 paint

先计算出四条直线的起止点坐标,然后调用drawLine()方法

下面的函数中,s即minScreenDimen

private void drawLine(Canvas c, int s, float radius) {
    c.drawLine(radius, Y_TRANSLATION, radius, s + Y_TRANSLATION, mPaintCircleAndLine);
    c.drawLine(0, radius + Y_TRANSLATION, s, radius + Y_TRANSLATION, mPaintCircleAndLine);

    final float cos45 = (float) Math.cos(Math.PI / 4);
    float d1 = radius * (1 - cos45);
    float d2 = radius * (1 + cos45);
    c.drawLine(d1, d1 + Y_TRANSLATION, d2, d2 + Y_TRANSLATION, mPaintCircleAndLine);
    c.drawLine(d2, d1 + Y_TRANSLATION, d1, d2 + Y_TRANSLATION, mPaintCircleAndLine);
}

3.3 绘制刻度


绘制刻度的实质就是绘制直线,计算出每一个刻度线段的起止点坐标,然后调用绘制直线的函数

这里,在正北、正东、正南、正西方向上还要给出N、E、S、W的文本,可以调用画布对象canvas的drawText()系统函数绘制


drawText()系统函数原型如下:

public void drawText(String text, float x, float y, Paint paint) {
    super.drawText(text, x, y, paint);
}

只需给出文本字符串、文本位置坐标、画笔对象


这里,使用rorate()系统函数进行旋转绘制,详细原理可以自行百度

private void drawDegree(Canvas c, float radius) {
    for (int i = 0; i < 360; i += 15) {
        if (i == 45 || i == 135 || i == 225 || i == 315) {
            c.drawText(String.valueOf(i), radius, 40 + Y_TRANSLATION, mPaintDegree);
        } else if (i == 0) {
            c.drawText("N", radius, 40 + Y_TRANSLATION, mPaintDegree);
        } else if (i == 90) {
            c.drawText("E", radius, 40 + Y_TRANSLATION, mPaintDegree);
        } else if (i == 180) {
            c.drawText("S", radius, 40 + Y_TRANSLATION, mPaintDegree);
        } else if (i == 270) {
            c.drawText("W", radius, 40 + Y_TRANSLATION, mPaintDegree);
        } else {
            c.drawLine(radius, Y_TRANSLATION, radius, 20 + Y_TRANSLATION, mPaintDegree);
        }

        c.rotate(15, radius, radius + Y_TRANSLATION);
    }
}

3.4 绘制结果

4 绘制卫星


4.1 计算卫星坐标

如上图,根据高度角可以计算出卫星的半径,即到圆心的距离 r,再根据方位角 α 和外圈圆的半径 R 即可确定卫星在画布坐标系中的坐标


4.2 获取卫星旗帜


这个比较简单,只需要预先准备好四大系统和日本的代表旗帜,然后根据星座类型来获取Bitmap对象


这里,准备了六张PNG图片,放在./res/drawable目录下

然后,使用BitmapFactory.decodeResource() 方法创建一个位图对象。这个方法的第一个参数为Android系统的资源对象resources,可以通过视图View对象的getResources() 方法得到;第二个参数为图片数据的资源ID


值得一提的是,一般我们准备的图片尺寸都各不相同,并且远大于在视图上展示的大小,而为了让所有星座的卫星使用同样小尺寸的图片,我们需要对位图Bitmap进行放缩

private Bitmap getSatelliteBitmap(int constellationType) {
    Bitmap baseMap, newMap;
    int width, height;
    switch (constellationType) {
        case GnssStatus.CONSTELLATION_BEIDOU:
            baseMap = BitmapFactory.decodeResource(getResources(), R.drawable.flag_of_china);
            break;
        case GnssStatus.CONSTELLATION_GPS:
            baseMap = BitmapFactory.decodeResource(getResources(), R.drawable.flag_of_america);
            break;
        case GnssStatus.CONSTELLATION_GALILEO:
            baseMap = BitmapFactory.decodeResource(getResources(), R.drawable.flag_of_europe);
            break;
        case GnssStatus.CONSTELLATION_GLONASS:
            baseMap = BitmapFactory.decodeResource(getResources(), R.drawable.flag_of_russia);
            break;
        case GnssStatus.CONSTELLATION_QZSS:
            baseMap = BitmapFactory.decodeResource(getResources(), R.drawable.flag_of_japan);
            break;
        default:
            baseMap = BitmapFactory.decodeResource(getResources(), R.drawable.flag_of_other);
    }
    width = baseMap.getWidth();
    height = baseMap.getHeight();
    newMap = UiUtils.scaling(baseMap, (SAT_RADIUS * 2.0f) / width, (SAT_RADIUS * 2.0f) / height);
    return newMap;
}

public class UiUtils {
    public static Bitmap scaling(Bitmap bitmap, float widthScale, float heightScale) {
        Matrix matrix = new Matrix();
        matrix.postScale(widthScale, heightScale); //长和宽放大缩小的比例
        return Bitmap.createBitmap(bitmap, 0, 0, bitmap.getWidth(), bitmap.getHeight(), matrix, true);
    }
}

4.3 绘制卫星


绘制卫星的代码如下,其中我们还要生成卫星星座+卫星PRN的文本字符串:

private void drawSatellite(Canvas c, int s, float elev, float azim, float snr, int prn, int constellationType) {
    double radius, angle;
    float x, y;

    Bitmap satMap;
    satMap = getSatelliteBitmap(constellationType);

    String satText;
    satText = getSatelliteText(prn, constellationType);

    radius = elevationToRadius(s / 2.0f, elev);
    angle = (float) Math.toRadians(azim);

    x = (float) ((s / 2.0f) + (radius * Math.sin(angle)));
    y = (float) ((s / 2.0f) - (radius * Math.cos(angle)));

    c.drawBitmap(satMap, x - SAT_RADIUS, y - SAT_RADIUS + Y_TRANSLATION, null);

    c.drawText(satText, x - SAT_RADIUS, y + SAT_RADIUS * 2 + Y_TRANSLATION, mPrnIdPaint);
}

private String getSatelliteText(int prn, int constellationType) {
    StringBuilder builder = new StringBuilder();
    switch (constellationType) {
        case GnssStatus.CONSTELLATION_BEIDOU:
            builder.append("C");
            break;
        case GnssStatus.CONSTELLATION_GPS:
            builder.append("G");
            break;
        case GnssStatus.CONSTELLATION_GALILEO:
            builder.append("E");
            break;
        case GnssStatus.CONSTELLATION_GLONASS:
            builder.append("R");
            break;
        case GnssStatus.CONSTELLATION_QZSS:
            builder.append("Q");
            break;
        default:
            builder.append("S");
    }
    builder.append(prn);
    return builder.toString();
}

5 自定义视图大小的控制


View的工作流程,主要是measure、layout和draw三步,measure用来测量View的宽高,layout用来确定View(在ViewGroup中)的位置,draw则用来绘制View。


决定View的大小只需要两个值:宽详细测量值(widthMeasureSpec)和高详细测量值(heightMeasureSpec)。也可以把详细测量值理解为视图View想要的大小说明(想要的未必就是最终大小)。


我们先获取屏幕的宽高,然后取较小值,因为一般是宽较小,所以将高度设为宽度+20dp,然后使用View的 setMeasuredDimension() 方法设置视图的大小。

protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
    super.onMeasure(widthMeasureSpec, heightMeasureSpec);

    int windowWidth = mDisplayMetrics.widthPixels;
    int windowHeight = mDisplayMetrics.heightPixels;

    int minL = Math.min(windowWidth, windowHeight);

    setMeasuredDimension(minL, minL + 20);
}
private void init(Context context) {
    mDisplayMetrics = mContext.getResources().getDisplayMetrics();
    getViewTreeObserver().addOnPreDrawListener(
        new ViewTreeObserver.OnPreDrawListener() {
            @Override
            public boolean onPreDraw() {
                mHeight = getHeight();
                mWidth = getWidth();
                return true;
            }
        }
    );

    invalidate();
}

以上是关于风云四号卫星运行的周期方向的主要内容,如果未能解决你的问题,请参考以下文章

紫光软件3998万元中标风云四号A星UNIX服务器项目

刚刚,微信启动页6年来首次“变脸”,你发现了没有

PIE SDK打开静止卫星数据

侠客风云传steam版mod怎么用 1.0.2.6mod放在那里攻略

风云——不虚指点聂风

SEO优化之如何利用百度风云榜获取百万流量