太空工程师吧 关注:36,685贴子:507,871

【太空程序员】良(keng)心(die)导弹商人的新产品

只看楼主收藏回复

经过长期(两晚上)的艰苦研发,本研究所终于实现了将跟踪器的传感器和陀螺仪数量降低到1个,填补了该技术领域的空白,抠门……哦不,是科技水平……国际领先……
为了保证科研进度,研发人员渴了喝水,饿了吃饭,每天都加班到困了才能睡觉。研发过程中,研发人员家属对研发工作表现出了极大的理解和支持(强行关灯、不给被子、背对研发人员不转身等),因此除了要感谢郭嘉以外还要感谢研发人员的家属。
现在跟踪器的基本组件数量已经减少至 4 个,加上反应堆也只有 5 个。
传统的跟踪器光四个感应器的能耗就超过了 100KW,远远超出了一个小型反应堆的负载能力。这款跟踪器减少了感应器数量,也就降低了整体功耗,一个小型反应堆就足以承载感应器、推进器以及天线等导弹所需的所有设备。
本款跟踪器还处于改进阶段,因此可能会有反应呆滞、翻跟头卖萌等问题,将本跟踪器用于装配实战导弹导致的一切损失,本研究所概不负责


IP属地:山东1楼2015-01-22 08:40回复
    就是


    IP属地:吉林来自Android客户端3楼2015-01-22 08:46
    回复
      产品呢


      来自Android客户端4楼2015-01-22 08:48
      回复
        楼主被有关部门带走了?


        IP属地:上海来自iPhone客户端5楼2015-01-22 09:17
        回复
          人呢?…………


          IP属地:贵州来自iPhone客户端6楼2015-01-22 09:21
          回复
            在讲本款跟踪器之前,先简单介绍一下传统的跟踪器原理

            上面是一个跟踪器的正视图:在一个方块上,上下左右四面各安装一个感应器(T上 B下 L左 R右),感应范围除了背面为最小,其他方向均为最大。
            这样就形成如图感应范围。
            基本运行原理是:
            当T感应区感应到物体时,控制陀螺仪向上转 —— Pitch+(在此视图中就是基于X轴旋转)
            当B感应区感应到物体时,控制陀螺仪向下转 —— Pitch-
            当T和B感应区都感应到物体时,陀螺仪 Pitch 归零。
            L和R感应区原理同上,只不过控制的是 Yaw 轴(面对陀螺仪时左为正,右为负)
            也就是说当T、B、L、R同时感应到物体时,也就意味着跟踪器已经对准了目标,这 时 Pitch 和 Yaw 都归零,陀螺仪保持姿势。
            传统的跟踪器中,每个感应器各控制一个陀螺仪,每个感应器大约耗电25~6KW,一个小型反应堆100KW(小型飞船),因此需要两个反应堆才能承载这个跟踪系统的电能,下面是这种跟踪器的材料清单:
            感应器 * 4
            陀螺仪 * 4
            反应堆 * 2


            IP属地:山东7楼2015-01-22 09:22
            回复
              →_→


              IP属地:广东来自Android客户端8楼2015-01-22 09:28
              回复
                在解决了编程器运行频率的问题以后,通过程序切换感应器感应范围、判断目标位置已经成为可能,下图就是新跟踪器的感应器布局。

                基本原理是:
                1. 程序不断切换感应器感应方向,并将各个方向上的感应结果存到缓存中
                2. 程序根据缓存中各个方向的侦测数据,改变陀螺仪参数
                3. 没了
                这中间有很多陷阱,大多数是游戏脚本系统的问题
                比如:
                * 类构造函数中不能给成员变量初始化
                * swtich语句不能判断int类型(编译通过但运行报错)
                * 感应器反应时间较长,因此需要空转等待


                IP属地:山东9楼2015-01-22 09:44
                收起回复
                  建造过程非常简单,简单到都不用我截图
                  建立一个小型飞船放一个计时器、一个传感器、一个陀螺仪、一个反应堆、一个编程器,要注意的是,陀螺仪正面朝你,传感器面朝上(根据陀螺仪判断上下左右)
                  计时器名字设置为"Timer Block"
                  陀螺仪名字设置为“Gyroscope”
                  传感器名字设置为“Sensor”
                  计时器添加动作:编程器->运行
                  编程器里粘贴下面代码:


                  IP属地:山东10楼2015-01-22 09:55
                  收起回复
                    void Main() {
                    InitBlockHelper();
                    InitMem();
                    Tracker.Run();
                    WriteMem();
                    BlockHelper.RunAction("Timer Block", "TriggerNow");
                    }
                    class Tracker{
                    private const float SENSI = 60;
                    private const int DELAY_TIMES = 6;
                    private const string gyroName = "Gyroscope";
                    private IMyGyro Gyro = (IMyGyro)BlockHelper.GetBlock(gyroName);
                    private IMySensorBlock Sensor = (IMySensorBlock)BlockHelper.GetBlock("Sensor");
                    //These Directions is base on the angle of view when you face to ship, not base on ship
                    private string[][] sensorSets = {new string[]{"50", "50", "50", "50", "01", "50"}, //Top L R T B B F
                    new string[]{"01", "50", "50", "50", "50", "50"}, //Right
                    new string[]{"50", "50", "50", "50", "50", "01"}, //Bottom
                    new string[]{"50", "01", "50", "50", "50", "50"}};//Left
                    private int watchDirectionIndex; //0:T 1:R 2:B 3:L
                    private int topDetectedCount;
                    private int rightDetectedCount;
                    private int bottomDetectedCount;
                    private int leftDetectedCount;
                    private static Tracker tracker;
                    private Tracker() {}
                    private void initTracker(){
                    this.topDetectedCount = Mem.GetInt("topDetectedCount");
                    this.rightDetectedCount = Mem.GetInt("rightDetectedCount");
                    this.bottomDetectedCount = Mem.GetInt("bottomDetectedCount");
                    this.leftDetectedCount = Mem.GetInt("leftDetectedCount");
                    this.watchDirectionIndex = Mem.GetInt("watchDirectionIndex");
                    }
                    static public void Run(){
                    if (tracker == null)
                    tracker = new Tracker();
                    if (tracker.NeedWait())
                    return;
                    tracker.initTracker();
                    tracker.Track();
                    }
                    public void Track(){
                    UpdateDirectionState();
                    SetGyro();
                    SwitchWatchDirection();
                    }
                    private void UpdateDirectionState(){
                    if (IsSensorDetected()) {
                    switch(Convert.ToString(watchDirectionIndex)) {
                    case "0":
                    Mem.SetInt("topDetectedCount", ++topDetectedCount);
                    break;
                    case "1":
                    Mem.SetInt("rightDetectedCount", ++rightDetectedCount);
                    break;
                    case "2":
                    Mem.SetInt("bottomDetectedCount", ++bottomDetectedCount);
                    break;
                    case "3":
                    Mem.SetInt("leftDetectedCount", ++leftDetectedCount);
                    break;
                    }
                    }
                    else {
                    switch(Convert.ToString(watchDirectionIndex)) {
                    case "0":
                    topDetectedCount = 0;
                    Mem.SetInt("topDetectedCount", topDetectedCount);
                    break;
                    case "1":
                    rightDetectedCount = 0;
                    Mem.SetInt("rightDetectedCount", rightDetectedCount);
                    break;
                    case "2":
                    bottomDetectedCount = 0;
                    Mem.SetInt("bottomDetectedCount", bottomDetectedCount);
                    break;
                    case "3":
                    leftDetectedCount = 0;
                    Mem.SetInt("leftDetectedCount", leftDetectedCount);
                    break;
                    }
                    }
                    }
                    private void SetGyro(){
                    if (topDetectedCount > 0 && bottomDetectedCount > 0) {
                    ResetXAxis();
                    }
                    else if (topDetectedCount > 0) {
                    TurnToTop();
                    }
                    else if (bottomDetectedCount > 0) {
                    TurnToBottom();
                    }
                    if (rightDetectedCount > 0 && leftDetectedCount > 0) {
                    ResetYAxis();
                    }
                    else if (rightDetectedCount > 0) {
                    TurnToRight();
                    }
                    else if (leftDetectedCount > 0) {
                    TurnToLeft();
                    }
                    }
                    private void SwitchWatchDirection(){
                    int index = watchDirectionIndex;//Mem.GetInt("watchDirectionIndex");
                    index = ++index % 4;
                    Sensor.SetValue("Left", SensorSet(index, 0));
                    Sensor.SetValue("Right", SensorSet(index, 1));
                    Sensor.SetValue("Top", SensorSet(index, 2));
                    Sensor.SetValue("Bottom", SensorSet(index, 3));
                    Sensor.SetValue("Back", SensorSet(index, 4));
                    Sensor.SetValue("Front", SensorSet(index, 5));
                    Mem.SetInt("watchDirectionIndex", index);
                    }
                    private bool NeedWait(){
                    int currentTimes = Mem.GetInt("currentTimes");
                    if (currentTimes < DELAY_TIMES) {
                    ++currentTimes;
                    }
                    else{
                    currentTimes = 0;
                    }
                    Mem.SetInt("currentTimes", currentTimes);
                    return currentTimes != 0;
                    }
                    private bool IsSensorDetected() {
                    return Sensor.IsActive;
                    }
                    private void ResetXAxis() {
                    Gyro.SetValue("Pitch", 0F);
                    }
                    private void ResetYAxis() {
                    Gyro.SetValue("Yaw", 0F);
                    }
                    private void TurnToTop() {
                    Gyro.SetValue("Pitch", SENSI);
                    }
                    private void TurnToBottom() {
                    Gyro.SetValue("Pitch", -SENSI);
                    }
                    private void TurnToLeft() {
                    Gyro.SetValue("Yaw", SENSI);
                    }
                    private void TurnToRight() {
                    Gyro.SetValue("Yaw", -SENSI);
                    }
                    private float SensorSet(int index, int i) {
                    return Convert.ToSingle(sensorSets[index][i]);
                    }
                    }


                    IP属地:山东11楼2015-01-22 09:56
                    回复
                      void InitBlockHelper(){
                      BlockHelper.Init(GridTerminalSystem);
                      }
                      static class BlockHelper{
                      static private IMyGridTerminalSystem GridTerminalSystem;
                      static public void Init(IMyGridTerminalSystem gts){
                      GridTerminalSystem = gts;
                      }
                      static public IMyTerminalBlock GetBlock(string name) {
                      IMyTerminalBlock block = GridTerminalSystem.GetBlockWithName(name);
                      if (block == null)
                      throw new Exception(String.Format("\"{0}\" Not Found"));
                      return block;
                      }
                      static public void RunAction(IMyTerminalBlock block, string actionName) {
                      var action = block.GetActionWithName(actionName);
                      if (action == null)
                      throw new Exception(String.Format("Action \"{0}\" of \"{1}\" NOT FOUND!", actionName,
                      block.CustomName));
                      action.Apply(block);
                      }
                      static public void RunAction(string blockName, string actionName) {
                      RunAction(GetBlock(blockName), actionName);
                      }
                      static public void RunAction(IList<string> blockNames, string actionName) {
                      for (int i = 0; i < blockNames.Count; ++i)
                      RunAction(blockNames[i], actionName);
                      }
                      static public void RunAction(IList<IMyTerminalBlock> blocks, string actionName) {
                      for (int i = 0; i < blocks.Count; ++i)
                      RunAction(blocks[i], actionName);
                      }
                      static public IMyTerminalBlock FirstBlockWithPrefix(string prefix) {
                      List<IMyTerminalBlock> allBlocks = GridTerminalSystem.Blocks;
                      for (int i = 0; i < allBlocks.Count; ++i) {
                      if (allBlocks[i].CustomName.StartsWith(prefix))
                      return allBlocks[i];
                      }
                      throw new Exception(String.Format("FirstBlockWithPrefix: prefix \"{0}\" not found", prefix));
                      }
                      }
                      void InitMem(){
                      if (Storage == null)
                      Storage = "";
                      Mem.Init(Storage);
                      }
                      void WriteMem(){
                      Mem.WriteToStr(ref Storage);
                      }
                      void SaveMem(){
                      WriteMem();
                      }
                      class Mem{
                      static private string itemSep = "|";
                      static private string nameSep = ":";
                      static private string arraySep = ",";
                      static private string memStr;
                      static private Dictionary<string, string> memDic;
                      static public void Init(string str){
                      Set(str);
                      }
                      static public void WriteToStr(ref string str){
                      str = Get();
                      }
                      static public void Set(string value){
                      memStr = value;
                      memDic = new Dictionary<string, string>();
                      string[] arr = memStr.Split(new string[]{itemSep}, StringSplitOptions.None);
                      for (int i = 0; i < arr.Length; ++i) {
                      if (arr[i] == "")
                      continue;
                      string[] nvArr = arr[i].Split(new string[]{nameSep}, StringSplitOptions.None);
                      memDic[nvArr[0]] = nvArr.Length == 1 ? "" : nvArr[1];
                      }
                      }
                      static public string Get(){
                      StringBuilder sb = new StringBuilder();
                      string[] keys = new string[memDic.Count];
                      memDic.Keys.CopyTo(keys,0);
                      for (int i = 0; i < keys.Length; ++i) {
                      sb.Append(keys[i]);
                      sb.Append(nameSep);
                      sb.Append(memDic[keys[i]]);
                      sb.Append(itemSep);
                      }
                      return sb.ToString();
                      }
                      static public string GetString(string name){
                      if (!memDic.ContainsKey(name))
                      memDic[name]="";
                      return memDic[name];
                      }
                      static public int GetInt(string name){
                      int value = 0;
                      int.TryParse(GetString(name), out value);
                      return value;
                      }
                      static public float GetFloat(string name){
                      float value = 0;
                      float.TryParse(GetString(name), out value);
                      return value;
                      }
                      static public void SetString(string name, string value){
                      memDic[name] = value;
                      }
                      static public void SetVar(string name, object value){
                      SetString(name, Convert.ToString(value));
                      }
                      static public void SetInt(string name, int value){
                      SetString(name, Convert.ToString(value));
                      }
                      static public void SetFloat(string name, float value){
                      SetString(name, Convert.ToString(value));
                      }
                      }


                      IP属地:山东12楼2015-01-22 09:58
                      回复
                        又见程序猿,来个游戏的截图呗


                        IP属地:广东13楼2015-01-22 10:05
                        收起回复
                          同,+1


                          来自Android客户端14楼2015-01-22 10:08
                          回复
                            需要注意的是,没有动力时光靠陀螺仪旋转特别慢,你可以在后面加上各个方向的推进器,这样看起来转身更快了一点
                            看样子是这样的:


                            IP属地:山东15楼2015-01-22 10:18
                            回复