< ros

http://wiki.ros.org/roscpp/Overview

roscpp

Prerequisito: ros nodes

roscpp genera automaticamente del codice, non confondere con rosgcc che invece è il nome del compilatore.

È una libreria utilizzabile dai client dei processi ROS (detti nodi all'interno di package). Questa libreria si usa per i programmi in C++ ma esiste anche la sua equivalente per il python chiamata rospy.

Quando si scrive un nuovo programma, il programmatore può usare le funzioni di questa libreria per comunicare tramite pubblicazione/sottoscrizione dei cosiddetti topic

NOTA: roscpp non supporta comunicazione in rete! Supporta la comunicazione tra node ROS, che possono appartenere allo stesso package, oppure no.

Per le comunicazioni in rete (socket) si può

  • usare direttamente i socket bsd c,c++,tcp,udp
  • sviluppare una nuova libreria ROS per client
  • usare UDPROS

In realtà rosccp è a sua volta un node (appartenente ad un package), come tanti altri.

In un programma in cui si vuole usare roscpp per le comunicazioni tra processi, prima di chiamare qualsiasi altra funzione di roscpp, si deve eseguire una funzione ros::init() e poi una funzione ros::start().

  1. La prima permette anche di rimappare tutti i nomi delle risorse di un node quando questo viene avviato dalla linea di comando. Quindi uno stesso nodo può essere avviato più volte usando diverse configurazioni dalla linea di comando (in runtime!) quando si avvia con roslaunch o rosrun. Gli argomenti di roslaunch vengono passati con argc,argv. Inizializzare non vuol dire contattare il master, per approfondimento vedere roscore, Approfondimento: link interno alla dichiarazione di ros::init()
    •   ros::init();
        ros::init(argc, argv, "my_node_name", ros::init_options::AnonymousName);
  2. Per eseguire uno start, invece, basta creare un manipolatore di nodi
    •   ros::NodeHandle nh;             //  ovviamente invoca il costruttore nello stack (non nell'heap)
        // ros::start();   // si invoca automaticamente con la creazione del manipolatore
        // delete nh;             //  errore, il distruttore si invocherebbe solo se avessi usato new.
        // ros::shutdown() // si invoca automaticamente con la distruzione del manipolatore nello stack

da leggere? https://courses.cs.washington.edu/courses/cse466/11au/calendar/ros_cc_2_patterns.pdf

In realtà la funzione shutdown() può essere chiamata anche manualmente per distruggere il processo. In questo modo si killeranno tutte le sottoscrizioni, pubblicazioni, chiamate di servizi e serventi. Se si preme CTRL C sulla linea dei comandi, viene intercettato il signal SIGINT e viene automaticamente avviato shutdown()

bool x = ros::ok();  // restituisce true mentre il nodo, o processo, è in esecuzione
 ;         // restituisce false quando il nodo è in shutdown...
 ;         // è utile dentro while()

Struttura del package

Oltre a usare le funzioni di inizializzazione il programmatore deve creare anche due cartelle nel package che contiene il suo nodo, affinché esso possa comunicare usando questa libreria. Si tratta delle cartelle “msg” e “srv” di cui si parla qui ros file.msg file.srv.

Codice di esempio: http://wiki.ros.org/ROS/Tutorials/WritingPublisherSubscriber%28c%2B%2B%29

Quando si avvia la compilazione (con [neurali:ros roscpp|roscpp]]), vengono analizzati i file delle cartelle “msg” e “srv” e viene generato automaticamente del codice C++. In questo esempio si comprende che ci potrebbe essere una sovrapposizione tra i nomi dei file nelle due cartelle a causa della sovrapposizione dei loro namespace.

package_name/msg/Prova.msg -> package_name::Prova
package_name/srv/Prova2.srv -> package_name::Prova2

Il codice generato automaticamente (prova.c, prova.h) viene salvato in questi percorsi predefiniti

msg_gen/cpp/include/package_name/ 
srv_gen/cpp/include/package_name/ 

Codice ottenuto?

#include <std_msgs/String.h>

std_msgs::String str;

La forward declaration è una dichiarazione anticipata in C++?

associazione


La forward declaration è una macro che permette di dichiarare un messaggio e il suo puntatore

  • il messaggio è un template di una struct
  • il suo puntatore è un tipo shared pointers di boost (smart pointers).
ROS_DECLARE_MESSAGE(MyMessage);

In python si può usare typeof ma non in C++. Per questo motivo è stato necessario introdurre un campo dentro la struttura del messaggio. Il campo si chiama _data_type.


(approfondimento)

dichiarazione_init

ROSCPP_DECL void init(const M_string& remappings, const std::string& name, uint32_t options = 0);
/**
* \brief alternate ROS initialization function.
*
* \param remappings A vector<pair<string, string> > where each one constitutes a name remapping, or one of the special remappings like __name, __master, __ns, etc.
* \param name Name of this node. The name must be a base name, ie. it cannot contain namespaces.
* \param options [optional] Options to start the node with (a set of bit flags from \ref ros::init_options)
* \throws InvalidNodeNameException If the name passed in is not a valid "base" name
*/
  • neurali/roscpp_tutorial.txt
  • Last modified: 2018/04/25 07:55
  • (external edit)