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

Last change on this file since 978 was 952, checked in by Maciej Komosinski, 5 years ago

Added new receptors (Gp:"gyroscope" on a Part, Tp:Touch-proximity and Tc:Touch-contact) and improved existing ones (T, G)

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