With the announcement of LabVIEW Robotics during the Day 1 keynote at NIWeek 2010, the R&D team at NI knew we had to step up and show off our product throughout the conference. Over the past several months, we’ve put our NI LabVIEW Robotics Starter Kit to the test by implementing vision-based obstacle avoidance and adding remotely-operated (teleoperable) functionality. For an audience of NIWeek attendees on the Exhibit Hall floor, however, we had to do more. We came up with a swarm of four Starter Kit robots who didn’t know anything about their surrounding environment and programmed them to work together to discover the physical space, collaborate with each other over WiFi, and collectively build a map.
To whet your appetite, here's a quick illustration of what went on in our demo.
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
<link rel="stylesheet" type="text/css" href="visio.css"/>
<title>
NIWeek System Diagram
</title>
<script type="text/javascript" language="javascript">
function UpdateTooltip(){};
function OnShapeClick(){};
</script>
<script src="png_1.js" type="text/javascript" language="javascript"></script>
<script type="text/javascript" language="javascript">
if( (parent.isSVG) ||
(parent.isVML && parent.vmlSupported) ||
(parent.isXAML && parent.isUpLevel))
{
location.replace(parent.g_FileList[parent.g_CurPageIndex].PriImage);
}
</script>
<script type="text/javascript" language="javascript">
var pageID = 0;
var isUpLevel = parent.isUpLevel;
var OnShapeClick = null;
if (!parent.isMac)
{
OnShapeClick = parent.OnShapeClick;
}
var OnShapeKey = parent.OnShapeKey;
var UpdateTooltip = parent.UpdateTooltip;
var clickMenu = parent.clickMenu;
var toggleMenuDiv = parent.toggleMenuDiv;
var toggleMenuLink = parent.toggleMenuLink;
var GoToPage = parent.GoToPage;
if (parent.isUpLevel)
{
if (parent.g_FirstPageToLoad != null && parent.g_FirstPageToLoad.length > 0)
{
if (parent.g_FileList[parent.g_CurPageIndex].PageID != pageID)
{
var fileEntry = parent.g_FileList[parent.g_CurPageIndex];
var fileToLoad = fileToLoad = fileEntry.PriImage;
if (fileEntry.SecImage.length > 0)
{
fileToLoad = fileEntry.SecImage;
}
location.replace(fileToLoad);
}
parent.g_FirstPageToLoad = null;
}
var viewMgr = new parent.CViewMgr();
parent.viewMgr = viewMgr;
viewMgr.SupportsDetails = true;
viewMgr.SupportsSearch = true;
viewMgr.put_Location = ViewMgrSetRasterLocation;
viewMgr.visBBoxLeft = 0.310764;
viewMgr.visBBoxRight = 10.459236;
viewMgr.visBBoxBottom = 2.540764;
viewMgr.visBBoxTop = 8.126736;
viewMgr.highlightDiv = null;
}
function load ()
{
if(isUpLevel)
{
arrowdiv.innerHTML = '<img id="arrowgif" alt="Shows the location of the selected shape" src="arrow.png"/>';
var pageIndex = parent.PageIndexFromID (pageID);
parent.CurPageUpdate (pageIndex);
}
}
function unload()
{
if(isUpLevel)
{
viewMgr = null;
parent.viewMgr = null;
}
}
window.onload = load;
window.onunload = unload;
document.onclick = clickMenu;
</script>
<style type="text/css">
body {
background:url(foo) fixed;
padding: 10px;
}
div.banner {
position: fixed;
_position: absolute;
top: 0;
left: 0;
_top: expression(eval(document.body.scrollTop));
_left: expression(eval(document.body.scrollLeft));
width: 100%;
_width: expression(eval(document.body.clientWidth));
margin: 0;
padding: 3px;
padding-left: 6px;
background:lime;
background-color: #FFFFC6;
font: 11px tahoma,arial,serif;
border-bottom: 2px ridge #FFFFC6;
}
</style>
</head>
<body class="pageView" bgcolor="#FFFFFF" style="margin: 0px">
<script type="text/javascript" language="javascript">
// Displays the banner prompt to install Silverlight
if (parent.slSupported && !parent.slInstalled)
{
var slBanner = document.createElement("div");
slBanner.className = "banner";
slBanner.innerHTML = 'To enable full functionality such as Pan and Zoom, <a href="http://www.microsoft.com/silverlight/resources/install.aspx" target="parent">click here</a> to install the Silverlight plug-in.';
document.body.appendChild(slBanner);
document.body.style.paddingTop = "2.5em";
}
</script>
<div id="arrowdiv" style="position:absolute;top:0;left:0;visibility:hidden;z-index:5">
</div>
<div id="menu1" onclick="clickMenu()" class="hlMenu">
</div>
<DIV id="RasterDiv" style="margin:10px">
<center>
<IMG id="ConvertedImage" SRC="png_1.png" ALT="Page-1" name=RasterImage BORDER="0" USEMAP="#visImageMap">
</center>
<MAP NAME="visImageMap">
<AREA shape="POLYGON" tabindex="1" ALT="" origTitle="" TITLE="" HREF="http://decibel.ni.com/content/docs/DOC-12952" target="_blank" COORDS="676,168,880,168,880,17,676,17,676,168" onmouseover="UpdateTooltip(this,0,75,event)" onfocus="UpdateTooltip(this,0,75,event)" onclick="return OnShapeClick(0,75,event);" onkeyup="OnShapeKey(0,75,event);">
<AREA shape="POLYGON" tabindex="1" ALT="Steering" origTitle="Steering" TITLE="Steering" HREF="http://decibel.ni.com/content/docs/DOC-13089" target="_blank" COORDS="619,451,751,451,751,351,619,351,619,451" onmouseover="UpdateTooltip(this,0,6,event)" onfocus="UpdateTooltip(this,0,6,event)" onclick="return OnShapeClick(0,6,event);" onkeyup="OnShapeKey(0,6,event);">
<AREA shape="POLYGON" tabindex="1" ALT="Path Planning" origTitle="Path Planning" TITLE="Path Planning" HREF="http://decibel.ni.com/content/docs/DOC-13091" target="_blank" COORDS="799,451,931,451,931,351,799,351,799,451" onmouseover="UpdateTooltip(this,0,5,event)" onfocus="UpdateTooltip(this,0,5,event)" onclick="return OnShapeClick(0,5,event);" onkeyup="OnShapeKey(0,5,event);">
<AREA shape="POLYGON" tabindex="1" ALT="Obstacle Avoidance" origTitle="Obstacle Avoidance" TITLE="Obstacle Avoidance" HREF="http://decibel.ni.com/content/docs/DOC-13089" target="_blank" COORDS="619,297,751,297,751,198,619,198,619,297" onmouseover="UpdateTooltip(this,0,4,event)" onfocus="UpdateTooltip(this,0,4,event)" onclick="return OnShapeClick(0,4,event);" onkeyup="OnShapeKey(0,4,event);">
<AREA shape="POLYGON" tabindex="1" ALT="Mapping" origTitle="Mapping" TITLE="Mapping" HREF="http://decibel.ni.com/content/docs/DOC-13089" target="_blank" COORDS="799,297,931,297,931,198,799,198,799,297" onmouseover="UpdateTooltip(this,0,3,event)" onfocus="UpdateTooltip(this,0,3,event)" onclick="return OnShapeClick(0,3,event);" onkeyup="OnShapeKey(0,3,event);">
<AREA shape="POLYGON" tabindex="1" ALT="" origTitle="" TITLE="" target="_top" COORDS="621,33,621,63,629,63,629,33,621,33" onmouseover="UpdateTooltip(this,0,37,event)" onfocus="UpdateTooltip(this,0,37,event)" onclick="return OnShapeClick(0,37,event);" onkeyup="OnShapeKey(0,37,event);">
<AREA shape="POLYGON" tabindex="1" ALT="" origTitle="" TITLE="" target="_top" COORDS="635,19,636,22,638,24,638,27,639,30,638,32,637,35,636,37,635,39,640,45,642,42,644,39,646,36,646,32,647,29,646,25,645,22,644,19,642,16,640,14,635,19" onmouseover="UpdateTooltip(this,0,37,event)" onfocus="UpdateTooltip(this,0,37,event)" onclick="return OnShapeClick(0,37,event);" onkeyup="OnShapeKey(0,37,event);">
<AREA shape="POLYGON" tabindex="1" ALT="" origTitle="" TITLE="" target="_top" COORDS="615,39,612,36,611,31,611,27,612,23,615,19,609,14,606,18,603,24,603,29,603,35,606,40,609,45,615,39" onmouseover="UpdateTooltip(this,0,37,event)" onfocus="UpdateTooltip(this,0,37,event)" onclick="return OnShapeClick(0,37,event);" onkeyup="OnShapeKey(0,37,event);">
<AREA shape="POLYGON" tabindex="1" ALT="" origTitle="" TITLE="" target="_top" COORDS="629,24,631,26,631,28,631,30,631,32,630,33,629,34,635,40,637,38,638,35,639,32,639,29,639,26,638,24,637,21,635,19,635,19,629,24" onmouseover="UpdateTooltip(this,0,37,event)" onfocus="UpdateTooltip(this,0,37,event)" onclick="return OnShapeClick(0,37,event);" onkeyup="OnShapeKey(0,37,event);">
<AREA shape="POLYGON" tabindex="1" ALT="" origTitle="" TITLE="" target="_top" COORDS="620,34,618,31,618,28,620,24,614,19,611,23,610,27,610,32,611,36,614,40,620,34" onmouseover="UpdateTooltip(this,0,37,event)" onfocus="UpdateTooltip(this,0,37,event)" onclick="return OnShapeClick(0,37,event);" onkeyup="OnShapeKey(0,37,event);">
<AREA shape="POLYGON" tabindex="1" ALT="" origTitle="" TITLE="" target="_top" COORDS="621,33,621,67,629,67,629,33,621,33" onmouseover="UpdateTooltip(this,0,37,event)" onfocus="UpdateTooltip(this,0,37,event)" onclick="return OnShapeClick(0,37,event);" onkeyup="OnShapeKey(0,37,event);">
<AREA shape="POLYGON" tabindex="1" ALT="" origTitle="" TITLE="" target="_top" COORDS="628,29,627,27,625,26,623,26,621,28,621,31,623,32,625,33,627,32,628,29" onmouseover="UpdateTooltip(this,0,37,event)" onfocus="UpdateTooltip(this,0,37,event)" onclick="return OnShapeClick(0,37,event);" onkeyup="OnShapeKey(0,37,event);">
<AREA shape="POLYGON" tabindex="1" ALT="" origTitle="" TITLE="" target="_top" COORDS="628,29,627,27,625,26,623,26,621,28,621,31,623,32,625,33,627,32,628,29" onmouseover="UpdateTooltip(this,0,37,event)" onfocus="UpdateTooltip(this,0,37,event)" onclick="return OnShapeClick(0,37,event);" onkeyup="OnShapeKey(0,37,event);">
<AREA shape="POLYGON" tabindex="1" ALT="" origTitle="" TITLE="" target="_top" COORDS="332,109,332,132,334,133,334,136,402,176,435,157,435,153,437,152,437,129,367,88,332,109" onmouseover="UpdateTooltip(this,0,9,event)" onfocus="UpdateTooltip(this,0,9,event)" onclick="return OnShapeClick(0,9,event);" onkeyup="OnShapeKey(0,9,event);">
<AREA shape="POLYGON" tabindex="1" ALT="" origTitle="" TITLE="" target="_top" COORDS="415,33,415,63,423,63,423,33,415,33" onmouseover="UpdateTooltip(this,0,76,event)" onfocus="UpdateTooltip(this,0,76,event)" onclick="return OnShapeClick(0,76,event);" onkeyup="OnShapeKey(0,76,event);">
<AREA shape="POLYGON" tabindex="1" ALT="" origTitle="" TITLE="" target="_top" COORDS="429,19,431,22,432,24,433,27,433,30,433,32,432,35,431,37,429,39,435,45,437,42,439,39,440,36,441,32,441,29,441,25,440,22,438,19,437,16,435,14,429,19" onmouseover="UpdateTooltip(this,0,76,event)" onfocus="UpdateTooltip(this,0,76,event)" onclick="return OnShapeClick(0,76,event);" onkeyup="OnShapeKey(0,76,event);">
<AREA shape="POLYGON" tabindex="1" ALT="" origTitle="" TITLE="" target="_top" COORDS="409,39,407,36,405,31,405,27,407,23,409,19,404,14,400,18,398,24,397,29,398,35,400,40,404,45,409,39" onmouseover="UpdateTooltip(this,0,76,event)" onfocus="UpdateTooltip(this,0,76,event)" onclick="return OnShapeClick(0,76,event);" onkeyup="OnShapeKey(0,76,event);">
<AREA shape="POLYGON" tabindex="1" ALT="" origTitle="" TITLE="" target="_top" COORDS="424,24,425,26,426,28,426,30,426,32,425,33,424,34,430,40,431,38,433,35,434,32,434,29,434,26,433,24,432,21,430,19,430,19,424,24" onmouseover="UpdateTooltip(this,0,76,event)" onfocus="UpdateTooltip(this,0,76,event)" onclick="return OnShapeClick(0,76,event);" onkeyup="OnShapeKey(0,76,event);">
<AREA shape="POLYGON" tabindex="1" ALT="" origTitle="" TITLE="" target="_top" COORDS="414,34,413,31,413,28,414,24,409,19,406,23,405,27,405,32,406,36,409,40,414,34" onmouseover="UpdateTooltip(this,0,76,event)" onfocus="UpdateTooltip(this,0,76,event)" onclick="return OnShapeClick(0,76,event);" onkeyup="OnShapeKey(0,76,event);">
<AREA shape="POLYGON" tabindex="1" ALT="" origTitle="" TITLE="" target="_top" COORDS="415,33,415,67,423,67,423,33,415,33" onmouseover="UpdateTooltip(this,0,76,event)" onfocus="UpdateTooltip(this,0,76,event)" onclick="return OnShapeClick(0,76,event);" onkeyup="OnShapeKey(0,76,event);">
<AREA shape="POLYGON" tabindex="1" ALT="" origTitle="" TITLE="" target="_top" COORDS="423,29,422,27,420,26,417,26,416,28,416,31,417,32,420,33,422,32,423,29" onmouseover="UpdateTooltip(this,0,76,event)" onfocus="UpdateTooltip(this,0,76,event)" onclick="return OnShapeClick(0,76,event);" onkeyup="OnShapeKey(0,76,event);">
<AREA shape="POLYGON" tabindex="1" ALT="" origTitle="" TITLE="" target="_top" COORDS="423,29,422,27,420,26,417,26,416,28,416,31,417,32,420,33,422,32,423,29" onmouseover="UpdateTooltip(this,0,76,event)" onfocus="UpdateTooltip(this,0,76,event)" onclick="return OnShapeClick(0,76,event);" onkeyup="OnShapeKey(0,76,event);">
<AREA shape="POLYGON" tabindex="1" ALT="" origTitle="" TITLE="" target="_top" COORDS="108,54,108,108,104,106,99,104,95,102,92,99,91,98,91,49,95,52,100,54,104,56,110,58,111,58,113,50,108,49,104,47,99,45,95,42,92,39,90,37,83,40,83,99,84,102,87,106,91,109,96,111,101,114,106,115,111,116,112,117,116,113,116,54,108,54" onmouseover="UpdateTooltip(this,0,60,event)" onfocus="UpdateTooltip(this,0,60,event)" onclick="return OnShapeClick(0,60,event);" onkeyup="OnShapeKey(0,60,event);">
<AREA shape="POLYGON" tabindex="1" ALT="" origTitle="" TITLE="" target="_top" COORDS="113,50,108,49,104,47,99,45,95,42,93,41,128,21,146,31,110,51,114,58,156,34,156,27,130,13,126,13,85,36,84,42,87,46,91,49,96,52,100,55,105,57,111,58,111,58,113,50" onmouseover="UpdateTooltip(this,0,60,event)" onfocus="UpdateTooltip(this,0,60,event)" onclick="return OnShapeClick(0,60,event);" onkeyup="OnShapeKey(0,60,event);">
<AREA shape="POLYGON" tabindex="1" ALT="" origTitle="" TITLE="" target="_top" COORDS="153,90,154,89,154,89,154,31,154,31,128,17,87,40,87,40,87,40,87,40,87,40,87,99,87,99,92,104,98,108,105,111,112,113,112,113,153,90" onmouseover="UpdateTooltip(this,0,60,event)" onfocus="UpdateTooltip(this,0,60,event)" onclick="return OnShapeClick(0,60,event);" onkeyup="OnShapeKey(0,60,event);">
<AREA shape="POLYGON" tabindex="1" ALT="" origTitle="" TITLE="" target="_top" COORDS="441,310,440,310,440,310,440,310,429,348,399,366,399,373,409,382,421,390,434,396,447,401,480,382,493,338,478,328,445,310,441,310" onmouseover="UpdateTooltip(this,0,45,event)" onfocus="UpdateTooltip(this,0,45,event)" onclick="return OnShapeClick(0,45,event);" onkeyup="OnShapeKey(0,45,event);">
<AREA shape="POLYGON" tabindex="1" ALT="" origTitle="" TITLE="" target="_top" COORDS="364,367,365,373,366,380,367,387,366,394,366,398,374,399,374,392,374,384,374,377,373,370,371,365,364,367" onmouseover="UpdateTooltip(this,0,29,event)" onfocus="UpdateTooltip(this,0,29,event)" onclick="return OnShapeClick(0,29,event);" onkeyup="OnShapeKey(0,29,event);">
<AREA shape="POLYGON" tabindex="1" ALT="" origTitle="" TITLE="" target="_top" COORDS="332,358,329,363,328,368,326,374,326,379,325,385,326,391,326,392,334,390,333,385,333,380,334,376,335,371,337,366,339,362,332,358" onmouseover="UpdateTooltip(this,0,29,event)" onfocus="UpdateTooltip(this,0,29,event)" onclick="return OnShapeClick(0,29,event);" onkeyup="OnShapeKey(0,29,event);">
<AREA shape="POLYGON" tabindex="1" ALT="" origTitle="" TITLE="" target="_top" COORDS="334,391,334,391,334,391,328,387,329,387,329,388,329,387,328,386,327,385,327,384,327,384,327,374,328,370,329,367,330,364,332,361,335,359,337,357,340,355,337,348,333,350,330,352,327,355,325,358,322,361,321,365,320,369,319,373,319,373,319,374,319,384,319,386,320,389,322,391,323,393,324,393,326,395,327,395,328,395,329,397,330,398,334,391" onmouseover="UpdateTooltip(this,0,29,event)" onfocus="UpdateTooltip(this,0,29,event)" onclick="return OnShapeClick(0,29,event);" onkeyup="OnShapeKey(0,29,event);">
<AREA shape="POLYGON" tabindex="1" ALT="" origTitle="" TITLE="" target="_top" COORDS="363,357,366,359,369,361,371,363,373,366,375,369,375,372,376,375,376,392,374,394,373,395,372,396,372,396,373,396,373,396,368,395,365,396,362,397,361,397,355,397,349,396,344,395,338,393,334,391,330,398,336,400,342,402,348,404,354,405,360,405,361,405,361,405,364,405,368,404,370,403,372,403,374,403,375,403,378,401,380,399,382,397,383,394,384,393,384,375,384,375,383,371,382,367,381,363,379,360,376,357,373,354,370,352,366,350,366,350,363,357" onmouseover="UpdateTooltip(this,0,29,event)" onfocus="UpdateTooltip(this,0,29,event)" onclick="return OnShapeClick(0,29,event);" onkeyup="OnShapeKey(0,29,event);">
<AREA shape="POLYGON" tabindex="1" ALT="" origTitle="" TITLE="" target="_top" COORDS="364,353,364,353,367,349,369,344,369,339,367,334,363,329,359,327,353,325,348,326,343,328,339,332,336,336,335,342,336,347,339,352,334,354,329,358,326,363,324,368,323,373,323,373,323,373,323,384,324,387,326,390,328,391,330,391,331,393,332,394,341,398,351,400,361,401,366,400,370,399,372,399,374,399,377,397,380,393,380,377,380,375,380,375,379,372,378,366,374,361,370,357,364,353" onmouseover="UpdateTooltip(this,0,29,event)" onfocus="UpdateTooltip(this,0,29,event)" onclick="return OnShapeClick(0,29,event);" onkeyup="OnShapeKey(0,29,event);">
<AREA shape="POLYGON" tabindex="1" ALT="" origTitle="" TITLE="" target="_top" COORDS="437,29,508,23,497,44,587,29,516,35,527,14,437,29" onmouseover="UpdateTooltip(this,0,23,event)" onfocus="UpdateTooltip(this,0,23,event)" onclick="return OnShapeClick(0,23,event);" onkeyup="OnShapeKey(0,23,event);">
<AREA shape="POLYGON" tabindex="1" ALT="Demo Operator UI" origTitle="Demo Operator UI" TITLE="Demo Operator UI" HREF="http://decibel.ni.com/content/docs/DOC-13050" target="_blank" COORDS="54,484,186,484,186,385,54,385,54,484" onmouseover="UpdateTooltip(this,0,8,event)" onfocus="UpdateTooltip(this,0,8,event)" onclick="return OnShapeClick(0,8,event);" onkeyup="OnShapeKey(0,8,event);">
<AREA shape="POLYGON" tabindex="1" ALT="Server UI" origTitle="Server UI" TITLE="Server UI" HREF="http://decibel.ni.com/content/docs/DOC-13050" target="_blank" COORDS="54,360,186,360,186,261,54,261,54,360" onmouseover="UpdateTooltip(this,0,7,event)" onfocus="UpdateTooltip(this,0,7,event)" onclick="return OnShapeClick(0,7,event);" onkeyup="OnShapeKey(0,7,event);">
<AREA shape="POLYGON" tabindex="1" ALT="Driver UI" origTitle="Driver UI" TITLE="Driver UI" HREF="http://decibel.ni.com/content/docs/DOC-13150" target="_blank" COORDS="357,511,490,511,490,411,357,411,357,511" onmouseover="UpdateTooltip(this,0,2,event)" onfocus="UpdateTooltip(this,0,2,event)" onclick="return OnShapeClick(0,2,event);" onkeyup="OnShapeKey(0,2,event);">
<AREA shape="POLYGON" tabindex="1" ALT="Localization" origTitle="Localization" TITLE="Localization" HREF="http://decibel.ni.com/content/docs/DOC-13051" target="_blank" COORDS="54,237,186,237,186,137,54,137,54,237" onmouseover="UpdateTooltip(this,0,1,event)" onfocus="UpdateTooltip(this,0,1,event)" onclick="return OnShapeClick(0,1,event);" onkeyup="OnShapeKey(0,1,event);">
</MAP>
</DIV>
</body>
</html>
And here's a quick peek at all of those parts coming together.
Our inspiration was a real-world rescue situation—a battlefield or a car accident in a remote area, for example—where a robot swarm like this one could be deployed to explore the area and then transmit sensor data to human operators or observers who must respond to the situation appropriately. The swarm of robots can operate autonomously or be controlled by remote operators, and out in the open, the robots would use GPS signals for localization.
Why should you care? We’re publishing all of our code for you to draw inspiration from. We used very specific hardware in our demo, which means you won’t just be able to load and run it. However, we think our code is useful because to produce our demo, we had to solve problems very common in the robotics world. Our code and our explanation of it will present some solutions you can draw from when designing your own LabVIEW Robotics applications. We’ll also explain our solutions for the following problems (and more!):
Over the next several weeks, we will explore the hardware and software solutions we put together to drive our swarm—everything from the data communication between the robots and a central computer down to the specific distance sensor drivers we used. The specific topics we will cover include:
As we mentioned before, our swarm consisted of four NI Robotics Starter Kit robots, which we’ve affectionately dubbed “DaNI.” Straight from NI, DaNI is a fully assembled robot base with an ultrasonic sensor, encoders, motors, a battery, and an NI Single-Board RIO-based controller, on which LabVIEW Robotics, LabVIEW Real-Time and LabVIEW FPGA Module software runs. You can read more about the stock Starter Kit product in its data sheet and in a system diagram that another Robotics user created. You also can check out the list of parts used on DaNI.
On each of our swarm robots, however, we swapped the ultrasonic sensor for an infrared distance sensor and added an Axis IP camera and a wireless router. You, too, can make these modifications to your DaNI robots using a quick procedure we’ve documented for you – Robot Recipe: Teleoperation Mode for NI Robotics Starter Kit. This was just one of several tasks we performed to produce our demo, but when we finished, DaNI herself was ready for action.
The environment the robots were to explore and map consisted of a 20 x 20 ft area with walls approximately 2 ft high surrounding the area. In the weeks leading up to NIWeek, we tested the demo in an open area of the office and used cinder blocks as our obstacles. Until we perfected our obstacle avoidance code, we wrapped the blocks in foam to protect the robots. For the actual demo at NIWeek, two large-scale LEGO models representing NI’s largest office building (Mopac C) and its parking garage were the primary obstacles in the arena. Combined, the two buildings consisted of about 14,000 LEGO blocks! We continued using cinder blocks as additional obstacles in the arena.
The image that follows is an overhead view of our robot arena.
Now what you’ve been waiting for—click here to download a zip file the code from our NIWeek demo! We used a few different pieces of NI software to write this code, so to open it without tons of VIs missing, you should use a computer with the following software installed:
Once you extract the files to the location where you want to work with the code, you’ll notice that the file structure is relatively flat. To access all of the code from a centralized location, open the following LabVIEW project:
_Main UIs\NIWeek 2010 Robotics Demo.lvproj
This LabVIEW project, shown below, organizes the code similarly to how the documentation in this series of blog posts will be laid out. That is, several virtual folders in the project correspond to forthcoming parts of this series. You can usually use the folder names in the main directory to find the code in which you are interested.
As we mentioned previously, we used very specific hardware in our demo, which means you probably won’t just be able to load the demo and run it. Even so, it’s useful for you to know that when we performed the demo, we ran each of the following VIs (paths as viewed in NIWeek 2010 Robotics Demo.lvproj😞
Now that we have your attention, we hope you'll come back to the read future installments in this series about how our robotic swarm came together. As we post future installments, we'll gradually explain each of the aspects of our demo until you have the complete story on our robotic swarm glory.
While the robots certainly weren't sleek and sexy (sorry DaNI), I have to say this is one of the coolest robot demos I've ever seen on a tradeshow floor. Not only did it demonstrate the technically-advanced concepts of swarm behavoirs and distributed processing, it was also an interactive demo that was really fun to play with. It's a shame we can't keep this demo up and running somewhere on campus for people to remotely access and control from their own computers around the world. It really was an awesome demo. Nice work, Karl and NI Robotics Team.
I have got to build me one of these !!!! I have just the spot.
What camera did you use for the top-down view (GPS simulation)?
Stay tuned! We will publish more details over the next few weeks! But if you're dying to know, it was a GigE camera from Basler.
Why did you swap the Ultrasonic sensors for infrared? Was it due to interference between the robots?
Yes, we found that when the ultra sonic sensors were close to each other and facing each other, there was some interference. If the robots didn't have to be so close to each other for the demo, this probably would have been a non-issue.
The IR rangefinder works by measuring the angle of incidence on the returning IR pulse. The pulse also has a much more narrow cone than an ultra sonic pulse, which keeps it from interfering with other sensors as much. We still noticed some interference with the IR rangefinder, but it occurred less frequently than with the ultra sonic sensor. Additionally, when there was interference, the rangefinder would return a consistent "no obstacle" reading; as opposed to the ultra sonic sensor that returned noisy data.
xunangua,
In this demo the robot locations and orientations were determined by an overhead camera. Each robot had a unique visual marker, so images taken by the camera were analyzed to find the markers of each of the robots, then the locations were transmitted to the robotos
In an unconfined outdoor environment you would need to use a GPS sensor to determine robot position. You would probably also want to use a compass to find robot direction, and other sensors like an IMU or LIDAR to improve position measurements.. LabVIEW Robotics includes drivers for these types of sensors (and many others). Do you have a specific application in mind?
-Chris
CMal:
I am so happy to recieve your respons ! The Robotic Swarm Demo I have read many times and know you use the camera to replace the GPS! It is a good idea!
As you konw Guilin is a very beautiful city .My school yard is arround with a beautiful river.I want to design the robots that can move on the load by itself in the school yard .The idea is Using the GPS to determine robot position and using the google map to plan the path.The LIDAR is so expensive that I don't have enough money to buy it .So first of all I will only use the digital map and the GPS to guid the robots without avoiding the obstacles.
How do you think about my idea? I want to know how to make a goodle map or a digital map becoming a grid map whitch can guid the robot?
two pictrues about my school yard!
Best wish !
--- 11年2月18日,周五, CMal <web.community@ni.com> 写道:
发件人: CMal <web.community@ni.com>
主题: Re: - NIWeek 2010 Robotic Swarm Demo
收件人: "南先 许" <xunangua@yahoo.cn>
日期: 2011年2月18日,周五,上午2:14
Community
NIWeek 2010 Robotic Swarm Demo new comment by CMal View all comments on this document
xunangua,
In this demo the robot locations and orientations were determined by an overhead camera. Each robot had a unique visual marker, so images taken by the camera were analyzed to find the markers of each of the robots, then the locations were transmitted to the robotos
In an unconfined outdoor environment you would need to use a GPS sensor to determine robot position. You would probably also want to use a compass to find robot direction, and other sensors like an IMU or LIDAR to improve position measurements.. LabVIEW Robotics includes drivers for these types of sensors (and many others). Do you have a specific application in mind?
-Chris
Reply to this email to respond to CMal's comment.
could u plz tell me how LIDAR can be used to determine position if u have any VI or program related to this plz share it..
What position do you want to determine ?
If the obs pos then just rewrite the example code to suit your sensor.
If the robot pos then you can use the encoders from DaNI to calculate the aprox. position. (easy and you don't need gps or any other sensor)
Does the open source code for this project still exist? The original hyperlink for downloading the code does not work. https://forums.ni.com/servlet/JiveServlet/download/13031-40-22941/NIWeek2010%20Robotics%20Demo.zip
Is there anywhere where I can be find the code?
This site uses cookies to offer you a better browsing experience. Learn more about our privacy statement and cookie policy.