Multi Agent Class
Note
This class is for advanced users wanting to control multiple robots through QUARC or Quanser SDK. Make sure you have installed the academic resources from the Quanser website. It will only work with Quanser robots that you have a valid Quanser Interactive Labs license for.
This class is still under development.
For any questions, please contact Quanser Support at tech@quanser.com
Description
This class can be utilized for spawning multiple robot agents in Quanser Interactive Labs for user control directly via QUARC or Quanser SDK. This library requires a complete installation of Quanser’s academic resources (available through www.quanser.com) for associated real-time application modules and other supporting libraries.
The class copies and creates all necessary files to run multiple robots at the same time. It will also create a JSON file called RobotAgents.json that will store the information of the agents that were spawned as well as its port and URI numbers.
See the MultiAgent Tutorial to get a better understanding of using the MultiAgent class to spawn multiple agents.
Library
Member Variables
- MultiAgent.robotActors = None
List of qlabs actor objects of the robots that were spawned. Use when using functions from qlabs library.
- MultiAgent.robotsDict = {}
Dictionary of dictionaries of all spawned robots. Includes the information that is saved into the JSON file. Including robotType, actorNumber, classID as well as all ports used for the RT file.
Methods
- MultiAgent.__init__(agentList)[source]
Constructor Method
- Parameters
agentList (list of dictionaries) – A list of dictionaries of the spawned robots.
Tip
- The dictionaries can have the following keys (one per robot that will be spawned):
“RobotType”: string - can be “QC2”/”QCar2” for QCar 2, “QBP” for QBot Platform, “QDrone2”/”QD2” for QDrone 2
“Location”: float array[3] - for spawning in x, y, z of the QLabs environment
“Rotation”: (Optional) float array[3] - for spawning in x, y, z. Can be in Degrees or Radians. If it is radians, set the “Radians” key to True. If not defined, will spawn with [0, 0, 0] rotation
“Radians”: (Optional) boolean - defaults to False. Only needed if rotation is in Radians
“Scale”: (Optional) float - if you want to change the scaling of the spawned object. If not defined, will spawn with scaling of 1. The scaling will apply in x, y, and z
“actorNumber”: (Optional) int - set only if you want a predefined actor number for your robot. If not, it will use the next available number for the type of robot. If the number is already in use, it will overwrite it. We do not recommend using it unless tracking of actors is done manually by the user.
If using a QCar 2, the file it will start will be different depending on the scale of 1 (QCar 2 real world car size) or .1 (QCar 2 actual size), to return measurements properly scaled.
- multi_agent.readRobots()
Function to read the JSON file created after spawning the robots. The file contains all necessary port/URI numbers to initialize the robots. The function will return the dictionary that was created when spawning the robots it contains the the robots and their properties. The function makes sure that the file is not being used by another process before reading it.
Important
This function is not part of the MultiAgent class. Do not initialize a MultiAgent object only to use this function. It can be called directly from the library.
MultiAgent Tutorial
Python Tutorial
Raw to download this tutorial: Multi Agent Tutorial (.py)
.
1"""
2Multiagent Example
3----------------------------
4
5.. note::
6 Make sure you have the teaching or research resources from the Quanser website
7 downloaded. It will not find the necessary files if you do not have them.
8
9 Make sure to only try to spawn robots your Quanser Interactive Labs license
10 allows for. It will not spawn robots you do not have access to.
11
12 Make sure you have Quanser Interactive Labs open before running this
13 example. This example is designed to best be run in any of the Open World environments.
14
15"""
16
17#imports to necessary libraries
18import time
19import numpy as np
20from qvl.multi_agent import MultiAgent, readRobots
21from qvl.qlabs import QuanserInteractiveLabs
22from qvl.free_camera import QLabsFreeCamera
23from qvl.basic_shape import QLabsBasicShape
24import numpy as np
25
26qlabs = QuanserInteractiveLabs()
27
28print("Connecting to QLabs...")
29if (not qlabs.open("localhost")):
30 print("Unable to connect to QLabs")
31
32print("Connected")
33
34qlabs.destroy_all_spawned_actors()
35
36# create a camera in this qlabs instance
37camera = QLabsFreeCamera(qlabs)
38camera.spawn_degrees(location=[0.063, 1.9, 0.603], rotation=[0, 9.186, -83.687])
39# to switch our view to the new camera we just initialized
40camera.possess()
41
42# add shapes in the space
43rectangle2 = QLabsBasicShape(qlabs)
44rectangle2.spawn(location=[-1,-.8,0], rotation=[0,0,0], scale=[.2,.2,1], configuration=QLabsBasicShape.SHAPE_CUBE, waitForConfirmation=True)
45rectangle2.set_material_properties(color=[0,1,0])
46time.sleep(1)
47cone = QLabsBasicShape(qlabs)
48cone.spawn(location=[0.7,-.4,0], rotation=[0,0,0], scale=[.2,.2,1], configuration=QLabsBasicShape.SHAPE_CONE, waitForConfirmation=True)
49cone.set_material_properties(color=[0,0,1])
50time.sleep(.5)
51
52qlabs.close()
53
54print("Disconnected from camera and object spawn")
55
56time.sleep(1)
57
58# Initialize an empty list (not a dictionary, because dictionaries are key-value pairs)
59myRobots = []
60
61# Adding a new robot to the list
62# comment out robots that you may not be licensed for
63
64#QCar 2 needs to be spawned at a smaller scale since it is made to work in
65# cityscape where it is made to spawn the size of a real car.
66# as a 1/10th car, spawning at 0.1 scale will make it the size of the real
67# QCar 2
68myRobots.append({
69 "RobotType": "QCar2",
70 "Location": [-.5, 0, 0],
71 "Rotation": [0, 0, 90],
72 "Scale": .1,
73 "ActorNumber" : 5 # set actor number to 5
74})
75
76
77myRobots.append({
78 "RobotType": "QD2",
79 "Location": [1, 0.5, 0],
80 "Rotation": [0, 0, 90],
81 "Scale": 1
82})
83
84myRobots.append({
85 "RobotType": "QBP",
86 "Location": [.15, -.3, -0],
87 "Rotation": [0, 0, 90],
88})
89
90# only need to call this once, and it will spawn and initialize all necessary
91# RT files to start talking to the Robots.
92mySpawns = MultiAgent(myRobots)
93
94# list of QLabs objects that were spawned
95actors = mySpawns.robotActors
96
97print(actors)
98print(actors[0].actorNumber)
99print(actors[0].classID)
100
101# this is how to still use the actor functions with the spawns
102# setting the color of the LED strip on the QCar 2 to purple
103# these functions are directly from qvl.qcar2
104actors[0].set_led_strip_uniform(color=[1,0,1])
105
106# robotsDict should be the same as the output of readRobots().
107# Use readRobots when reading the JSON file from a different python file.
108actorsDict = mySpawns.robotsDict
109print(actorsDict)
110
111robotsDir = readRobots()
112print(robotsDir)
113
114# this would be used when initializing a QCar 2 using HIL to find the assigned port.
115print(robotsDir["QC2_5"]["hilPort"])
116
117mySpawns.qlabs.close()
118
119
120
Matlab Tutorial
Raw to download this tutorial: Multi Agent Tutorial (.m)
.
1% MultiAgent Example
2% ----------------------------------
3%
4% .. note::
5%
6% Make sure you have the teaching or research resources from the Quanser website
7% downloaded. It will not find the necessary files if you do not have them.
8%
9% Make sure to only try to spawn robots your Quanser Interactive Labs license
10% allows for. It will not spawn robots you do not have access to.
11%
12% Make sure you have Quanser Interactive Labs open before running this
13% example. This example is designed to best be run in any of the Open World environments.
14%
15
16close all;
17clear all;
18clc;
19
20% --------------------------------------------------------------
21% Setting MATLAB Path for the libraries
22% Always keep at the start, it will make sure it finds the correct references
23newPathEntry = fullfile(getenv('QAL_DIR'), 'libraries', 'matlab', 'qvl');
24pathCell = regexp(path, pathsep, 'split');
25if ispc % Windows is not case-sensitive
26 onPath = any(strcmpi(newPathEntry, pathCell));
27else
28 onPath = any(strcmp(newPathEntry, pathCell));
29end
30
31if onPath == 0
32 path(path, newPathEntry)
33 savepath
34end
35% --------------------------------------------------------------
36
37fprintf('\n\n------------------------------ Communications --------------------------------\n\n');
38
39qlabs = QuanserInteractiveLabs();
40connection_established = qlabs.open('localhost');
41
42if connection_established == false
43 disp("Failed to open connection.")
44 return
45end
46
47disp('Connected')
48
49num_destroyed = qlabs.destroy_all_spawned_actors();
50pause(1)
51num_destroyed = qlabs.destroy_all_spawned_actors();
52
53fprintf('%d actors destroyed', num_destroyed, '');
54
55
56% Initialize an instance of a camera
57camera = QLabsFreeCamera(qlabs);
58
59% Set the spawn of the camera in a specific location
60camera.spawn_degrees([0.063, 1.9, 0.603], [0, 9.186, -83.687])
61
62% Spawn the camera
63camera.possess();
64
65% Spawn random objects in the scene
66rectangle2 = QLabsBasicShape(qlabs);
67rectangle2.spawn([-1,-.8,0], [0,0,0], [.2,.2,1], QLabsBasicShape.SHAPE_CUBE, true);
68rectangle2.set_material_properties([0,1,0]);
69pause(1);
70
71cone = QLabsBasicShape(qlabs);
72cone.spawn([0.7,-.4,0], [0,0,0], [.2,.2,1], QLabsBasicShape.SHAPE_CONE, true);
73cone.set_material_properties([0,0,1]);
74pause(0.5);
75
76% Closing qlabs
77qlabs.close();
78disp('Finish Objects Spawn!');
79
80%%
81
82myRobots = {};
83
84% Adding a new robot to the list
85% comment out robots that you may not be licensed for
86
87%QCar 2 needs to be spawned at a smaller scale since it is made to work in
88% cityscape where it is made to spawn the size of a real car.
89% as a 1/10th car, spawning at 0.1 scale will make it the size of the real
90% QCar 2
91myRobots{end+1} = struct(...
92 "RobotType", "QCar2", ...
93 "Location", [-.5, 0, 0], ...
94 "Rotation", [0, 0, 90], ...
95 "Scale", .1, ...
96 "ActorNumber" , 5 ... % set actor number to 5
97);
98
99myRobots{end+1} = struct(...
100 "RobotType", "QD2", ...
101 "Location", [1, 0.5, 0], ...
102 "Rotation", [0, 0, 90], ...
103 "Scale", 1 ...
104);
105
106myRobots{end+1} = struct(...
107 "RobotType", "QBP", ...
108 "Location", [.15, -.3, -0], ...
109 "Rotation", [0, 0, 90], ...
110 "Scale", 1 ...
111);
112
113
114% Spawn robots
115mySpawns = MultiAgent(myRobots);
116
117% cell array with of qlabs actor objects of the robots that were spawned. Use when using functions from qlabs library.
118actors = mySpawns.robotActors;
119disp(actors)
120disp(actors{1}.actorNumber)
121disp(actors{1}.classID)
122
123% this is how to still use the actor functions with the spawns
124% setting the qcar 2 into ghost mode and to purple
125% these functions are directly from qvl.QLabsQCar2
126pause(1);
127actors{1}.ghost_mode(true,[1,0,1]);
128pause(1);
129actors{1}.ghost_mode(true,[0,0,1]);
130pause(1);
131actors{1}.ghost_mode(false);
132
133actorsDict = mySpawns.robotsDict;
134disp(actorsDict.QC2_5.hilPort)
135disp(actorsDict.QBP_0.videoPort)
136
137% struct of structs of all spawned robots. Includes the information that is saved into the JSON file.
138
139mySpawns.qlabs.close()