Difference between revisions of "Architecture Tutorial: Retrieve laser scans"

From The BABEL Development Site
(Calling getObservations)
(Calling getObservations)
Line 43: Line 43:
* The point "ARACNE_ATOM_HERE" at which the aracne atom "request-synchronous&blocking" must be inserted.  
* The point "ARACNE_ATOM_HERE" at which the aracne atom "request-synchronous&blocking" must be inserted.  
Also, note that the macro #JMS-INCLUDE()#, if not inserted through the BABEL menu will NOT automatically add the dependency to your module, so it is recommended to either add the dependency on "BS_RangeSensors::getObservations" manually (first BABEL_MD tab, "Deps" button) or to insert the JMS macro from the menu and fill the parameters by hand (see the correct order of the parameters in the code below).

Revision as of 09:20, 23 July 2009


Following the Robotic Architecture proposed here, laser scans from either a simulated or a real robot should be accessible from a single module, named BS_RangeSensors.

The interface of this module is described in this section and this tutorial explains how to write a client module to query the latest laser scans from BS_RangeSensors.

Notice that this tutorial only covers the specific case of implementing a module with the C/C++ language.


Calling getObservations

At the point in your module where you need to request the laser scans, the service "getObservations" from "BS_RangeSensors" must be invoked. This is the definition of that service, just to know how it looks like:

Tut-scans service.jpg

To call that service, you must use the aracne-atom "request-synchronous&blocking". It can be inserted in your code from the BABEL_MD menu. A dialog will appear asking you which module and service you want to call. Write this information by hand or by using the button "From ICE..." as in the image:

Tut-scans wizard1.jpg

Accept and a wizard will appear asking you for the arguments of the service. Fill it out as in the figure:

Tut-scans wizard2.jpg

Now, this aracne atom must have some preparatory C++ code before it, and some C++ code after it to process the results.

You can use the following fragments of code, self-explained in its comments. Pay attention to:

  • The label "YOUR CODE HERE" for the place where to process the laser scan.
  • The point "ARACNE_ATOM_HERE" at which the aracne atom "request-synchronous&blocking" must be inserted.

<cpp> using namespace mrpt; using namespace mrpt::utils; using namespace mrpt::slam;

// Retrieve the latest laser scan // ----------------------------------------------------- BABEL::BS_RangeSensors::SeqOfBytes *SF; // The sequence of bytes sent by the server module BABEL::Boolean sensorError; // Sensor error? bool err_var; // BABEL communication error?


// Error? Propagate it: if (err_var) { // process error }

CObservation2DRangeScanPtr laserScan; // A smart-pointer to the laser scan (read below)

if (!err_var && !sensorError) { try { // De-serialize the object: mrpt::utils::CSerializablePtr obj = SeqOfBytes2MRPTObject(SF);

// Assure it's a valid observation: ASSERT_(obj) ASSERT_( IS_CLASS(obj,CSensoryFrame) )

CSensoryFramePtr theSF = CSensoryFramePtr(obj);

laserScan = theSF->getObservationByClass<CObservation2DRangeScan>(); // Get the first scan, if any. } catch(std::exception &e) { // Process ERROR, message in e.what() } }

// Free memory of the Sequence if (!err_var) { delete SF; SF = NULL; }

// Now, we have the latest scan laser in the variable "laserScan", which // is a smart pointer to a mrpt::slam::CObservation2DRangeScan // ------------------------------------------------------------------------- if (laserScan) { // ******* YOUR CODE HERE ************** // Access to the object data members to get the scan data. // Refer to: http://babel.isa.uma.es/mrpt/reference/svn/classmrpt_1_1slam_1_1_c_observation2_d_range_scan.html // Examples: // Scan size: laserScan->scan.size() // Scan point[0]: laserScan->scan[0] // Scan point[0] is valid: laserScan->validRange[0]!=0 } else { // For some reason (comms error, hardware error, etc...) there is no laser scan. }


Auxiliary code

Add the following auxiliary function to your module "Auxiliary logic" section, since this function is used in the code above:

<cpp> // SeqOfBytes2MRPTObject: Convert a BABEL sequence of bytes into a MRPT object. // IMPORTANT: "T of seqofbytes" must be a POINTER to a BABEL sequence, not a reference to it. template <typename T> mrpt::utils::CSerializablePtr SeqOfBytes2MRPTObject(const T &seqofbytes) { if (seqofbytes->length()==0) return mrpt::utils::CSerializablePtr(); mrpt::utils::CMemoryStream memBlock;

	memBlock.assignMemoryNotOwn(&(*seqofbytes)[0], seqofbytes->length() );

return memBlock.ReadObject(); } </cpp>

Non-deportabilities of the module

If your module didn't use MRPT before adding these code fragments, it must be inserted by:

  • Selecting the tab "Non-deportabilities" in BABEL_MD.
  • Select "Execution".
  • Add "mrpt-core" from the list below.
  • Save the module.

You'll need MRPT installed as explained here.