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

Last change on this file since 836 was 721, checked in by Maciej Komosinski, 6 years ago

Code formatting

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