Communicating with CLARAty Strategies for Communication and Coordination Across the Network.

  • Published on

  • View

  • Download


<ul><li><p>Communicating with CLARAtyStrategies forCommunication and CoordinationAcross the Network</p></li><li><p>Where We Are Today Caroline Chouinardpresents</p><p>The Design and Implementationof theFunctional Layer/Decision LayerConnector Class</p></li><li><p>Presentation LayoutShow need for Connector Explain parts on DL (comm to and from TDL)Explain parts on FL (commanding to rover (sim and real) and feedback)Discuss integration (with code examples)Propose other alternatives</p></li><li><p>Why do we need a Connector between DL and FL?Defined interface means plug and playRocky7, Rocky8, ROAMS, HappySimRunning DL and FL on separate subnets is easier and sometimes necessaryTo be onboard or not? Ground vs. OnboardDL not compiled for VxWorks</p></li><li><p>DL to ConnectorTDLConnectorTLDLTTalker ThreadLListener ThreadSocketMapping</p><p>Creates FL_Interface to allow API forsending and receivingdata</p><p>Command maps directly to Rover function callsFL_CommandFL_Update</p></li><li><p>Connector to FLConnectorLTTLTalkerListenerFLRoverData translated to FL_UpdateFL_Command translated to Rover functionsMappingGeneric Rover to specifictype Commands turn into actions withfeedback(contained in FL)</p></li><li><p>IntegrationDL connection to ConnectorFirst create an FL_InterfaceCreate an FL_Command and add to queue Open socket and send all FL_Commands (one at a time)Listen for responses over another socketProcess any feedback and react accordingly (ex. Low energy update causing replanning)</p><p>Connector to FLCreate a generic Rover which is determined by the compile target Create an object mapping from FL_Interface commands to real rover function callsRetrieve data manually from the Rover through function calls, as necessary Translate data into FL_Update and send across socket</p></li><li><p>Setting up the system: Setting the required parameters on the FL Sending the appropriate DEFINE flags Choosing the right Rover type</p><p>API design: Base design of the FL_Command and FL_Update (both inherit from FL_Message)Sample Code and Web Pages</p></li><li><p>Sample Code and Web Pages (continued)Start to Finish:Spawning a Listener threadSpawning a thread for each commandChoosing the appropriate command mappingSample go_to_location command</p><p>Commands revisited:List of all allowed commands</p></li><li><p>Connector ClientSimulated DLLimited use no synchronous commandingUsed for testing commands to the FL through the connectorSee: ConnectorClient Documentation</p></li><li><p>Propose Other Alternatives - future</p><p>Gene Chalfant</p></li><li><p>Example:Extending CLARAty across Multiple HostsThe Motor Level SimulationDIFFERENT:</p><p>Platforms and libraries</p><p>Communication characteristics</p><p>Programming styles and philosophies</p></li><li><p>Different Communication CharacteristicsDecision support: infrequent requests for highly processed abstracted services (e.g., position estimates, terrain traversal costs), abstract commands (paths, activities)Hardware level simulation: small frequent requests (motor control) and steady trickle of status telemetry (encoder counts) and minimally processed, hardware-acquired data (images)</p></li><li><p>Connector FeaturesProvides a command-line interface to the Functional Layer for high-level commandsConnector is the main() object (all other objects are created by Connector)Interprets command messages and maps them to object methods using a registrySets up periodic upstream status (telemetry) messages</p></li><li><p>Connector IssuesInitial design as a message-based conduit between only two hosts limits scalabilityAdding a new command or changing semantics of an existing command requires modification of Connector class codeConnector thread is involved in command execution for the entire duration of the commandCommand queueing mechanism adds complexity (channel already queued in transport layer)Simulation requires exchange of many small messages, each requiring a queue and thread</p></li><li><p>A General Solution: Port-based ComponentsComponents are independent, self-contained computational units that process dataPorts are the components sole means of interacting with the rest of the worldConnectors transport and adapt data (as untyped byte packets - messages) between components The component framework provides any component with communication and scheduling mechanisms</p></li><li><p>Specific Enhancements Cross-host connectiions are inherently scalable: each component sees its own dedicated channel to a remote component on any hostMessage semantics are dealt with by the consuming component; connectors merely transport bytes to the consumerBuffers (ports) reside within the consumer: queueing messages inside the connector isnt necessaryMessages are immediately copied to the consumers buffer - extra waiting threads are not necessary</p></li><li><p>Connector Enhancements using Port-Based Communication</p></li><li><p>Initial Framework Demonstration: ObstacleMapperROAMSSimDLObstacleMapperFL Comm FrameworkElevation MapGoodness (Traversability) Map</p></li><li><p>Component Connections Match Deployment TopologyEach host appears as a port-based componentMinimal impact adoption - only host-to-host communication is modifiedRemote host library encapsulates communication mechanism as a pair of function calls</p></li><li><p>Introducing TUIdeas About Structure</p></li><li><p>The TU DecompositionAnalysisStackProprioceptive ControlActionSelectorActionStackStrategySensorsMotorsThe World</p></li><li><p>T: Plans &amp; DecisionsAction SelectorObstacle avoidanceNavigationManipulationStrategyMission planning, Tradeoff Analysis, Contingency planningSensorsMotorsThe World</p></li><li><p>U: Sensing and MovingAnalysis Stack VisionLocalizationMapmakingEstimationProprioceptive ControlMotor servoing, Pose maintenance, GaitAction StackCoordinated motionLocomotionCamera pointingSensorsMotorsThe World</p></li><li><p>Data FlowProprioceptive ControlNear horizonReal-time/feedback (msecs)AnalysisStackActionSelectorActionStackStrategyMedium horizonNavigationSciActivities(secs, mins)Far horizonPlanning (hours, days)SensorsMotorsThe World</p></li><li><p>Control FlowAnalysisStackProprioceptive ControlActionSelectorActionStackStrategySensorsMotorsThe World</p></li><li><p>StatusPhase I: Component, Port, Connector classes about 90% implemented; round-robin scheduling, cross-host and local communicationObstacleMapper implemented as a rudimentary component, executes in a standalone testing framework, cross-host communication will initially use shared file systemContinuing incremental framework design refinement</p></li><li><p>Sample Code Listings</p></li><li><p>Component.hHeader file for any module using framework#ifndef _COMPONENT_H#define _COMPONENT_H</p><p>#include #include #include #include </p><p>//#include "CL/comm.h"#include "CL/sockets.h"</p><p>/*| Port has one-value (overwritable) buffer.| Ports can be many-to-one or one-to-many.| _age is for the Port user's optional use.| _newData is for the Connection's use.| _remote indicates a port on a client host.*/</p><p>// different effects of overwrite for many-to-one connectionsenum PortBehavior { minB, maxB, priorityB, sumB };</p></li><li><p>Component.h (2/7)</p><p>// Data types handled by this Portenum PortType { shortP, floatP, doubleP, msgP };</p><p>typedef unsigned char* byte;</p><p>class Port { friend class Connection;</p><p> public: Port() {}; Port(char*, int = 1, PortType = shortP, PortBehavior = minB);</p><p> void setValue(short); void setValue(float); void setValue(double); void setValue(char*, int);</p><p> // accessor must return buffer pointer since type is dynamic unsigned char* getValuePtr() { return _buffer.bytePtr; } PortType getType() { return _type; }</p><p> // Aggregate data handlers (eg. serialized class or struct) void loadValueBuffer(char *);</p><p> int getAge() { return _age; } bool isDataNew() { return _newData; }</p></li><li><p>Component.h (3/7)protected: union { // for mult. interp. of ptr w/o cast unsigned char* bytePtr; short* shortPtr; float* floatPtr; double* doublePtr; } _buffer; char* _name; bool _newData; int _age;// -&gt; 0 each write, incr each cycle int _bufSize; PortBehavior _behavior; PortType _type; }; </p></li><li><p>Component.h (4/7)/* | RepeaterPort is an inter-host Port. It creates a UDP server socket which | listens for client requests for port data transfers. | The software on the remote host can use the updComm/Socket library to | communicate. Currently uses port 2002. */ class RepeaterPort : Port { public: RepeaterPort(char*,// Port name int = 128,// data buffer size PortType = msgP,// Port data type PortBehavior = minB);// Port behavior private: Socket* _uServer; short _ipPortNum; pthread_t serverThread; }; </p></li><li><p>Component.h (5/7)/* | A list of ports used by Component */ class PortList { public: PortList(); // allocs 10 ports initially int getLength() { return _length; } int add(Port&amp;); // returns length private: int _length; Port** _portList; // pointer to buffer Port** _endOfPortList; // pointer to end of buffer }; </p></li><li><p>Component.h (6/7)/* | Components have Ports (which are non-directional), and some code (runOnce()) | */ class Component { public: virtual void runOnce() = 0; int getCycle() { return _cycle; } private: PortList _portList; // Component has any # of Ports int _cycle; // variable interval scheduling }; </p></li><li><p>Component.h (7/7)/* | Connections connect two Ports */ class Connection { public: // type of connection enum ConnType { normal, inhibit, inhibitWrite, suppress, overrideIn, overrideOut }; // args: source, dest, type Connection(Port*, Port*, ConnType = normal); Connection(Port*, RepeaterPort*, ConnType = normal); void propagate(); // copy data from source to dest private: Port* _source; // Ports connected Port* _dest; enum ConnType _connType; int _priority; // highest priority is 0 }; #endif</p></li><li><p>Test.ccApplication demonstration using framework#include #include "Component.h"</p><p>/* ===== Test Application Class Declarations ===== */</p><p>// Define the talker with a talk portclass Talker : Component { public: Port* talkP; Talker();// override null constructor void runOnce();// must declare runOnce()};</p><p>// Define the listener with a listen portclass LocalListener : Component { public: Port* listenP; RepeaterPort* repeaterP; LocalListener(); void runOnce();};</p></li><li><p> (2/4)// Define a RepeaterPort which exists outside of a componentRepeaterPort* repeaterP = new RepeaterPort("rport");</p><p>/* ==== Test Method Definitions ===== */</p><p>// Construct the ports as integer portsTalker::Talker() { talkP = new Port("talker", sizeof(short));}</p><p>LocalListener::LocalListener() { listenP = new Port("listener", sizeof(short));}</p><p>// Define the behavior of the talkervoid Talker::runOnce(){ // Talker only generates a constant value talkP-&gt;setValue((short)3); printf("I said 3!\n");}</p></li><li><p> (3/4)</p><p>// Define the behavior of the listenervoid LocalListener::runOnce(){ // LocalListener is only smart enough to know to expect an int int input = *(int*)listenP-&gt;getValuePtr();</p><p> printf("I heard %d.\n", input);}</p></li><li><p> (4/4)</p><p>/* ===== Demonstration Program ===== */</p><p>int main() {</p><p> // Define a talker and listener, and their connections Talker t; LocalListener l; Connection c(t.talkP, l.listenP); Connection r(t.talkP, (Port*) repeaterP);</p><p> // Rudimentary &amp; explicit scheduler for (int i=0; i</p></li><li><p>ObstacleMapper.h#include "MapDouble.h"// for Map class of doubles#include "nav_grid.h"// for Grid class#include "nav_rover.h"// for Rover class#include "JPLPic.h"// for output elevation map#include </p><p>class ObstacleMapper : Component{public: ObstacleMapper(float gridCellSize = 0.2,// m float roverWheelRad = 67,// = .3*maxObstHeight float roverWidth = 0.84,// m float roverLength = 0.84, float roughnessPercentage = 50); void runOnce();</p><p>/*| Rudimentary typed "ports": need to be changed to Port objects*/</p><p> JPLPic*goodnessMapPic;// these are essentially JPLPic*certaintyMapPic;// the desired output ports</p><p> Grid*gestalt;// have to use these for now Rover*rover;// for communication</p><p> MemoryManager* mm;// Should be a singleton}; </p></li><li><p>ObstacleMapper.ccWrapper class for Gestalt Grid class/*||| Wrapper for Grid object implementing Gestalt algorithm. Gestalt developed by| Mark Maimone.|| Gene Chalfant, May 22, 2002*/</p><p>#include "ObstacleMapper.h"</p><p>ObstacleMapper::ObstacleMapper(float gridCellSize,// default = 20 cm float roverWheelRad,// =.3*maxObstHeight float roverWidth,// millimeters float roverLength, float roughnessPercentage) {</p><p> // Set up MemoryManager options mm = new MemoryManager; mm-&gt;SetFlags(MM_FLAG_ALLOW_SYS_FALLBACK); mm-&gt;SetVerbosity(0);</p><p> // The active Grid object constitutes the Gestalt navigation code gestalt = new Grid(-20, -20, 20, 20,// bounds of map in meters// (minx, miny, maxx, maxy) gridCellSize, gridCellSize,// cell size in meters (x,y) mm);// new arg (memory manager)</p></li><li><p> (2/2)// Grid object requires an external Rover object rover = new Rover (1.0, 1.0, 1.0, "Rocky8", mm); rover-&gt;SetRoverDimensions (roverWheelRad,// wheel radius roverWidth,// body width roughnessPercentage, roverLength, 1);}</p><p>void ObstacleMapper::runOnce() { // Make the Grid object process the input if (gestalt-&gt;GeneratePlanes (rover) != NO_ERR) printf("GeneratePlanes failed!\n"); else if (gestalt-&gt;GenerateEvaluations (rover, 1, 1) != NO_ERR) printf("GenerateEvaluations failed!\n");</p><p> // Write ASCII goodness map to stdout gestalt-&gt;ShowGoodnessMap( stdout, rover, 1, 0, 0 );</p><p> // Extract the maps to public pointer ports goodnessMapPic = gestalt-&gt;ExtractGoodnessMap(0); certaintyMapPic = gestalt-&gt;ExtractCertaintyMap(0);</p><p> // For D*/D-Layer, goodness must be inverted and scaled from 0:255 to 2:252 // (so, multiply by -1 * / (gives -250:0) and add 255 - 3) goodnessMapPic-&gt;LinearOperator(-(250.0/255.0), 252.0);}</p></li><li><p>Extra Slides</p></li><li><p>Strategy LayerMission planning and objectivesHuman controlHigh-level value judgements</p></li><li><p>Analysis StackAbstraction of sensor dataEstimation, localizationMapping servicesVision processing</p></li><li><p>Action StackRealization &amp; deabstraction of coordinated motionsMulti-rover operations Example: Locomotor</p></li><li><p>Action SelectorResource/Cost analysisSearchVotingChoosing the best course of action</p></li><li><p>Proprioception LayerTight feedback loops within the machineNo direct environmental interactionRaw sensors, encodersExample: motor servoing</p></li><li><p>ObstacleMapper Demonstration ImplementationObstacle Mapper functionality developed as a component: will require data transfer with ROAMS simulator (or other source of local elevation maps) and with Decision Layer (consumer of goodness (traversability) maps)</p><p>Conduit model means its hard to extend to other components, its not inherently scalable to multiple hostsSpawning thread means the Connector (its thread, actually) has to wait for a destination object to deal with the commandObsta...</p></li></ul>


View more >