如何修复tcl中的“无法读取“ node_(0)”:无此类变量”错误?

时间:2019-08-20 09:26:43

标签: tcl ns2

我正在建立一个网络环境,其中有DSR协议将n个节点围成一个圆圈。但是,当我修复大多数错误时,标题无法解决的最困惑的错误。如何修复“无法读取“ node_(0)”:无此类变量”错误?我不是已经在第86行的for循环中定义它了吗?

我找不到解决方法,当我改变时

set node_($i) [$ns node]

set node_($i) [$ns_ node]

这是完整的代码。

set val(chan)   Channel/WirelessChannel
set val(prop)   Propagation/TwoRayGround
set val(netif)  Phy/WirelessPhy
set val(mac)    Mac/802_11
set val(ifq)    CMUPriQueue
set val(ll)     LL
set val(ant)    Antenna/OmniAntenna
set val(ifqlan) 50
set val(nn)     0
set val(rp)     DSR
set val(x)      1000
set val(y)      1000
set val(r)      400

proc usage {} \
{
    global argv0
    puts "\nusage: $argv0 \[-nn node\] \[-r r\] \[-x x\] \[-y y\]\n"
    puts "note: \[-nn nodes\] is essential, and the others are optional.\n"
}

proc getval {argc argv} \
{
    global val
    lappend vallist nn r x y z
    for {set i 0} {$i < $argc} {incr i} {
        set arg [lindex $argv $i]
        if {[string range $arg 0 0] != "-"} continue
        set name [string range $arg 1 end]
        set val($name) [lindex $argv[expr $i+1]]
    }
}


getval $argc $argv
if {$val(nn) == 0} {
    usage
    exit
}


set ns [new Simulator]  

set tracefd [open circle.tr w]
$ns trace-all $tracefd

set namtracefd [open circle.nam w]  
$ns namtrace-all-wireless $namtracefd $val(x) $val(y)


proc finish {} \
{
    global ns tracefd namtracefd
    $ns flush-trace 
    #close the trace file
    close $tracefd
    close $namtracefd
    #execute nam on the trace file
    exec nam circle.nam &
    exit 0
}


set topo [new Topography]   

$topo load_flatgrid $val(x) $val(y)

create-god $val(nn)
$ns node-config     -addressType    def\
        -adhocRouting   $val(rp)\
        -llType         $val(ll)\
        -macType        $val(mac)\
        -ifqType        $val(ifq)\
        -ifqLan         $val(ifqlan)\
        -antType        $val(ant)\
        -propType       $val(prop)\
        -phyType        $val(netif)\
        -channelType    $val(chan)\
        -topoInstance   $topo\
        -agenttrace     ON\
        -routertrace    ON\
        -mactrace       OFF\
        -movementtrace  OFF

##################################
for {set i 0} {$i < $val(nn)} {incr i} {
    set node_($i) [$ns node]
    $node_($i) random-motion 0
    $node_($i) set X_ [expr $val(r) * cos($i * 2 * 3.14159 / $val(nn))]
    $node_($i) set Y_ [expr $val(r) * sin($i * 2 * 3.14159 / $val(nn))]
    $node_($i) set Z_ 0
    $ns initial_node_pos $node_($i) [expr $val(x) / 10]
}
##################################

set tcp [new Agent/UDP]
$ns attach-agent $node_(0) $tcp
set null [new Agent/Null]
$ns attach-agent $node_([expr $val(nn) / 2]) $null

set cbr [new Application/Traffic/CBR]
$cbr set packetSize_ 5000
$cbr set interval_ 0.05
$cbr attach-agent $tcp
$ns connect $tcp $null

$ns at 0.1 "$cbr start"
$ns at 3.0 "$cbr stop"
$ns at 5.0 "finish"
$ns run

当我输入ns circle.tcl -nn 12时,我期望输出:

num_node is set 12
warning: Please use -channel as shown in tcl/ex/wireless-mitf.tcl
INITIALIZE THE LIST xListHead
channel.cc:sendUp - Calc highestAntennaZ_and distCST_
SORTING LISTS ...DONE!

请帮助我,我已经被困了很长时间了。

2 个答案:

答案 0 :(得分:2)

只要val(nn)不大于零,就会产生该错误,因为这样会创建节点的循环:

for {set i 0} {$i < $val(nn)} {incr i} {
    set node_($i) [$ns node]
    $node_($i) random-motion 0
    $node_($i) set X_ [expr $val(r) * cos($i * 2 * 3.14159 / $val(nn))]
    $node_($i) set Y_ [expr $val(r) * sin($i * 2 * 3.14159 / $val(nn))]
    $node_($i) set Z_ 0
    $ns initial_node_pos $node_($i) [expr $val(x) / 10]
}

只会简单地决定它无事可做,甚至不会执行一次循环主体。是什么原因造成的?好吧,如果我们看一下参数解析过程:

proc getval {argc argv} \
{
    global val
    lappend vallist nn r x y z
    for {set i 0} {$i < $argc} {incr i} {
        set arg [lindex $argv $i]
        if {[string range $arg 0 0] != "-"} continue
        set name [string range $arg 1 end]
        set val($name) [lindex $argv[expr $i+1]]
    }
}

我们可以看到许多问题,其中最大的问题是(与set val($name)相同的行:

lindex $argv[expr $i+1]

这里的问题是$argv与表达式求值之间缺少空格;在将结果作为单个参数输入lindex之前将两个字符串连接起来! ({lindex仅带有一个自变量,只是使用“优雅地执行任何操作”的原则返回该自变量。)这在语法上甚至在所有情况下都不正确,但可能是在您尝试并导致{{1 }}设置为类似于字符串val(nn)的内容。现在, -nn 101运算符(在节点生成循环中)每当 端看起来都是非数字时,将使用ASCII排序。字符串中有多余的垃圾,因此绝对是非数字的。噢亲爱的。 ({<是ASCII字符代码45,而-是ASCII字符代码48,因此0-之前。)这不是您想要的!

这是参数解析器的固定版本:

0

记住,在Tcl中,空格很重要!

答案 1 :(得分:0)

添加四行,可以运行模拟。

if(require(seqinr)){
  mase.res   <- read.alignment(file=system.file("sequences/test.mase",package="seqinr"), format = "mase")
  mase.res
  x <- alignment2genind(mase.res)
  x
} 

/// GENIND OBJECT /////////

 // 6 individuals; 82 loci; 212 alleles; size: 57.2 Kb

 // Basic content
   @tab:  6 x 212 matrix of allele counts
   @loc.n.all: number of alleles per locus (range: 2-5)
   @loc.fac: locus factor for the 212 columns of @tab
   @all.names: list of allele names for each locus
   @ploidy: ploidy of each individual  (range: 1-1)
   @type:  codom
   @call: alignment2genind(x = mase.res)

 // Optional content
   @other: a list containing: com 

set val(ifqlen) 50 ;# added (Line 7) set val(nn) 10 ;# added (Line 10) . -movementtrace OFF \ -ifqLen $val(ifqlen) ;# added (Line 85) . for {set i 0} {$i < [expr $val(nn)]} {incr i} { set node_($i) [$ns node] ;# added (Line 89) 的原因:我没有使用[$ argv]。 (set val(nn) 10$ ns file.tcl -nn 10

链接到已编辑文件:https://www.dropbox.com/s/m7zsnga6wf29r95/2Ezio-Auditore-DSR.tcl?dl=0

https://drive.google.com/drive/folders/0B7S255p3kFXNSmRYb2lGcDRUdWs?usp=sharing之前的所有3500 ns2仿真


EDIT:添加了@Donal Fellows的'argument parser',现在可以与$ ns file.tcl nn 10一起运行。新示例https://www.dropbox.com/s/br6qaeg5kj73k14/4-circle-Ezio-Auditore.tar.gz?dl=0

ns2分析脚本https://drive.google.com/drive/folders/1rU_MFAEl1GCLMTJPLR3zbxPxkQQHkQ7T?usp=sharing