2017-07-15 4 views
0

$resultproc Inverse2を1秒ごとにスケジュールして保存しようとしています(別のプロシージャ内で呼び出され、そのプロシージャは1秒間に再スケジュールされます)。 Inverse2手順) 私は{今のxy}で出力を取得し、最新のためにそれに変数を割り当てる2つのインスタンス エラーの原因「浮動小数点例外(コアダンプ)」

x1-> x location at current time (for example at 8.0) 
y1-> y location at current time 
x2-> x location at (current time+1) (for example at 9.0) 
y2-> y location at (current time+1) 

をし、さらに計算に使用したい理由です。 以下は試したコードですが、2回繰り返した後にエラーが発生するのは Floating point exception (core dumped)です。どこが間違っているの?

コード:

set result {} 

proc Inverse2 {m} { 
    set op [open output.tr w] 
    global result 
    global ns 
    set now [$ns now] 
    lassign [lindex $m 0 2] x1 
    lassign [lindex $m 0 3] y1 
    lassign [lindex $m 0 6] d1 
    lassign [lindex $m 1 2] x2 
    lassign [lindex $m 1 3] y2 
    lassign [lindex $m 1 6] d2 
    lassign [lindex $m 2 2] x3 
    lassign [lindex $m 2 3] y3 
    lassign [lindex $m 2 6] d3 

    set mt {{? ?} {? ?}} 
    lset mt 0 0 [expr 2*($x1-$x2)] 
    lset mt 0 1 [expr 2*($y1-$y2)] 
    lset mt 1 0 [expr 2*($x1-$x3)] 
    lset mt 1 1 [expr 2*($y1-$y3)] 
    set const {{?} {?}} 
    lset const 0 [expr {(pow($x1,2)+pow($y1,2)-pow($d1,2))-(pow($x2,2)+pow($y2,2)-pow($d2,2))}] 
    lset const 1 [expr {(pow($x1,2)+pow($y1,2)-pow($d1,2))-(pow($x3,2)+pow($y3,2)-pow($d3,2))}] 
    #puts $result "$const" 
    # puts $result "$mt" 
    set x [expr {double([lindex [Inverse3 $mt] 0 0] * [lindex $const 0] 
         + [lindex [Inverse3 $mt] 0 1] * [lindex $const 1])}] 
    set y [expr {double([lindex [Inverse3 $mt] 1 0] * [lindex $const 0] 
         + [lindex [Inverse3 $mt] 1 1] * [lindex $const 1])}] 

    lappend result "$x $y $now" 
    puts $result 
    for {set i 0} {$i< [llength $result]} {incr i} { #for latest two instances 
     for {set j 1} {$i< [llength $result]} {incr j} {  
      set X1 [lindex $result $i 0] 
      set Y1 [lindex $result $i 1] 
      if {[llength $result] >1} { #to ensure length of list is greater than 1 
       set X2 [lindex $result $j 0] 
       set Y2 [lindex $result $j 1] 

       set v [expr hypot($X2-$X1,$Y2-$Y1)/ ($now-($now-1))] 
       set theta [expr acos(($X2-$X1)/(hypot($X2-$X1,$Y2-$Y1)))] 
       set Xp [expr ($X2+($v*$now*cos($theta)))] 
       set Yp [expr ($Y2+($v*$now*sin($theta)))] 
       puts "$Xp $Yp" 
      } 
      break 
     } 
    } 
} 

答えて

1

浮動小数点例外がいくつかの異なるものから来ることができます。一般的に、主な原因はゼロを0で割るようなひどいことです。しかし、Tclは、通常、あなたのプログラムを完全にクラッシュさせないようにし、代わりにあなたが捕まえることができるエラーを生成するのにかなり良いです。したがって、何が起こっているのかは、より厄介なケースのいずれか、またはns2で実行されていることと、信号浮動小数点エラーをオンにすること(Tclの標準実装は、おそらく不当な致命的なクラッシュを避けるため、

後者の場合、プロセスからプロセスを標準tclshに移動するのが最も簡単な方法です。私たちはFPUフラグのようなトリッキーなものをもっとコントロールするので、そこでの動作の正確さをより強固に保証することができます。

しかし、それはかつてのであれば...問題は、これらの行にある必要があります。そこにライン

  set v [expr hypot($X2-$X1,$Y2-$Y1)/ ($now-($now-1))] 
      set theta [expr acos(($X2-$X1)/(hypot($X2-$X1,$Y2-$Y1)))] 
      set Xp [expr ($X2+($v*$now*cos($theta)))] 
      set Yp [expr ($Y2+($v*$now*sin($theta)))] 

を、最も疑わしい1はthetaの計算です。あなたがやっていることにはいくつかの問題があります(例えば、三角測量のためにいくつかの象限が正しく処理されません)。しかし、大きな厄介な点は、そこに2つの連続した位置が同じ。 hypot()を使用することができれば、角度を計算することはで最もよく計算されたです。これは、厄介なエッジケースをはるかによく扱うためです(例えば、ひどい無限大の問題はありません)。これを試してみてください:私は上記のやったよう

  set theta [expr { atan2($Y2-$Y1, $X2-$X1) }] 

はまた{かっこ}であなたの表情を置きます。これは、Tclが式をバイトコードでコンパイルできるようにし、コードをかなり速くします。また、式の中にスペースを入れて、複数の行にまたがっていなくても読みやすくすることができます。また、変数を使用して、式の数値。簡単に言えば、これは簡単で、コードをより良くすることができます。


他のマイナーな問題は

  1. あなたは($now-($now-1))が今まで1以外のものを計算するために期待していますか?または、シミュレーション時間の浮動小数点数を扱っていることを考えると、少なくとも1.0に非常に近い値ですか?私はvのあなたの計算をhypot()のストレート使いに安全に簡素化できると思います。

  2. これらのネストされた2つのループは奇妙に見える:残りかどうかに応じて

    for {set i 0} {$i< [llength $result]} {incr i} { 
        for {set j [expr {$i + 1}]} {$j< [llength $result]} {incr j} { 
         # Just the upper triangle of the comparison matrix 
    

    for {set i 0} {$i< [llength $result]} {incr i} { 
        for {set j 0} {$j< [llength $result]} {incr j} {  
         if {$i == $j} continue; # Skip the diagonal in the comparison matrix 
    

    またはこの:

    for {set i 0} {$i< [llength $result]} {incr i} { 
        for {set j 1} {$i< [llength $result]} {incr j} {  
    

    は、私はあなたがこれを行うには意味のどちらかだと思いますの両方の値を比較する必要があります(ただし決してそれ自体ではありません) d。後者はあまり機能しませんが、比較が対称でない場合(間違っていることの詳細に依存します)、間違っている可能性があります。 loop.I用に関する

+0

はこの{500.1 450 8.0} {378.1 478 9.0}のように見えるresult' 2回の反復 '$後this.egなどの最新の2組のために、すなわち、' $のresult'出力に変数を割り当てますだから、x1> [lindex $ result 0 0]&y1> [lindex $ result 0 1]とx2> [lindex $ result 1 0]&y2> [lindex $ result 1 1]を割り当てる必要があります。 "j"に1をつけて、各繰り返しの後にリストから最新の2つのタプルを取ります。最初のリストにはタプルが1つしかないので、2番目のforループは変数を代入することができず、エラーをスローします。 –

関連する問題