You are here

Report #3 - Clarion: Controlling WorldServer3D

 

 

1. ACTIVITIES

1.1 Controlling WorldServer3D

For controlling WorldServe3D with Clarion framework, it was provided a Solution, with some basic functions implemented, for using as a start reference for implementing the leaflet collection.

Due to development coding nature of the framework it required a basic overview of the C# language.

As a  development tool, Xamarin Studio was the natural choice due to its availability for Linux and Windows. Despite knowing that WorldServer3D was compatible with Windows environment, the preferred target OS for development was Linux during the execution of the activities in the laboratory.

The complete source code of ClarionDEMO with the coding presented in the sections following can be found here.

Also, the runnable version of ClarionDEMO is available for downloading here.

A complete package with DemoSOAR, Clarion and WordServer3D can be downloaded here. For running it, just uncompress the package and inside the extrated folder call ./run.sh. Notice that both java and mono have to be available in the target machine.

1.1.1 WordServerAgent Project Code Additions

For supporting the leaflet implementation, the WorldServerAgent ClarionAgent class has been extended with the code additions presented in the snippets following.

1
2
3
4
5
6
7
8
    private String DIMENSION_LEAFLET_AHEAD = "LeafletAhead";
    private String DIMENSION_LEAFLET_NEAR = "LeafletNear";
    ...
    private DimensionValuePair InputLeafletAhead;
    private DimensionValuePair InputLeafletNear;
    ...
    private ExternalActionChunk OutputGetLeaflet;
    private ExternalActionChunk OutputGoToLeaflet;

Code Snippet 1 - ClarionAgent new field variables.

In ClarionAgent constructor, some lines of code were also added as follows:

 1
 2
 3
 4
 5
 6
 7
 8
 9
    // Initialize Input Information
    ...
    InputLeafletAhead = World.NewDimensionValuePair(SENSOR_VISUAL_DIMENSION, DIMENSION_LEAFLET_AHEAD);
    InputLeafletNear = World.NewDimensionValuePair(SENSOR_VISUAL_DIMENSION, DIMENSION_LEAFLET_NEAR);
    ...
    // Initialize Output actions
    ...
    OutputGoToLeaflet = World.NewExternalActionChunk(ClarionAgentActionType.GOTO_ITEM.ToString());
    OutputGetLeaflet = World.NewExternalActionChunk(ClarionAgentActionType.GET_ITEM.ToString());

Code Snippet 2 - ClarionAgent constructor changes.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
    // Define leaflet rule
    SupportCalculator gotoLeafLetSupportCalculator = FixedRuleDelegateGoToLeaflet;
    FixedRule ruleGotoLeaflet = AgentInitializer.InitializeActionRule(CurrentAgent, 
                                                                      FixedRule.Factory, 
                                                                      OutputGoToLeaflet, 
                                                                      gotoLeafLetSupportCalculator);

    // Commit this rule to Agent (in the ACS)
    CurrentAgent.Commit(ruleGotoLeaflet);

    // Define leaflet rule
    SupportCalculator getLeafLetSupportCalculator = FixedRuleDelegateToGetLeaflet;
    FixedRule ruleGetLeaflet = AgentInitializer.InitializeActionRule(CurrentAgent, 
                                                                     FixedRule.Factory, 
                                                                     OutputGetLeaflet, 
                                                                     getLeafLetSupportCalculator);

    // Commit this rule to Agent (in the ACS)
    CurrentAgent.Commit(ruleGetLeaflet);

Code Snippet 3 - ClarionAgent SetupACS changes.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
    Boolean leafletAhead = sensorialInformation.Any(item => ((item.CategoryId == Thing.categoryPFOOD || 
                                                              item.CategoryId == Thing.CATEGORY_NPFOOD || 
                                                              item.CategoryId == Thing.CATEGORY_JEWEL)));
    double leafletAheadActivationValue = leafletAhead ? CurrentAgent.Parameters.MAX_ACTIVATION : 
                                                        CurrentAgent.Parameters.MIN_ACTIVATION;
    si.Add(InputLeafletAhead, leafletAheadActivationValue);

    Boolean leafletNear = sensorialInformation.Any(item => ((item.CategoryId == Thing.categoryPFOOD || 
                                                             item.CategoryId == Thing.CATEGORY_NPFOOD || 
                                                             item.CategoryId == Thing.CATEGORY_JEWEL) &&
                                                                  item.DistanceToCreature <= 30));
    double leafletNearActivationValue = leafletNear ? CurrentAgent.Parameters.MAX_ACTIVATION : 
                                                      CurrentAgent.Parameters.MIN_ACTIVATION;
    si.Add(InputLeafletNear, leafletNearActivationValue);

Code Snippet 4 - ClarionAgent MakePerceptionFromSensorialInput changes.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
   private double FixedRuleDelegateToGetLeaflet(ActivationCollection currentInput, Rule target)
   {
   // See partial match threshold to verify what are the rules available for action selection
   return ((currentInput.Contains(InputLeafletNear, CurrentAgent.Parameters.MAX_ACTIVATION))) ? 1.0 : 0.0;
   }

   private double FixedRuleDelegateGoToLeaflet(ActivationCollection currentInput, Rule target)
   {
   // Here we will make the logic to go dont go ahead
   return ((currentInput.Contains(InputLeafletAhead, CurrentAgent.Parameters.MAX_ACTIVATION))) ? 1.0 : 0.0;
   }

Code Snippet 5 - ClarionAgent new rules.

1.1.2 ClarionDEMO Project Code Additions

Also for supporting the leaflet implementation, the ClarionDEMO Main class has been extended with the code additions presented in the snippets following.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
                        foodsDict = new Dictionary<string, Thing>();
			jewelsDict = new Dictionary<string, Thing>();
 
			if (worldServer != null && worldServer.IsConnected) {
				...
				foreach (Thing item in response) {
					switch (item.CategoryId) {
					case Thing.categoryPFOOD:
					case Thing.CATEGORY_FOOD:
					case Thing.CATEGORY_NPFOOD:
						if (!foodsDict.ContainsKey (item.Name)) {
							Console.WriteLine ("[" + 
                                                                           creatureName + 
                                                                           "] " + 
                                                                           "I see food: " + 
                                                                           item.Name);
							foodsDict.Add (item.Name, item);
						}	
						break;
					case Thing.CATEGORY_JEWEL:
						if (!jewelsDict.ContainsKey (item.Name)) {
							Console.WriteLine ("[" + 
                                                                           creatureName + 
                                                                           "] " + 
                                                                           "I see jewel: " + 
                                                                           item.Name);
							jewelsDict.Add (item.Name, item);
						}
						break;
					}
				}
                        } 

Code Snippet 6 - agent_OnNewVisualSensorialInformationHandler new rules.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68 
				switch (externalAction) {
				case ClarionAgentActionType.DO_NOTHING:
                                ...
				//Hirley-->>
				case ClarionAgentActionType.GO_AHEAD:
					{

						Dictionary<String,Thing> itemsDict = 
                                                                     new Dictionary<String, Thing> ();
						
						if (foodsDict != null && foodsDict.Count > 0) {
							foreach (Thing food in foodsDict.Values) {
								itemsDict.Add (food.Name, food);
							}
						}
						if (jewelsDict != null && jewelsDict.Count > 0) {
							foreach (Thing jewel in jewelsDict.Values) {
								itemsDict.Add (jewel.Name, jewel);
							}
						}

						if (itemsDict.Count > 0) {
							foreach (Thing item in itemsDict.Values) {
								Console.WriteLine ("[" + 
                                                                                   creatureName + 
                                                                                   "] " +
                                                                                   "Going to: " + 
                                                                                   item.Name);
								worldServer.SendSetGoTo (creatureId, 1, 1, 
                                                                                         item.comX, 
                                                                                         item.comY);
								itemToGet = item;
							}
						} else {
							worldServer.SendSetAngle (creatureId, 1, 
                                                                                  1, prad);
						}
						break;
					}
				case ClarionAgentActionType.GET_ITEM:
					if (itemToGet != null) {
						var worldServer2 = worldServer;
						switch (itemToGet.CategoryId) {
						case Thing.categoryPFOOD:
						case Thing.CATEGORY_FOOD:
						case Thing.CATEGORY_NPFOOD:
							Console.WriteLine ("[" + creatureName + "] " 
                                                                               + "Eating: " + 
                                                                                 itemToGet.Name);
							worldServer.SendEatIt (creatureId, 
                                                                               itemToGet.Name);
							if (foodsDict.ContainsKey (itemToGet.Name)) {
								foodsDict.Remove (itemToGet.Name);
							}
							break;
						case Thing.CATEGORY_JEWEL:
							Console.WriteLine ("[" + creatureName + "] " 
                                                                               + "Saking: " + 
                                                                                 itemToGet.Name);
							worldServer2.SendSackIt (creatureId, 
                                                                                 itemToGet.Name);
							if (jewelsDict.ContainsKey (itemToGet.Name)) {
								jewelsDict.Remove (itemToGet.Name);
							}
							break;
						}
					}
					break;

Code Snippet 6 - agent_OnNewExternalActionSelectedHandler new rules.

1.2 WorldServer3D: ClarionDEMO vs. DemoSOAR

The movie following shows both ClarionDEMO and DemoSOAR interacting with WorldServer3D creatures.

As shown, the creature controlled by DemoSOAR had no movement and stayed immobilized in the top left corner of the game table. No apparent coding reason caused the DemoSOAR's creature unexpected behavior and the only possible explanation was that it was caused by a overload of either WorldServer3D application or the computer.

ClarionDEMO did not implement any code for populating the game with items. DemoSOAR had already implemented such function and both DemoSOAR and ClarionDEMO creatures should collect the disposed of items provided by that DemoSOAR's function.

ClarionDEMO's creature managed to collect both jewels and foods, with preference to jewels, trying to follow the objects detected by its visual sensorial information. External action was triggered based on the objects that have been detected by the sensorial information.

2 CONCLUSIONS

Despite of the complexity the Clarion framework, the language and code structure was easy to learn and the implementation presented in this report was not difficult when comparing to SOAR.

After some initial issues when running both Clarion and SOAR for controlling creatures in WorldServer3D, the competition run successfully as show in the video above..

 

 

 

 

 

Theme by Danetsoft and Danang Probo Sayekti inspired by Maksimer