RobotLib Module CommandInterface

Uit RobotMC.be
Ga naar: navigatie, zoeken

Zie deze pagina voor een overzicht van alle RobotLib documentatie op deze wiki.

Inleiding

Aan een robot moet je opdrachten kunnen geven. Bijvoorbeeld de opdracht om een missie uit te voeren, instelling te veranderen of status op te vragen. Hiervoor gebruiken we de CommandoInterface. Voordat we ingaan op 'opdrachten geven' kijken we eerst even naar een aantal modules die hierbij een belangrijke rol spelen.

Registry

De Registry wordt gebruikt om variabelen 'beschikbaar' te stellen aan de gebruiker. Veelal zijn dit sensor-waarden of instellingen.

Command Executer

De Command Executer bevat alle menu's die zijn aangemeld. Een overzicht van deze menu's kan worden opgevraagd met '?'. Als een commando-string wordt ingegeven, roept de Command Executer het gekozen commando uit één van deze menu's aan.

CmdRepository

De CmdRepository is een verzameling van commando-strings. De strings kunnen gekoppeld worden aan een toets op de afstandsbediening.

KDU

KDU - KeyBoard Display Unit - is de gebruikersinterface op de robot zelf. Met een paar knopjes van de afstandsbediening en een klein display biedt het de volgende functies:

  • Inspecteren van variabelen in de Registry en - als ze niet read-only zijn - aanpassen.
  • Bladeren door de CmdRepository en commando-strings uit laten voeren.
  • Afhandelen van dialogen in de commando-strings.

Opdrachten geven

Robotlib heeft twee kanalen om 'opdrachten' te geven aan de robot. Het eerste kanaal zijn de knoppen van de afstandsbediening, die als nummers (RC5 codes) worden verwerkt. Het tweede kanaal zijn tekst-strings met opdrachten.

RC5

De RC5 codes worden ontvangen door een IR detector en de ontvangen code wordt doorgegeven aan routine RcDispatch. Deze handelt een aantal codes af voor:

  • KDU (Keyboard Display Unit) – de bediening van de robot via (in dit geval) een aantal toetsen van de afstandsbediening in combinatie met tekst op een lcd schermpje.
  • PfKeys – een set codes die is toegewezen als ‘programmeerbare functietoetsen’.

Voor de overige codes wordt de CmdRepository doorzocht. Als de code in de CmdRepository staat, wordt het bijbehorende commando uitgevoerd.

Als de code niet in de CmdRepository staat, wordt deze doorgegeven aan de UserDispatch functie.

Je kunt dus op drie manieren een functie toekennen aan de afstandsbediening:

1. Maak je eigen set(s) van PfKey handlers. PfKey handlers worden geregistreerd in robotlib en kunnen om de beurt worden geactiveerd. De actieve PfKey handler handelt alle toegewezen functietoetsen af en werkt naar keuze met commando-strings of programma-code. Gebruik deze methode als je een aantal toetsen wilt gebruiken en het niet noodzakelijk is dat deze codes altijd direct toegankelijk zijn.

2. Meldt je commando als commando-string en code aan bij de CmdRepository. Gebruik deze methode als je een commando vast wilt toekennen aan een toets.

3. Maak je eigen UserDispatch functie en schrijf programma-code per RC5 code. Gebruik deze functie als de vorige twee niet voldoen. Bijvoorbeeld omdat je functionaliteit vast wilt toekennen aan een toets en de functionaliteit niet via een commando-string benaderd kan worden. Vaak zijn dit tijdelijke (hele specifieke) functies. (Voor permanente functies loont het de moeite ze via een menu aan te melden: ze worden dan (met helptekst) vermeld in het commando overzicht en je kunt ze dan ook via de seriele poort.)

De verwerking van RC5 codes is met gestippelde pijlen weergegeven in onderstaande figuur. De gestippelde pijlen geven de overdracht van (RC5) codes aan en de rode pijlen zijn commando-strings. De groene pijlen zijn uitwisseling van informatie tussen de modules.

CommandInterface.jpg

CommandInterface

De tweede input-kanaal is de command interface. Via de seriele poort (‘het console’) kunnen commando’s worden ingevoerd met behulp van CommandLineInput module. Ingevoerde commando’s worden door de CmdParser verwerkt (waarover zo meer…) en daarna doorgegeven aan de CmdExecuter. De CmdExecuter zoekt het ingegeven commando in de aangemelde lijsten met commando, controleert eventueel of het aantal parameters klopt en roept het betreffende commando aan.

CmdParser, registry & dialogen

Commando’s die vanaf het console worden ingevoerd zijn meestal specifiek. Ze worden door de CmdParser in stukken geknipt en doorgegeven aan de CmdExecutor. Een voorbeeld hiervan is:

PittMan> um xy 1000 0 300 0

Deze is de opdracht om de robot naar het punt (1000,0) te laten rijden met een snelheid van 300 mm/s. Op het eindpunt moet de robot stoppen (snelheid 0).

Maar commando’s kunnen ook afkomstig zijn uit de CmdRepository. De CmdParser heeft een tweetal functies die dit soort commando’s een stuk krachtiger maken: variabelen en dialogen.

Variabelen hebben een naam en een waarde en worden opgeslagen in de Registry. We kunnen bijvoorbeeld een variabele met de naam ‘speed’ opnemen in de registry en deze de waarde 200 geven (zie registry demo voor meer details of gebruik het commando ‘? reg’). Een ‘$’ teken op de commandline geeft aan dat een variabele wordt gebruikt.

PittMan> reg set speed 200
PittMan> um xy 1000 0 $speed 0

Deze opdracht gebruikt de waarde van speed (200 in ons voorbeeld) als snelheid om naar het opgegeven punt te rijden.

Dialogen zijn een alternatief voor variabelen, waarmee je via KDU (LCD + afstandsbediening) input kunt vragen. Een dialoog is een string tussen vierkante haken, bijvoorbeeld:

 [i|myspeed|100..500|50|150]

Waarbij:

  i        : type (vooralsnog alleen integer)
  myspeed  : naam die op het display wordt getoond
  100..500 : de minimale en maximale waarde van de parameter
  50       : de stap-waarde van de variabele
  150      : de default (start) waarde van de variabele

Het commando als geheel ziet er als volgt uit:

PittMan> um xy 1000 0 [i|myspeed|100..500|50|150] 0

Als dit commando wordt gegeven (bijvoorbeeld via een functietoets, maar het kan ook vanaf het console), wordt dit op het LCD getoond. De bovenste regel bevat het commando (waarbij de dialoog is vervangen door ‘150’). De onderste regel bevat de naam van de actieve dialoog (in dit geval de enige: ‘myspeed’). Met het pijltje omhoog kan de waarden in stappen van 50 worden verhoogd tot 500, en met het pijltje omlaag verminderd tot 100. Met de pijltjes links en rechts kunnen, als er meerdere zijn, de andere dialogen worden geselecteerd. Met enter worden de geselecteerde waarden opgeslagen en doorgegeven aan de CmdExecuter.

Maar ook de combinatie van variabelen en dialogen is mogelijk. In dit geval wordt de dialoog toegevoegd aan de registry:

PittMan> reg dialog speed i|myspeed|100..500|50|150

Merk op dat de blokhaken ontbreken. We willen immers de string laten opslaan en niet laten uitvoeren. De dialoog wordt uitgevoerd als we de variabele tussen vierkante haken in een commando gebruiken, bijvoorbeeld:

PittMan> Um xy 1000 0 [$speed] 0

Als startwaarde wordt nu niet de waarde uit de dialoog gebruikt, maar de actuele waarde van de variabele speed uit de registry, 200 in ons voorbeeld. Met het pijltje omhoog kan de waarde van de variabele worden verhoogd naar bijvoorbeeld 400. Dit wordt direct bijgewerkt in de registry, dus de gekozen waarde is de volgende keer de startwaarde. Met het commando 'reg dump' zie je alle variabelen in de registry met (onder meer) de bijbehorende dialoog.

KDU

De Keyboard Display Unit (KDU) is de user interface op de robot zelf. In de huidige vorm zijn dit enkele knoppen van de afstandsbediening en, met naar keuze, een tekst lcd of grafisch oled scherm. Maar het is ook goed mogelijk een KDU te maken die werkt met een ander type display, een joystick of touch screen.

KDU gebruikt een display en 5 knopjes:

  • Up & Down
  • Left & Right
  • Enter

Zoals aangegeven worden hiervoor normaal 5 toetsen van de afstandsbediening voor gebruikt.

KDU kent 4 modes:

Idle mode

In deze mode gebruikt KDU het toegewezen display-deel (normaal 16x2 tekens vanaf links-boven) niet.

Toets-functies:
UP   - Start Repos browser
DOWN - Start Registry browser
LEFT, RIGHT ENTER - geen functie

Repos browser

In deze mode kun je door de commando-strings in de repository bladeren.

Toets-functies:
UP     - Volgende commando-string
DOWN   - Vorige commando-string
ENTER: - Voer commando-string uit (inclusief eventuele dialoog)
LEFT, RIGHT - cancel browser (terug naar Idle mode)

Registry browser

In deze mode kun je door de variabelen in de registry bladeren. De naam en de waarde wordt getoond.

Toets-functies:
UP     - Volgende variabele
DOWN   - Vorige variabele
ENTER: - Start dialoog (indien gedefinieerd, zie verder)
LEFT, RIGHT - cancel browser (terug naar Idle mode)

Aan een variabele in de registry kan een dialoog worden gekoppeld.

Dialog mode

Robotlib ondersteunt dialogen in commando-strings. Deze dialogen worden uitgevoerd door de CommandParser en deze neemt daarvoor KDU 'over'.

Dialoog-mode wordt steeds gestart als een commando-string met dialoog wordt verwerkt, bijvoorbeeld doordat:

  • Een commando-string met dialoog vanaf het console wordt ingegeven.
  • Een commando-string met dialoog uit de repository wordt geselecteerd. Dit kan via KDU maar ook met een functietoets of vanuit het programma.
  • Selectie van een Registry dialoog (normaal via KDU).
Toets-functies:
UP    - Waarde stapje omhoog
DOWN  - Waarde stapje omlaag
RIGHT - Selecteer volgende waarde parameter
LEFT  - Selecteer vorige waarde parameter
ENTER - Voer commando-string uit (einde dialoog)

Nadat de dialoog is uitgevoerd, gaat KDU terug naar de vorige mode (registry, repos of idle).

CommandInterface

Functie

De RobotLib Command Line Interface (CLI) handelt opdrachten af die via de seriele poort (console) worden gegeven. De module heeft de volgende functies:

  • Invoer van een commando-regel (inclusief backspace en ESC ondersteuning)
  • Na ENTER wordt de regel verwerkt.
  • Het eerste woord of de eerste twee woorden zijn het commando. De rest zijn (spatie-gescheiden) parameters.
  • Numerieke parameters decimaal als positief (12) of negatief (-4) getal worden ingevoerd. Ook kan een hex waarde worden ingevoer (0x24 of 0xEA).
  • Ook text-parameters zijn mogelijk.
  • Het commando '?' geeft een overzicht van de commando-groepen met een korte omschrijving.
  • Het commando '? xyz' geeft een overzicht van alle commando's (met korte omschrijving) in de commandogroep xyz.
  • Het commando '? *' geeft een overzicht van alle commando's.
  • Het commando '`' (accent grave, onder '~' op een US keyboard) herhaalt het laatste commando.

Met de volgende definitie kun je een ander karakter instellen om het laatste command te herhalen:

#define CLI_HISTORY_CHAR  '!' 

Gebruik (runtime)

Geef het commando '?' op het console voor een overzicht van de beschikbare commando-groepen:

F4Bot> ?

Default commands               (enter '? default' for details).
Programmable function keys     (enter '? pf' for details).
System tests                   (enter '? system' for details).
Universal Mover                (enter '? um' for details).
Registry                       (enter '? reg' for details).
Repository                     (enter '? repos' for details).
Servo commands                 (enter '? servo' for details).
Sharp                          (enter '? sharp' for details).
Pid                            (enter '? pid' for details).
PidAutoTune                    (enter '? tune' for details).
Enter '? *' for all commands.
F4Bot> 

Een commando-set heeft een naam en een keyword. Bijvoorbeeld de eerste set heet 'Default commands' en het keyword is 'default'. Deze laatste gebruik je bij het uitvoeren van een commando uit deze set en als je een overzicht van de beschikbare commando's:

F4Bot> ? default

Default commands
   tasks                   - Print lijst met taken
   tasksclr                - Wis tasks stats
   dlevel          <module> [<level>] - Set (get) debug level of <Module> to 0=errors, 1=warnings, 2=info, 3=debug
   dheader         <nr> - Select header format <nr>
   pointstoab      <x1> <y1> <x2> <y2> - calculate a, b of y =ax +b for given points
   test                 - Generic test command
   demo                 - Generic default demo command
   stop                 - Stop robot
   position             - Print robot positie
   positionreset        - Reset robot positie
   reset           1234 - reset processor
   nop                  - No OPeration (do nothing)
   paramdump            - Just dump command params
   presentation         - Set presentation mode
   mark                 - Mark position
   ?                    - This list.
F4Bot> 

PFKey handlers

De PFKey handlers handelen de functie-toetsen af. Er kunnen meerdere PFKey handlers aangemeld worden. Van de aangemelde handlers is er één actief.

SimBot> ? pf
Programmable function keys
  pf list                 - list registered PfKeyHandler functions
  pf set          nr      - set (activate) PfKeyHandler function # (see pflist)
  pf key          nr      - call Programmable Function Key <nr> function

Het commando 'pf list' geeft een overzicht van de handlers, waarbij de active handler wordt gemarkeerd met een *.

SimBot>  pf list
0   PFKeyMotorCalibrate1
1   PFKeyMotorCalibrate2
2   PFKeyUmTest1
3   PFKeyUmTest2
4 * PFKeyRepository

Met 'pf set 2' kan de handler 'PFKeyUmTest1' worden geactiveerd en met 'pf set 4' wordt opnieuw de handler 'PFKeyRepository' geactiveerd.

De handler PFKeyRepository is bijzonder: deze heeft geen vaste commando's per toets zoals de andere handlers, maar zoekt de commando-string voor een functietoets op in de repository. Met het commando 'repos updatepf' wordt een commando-strings ingesteld voor een functie-toets.

SimBot> repos updatepf 1 "um xy 1000 0 300 0"

Als we nu weer 'pf list' ingeven, zien we het volgende:

SimBot> pf list
0   PFKeyMotorCalibrate1
1   PFKeyMotorCalibrate2
2   PFKeyUmTest1
3   PFKeyUmTest2
4 * PFKeyRepository
    1 - um xy 1000 0 300 0

PFKeyRepository is nog steeds de active handler. Van de actieve handler wordt weergegeven welke toetsen ondersteund worden. Eerder werden blijkbaar geen toetsen ondersteund door PFKeyRepository (of eigenlijk: de CmdRepository). We hebben nu echter een commando toegevoegd voor functietoets 1 en dit commando wordt bij 'pf list' weergegeven.

Uitvoeren van een pfkey commandstring kan door op de functie-toets te drukken, of via de commandline met het commando 'pf key <n>'. Zo wordt met het commando 'pf key 1' de hiervoor ingestelde commandstring 'um xy 1000 0 300 0' uitgevoerd.

SimBot> pf key 1
SimBot> [DATA] P_x:0 P_y:-3 Hd:22 [/DATA]
...

CommandString Repository

De CmdRepository is een verzameling van commando-strings. Hiervoor hebben we al gezien hoe de strings kunnen gekoppeld worden aan een toets op de afstandsbediening. Voor het beheer van de repository via de command line hebben we het volgende opties:

BluePlanck> ? repos
Repository
  repos add          cmdstr         - Add cmd to repository
  repos addpf        pfkey  cmdstr  - Add cmd to repository for pfkey
  repos addrc        rccode cmdstr  - Add cmd to repository for rccode
  repos updatepf     pfkey  cmdstr  - Update cmd to repository with pfkey
  repos updaterc     rccode cmdstr  - Update cmd to repository with rccode
  repos delete       nr             - Delete cmd <nr>
  repos exec         nr             - Execute cmd <nr>
  repos load         filename       - load repos from file
  repos save         filename       - save repos to file
  repos dump                        - Dump repos

Het volgende commando geeft de inhoud van de repository weer:

BluePlanck> repos dump
0 (5985) 'positionreset'
1 (6005) 'stop'
2 (6006) 'demo'
3 (pf1) 'um xy 1000 0 300 0'

Iedere regel bevat het index-nummer, de rc-code (vertaald naar pf-toets indien mogelijk) en de commando-string.

Strings toevoegen

Wat opvalt in het de lijst van commando's is dat we drie versies van 'repos add' hebben:

  • 'repos add' voegt een commando-string toe zonder rc-code. Strings zonder rc-code kunnen worden gestart via kdu.
  • 'repos addrc' voegt een command-string toe met rc-code. Als de rc-code al is toegekend aan een andere commando-string, wordt de nieuwe string niet toegevoegd. Hiermee wordt voorkomen dat (onbedoeld) een koppeling van een toets met een commando ongedaan wordt gemaakt. Strings met rc-code kunnen (natuurlijk) worden gestart met de rc-code en ook via kdu.
  • 'repos addpf' is in essentie addrc. Alleen wordt voor aanroep van 'addrc' de pf-key vertaald naar de rc-code.

Strings bijwerken

Zoals aangegeven kun je met 'addrc' geen bestaande entry bijwerken. Hiervoor gebruik je 'updaterc' (of 'updatepf'). Als de rc-code nog niet gebruikt wordt, geeft dit een melding en wordt de entry toegevoegd. Als de rc-code is gebruikt, wordt de bijbehorende commando-string bijgewerkt.

Save en Load

RobotLib kan gegevens opslaan op het MicroFileSystem. De inhoud van de repository kun je opslaan met het commando

repos save myfilename

En met het volgende commando kun je de inhoud uit 'myfilename' terug inladen:

repos load myfilename

Bij het opstarten probeert RobotLib de inhoud van de file 'ReposDefault' in te laden. Deze file kun je dus gebruiken voor 'defaults'.

Gebruik (commando's toevoegen)

Een krachtige feature van de command interface is de optie om eenvoudig een set van eigen commando's worden toegevoegd. Dit gaat in de volgende stappen:

  • Maak de functie om het commando uit te voeren. Deze functie heeft als prototype:
void CliCmd_XyzPwm     (int NrParams, TCiParams *P)

Indien een functie met andere parameters aangeroepen moet worden, wordt een 'stub functie' gebruikt.

  • Voeg de functie toe aan een command-set tabel (t_cli_record[]).
  • Link de tabel via een structure (TCliGroup) aan een groep-keyword.
  • Registreer de command-set tabel bij de CommandLineInterface module met de CliAddCommands() functie (en geef daarbij de groep naam op).

De demo "DemoCommandLine.cpp" laat zien hoe dit precies werkt.

command-set tabel (t_cli_record)

Nadat we een commando functie hebben gemaakt, voegen we deze toe aan een commando-set.

static const t_cli_record CliRecords[] = {   
  // Function             keyword     #param   help_text
  { CliCmd_XyzDemo,       "demo",    -1,    "        - Demo command, parameters optional." },

  { CliCmd_XyzPwm,        "pwm",      2,    "<l> <r> - umpwm(l, r) (via Univ ersalMover)" },
  { CliCmd_XyzCurve,      "curve",    0,    "        - start MSM_PwmCurve" } ,
  { CliCmd_XyzCal,        "cal",      0,    "        - start MSM_MotorCal" },    
  { CliCmd_XyzParams,     "params",  -1,    "        - show use of float/string params" },    

   // Don't change or remove this last line
   { 0, "", 0, ""   } // last one has function pointer value 0 
};

const TCliGroup CliRecord_CliDemo = { "xyz", CliRecords};

De interne naam van deze commandoset is 'CliRecords' en iedere regel bevat 4 parameters die samen het commando beschrijven. De laatste regel - met een waarde 0 in het eerste veld - geeft aan dat het einde van de tabel is bereikt. De tabel is toegankelijk via de structure CliRecord_CliDemo, waarin ook het keyword van de groep wordt opgegeven.

Dit zijn de 4 parameters die het commando beschrijven:

1. Functie - de naam van de functie die aangeroepen moet worden. Het is handig om de functies in bovenin de file te zetten en deze tabel onderaan. De format van de functie is altijd 'void CliCmd_Test(int NrParams, TCiParams *P)', ook al worden parameters niet gebruikt. De naam van de functie moet natuurlijk uniek zijn.

2. Keyword De string is het commando dat ingetypt moet worden.

3. #param Het aantal params dat dit commando nodig heeft. Als hier een waarde is ingevuld, wordt het aantal parameters vooraf gecontroleerd en eventuele afwijking afgehandeld. Als het commando een variabel aantal parameters ondersteunt, maak #param dan -1 om de controle in de library uit te schakelen.

4. help tekst Tekst die wordt uitgeprint voor dit commando als de gebruiker het help commando geeft ('?')

command-set aanmelden

De laatste stap is het aanmelden van de commando-set bij de CLI met:

CliAddCommands(CliRecord_CliDemo, "CliDemo commands"); 

Plaats dit commando in main(), voor de hoofdlus. De eerste parameter is de command-groep structure en de tweede parameter is de commando-set naam die door '?' wordt als kopje wordt geprint.

Werking & configuratie

In RobotLib_conf.h wordt een aantal parameters opgegeven voor de CLI:

#define CLI_NR_PARAM       12    // Parameter space (max # of int params)
#define CLI_BUFFER_SIZE    100   // input buffer size (# char)
#define CLI_PROMPT "F4Bot"

De aanroep van de CLI wordt door Framework.cpp verzorgd. Om het helemaal af te maken kan vlak voor de hoofdlus de buffer van de CLI worden gewist en de command prompt worden geprint met:

CliClear(); // reset & print prompt