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

From The BABEL Development Site
(Calling getObservations)
(Calling getObservations)
 
(3 intermediate revisions by 2 users not shown)
Line 6: Line 6:
  
  
'''Notice that this tutorial only covers the specific case of implementing a module with the C/C++ language.'''
+
'''Notice that this tutorial only covers the specific case of writing the codification of the client module in the C/C++ language.'''
  
  
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).
+
 
 +
 
  
  
Line 57: Line 58:
 
bool err_var;                              // BABEL communication error?
 
bool err_var;                              // BABEL communication error?
  
/** ARACNE_ATOM_HERE  **/
+
/**** ARACNE_ATOM_HERE  ****/
  
// Error? Propagate it:
+
// Communications error? Propagate it:
 
if (err_var)
 
if (err_var)
 
{
 
{
// process error
+
// communication error
 
}
 
}
 +
else
 +
{
 +
// service requested ok
  
 +
CObservation2DRangeScanPtr laserScan; // A smart-pointer to the laser scan (read below)
  
CObservation2DRangeScanPtr laserScan; // A smart-pointer to the laser scan (read below)
+
if (!sensorError)
 
 
if (!err_var && !sensorError)
 
{
 
try
 
 
{
 
{
// De-serialize the object:
+
try
mrpt::utils::CSerializablePtr obj = SeqOfBytes2MRPTObject(SF);
+
{
 +
// De-serialize the object:
 +
mrpt::utils::CSerializablePtr obj = SeqOfBytes2MRPTObject(SF);
  
// Assure it's a valid observation:
+
// Assure it's a valid observation (if not, the "catch" block will take control):
ASSERT_(obj)
+
ASSERT_(obj)
ASSERT_( IS_CLASS(obj,CSensoryFrame) )
+
ASSERT_( IS_CLASS(obj,CSensoryFrame) )
  
CSensoryFramePtr theSF = CSensoryFramePtr(obj);
+
CSensoryFramePtr theSF = CSensoryFramePtr(obj);
  
laserScan = theSF->getObservationByClass<CObservation2DRangeScan>(); // Get the first scan, if any.
+
laserScan = theSF->getObservationByClass<CObservation2DRangeScan>(); // Get the first scan, if any.
 +
}
 +
catch(std::exception &e)
 +
{
 +
// Process ERROR, message in e.what()
 +
}
 
}
 
}
catch(std::exception &e)
 
{
 
// Process ERROR, message in e.what()
 
}
 
}
 
  
// Free memory of the Sequence
+
// Free memory of the Sequence
if (!err_var)
 
{
 
 
delete SF;
 
delete SF;
 
SF = NULL;
 
SF = NULL;
}
 
  
  
// Now, we have the latest scan laser in the variable "laserScan", which  
+
// Now, we have the latest scan laser in the variable "laserScan", which  
//  is a smart pointer to a mrpt::slam::CObservation2DRangeScan
+
//  is a smart pointer to a mrpt::slam::CObservation2DRangeScan
// -------------------------------------------------------------------------
+
// -------------------------------------------------------------------------
if (laserScan)
+
if (laserScan)
{
+
{
// ******* YOUR CODE HERE **************
+
// ******* YOUR CODE HERE **************
// Access to the object data members to get the scan data.
+
// 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
+
// Refer to: http://babel.isa.uma.es/mrpt/reference/svn/classmrpt_1_1slam_1_1_c_observation2_d_range_scan.html
// Examples:
+
// Examples:
//  Scan size: laserScan->scan.size()
+
//  Scan size: laserScan->scan.size()
//  Scan point[0]: laserScan->scan[0]
+
//  Scan point[0]: laserScan->scan[0]
//  Scan point[0] is valid: laserScan->validRange[0]!=0
+
//  Scan point[0] is valid: laserScan->validRange[0]!=0
 +
}
 +
else
 +
{
 +
// For some reason (comms error, hardware error, etc...) there is no laser scan.
 +
}
 
}
 
}
else
 
{
 
// For some reason (comms error, hardware error, etc...) there is no laser scan.
 
}
 
 
 
</cpp>
 
</cpp>
  

Latest revision as of 17:58, 23 July 2009

Overview

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 writing the codification of the client module in the C/C++ language.



Steps

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?

/**** ARACNE_ATOM_HERE ****/

// Communications error? Propagate it: if (err_var) { // communication error } else { // service requested ok

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

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

// Assure it's a valid observation (if not, the "catch" block will take control): 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 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. } } </cpp>

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.