火星探測器著陸控制方案
本題聚焦于探測器從火星同步軌道出發到探測器在火星地表上
方懸停的程序(以下簡稱著陸程序),要求參賽隊收集有關天問一號
探測器的音像和文字等公開資料,建立數學模型,研究如下問題:
- 確定探測器著陸程序時間最短的操控方案(包括環繞器與著
陸巡視器分離、阻尼傘打開、發動機系統點火等時間,以及
發動機系統運行方案); - 對給定的著陸程序時間,確定消耗能量最少的操控方案;
- 如果希望探測器著陸程序與公開的音像和文字資料盡量一致,
如何設計操控方案
相關資料及資料分析

火星著陸器開傘條件均為超聲速開傘,但為了確保降落傘的開傘可靠,
一般都控制開傘馬赫數不大于 2.2;
? 由于大氣密度小,開傘動壓較小,一般采用彈傘筒直接彈傘和一次開傘
技術;
? 大部分火星著陸器均使用了盤縫帶傘,其中在著陸前沒有姿態控制的著
陸器均采用了火星探路者型別及其改進型的盤縫帶傘(降落傘的穩定性高),在著陸前進行姿態控制的著陸器均采用海盜號型別的盤縫帶傘(降落傘的阻力系數大);
最小彈射分離速度的確定方法
對于降落傘系統而言,確定彈射分離速度非常關鍵,該彈射分離速度取得過小,將可能導致降落傘無法越過回收物的尾流或無法正常拉直;該彈射分離速度取得過大,由于彈射分離推力一般與該速度的二次方成正比,過大的彈射分離推力將導致彈傘載荷偏大,并對回收物的結構設計、降落傘連接分離機構的結構設計帶來影響,從而導致更大的結構重量,選取合適的彈射分離速度,首先需要得到所需的最小彈射分離速度,


受力分析


import java.util.*;
public class test9 {
private static String Time[] = { "0", "20", "50", "100", "150", "200",
"240", "290", "320", "400", "450", "490" };
private static int verticalspeed[] = { 1400, 1600, 1550, 1300, 1700, 1000, 1100, 800, 700, 40,
200, 400 };
private static int horizonspeed[] = { 0, 10, 15, 10, 5, 3, 0, -20, -30, -32, -35, -32, -21,
-11, 0 };
private static int b2[] = { 98, 78, 63, 50, 40, 33 };
private static int thrust[] = { 7500,7500,7500,7500,7500,7500,7500,7500,7500,7500,7500,7500 };
private static int angle[] = { 85, 85, 84, 82, 80, 78, 77, 75, 74, 72, 68, 65 };
private int timeNum = Time.length;
private int popSize = 50;
private int maxgens = 10000;
private double pxover = 0.8;
private double pmultation = 0.05;
private long[][] distance = new long[timeNum][timeNum];
private int range = 2000;
private class genotype {
int city[] = new int[timeNum];
long fitness;
double selectP;
double exceptp;
int isSelected;
}
private genotype[] citys = new genotype[popSize];
/**
* 建構式,初始化種群
*/
public test9() {
for (int i = 0; i < popSize; i++) {
citys[i] = new genotype();
int[] num = new int[timeNum];
for (int j = 0; j < timeNum; j++)
num[j] = j;
int temp = timeNum;
for (int j = 0; j < timeNum; j++) {
int r = (int) (Math.random() * temp);
citys[i].city[j] = num[r];
num[r] = num[temp - 1];
temp--;
}
citys[i].fitness = 0;
citys[i].selectP = 0;
citys[i].exceptp = 0;
citys[i].isSelected = 0;
}
initDistance();
}
/**
* 計算每個種群每個基因個體的適應度,選擇概率,期望概率,和是否被選擇,
*/
public void CalAll() {
for (int i = 0; i < popSize; i++) {
citys[i].fitness = 0;
citys[i].selectP = 0;
citys[i].exceptp = 0;
citys[i].isSelected = 0;
}
CalFitness();
CalSelectP();
CalExceptP();
CalIsSelected();
}
/**
* 填充,將多選的填充到未選的個體當中
*/
public void pad() {
int best = 0;
int bad = 0;
while (true) {
while (citys[best].isSelected <= 1 && best < popSize - 1)
best++;
while (citys[bad].isSelected != 0 && bad < popSize - 1)
bad++;
for (int i = 0; i < timeNum; i++)
citys[bad].city[i] = citys[best].city[i];
citys[best].isSelected--;
citys[bad].isSelected++;
bad++;
if (best == popSize || bad == popSize)
break;
}
}
/**
* 交叉主體函式
*/
public void crossover() {
int x;
int y;
int pop = (int) (popSize * pxover / 2);
while (pop > 0) {
x = (int) (Math.random() * popSize);
y = (int) (Math.random() * popSize);
executeCrossover(x, y);// x y 兩個體執行交叉
pop--;
}
}
/**
* 執行交叉函式
*
* @param 個體x
* @param 個體y
* 對個體x和個體y執行佳點集的交叉
*/
private void executeCrossover(int x, int y) {
int dimension = 0;
for (int i = 0; i < timeNum; i++)
if (citys[x].city[i] != citys[y].city[i]) {
dimension++;
}
int diffItem = 0;
double[] diff = new double[dimension];
for (int i = 0; i < timeNum; i++) {
if (citys[x].city[i] != citys[y].city[i]) {
diff[diffItem] = citys[x].city[i];
citys[x].city[i] = -1;
citys[y].city[i] = -1;
diffItem++;
}
}
Arrays.sort(diff);
double[] temp = new double[dimension];
temp = gp(x, dimension);
for (int k = 0; k < dimension; k++)
for (int j = 0; j < dimension; j++)
if (temp[j] == k) {
double item = temp[k];
temp[k] = temp[j];
temp[j] = item;
item = diff[k];
diff[k] = diff[j];
diff[j] = item;
}
int tempDimension = dimension;
int tempi = 0;
while (tempDimension > 0) {
if (citys[x].city[tempi] == -1) {
citys[x].city[tempi] = (int) diff[dimension - tempDimension];
tempDimension--;
}
tempi++;
}
Arrays.sort(diff);
temp = gp(y, dimension);
for (int k = 0; k < dimension; k++)
for (int j = 0; j < dimension; j++)
if (temp[j] == k) {
double item = temp[k];
temp[k] = temp[j];
temp[j] = item;
item = diff[k];
diff[k] = diff[j];
diff[j] = item;
}
tempDimension = dimension;
tempi = 0;
while (tempDimension > 0) {
if (citys[y].city[tempi] == -1) {
citys[y].city[tempi] = (int) diff[dimension - tempDimension];
tempDimension--;
}
tempi++;
}
}
/**
* @param individual
* 個體
* @param dimension
* 維數
* @return 佳點集 (用于交叉函式的交叉點) 在executeCrossover()函式中使用
*/
private double[] gp(int individual, int dimension) {
double[] temp = new double[dimension];
double[] temp1 = new double[dimension];
int p = 2 * dimension + 3;
while (!isSushu(p))
p++;
for (int i = 0; i < dimension; i++) {
temp[i] = 2 * Math.cos(2 * Math.PI * (i + 1) / p)
* (individual + 1);
temp[i] = temp[i] - (int) temp[i];
if (temp[i] < 0)
temp[i] = 1 + temp[i];
}
for (int i = 0; i < dimension; i++)
temp1[i] = temp[i];
Arrays.sort(temp1);
// 排序
for (int i = 0; i < dimension; i++)
for (int j = 0; j < dimension; j++)
if (temp[j] == temp1[i])
temp[j] = i;
return temp;
}
/**
* 變異
*/
public void mutate() {
double random;
int temp;
int temp1;
int temp2;
for (int i = 0; i < popSize; i++) {
random = Math.random();
if (random <= pmultation) {
temp1 = (int) (Math.random() * (timeNum));
temp2 = (int) (Math.random() * (timeNum));
temp = citys[i].city[temp1];
citys[i].city[temp1] = citys[i].city[temp2];
citys[i].city[temp2] = temp;
}
}
}
/**
* 初始化各狀態之間的距離
*/
private void initDistance() {
for (int i = 0; i < timeNum; i++) {
for (int j = 0; j < timeNum; j++) {
distance[i][j] = Math.abs(i - j);
}
}
}
/**
* 計算所有狀態序列的適應度
*/
private void CalFitness() {
for (int i = 0; i < popSize; i++) {
for (int j = 0; j < timeNum - 1; j++)
citys[i].fitness += distance[citys[i].city[j]][citys[i].city[j + 1]];
citys[i].fitness += distance[citys[i].city[0]][citys[i].city[timeNum - 1]];
}
}
/**
* 計算選擇概率
*/
private void CalSelectP() {
long sum = 0;
for (int i = 0; i < popSize; i++)
sum += citys[i].fitness;
for (int i = 0; i < popSize; i++)
citys[i].selectP = (double) citys[i].fitness / sum;
}
/**
* 計算期望概率
*/
private void CalExceptP() {
for (int i = 0; i < popSize; i++)
citys[i].exceptp = (double) citys[i].selectP * popSize;
}
/**
* 計算該狀態序列是否較優,較優則被選擇,進入下一代
*/
private void CalIsSelected() {
int needSelecte = popSize;
for (int i = 0; i < popSize; i++)
if (citys[i].exceptp < 1) {
citys[i].isSelected++;
needSelecte--;
}
double[] temp = new double[popSize];
for (int i = 0; i < popSize; i++) {
temp[i] = citys[i].exceptp * 10;
}
int j = 0;
while (needSelecte != 0) {
for (int i = 0; i < popSize; i++) {
if ((int) temp[i] == j) {
citys[i].isSelected++;
needSelecte--;
if (needSelecte == 0)
break;
}
}
j++;
}
}
/**
* @param x
* @return 判斷一個數是否是素數的函式
*/
private boolean isSushu(int x) {
if (x < 2)
return false;
for (int i = 2; i <= x / 2; i++)
if (x % i == 0 && x != 2)
return false;
return true;
}
/**
* @param x
* 陣列
* @return x陣列的值是否全部相等,相等則表示x.length代的最優結果相同,則演算法結束
*/
private boolean isSame(long[] x) {
for (int i = 0; i < x.length - 1; i++)
if (x[i] != x[i + 1])
return false;
return true;
}
public int[] sort(int a[]) {
for (int i = 1; i < a.length; i++) {// 外層回圈從i=1開始
for (int j = 0; j < a.length - 1; j++) {// 內層回圈從i=0開始
if (a[j] > a[j + 1]) {// 比較陣列元素相鄰兩個元素的大小,如果前者大于后者就將兩個值進行交換
int temp1 = a[j];
a[j] = a[j + 1];
a[j + 1] = temp1;
}
}
}
return a;
}
/**
* 列印任意代最優的路徑序列
*/
private void printBestRoute() {
CalAll();
long temp = citys[0].fitness;
int index = 0;
for (int i = 1; i < popSize; i++) {
if (citys[i].fitness < temp) {
temp = citys[i].fitness;
index = i;
}
}
for (int j = 0; j < timeNum; j++) {
String cityEnd[] = { Time[citys[index].city[j]] };
for (int m = 0; m < cityEnd.length; m++) {
System.out.print(cityEnd[m] + " ");
}
}
System.out.println();
}
/**
* 演算法執行
*/
public void run() {
long[] result = new long[range];
// result初始化為所有的數字都不相等
for (int i = 0; i < range; i++)
result[i] = i;
int index = 0; // 陣列中的位置
int num = 1; // 第num代
while (maxgens > 0) {
CalAll();
pad();
crossover();
mutate();
maxgens--;
long temp = citys[0].fitness;
for (int i = 1; i < popSize; i++)
if (citys[i].fitness < temp) {
temp = citys[i].fitness;
}
result[index] = temp;
if (isSame(result))
break;
index++;
if (index == range)
index = 0;
num++;
}
printBestRoute();
}
/**
* @param a
* 開始時間
* @param b
* 結束時間
*/
public static void CalTime(Calendar a, Calendar b) {
long x = b.getTimeInMillis() - a.getTimeInMillis();
long y = x / 1000;
x = x - 1000 * y;
System.out.println("演算法執行時間:" + y + "." + x + " 秒");
}
/**
* 程式入口
*/
public static void main(String[] args) {
Arrays.sort(verticalspeed);
System.out.println("時間:");
for(int i=0;i<Time.length;i++)
{
System.out.print(Time[i]+" ");
}
System.out.println();
System.out.println("垂直速度");
for(int i=0;i<verticalspeed.length;i++)
{
System.out.print(verticalspeed[i]+" ");
}
System.out.println();
System.out.println("水平速度");
for(int i=0;i<horizonspeed.length;i++)
{
System.out.print(horizonspeed[i]+" ");
}
System.out.println();
System.out.println("推力");
for(int i=0;i<thrust.length;i++)
{
System.out.print(thrust[i]+" ");
}
System.out.println();
System.out.println("姿態角");
for(int i=0;i<angle.length;i++)
{
System.out.print(angle[i]+" ");
}
}
}
阻尼傘打開的數學模型為:
企鵝
917267119
轉載請註明出處,本文鏈接:https://www.uj5u.com/ruanti/290127.html
標籤:其他
