source: cpp/frams/neuro/neuroimpl.h @ 372

Last change on this file since 372 was 372, checked in by sz, 9 years ago

Renamed some classes and functions to make their purpose more obvious:

All MessageHandlers? must now be given the explicit "Enable" argument if you want them to automatically become active. This makes side effects clearly visible.

  • Property svn:eol-style set to native
File size: 9.2 KB
Line 
1// This file is a part of Framsticks SDK.  http://www.framsticks.com/
2// Copyright (C) 1999-2015  Maciej Komosinski and Szymon Ulatowski.
3// See LICENSE.txt for details.
4
5#ifndef _NEUROIMPL_H_
6#define _NEUROIMPL_H_
7
8#include <frams/model/model.h>
9#include <frams/param/param.h>
10#include <common/hmessage.h>
11#ifdef NEURO_SIGNALS
12#include <frams/simul/signals.h>
13#endif
14
15class NeuroImpl;
16extern ParamEntry neuroimpl_tab[];
17
18class Creature;
19class NeuroLibrary;
20class NeuroFactory;
21
22class NeuroNetConfig
23{
24public:
25NeuroNetConfig(NeuroFactory *fac);
26
27Param par;
28double randominit;
29double nnoise;
30double touchrange;
31
32NeuroFactory *factory;
33//static NeuroNetConfig& getGlobalConfig();
34};
35
36#ifdef NEURO_SIGNALS
37class NeuroSignals: public SignalSet
38{
39  protected:
40Creature *cr;
41NeuroImpl *owner;
42Creature *getCreature();
43  public:
44
45NeuroSignals(NeuroImpl *n):cr(0),owner(n) {}
46
47#define STATRICKCLASS NeuroSignals
48PARAMPROCDEF(p_add);
49PARAMPROCDEF(p_get);
50PARAMGETDEF(size);
51PARAMPROCDEF(p_receive);
52PARAMPROCDEF(p_receiveSet);
53PARAMPROCDEF(p_receiveFilter);
54PARAMPROCDEF(p_receiveSingle);
55#undef STATRICKCLASS
56
57static Param& getStaticParam();
58};
59#endif
60
61/// Neuro net implementation
62class NeuroNetImpl
63{
64CallbackNode *cnode;
65Model &mod;
66SList neurons[4];
67NeuroNetConfig& config;
68int isbuilt,errorcount;
69STCALLBACKDEFC(NeuroNetImpl,destroyNN);
70int minorder,maxorder;
71
72  public:
73#ifdef NEURO_SIGNALS
74ChannelSpace *channels;
75#endif
76static int mytags_id;
77static double getStateFromNeuro(Neuro *n);
78int getErrorCount() {return errorcount;}
79NeuroNetConfig &getConfig() {return config;}
80NeuroNetImpl(Model& model, NeuroNetConfig& conf
81#ifdef NEURO_SIGNALS
82, ChannelSpace *ch=0
83#endif
84);
85~NeuroNetImpl();
86void simulateNeuroNet();
87void simulateNeuroPhysics();
88
89static NeuroImpl *getImpl(Neuro* n) {return (NeuroImpl*)n->userdata[mytags_id];}
90};
91
92
93/**
94   Neuro implementation - this object calculates the Neuron's state
95   (Neuro::state) in each simulation step.
96
97SUBCLASSING TUTORIAL
98====================
99
1001.Derive your custom neuron from NeuroImpl class. The name must be prefixed with NI_
101
102class NI_MyNeuron: public NeuroImpl
103{ ... };
104
1052.Public parameters
106Create any number of public fields, they will be adjustable from the genotype level.
1073 datatypes are supported: long, double and SString
108
109public:
110  paInt intParameter;
111  double fpParameter;
112  SString txtParameter;
113
114
1153.Required method: "instantiator".
116It is always the same, just create a new instance of your neuron.
117public:
118  NeuroImpl* makeNew() { return new NI_MyNeuron(); };
119
120
1214.Required method: default constructor
122Set the "paramentries" variable if you need public parameters in your neuron.
123NI_..._tab is created automatically and should be declared as: extern ParamEntry NI_..._tab[];
124At this stage the parameter values are not yet available.
125
126public:
127 NI_MyNeuron() // no parameters!
128 {
129 paramentries=NI_MyNeuron_tab;
130 // you add here: some general initialization
131 }
132
133
1345.Optional method: initialization
135This method is called once before the neuron is actually used in the simulation.
136The parameter values are already initialized (according to the genotype) and the neuron is bound to the creature (i.e. this->neuro is valid).
137Return 0 if the neuron cannot be initialized.
138
139int lateinit()
140 {
141 // you add here: initialization using full neuron context
142 // example: if (!neuro->joint) return 0; //this neuron must be attached to joint
143 return 1;//OK
144 }
145
146
1476.Required method: simulation step
148If it has output: calculate the next neuron state and call setState()
149If it is an effector: do anything else
150
151void go()
152 {
153 // you add here: things called every simulation step
154 }
155
156Note: You can make your neuron fire before or after "regular" neurons by changing its "simorder" property (during initialization). The default value is 1, whereas receptors have simorder=0 and effectors have simorder=2.
157
158
1597.Neuron definition
160In order to incorporate the new neuron into Framsticks you need to provide some additional information (to be added to "f0.def" file).
161
162NEUROCLASS(MyNeuron,MN,This is the name,`Neuron description',-1,1,0)
163NEUROPROP(int,0,0,name of the int,d,,,,intParameter)
164NEUROPROP(fp,0,0,name of the floating point,f,,,,fpParameter)
165NEUROPROP(txt,0,0,name of the text,s,,,,txtParameter)
166ENDNEUROCLASS
167
168NEUROCLASS:
169- MyNeuron: neuron class name (without the NI_ prefix)
170- MN: neuron symbol (used in genotypes)
171- full name and description
172- -1: preferred number of inputs (special case: -1=any)
173- 1: provides output: 1=yes/0=no
174- 0: preferred location: 0=none, 1=part, 2=joint
175
176NEUROPROP:
177- int/fp/txt: parameter names as visible in genotypes and scripting
178- "name of the ...": descriptive name
179- d/f/s: type (int/floating point/string)
180- intParameter/fpParameter/txtParameter: C++ field names
181
182   
183 */
184class NeuroImpl
185{
186protected:
187int simorder;
188int channels;
189SListTempl<double> chstate;
190SListTempl<double> chnewstate;
191Param *fields_param;
192ExtObject *fields_object;
193public:
194static const int ENDDRAWING;
195static const int MAXDRAWINGXY;
196
197enum NeuroImplStats { BeforeInit=0, InitError=1, InitOk=2 };
198NeuroImplStats status;
199/** originating neuron object (from the model) */
200Neuro *neuro;
201NeuroClass *neuroclass;
202/** don't access directly */
203double newstate;
204NeuroNetImpl *owner;
205/** will be used by readParam() method, if not null  */
206ParamEntry *paramentries; // no extra properties if ==0
207
208#ifdef NEURO_SIGNALS
209NeuroSignals sigs;
210ExtObject sigs_obj;
211#endif
212
213/** "virtual constructor" - NeuroFactory uses this method to create the proper implementation object.
214    subclasses must return new object here. */
215virtual NeuroImpl* makeNew() {return 0;} //
216/** read additional properties from "moredata" field of the originating Neuro */
217void readParam();
218/** called when all other neuro objects were already created and "moredata" transferred to
219    object fields.
220    useful for initialization that cannot be performed in the constructor.
221    @return 1=ok  0=failure
222*/
223virtual int lateinit() {return 1;}
224/** calculate 'newstate - implementation dependent */
225virtual void go(){}
226/** for neurons doing some physical actions (called each simulation step when nnspeed!=1.0) */
227virtual void goPhysics(){}
228
229int getSimOrder() {return simorder;}
230virtual int getNeedPhysics() {return 0;}
231
232void setChannelCount(int c);
233int getChannelCount() {return channels;}
234
235int getInputCount() {return neuro->getInputCount();}
236int getInputChannelCount(int i);
237double getInputState(int i,int channel=0);
238double getWeightedInputState(int i,int channel=0);
239double getInputSum(int startwith=0);
240double getWeightedInputSum(int startwith=0);
241double getInputWeight(int i) {return neuro->getInputWeight(i);}
242void setState(double st,int channel);
243void setState(double st) {validateNeuroState(st); newstate=st;}
244double getState(int channel);
245double getState() {return neuro->state;}
246
247virtual int getDrawingCount() {return 0;}
248virtual int* getDrawing(int i) {return 0;}
249
250void commit();
251void validateNeuroState(double& st) {if (st<=-1e10) st=-1e10; else if (st>1e10) st=1e10;}
252
253NeuroImpl():simorder(1),channels(1),fields_param(0),fields_object(0),status(BeforeInit),neuro(0),newstate(0),owner(0),paramentries(0)
254#ifdef NEURO_SIGNALS
255,sigs(this),sigs_obj(&NeuroSignals::getStaticParam(),&sigs)
256#endif
257 {}
258virtual ~NeuroImpl();
259virtual void createFieldsObject();
260
261/** usually == "newstate" but will obey the "hold state" */
262double getNewState(int channel=0);
263
264/** don't use! */
265void setCurrentState(double st,int channel=0);
266
267bool getPosition(Pt3D &pos);
268Creature* getCreature();
269
270#define STATRICKCLASS NeuroImpl
271PARAMGETDEF(count) {arg1->setInt(getInputCount());}
272PARAMPROCDEF(p_get) {arg2->setDouble(getInputState(arg1->getInt()));}
273PARAMPROCDEF(p_getweight) {arg2->setDouble(getInputWeight(arg1->getInt()));}
274PARAMPROCDEF(p_getw) {arg2->setDouble(getWeightedInputState(arg1->getInt()));}
275PARAMPROCDEF(p_getsum) {arg2->setDouble(getInputSum(arg1->getInt()));}
276PARAMPROCDEF(p_getwsum) {arg2->setDouble(getWeightedInputSum(arg1->getInt()));}
277PARAMGETDEF(sum) {arg1->setDouble(getInputSum(0));}
278PARAMGETDEF(wsum) {arg1->setDouble(getWeightedInputSum(0));}
279PARAMPROCDEF(p_getchancount) {arg2->setInt(getInputChannelCount(arg1->getInt()));}
280PARAMPROCDEF(p_getchan) {arg2->setDouble(getInputState(arg1[1].getInt(),arg1[0].getInt()));}
281PARAMPROCDEF(p_getwchan) {arg2->setDouble(getWeightedInputState(arg1[1].getInt(),arg1[0].getInt()));}
282PARAMGETDEF(state) {arg1->setDouble(getState());}
283PARAMSETDEF(state) {setState(arg1->getDouble()); return 0;}
284PARAMGETDEF(cstate) {arg1->setDouble(neuro->state);}
285PARAMSETDEF(cstate) {setCurrentState(arg1->getDouble()); return 0;}
286PARAMGETDEF(hold) {arg1->setInt((neuro->flags&(Neuro::HoldState))?1:0);}
287PARAMSETDEF(hold) {neuro->flags=(neuro->flags&~Neuro::HoldState)|(arg1->getInt()?Neuro::HoldState:0); return 0;}
288PARAMGETDEF(channels) {arg1->setInt(getChannelCount());}
289PARAMSETDEF(channels) {setChannelCount(arg1->getInt()); return 0;}
290PARAMPROCDEF(p_getstate) {arg2->setDouble(getState(arg1->getInt()));}
291PARAMPROCDEF(p_setstate) {setState(arg1[0].getDouble(),arg1[1].getInt());}
292PARAMPROCDEF(p_setcstate) {setCurrentState(arg1[0].getDouble(),arg1[1].getInt());}
293PARAMGETDEF(creature);
294PARAMGETDEF(part);
295PARAMGETDEF(joint);
296PARAMGETDEF(position_x);
297PARAMGETDEF(position_y);
298PARAMGETDEF(position_z);
299PARAMGETDEF(fields);
300PARAMGETDEF(neurodef);
301PARAMGETDEF(classObject);
302#undef STATRICKCLASS
303
304  static Param& getStaticParam();
305};
306
307#endif
Note: See TracBrowser for help on using the repository browser.