MOOS-ivp 实验八 多水下机器人作业(3)
希望每天都可以学到新的知识,有新的收获~
时间不知不觉过去了很久,距离上一次MOOS课程的学习已经有了4个月的时间,是时候继续MOOS课程的学习了~
文章目录
七、The Henry Gilda Refuel Mission
找到如下目录进行初始模板文件复制
cd moos-ivp/ivp/missions-2680
cp -rp lab_08_henry_gilda_baseline moos-ivp-janedoe/missions/lab_08/henry_gilda_baseline
该任务需要完成的目标如下:
(1)添加一个新的加油按钮到pMarineViewer配置快中去,按下按钮之后会发布消息 REFUEL_NEEDED ALL=true.
(2)通过增加meta_shoreside.moos文件中的uFldShoreBroker配置块,确保所有vehicle共享该变量
(3)不要对targ *文件进行编辑,这个是通过plug自动生成的文件,使用后需要对其进行删除
(4)添加一个Timer行为到vehicle行为配置文件中去。要求vehicle自动加油完成后等待60s发布endflag标志。然后恢复loiter行为。时间及时完成之后,vehicle应该自己返回执行loiter任务。
(5)一旦user发出命令,stationkeep应该立即工作
(6)使用RETURN按钮之后,vehicle应该仍然返回,但是当以这种方式返回时,它就像在基线任务中一样工作——它保持并无限期地保持不变,直到重新部署。
1.配置meta_shoreside.moos文件
打开meta_shoreside.moos文件修改pMarineViewer配置块为如下代码:
ProcessConfig = pMarineViewer
{
AppTick = 4
CommsTick = 4
TIFF_FILE = forrest19.tif
set_pan_x = -90
set_pan_y = -280
zoom = 0.65
vehicles_shape_scale = 1.5
vehicles_name_mode = names+shortmode
point_viewable_labels = false
polygon_viewable_labels = false
appcast_viewable = true
appcast_color_scheme = indigo
hash_delta = 50
hash_viewable = true
hash_shade = 0.35
SCOPE = PHI_HOST_INFO
BUTTON_ONE = DEPLOY # DEPLOY_ALL=true
BUTTON_ONE = MOOS_MANUAL_OVERRIDE_ALL=false
BUTTON_ONE = RETURN_ALL=false # STATION_KEEP_ALL=false
BUTTON_TWO = RETURN # RETURN_ALL=true
BUTTON_TWO = STATION_KEEP_ALL=false
BUTTON_THREE = STATION # STATION_KEEP_ALL=true
BUTTON_FOUR = REFUEL # REFUEL_NEEDED_ALL=true
}
可以看到 在BUTTON_FOUR中已经对REFUEL按钮进行添加。
接下来对uFldShoreBroker配置块进行修改
ProcessConfig = uFldShoreBroker
{
AppTick = 1
CommsTick = 1
QBRIDGE = DEPLOY, NODE_REPORT
QBRIDGE = STATION_KEEP, APPCAST_REQ
QBRIDGE = MOOS_MANUAL_OVERRIDE
QBRIDGE = REFUEL_NEEDED
BRIDGE = src=RETURN_ALL, alias=RETURN
BRIDGE = src=RETURN_$V, alias=RETURN
}
2.uFldShoreBroker详解
要理解上面的配置首先需要对uFldShoreBroker有一定了解。知道各个部分都是用来做什么的。uFldShoreBroker主要功能是对community与各个通讯节点进行自动配置和连接的一个工具。
上图展示了一个vehicle发送消息给shoreside,通过uFldShoreBroker工具对各个节点进行连接,尤其是建立一个关于MOOS变量的bridge。
下面是uFldShoreBroker的主要功能:
(1)发现shoreside自己的host信息
(2)等待非本地vehicle发来的NODE BROKER PING消息
(3)针对一个到来的ping,对指定位置的节点回复 NODE BROKER ACK消息
(4)通过对模块进行配置,可以对指定变量建立相关节点bridge
(5)保持周期性的发送消息,以对vehicle与community的实时连接进行确认。
上述的代码块中的:
BRIDGE = src=RETURN_ALL, alias=RETURN
BRIDGE = src=RETURN_$V, alias=RETURN
这表示bridge连接,连接的对象是本地已知的变量以及远程已知的变量。比如上述代码块中将src变量RETURN_ALL和dest变量相连接。如果pshare发布消息,这三个消息来自三个不同的vehicle:
PSHARE_CMD = "src_name=DEPLOY_ALL, dest_name=DEPLOY, route=2.56.111.1:9200"
PSHARE_CMD = "src_name=DEPLOY_ALL, dest_name=DEPLOY, route=2.56.111.3:9200"
PSHARE_CMD = "src_name=DEPLOY_ALL, dest_name=DEPLOY, route=2.56.111.6:9200"
这就相当于在pshare模块中同时配置以下三个内容:
output = src_name=DEPLOY_ALL, dest_name=DEPLOY, route=12.56.111.1:9200
output = src_name=DEPLOY_ALL, dest_name=DEPLOY, route=12.56.111.3:9200
output = src_name=DEPLOY_ALL, dest_name=DEPLOY, route=12.56.111.6:9200
而RETURN_ V 中 的 V中的 V中的V则表示宏语句,可以代表前缀是RETURN_的任何变量,下面举一个例子来看看,在uFldShoreBroker 中配置下面语句:
bridge = src=DEPLOY_$V, alias=DEPLOY
$V宏将在需要申请新桥时扩展到车辆名称。如果新接收到的ping来自名为gilda的节点,则来自上述模式的桥接请求可能如下所示:
PSHARE_CMD = cmd=output, src_name=DEPLOY_GILDA, dest_name=DEPLOY,
route=2.56.111.1:9200
快捷配置qbridge表示quick bridge,用于对常用配置的一种简便写法:
bridge = src=DEPLOY_ALL, alias=DEPLOY
bridge = src=DEPLOY_$V, alias=DEPLOY
bridge = src=RETURN_ALL, alias=RETURN
bridge = src=RETURN_$V, alias=RETURN
上面的语句是对一个非常常用的给定变量桥接,当我们发送DEPLOY ALL="true"时,所有的vehicle都会被部署。当我们只想部署james vehicle时,仅仅发布 RETURN JAMES=“true” 就可以了。那么以上四种配置可以简写为:
qbridge = DEPLOY, RETURN
像上图所展示的,对于像DEPLOY这样的变量,在shoreside社区中发布的DEPLOY ALL将适用于所有已知车辆,而发布的DEPLOY HENRY将只适用于该特定车辆。
3.配置meta_vehicle.bhv文件
唉,不得不感叹一句,之前有各种事情需要去做,MOOS太久没看了,搞得我现在好多都忘了。还得去翻看之前写的博客,学习还是要一蹴而就比较好,中断太久再回来弥补需要的时间成本实在是太高了~。
主要对meta_vehicle.bhv文件进行配置 ,配置内容如图所示:
//-----------------------------------------------
// Helm Behavior file
initialize DEPLOY = true
initialize RETURN = false
initialize STATION_KEEP = false
initialize LOITER = true
initialize REFUEL_NEEDED = false
initialize AT_START_PT = false
set MODE = ACTIVE {
DEPLOY = true
} INACTIVE
set MODE = STATION-KEEPING {
MODE = ACTIVE
STATION_KEEP = true
}
set MODE = RETURNING {
MODE = ACTIVE
RETURN = true
}
set MODE = RETURNING_REFUEL {
MODE = ACTIVE
REFUEL_NEEDED = true
AT_START_PT = false
}
set MODE = LOITERING {
MODE = ACTIVE
LOITER = true
REFUEL_NEEDED = false
}
set MODE = REFUELING {
MODE = ACTIVE
REFUEL_NEEDED = true
AT_START_PT = true
}
//----------------------------------------------
Behavior = BHV_Loiter
{
name = loiter
pwt = 100
condition = MODE==LOITERING
post_suffix = A
speed = 1.3
clockwise = false
radius = 8.0
nm_radius = 15.0
polygon = radial::$(LOITER_POS), radius=20, pts=8, snap=1, label=$(VNAME)_LOITER
visual_hints = nextpt_color=white, nextpt_lcolor=khaki
visual_hints = edge_color=orange, vertex_color=white
visual_hints = edge_size=1, vertex_size=2
}
//----------------------------------------------
Behavior = BHV_Waypoint
{
name = waypt_return
pwt = 100
condition = MODE==RETURNING
endflag = STATION_KEEP = true
perpetual = true
speed = 1.3
radius = 3.0
nm_radius = 15.0
points = $(START_POS)
lead = 8
}
//----------------------------------------------
Behavior = BHV_StationKeep
{
name = station-keep
pwt = 100
condition = MODE==STATION-KEEPING
center_activate = true
inner_radius = 5
outer_radius = 10
outer_speed = 1.0
transit_speed = 1.3
swing_time = 7
visual_hints = vertex_size=0, edge_color=gray50
}
//--------------------------------------------------
Behavior = BHV_Timer
{
name = bhv_refuel
condition = MODE == REFUELING
condition = AT_START_PT = true
duration =60
duration_idle_decay= false
perpetual = true
endflag = REFUEL_NEEDED = false
endflag = AT_START_PT = false
endflag = LOITER = true
}
//----------------------------------------------
Behavior = BHV_Waypoint
{
name = refuel_return
pwt = 100
condition = MODE==RETURNING_REFUEL
endflag = AT_START_PT = true
perpetual = true
speed = 1.3
radius = 3.0
nm_radius = 15.0
points = $(START_POS)
lead = 8
}
//------------------------------------------------
下面我对代码块进行一下分析:
首先看一下什么是set MODE。这是一个设置层级和节点的关系式子,可以通过左边的节点图看出,设置的节点都是一层一层向下递推的关系。在执行.bhv文件时,一旦读取了开头声明的节点设置,那么其后运行都会保持一个静态的设置,节点层级不会随意变更。整个层级结构和一个特别的MOOS变量相关,这个变量就是MODE变量。虽然层级结构保持静止,但是在helm每次迭代过程中都会对基于层级结构中的节点相关联条件进行重新评估。如上图所示,MODE变量开始时的值被重置为空字符,在经过第一个块之后,变量将会被设置为“Active”和“inactive”。在进行第二个块评估时,将根据第一个块的模式“MODE=Active”来评估,因此在之后的行为模块中,需要将子代的模式声明列在父代声明之后。
一旦评估了 模式,就可以在行为条件下使用如同上述“ condition = MODESTATION-KEEPING”所展示的这样,注意一下“”,一旦使用了“ condition = MODESTATION-KEEPING”就代表了MODE=ACTIVE:STATION-KEEPING,表示的是关联了父节点下的子节点。如上图,如果使用“ActiveActive:Returning”或者“Returning==Active:Returning”则表示仅仅跟后面匹配的字符模式相关联。
至于station-keeping行为参数的具体示例和解释可以参考官网给出的说明,这里就贴在下面了:
各个行为之间,设置好节点模式之后,就会相继执行触发,所以只要提前设置好节点模式,在行为触发condition条件处写好触发条件,并对各个行为模块进行合理配置,那么就可以实现自己想要实现的AUV巡航行为的要求了。而条件触发和改变,需要通过
配置.moos文件中pMarineViewer块来进行,配置按钮触发不同的条件,那么AUV在仿真环境下就会执行条件下相应的命令了。
4.配置launch.sh文件
主要需要 对第二部分进行配置,可以看到launch.sh文件中第二部分内容,对两台AUV的名称,初始地点,LOITER行为的位置都进行了初始化配置
#-----------------------------------------------------------
# Part 2: Create the .moos and .bhv files.
#-----------------------------------------------------------
VNAME1="gilda"
VNAME2="henry"
START_POS1="0,0"
START_POS2="80,0"
LOITER_POS1="x=0,y=-75"
LOITER_POS2="x=125,y=-50"
SHORE_LISTEN="9300"
nsplug meta_vehicle.moos targ_$VNAME1.moos -f WARP=$TIME_WARP \
VNAME=$VNAME1 START_POS=$START_POS1 \
VPORT="9001" SHARE_LISTEN="9301" \
VTYPE="kayak" SHORE_LISTEN=$SHORE_LISTEN
nsplug meta_vehicle.moos targ_$VNAME2.moos -f WARP=$TIME_WARP \
VNAME=$VNAME2 START_POS=$START_POS2 \
VPORT="9002" SHARE_LISTEN="9302" \
VTYPE="kayak" SHORE_LISTEN=$SHORE_LISTEN
nsplug meta_vehicle.bhv targ_$VNAME1.bhv -f VNAME=$VNAME1 \
START_POS=$START_POS1 LOITER_POS=$LOITER_POS1
nsplug meta_vehicle.bhv targ_$VNAME2.bhv -f VNAME=$VNAME2 \
START_POS=$START_POS2 LOITER_POS=$LOITER_POS2
nsplug meta_shoreside.moos targ_shoreside.moos -f WARP=$TIME_WARP \
VNAME="shoreside" SHARE_LISTEN=$SHORE_LISTEN VPORT="9000"
if [ ${JUST_MAKE} = "yes" ] ; then
exit 0
fi
这里由于使用了uFldShoreBroker的宏,所以在使用nsplug指令时可以直接将变量名称进行替换,就可以实现一个.moos文件配置两台AUV进行巡航任务了。
5.使用nsplug实用程序配置任务和行为文件
忘了之前有没有补充过了,为了防止 大家看不懂上面的launch文件配置内容,这里在补充一部分。
在多vehicle任务中,跨vehicle的任务和行为文件的维护会变得很麻烦,并且容易出现用户错误的现象。因为许多文件组件在vehicle之间是相同的,所以通过从文件模板文件构建文件来可以减少相当多的问题,文件模板文件包括来自单独文件的公共组件。
nsplug命令行实用程序用于将模板文件扩展到目标文件,传递的参数通常会将生成的文件与从同一模板生成的其他文件区分开来。例如,两个任务文件,一个用于vehicle的“charlie”,另一个用于vehicle“frankie”,可能仅在vehicle的名称和IP端口号上有所不同,并且可以由具有以下两个命令的模板文件产生:
nsplug meta_vehicle.moos targ_charlie.moos VNAME=charlie PORT=9201
nsplug meta_vehicle.moos targ_frankie.moos VNAME=charlie PORT=9202
在实际文件中,其实并没有包含类似于targ_frankie.moos这样的文件,这些文件都是在执行launch.sh文件时生成的,执行命令如下所示:
./launch.sh
上述调用将构建任务和行为文件,并为每辆vehicle调用pAntler来启动模拟。某些常见的命令行选项,如"/launch - just build “是表示构建任务文件而不启动。关于模板和nsplug的一些约定如下:
(1)用作模板的文件有一个“meta_”前缀
(2)要包含或插入另一个模板文件的文件有一个“plug_”前缀
(3)通过nsplug从模板和插件构建的输出文件具有“targ_”前缀。
(4)构成目标MOOS文件的模板或插件文件具有”.moos “后缀。
(5)构成目标Helm behavior文件的模板或插件文件具有”.bhv "后缀。
下面给一个 示例:
执行launch命令前:
$ cd missions/m2_berta
$ ls
clean.sh* plug_uSimMarine.moos plug_pMOOSBridgeV.moos
launch.sh* plug_origin_warp.moos plug_pMarinePID.moos
meta_shoreside.moos plug_pBasicContactMgr.moos plug_pNodeReporter.moos
meta_vehicle.bhv plug_pHelmIvP.moos plug_uProcessWatch.moos
meta_vehicle.moos plug_pLogger.moos plug_uXMS.moos
执行后,多了许多targ前缀文件:
$ ./launch.sh --just_build
$ ls
clean.sh* plug_pBasicContactMgr.moos plug_uXMS.moos
launch.sh* plug_pHelmIvP.moos targ_gilda.bhv
meta_shoreside.moos plug_pLogger.moos targ_gilda.moos
meta_vehicle.bhv plug_pMOOSBridgeV.moos targ_henry.bhv
meta_vehicle.moos plug_pMarinePID.moos targ_henry.moos
plug_uSimMarine.moos plug_pNodeReporter.moos targ_shoreside.moos
plug_origin_warp.moos plug_uProcessWatch.moos
在MOOSTimeWarp=10的情况下,启动:
./launch.sh 10
总结
终于第八个实验算是告一段落了,最近一段时间一直没有更新学习,导致我个人也遗忘了不少东西,所以需要继续加油,这篇博客也写了不少内容,粗略看下包含代码来大约1W字左右,有点长,下次分开来写。