Changeset 720 for cpp/frams/neuro


Ignore:
Timestamp:
01/14/18 11:24:22 (6 years ago)
Author:
Maciej Komosinski
Message:

Param::save2() renamed to saveSingleLine(); unified Param::load() so that it gets a single-line/multi-line format selector

File:
1 edited

Legend:

Unmodified
Added
Removed
  • cpp/frams/neuro/neuroimpl.cpp

    r492 r720  
    11// This file is a part of Framsticks SDK.  http://www.framsticks.com/
    2 // Copyright (C) 1999-2015  Maciej Komosinski and Szymon Ulatowski.
     2// Copyright (C) 1999-2018  Maciej Komosinski and Szymon Ulatowski.
    33// See LICENSE.txt for details.
    44
     
    1414#endif
    1515
    16 const int NeuroImpl::ENDDRAWING=-9999;
    17 const int NeuroImpl::MAXDRAWINGXY=0xffff;
    18 
    19 int NeuroNetImpl::mytags_id=0;
     16const int NeuroImpl::ENDDRAWING = -9999;
     17const int NeuroImpl::MAXDRAWINGXY = 0xffff;
     18
     19int NeuroNetImpl::mytags_id = 0;
    2020
    2121/////////////////////////////////////////////////////////
    2222
    2323#define FIELDSTRUCT NeuroNetConfig
    24 static ParamEntry nncfg_paramtab[]=
    25 {
    26 {"Creature: Neurons",1,3,"nnsim",},
    27 {"randinit",1,0,"Random initialization","f 0 10 0.01",FIELD(randominit),"Allowed range for initializing all neuron states with uniform distribution random numbers and zero mean. Set to 0 for deterministic initialization."},
    28 {"nnoise",1,0,"Noise","f 0 1 0",FIELD(nnoise),"Gaussian neural noise: a random value is added to each neural output in each simulation step. Set standard deviation here to add random noise, or 0 for deterministic simulation."},
    29 {"touchrange",1,0,"T receptor range","f 0 100 1",FIELD(touchrange),},
    30 {0,0,0,},
    31 }; 
     24static ParamEntry nncfg_paramtab[] =
     25{
     26        { "Creature: Neurons", 1, 3, "nnsim", },
     27        { "randinit", 1, 0, "Random initialization", "f 0 10 0.01", FIELD(randominit), "Allowed range for initializing all neuron states with uniform distribution random numbers and zero mean. Set to 0 for deterministic initialization." },
     28        { "nnoise", 1, 0, "Noise", "f 0 1 0", FIELD(nnoise), "Gaussian neural noise: a random value is added to each neural output in each simulation step. Set standard deviation here to add random noise, or 0 for deterministic simulation." },
     29        { "touchrange", 1, 0, "T receptor range", "f 0 100 1", FIELD(touchrange), },
     30        { 0, 0, 0, },
     31};
    3232#undef FIELDSTRUCT
    3333
    3434NeuroNetConfig::NeuroNetConfig(NeuroFactory *fac)
    35         :par(nncfg_paramtab,this),
    36          randominit(0.01),
    37          nnoise(0),
    38          touchrange(1),
    39          factory(fac)
     35        :par(nncfg_paramtab, this),
     36        randominit(0.01),
     37        nnoise(0),
     38        touchrange(1),
     39        factory(fac)
    4040{}
    4141
     
    4444NeuroNetImpl::NeuroNetImpl(Model& model, NeuroNetConfig& conf
    4545#ifdef NEURO_SIGNALS
    46 , ChannelSpace *ch
    47 #endif
    48 )
    49         :mod(model),config(conf),
    50          isbuilt(1),errorcount(0)
     46        , ChannelSpace *ch
     47#endif
     48        )
     49        :mod(model), config(conf),
     50        isbuilt(1), errorcount(0)
    5151#ifdef NEURO_SIGNALS
    52 ,channels(ch)
    53 #endif
    54 {
    55 if (!mytags_id) mytags_id=mod.userdata.newID();
    56 
    57 Neuro *n;
    58 NeuroImpl *ni;
    59 Joint *j;
    60 int i;
    61 DB(printf("makeNeuroNet(%p)\n",&mod));
    62 
    63 minorder=3; maxorder=0;
    64 errorcount=0;
    65 
    66 for (i=0;j=mod.getJoint(i);i++)
    67         j->flags&=~(4+8); // todo: !!!neuroitems shouldn't use model fields!!!
    68 
    69 for (i=0;n=mod.getNeuro(i);i++)
    70         {
    71         ni=conf.factory->createNeuroImpl(n);
    72         n->userdata[mytags_id]=ni;
    73         if (!ni) { errorcount++;
    74                 logPrintf("NeuroNetImpl","create",LOG_WARN,"neuron #%d (%s) implementation not available",
    75                          i,n->getClassName().c_str());
    76                 continue; } // implementation not available?!
    77         ni->owner=this;
    78         ni->neuro=n;
    79         ni->readParam();
    80         }
    81 
    82 for (i=0;n=mod.getNeuro(i);i++)
    83         {
    84         n->state+=(rnd01-0.5)*config.randominit;
    85         ni=(NeuroImpl*)n->userdata[mytags_id];
    86         if (!ni) continue;
    87         if (!ni->lateinit())
    88                 { ni->status=NeuroImpl::InitError; errorcount++;
    89                 logPrintf("NeuroNetImpl","create",LOG_WARN,"neuron #%d (%s) initialization failed",
    90                          i,n->getClassName().c_str());
    91                 continue; }
    92         ni->status=NeuroImpl::InitOk;
    93         int order=ni->getSimOrder();
    94         if (order<0) order=0; else if (order>2) order=2;
    95         if (order<minorder) minorder=order;
    96         if (order>maxorder) maxorder=order;
    97         neurons[order]+=ni;
    98         if (ni->getNeedPhysics())
    99                 neurons[3]+=ni;
    100         }
    101 cnode=mod.delmodel_list.add(STATRICKCALLBACK(this,&NeuroNetImpl::destroyNN,0));
     52        , channels(ch)
     53#endif
     54{
     55        if (!mytags_id) mytags_id = mod.userdata.newID();
     56
     57        Neuro *n;
     58        NeuroImpl *ni;
     59        Joint *j;
     60        int i;
     61        DB(printf("makeNeuroNet(%p)\n", &mod));
     62
     63        minorder = 3; maxorder = 0;
     64        errorcount = 0;
     65
     66        for (i = 0; j = mod.getJoint(i); i++)
     67                j->flags &= ~(4 + 8); // todo: !!!neuroitems shouldn't use model fields!!!
     68
     69        for (i = 0; n = mod.getNeuro(i); i++)
     70        {
     71                ni = conf.factory->createNeuroImpl(n);
     72                n->userdata[mytags_id] = ni;
     73                if (!ni)
     74                {
     75                        errorcount++;
     76                        logPrintf("NeuroNetImpl", "create", LOG_WARN, "neuron #%d (%s) implementation not available",
     77                                i, n->getClassName().c_str());
     78                        continue;
     79                } // implementation not available?!
     80                ni->owner = this;
     81                ni->neuro = n;
     82                ni->readParam();
     83        }
     84
     85        for (i = 0; n = mod.getNeuro(i); i++)
     86        {
     87                n->state += (rnd01 - 0.5)*config.randominit;
     88                ni = (NeuroImpl*)n->userdata[mytags_id];
     89                if (!ni) continue;
     90                if (!ni->lateinit())
     91                {
     92                        ni->status = NeuroImpl::InitError;
     93                        errorcount++;
     94                        logPrintf("NeuroNetImpl", "create", LOG_WARN, "neuron #%d (%s) initialization failed",
     95                                i, n->getClassName().c_str());
     96                        continue;
     97                }
     98                ni->status = NeuroImpl::InitOk;
     99                int order = ni->getSimOrder();
     100                if (order < 0) order = 0; else if (order>2) order = 2;
     101                if (order < minorder) minorder = order;
     102                if (order > maxorder) maxorder = order;
     103                neurons[order] += ni;
     104                if (ni->getNeedPhysics())
     105                        neurons[3] += ni;
     106        }
     107        cnode = mod.delmodel_list.add(STATRICKCALLBACK(this, &NeuroNetImpl::destroyNN, 0));
    102108}
    103109
    104110void NeuroNetImpl::destroyNN(CALLBACKARGS)
    105111{
    106 if (!isbuilt) return;
    107 DB(printf("destroyNeuroNet(%p)\n",&mod));
    108 NeuroImpl *ni;
    109 Neuro *n;
    110 for (int i=0;n=mod.getNeuro(i);i++)
    111         {
    112         ni=(NeuroImpl*)n->userdata[mytags_id];
    113         delete ni;
    114         n->userdata[mytags_id]=0;
    115         }
    116 mod.delmodel_list.remove(cnode);
    117 isbuilt=0; errorcount=0;
    118 delete this;
     112        if (!isbuilt) return;
     113        DB(printf("destroyNeuroNet(%p)\n", &mod));
     114        NeuroImpl *ni;
     115        Neuro *n;
     116        for (int i = 0; n = mod.getNeuro(i); i++)
     117        {
     118                ni = (NeuroImpl*)n->userdata[mytags_id];
     119                delete ni;
     120                n->userdata[mytags_id] = 0;
     121        }
     122        mod.delmodel_list.remove(cnode);
     123        isbuilt = 0; errorcount = 0;
     124        delete this;
    119125}
    120126
    121127NeuroNetImpl::~NeuroNetImpl()
    122128{
    123 destroyNN(0,0);
     129        destroyNN(0, 0);
    124130}
    125131
    126132void NeuroNetImpl::simulateNeuroNet()
    127133{
    128 NeuroImpl *ni;
    129 for (int order=minorder;order<=maxorder;order++)
    130         {
     134        NeuroImpl *ni;
     135        for (int order = minorder; order <= maxorder; order++)
     136        {
     137                int i;
     138                SList &nlist = neurons[order];
     139                for (i = 0; ni = (NeuroImpl*)nlist(i); i++)
     140                        ni->go();
     141                for (i = 0; ni = (NeuroImpl*)nlist(i); i++)
     142                        ni->commit();
     143        }
     144}
     145
     146void NeuroNetImpl::simulateNeuroPhysics()
     147{
     148        NeuroImpl *ni;
    131149        int i;
    132         SList &nlist=neurons[order];
    133         for (i=0;ni=(NeuroImpl*)nlist(i);i++)
    134                 ni->go();
    135         for (i=0;ni=(NeuroImpl*)nlist(i);i++)
    136                 ni->commit();
    137         }
    138 }
    139 
    140 void NeuroNetImpl::simulateNeuroPhysics()
    141 {
    142 NeuroImpl *ni;
    143 int i;
    144 SList &nlist=neurons[3];
    145 for (i=0;ni=(NeuroImpl*)nlist(i);i++)
    146         ni->goPhysics();
     150        SList &nlist = neurons[3];
     151        for (i = 0; ni = (NeuroImpl*)nlist(i); i++)
     152                ni->goPhysics();
    147153}
    148154
     
    151157void NeuroImpl::setChannelCount(int c)
    152158{
    153 if (c<1) c=1;
    154 if (c==channels) return;
    155 if (c<channels) {channels=c; chstate.trim(c-1); chnewstate.trim(c-1); return;}
    156 double s=getState(channels-1);
    157 chnewstate.setSize(c-1);
    158 chstate.setSize(c-1);
    159 for(int i=channels;i<c;i++)
    160         {chstate(i-1)=s; chnewstate(i-1)=s;}
    161 channels=c;
    162 }
    163 
    164 void NeuroImpl::setState(double st,int channel)
    165 {
    166 validateNeuroState(st);
    167 if (channel>=channels) channel=channels-1;
    168 if (channel<=0) {newstate=st;return;}
    169 chnewstate(channel-1)=st;
    170 }
    171 
    172 void NeuroImpl::setCurrentState(double st,int channel)
    173 {
    174 validateNeuroState(st);
    175 if (channel>=channels) channel=channels-1;
    176 if (channel<=0) {neuro->state=st; return;}
    177 chstate(channel-1)=st;
     159        if (c < 1) c = 1;
     160        if (c == channels) return;
     161        if (c < channels) { channels = c; chstate.trim(c - 1); chnewstate.trim(c - 1); return; }
     162        double s = getState(channels - 1);
     163        chnewstate.setSize(c - 1);
     164        chstate.setSize(c - 1);
     165        for (int i = channels; i < c; i++)
     166        {
     167                chstate(i - 1) = s;
     168                chnewstate(i - 1) = s;
     169        }
     170        channels = c;
     171}
     172
     173void NeuroImpl::setState(double st, int channel)
     174{
     175        validateNeuroState(st);
     176        if (channel >= channels) channel = channels - 1;
     177        if (channel <= 0) { newstate = st; return; }
     178        chnewstate(channel - 1) = st;
     179}
     180
     181void NeuroImpl::setCurrentState(double st, int channel)
     182{
     183        validateNeuroState(st);
     184        if (channel >= channels) channel = channels - 1;
     185        if (channel <= 0) { neuro->state = st; return; }
     186        chstate(channel - 1) = st;
    178187}
    179188
    180189double NeuroImpl::getNewState(int channel)
    181190{
    182 if (neuro->flags&Neuro::HoldState) return getState(channel);
    183 if (channel>=channels) channel=channels-1;
    184 if (channel<=0) {return newstate;}
    185 return chnewstate(channel-1);
     191        if (neuro->flags&Neuro::HoldState) return getState(channel);
     192        if (channel >= channels) channel = channels - 1;
     193        if (channel <= 0) { return newstate; }
     194        return chnewstate(channel - 1);
    186195}
    187196
    188197double NeuroImpl::getState(int channel)
    189198{
    190 if (channel>=channels) channel=channels-1;
    191 if (channel<=0) return neuro->state;
    192 return chstate(channel-1);
     199        if (channel >= channels) channel = channels - 1;
     200        if (channel <= 0) return neuro->state;
     201        return chstate(channel - 1);
    193202}
    194203
    195204void NeuroImpl::commit()
    196205{
    197 if (!(neuro->flags&Neuro::HoldState))
    198         {
    199         if (channels>1)
    200                 chstate=chnewstate;
    201         neuro->state=newstate;
    202         if (owner->getConfig().nnoise>0.0)
     206        if (!(neuro->flags&Neuro::HoldState))
     207        {
     208                if (channels > 1)
     209                        chstate = chnewstate;
     210                neuro->state = newstate;
     211                if (owner->getConfig().nnoise > 0.0)
    203212                {
    204                 neuro->state+=RndGen.GaussStd()*owner->getConfig().nnoise;
    205                 if (channels>1)
    206                         for(int i=0;i<chstate.size();i++)
    207                                 chstate(0)+=RndGen.GaussStd()*owner->getConfig().nnoise;
     213                        neuro->state += RndGen.GaussStd()*owner->getConfig().nnoise;
     214                        if (channels > 1)
     215                                for (int i = 0; i < chstate.size(); i++)
     216                                        chstate(0) += RndGen.GaussStd()*owner->getConfig().nnoise;
    208217                }
    209218        }
     
    212221int NeuroImpl::getInputChannelCount(int i)
    213222{
    214 if ((i<0)||(i >= neuro->getInputCount())) return 1;
    215 Neuro *nu=neuro->getInput(i);
    216 NeuroImpl *ni=NeuroNetImpl::getImpl(nu);
    217 if (!ni) return 1;
    218 return ni->channels;
    219 }
    220 
    221 double NeuroImpl::getInputState(int i,int channel)
    222 {
    223 if ((i<0)||(i >= neuro->getInputCount())) return 0;
    224 Neuro *nu=neuro->getInput(i);
    225 if (channel<=0) return nu->state;
    226 NeuroImpl *ni=NeuroNetImpl::getImpl(nu);
    227 if (!ni) return nu->state;
    228 if (channel>=ni->channels) channel=ni->channels-1;
    229 if (!channel) return nu->state;
    230 return ni->chstate(channel-1);
     223        if ((i < 0) || (i >= neuro->getInputCount())) return 1;
     224        Neuro *nu = neuro->getInput(i);
     225        NeuroImpl *ni = NeuroNetImpl::getImpl(nu);
     226        if (!ni) return 1;
     227        return ni->channels;
     228}
     229
     230double NeuroImpl::getInputState(int i, int channel)
     231{
     232        if ((i < 0) || (i >= neuro->getInputCount())) return 0;
     233        Neuro *nu = neuro->getInput(i);
     234        if (channel <= 0) return nu->state;
     235        NeuroImpl *ni = NeuroNetImpl::getImpl(nu);
     236        if (!ni) return nu->state;
     237        if (channel >= ni->channels) channel = ni->channels - 1;
     238        if (!channel) return nu->state;
     239        return ni->chstate(channel - 1);
    231240}
    232241
    233242double NeuroImpl::getWeightedInputState(int i, int channel)
    234243{
    235 if ((i<0)||(i >= neuro->getInputCount())) return 0;
    236 double w;
    237 Neuro *nu=neuro->getInput(i,w);
    238 if (channel<=0) return nu->state * w;
    239 NeuroImpl *ni=NeuroNetImpl::getImpl(nu);
    240 if (!ni) return nu->state * w;
    241 if (channel>=ni->channels) channel=ni->channels-1;
    242 if (!channel) return w * nu->state;
    243 return w * ni->chstate(channel-1);
     244        if ((i < 0) || (i >= neuro->getInputCount())) return 0;
     245        double w;
     246        Neuro *nu = neuro->getInput(i, w);
     247        if (channel <= 0) return nu->state * w;
     248        NeuroImpl *ni = NeuroNetImpl::getImpl(nu);
     249        if (!ni) return nu->state * w;
     250        if (channel >= ni->channels) channel = ni->channels - 1;
     251        if (!channel) return w * nu->state;
     252        return w * ni->chstate(channel - 1);
    244253}
    245254
    246255double NeuroImpl::getInputSum(int startwith)
    247256{
    248 if (startwith<0) return 0;
    249 Neuro *inp;
    250 double sum=0.0;
    251 while(inp=neuro->getInput(startwith++))
    252         sum+=inp->state;
    253 return sum;
     257        if (startwith < 0) return 0;
     258        Neuro *inp;
     259        double sum = 0.0;
     260        while (inp = neuro->getInput(startwith++))
     261                sum += inp->state;
     262        return sum;
    254263}
    255264
    256265double NeuroImpl::getWeightedInputSum(int startwith)
    257266{
    258 if (startwith<0) return 0;
    259 Neuro *inp;
    260 double sum=0.0;
    261 double w;
    262 while(inp=neuro->getInput(startwith++,w))
    263         sum+=inp->state*w;
    264 return sum;
     267        if (startwith < 0) return 0;
     268        Neuro *inp;
     269        double sum = 0.0;
     270        double w;
     271        while (inp = neuro->getInput(startwith++, w))
     272                sum += inp->state*w;
     273        return sum;
    265274}
    266275
    267276void NeuroImpl::readParam()
    268277{
    269 Param par;
    270 if (!paramentries) return;
    271 par.setParamTab(paramentries);
    272 par.select(this);
    273 par.setDefault();
    274 int zero=0;
    275 par.load2(neuro->getClassParams(),zero);
     278        Param par;
     279        if (!paramentries) return;
     280        par.setParamTab(paramentries);
     281        par.select(this);
     282        par.setDefault();
     283        par.load(ParamInterface::FormatSingleLine, neuro->getClassParams());
    276284}
    277285
    278286Param& NeuroImpl::getStaticParam()
    279287{
    280 static Param p(neuroimpl_tab,0,"Neuro");
    281 return p;
     288        static Param p(neuroimpl_tab, 0, "Neuro");
     289        return p;
    282290}
    283291
     
    291299
    292300#define FIELDSTRUCT NeuroImpl
    293 ParamEntry neuroimpl_tab[]=
    294 {
    295 {"Neuro",1,27+NEUROIMPL_SIGNAL_PROPS,"Neuro","Live Neuron object."},
    296 
    297 {"getInputState",0,0,"Get input signal","p f(d input)",PROCEDURE(p_get),},
    298 {"getInputWeight",0,0,"Get input weight","p f(d input)",PROCEDURE(p_getweight),},
    299 {"getWeightedInputState",0,0,"Get weighted input signal","p f(d input)",PROCEDURE(p_getw),},
    300 {"getInputSum",0,0,"Get signal sum","p f(d input)",PROCEDURE(p_getsum),},
    301 {"getWeightedInputSum",0,0,"Get weighted signal sum","p f(d input)",PROCEDURE(p_getwsum),"Uses any number of inputs starting with the specified input. getWeightedInputSum(0)=weightedInputSum"},
    302 {"getInputCount",0,PARAM_READONLY,"Get input count","d",GETONLY(count),},
    303 {"inputSum",0,PARAM_READONLY,"Full signal sum","f",GETONLY(sum),},
    304 {"weightedInputSum",0,PARAM_READONLY,"Full weighted signal sum","f",GETONLY(wsum),},
    305 {"getInputChannelCount",0,0,"Get channel count for input","p d(d input)",PROCEDURE(p_getchancount),},
    306 {"getInputStateChannel",0,0,"Get input signal from channel","p f(d input,d channel)",PROCEDURE(p_getchan),},
    307 {"getWeightedInputStateChannel",0,0,"Get weighted input signal from channel","p f(d input,d channel)",PROCEDURE(p_getwchan),},
    308 {"state",0,0,"Neuron state (channel 0)","f",GETSET(state),"When read, returns the current neuron state.\nWhen written, sets the 'internal' neuron state that will become current in the next step.\nTypically you should use this field, and not currState."},
    309 {"channelCount",0,0,"Number of output channels","d",GETSET(channels),},
    310 {"getStateChannel",0,0,"Get state for channel","p f(d channel)",PROCEDURE(p_getstate),},
    311 {"setStateChannel",0,0,"Set state for channel","p(d channel,f value)",PROCEDURE(p_setstate),},
    312 {"hold",0,0,"Hold state","d 0 1",GETSET(hold),"\"Holding\" means keeping the neuron state as is, blocking the regular neuron operation. This is useful when your script needs to inject some control signals into the NN. Without \"holding\", live neurons would be constantly overwriting your changes, and the rest of the NN could see inconsistent states, depending on the connections. Setting hold=1 ensures the neuron state will be only set by you, and not by the neuron. The enforced signal value can be set using Neuro.currState before or after setting hold=1. Set hold=0 to resume normal operation.",},
    313 {"currState",0,0,"Current neuron state (channel 0)","f",GETSET(cstate),"When read, it behaves just like the 'state' field.\nWhen written, changes the current neuron state immediately, which disturbs the regular synchronous NN operation.\nThis feature should only be used while controlling the neuron 'from outside' (like a neuro probe) and not in the neuron definition. See also: Neuro.hold",},
    314 {"setCurrStateChannel",0,0,"Set current neuron state for channel","p(d channel,f value)",PROCEDURE(p_setcstate),"Analogous to \"currState\"."},
    315 {"position_x",0,PARAM_READONLY,"Position x","f",GETONLY(position_x),},
    316 {"position_y",0,PARAM_READONLY,"Position y","f",GETONLY(position_y),},
    317 {"position_z",0,PARAM_READONLY,"Position z","f",GETONLY(position_z),},
    318 {"creature",0,PARAM_READONLY,"Gets owner creature","o Creature",GETONLY(creature),},
    319 {"part",0,PARAM_READONLY,"The Part object where this neuron is located","o MechPart",GETONLY(part),},
    320 {"joint",0,PARAM_READONLY,"The Joint object where this neuron is located","o MechJoint",GETONLY(joint),},
    321 {"neuroproperties",0,PARAM_READONLY,"Custom neuron fields","o NeuroProperties",GETONLY(fields),
    322 "Neurons can have different fields depending on their class. Script neurons have their fields defined using the \"property:\" syntax. If you develop a custom neuron script you should use the NeuroProperties object for accessing your own neuron fields. The Neuro.neuroproperties property is meant for accessing the neuron fields from the outside script.\n"
    323 "Examples:\n"
    324 "var c=Populations.createFromString(\"X[N]\");\n"
    325 "Simulator.print(\"standard neuron inertia=\"+c.getNeuro(0).neuroproperties.in);\n"
    326 "c=Populations.createFromString(\"X[Nn,e:0.1]\");\n"
    327 "Simulator.print(\"noisy neuron error rate=\"+c.getNeuro(0).neuroproperties.e);\n"
    328 "\n"
    329 "The Interface object can be used to discover which fields are available for a certain neuron object:\n"
    330 "c=Populations.createFromString(\"X[N]\");\n"
    331 "var iobj=Interface.makeFrom(c.getNeuro(0).neuroproperties);\n"
    332 "var i;\n"
    333 "for(i=0;i<iobj.size;i++)\n"
    334 " Simulator.print(iobj.getId(i)+\" (\"+iobj.getName(i)+\")\");",},
    335 {"def",0,PARAM_READONLY,"Neuron definition from which this live neuron was built","o NeuroDef",GETONLY(neurodef),},
    336 {"classObject",0,PARAM_READONLY,"Neuron class for this neuron","o NeuroClass",GETONLY(classObject),},
     301ParamEntry neuroimpl_tab[] =
     302{
     303        { "Neuro", 1, 27 + NEUROIMPL_SIGNAL_PROPS, "Neuro", "Live Neuron object." },
     304
     305        { "getInputState", 0, 0, "Get input signal", "p f(d input)", PROCEDURE(p_get), },
     306        { "getInputWeight", 0, 0, "Get input weight", "p f(d input)", PROCEDURE(p_getweight), },
     307        { "getWeightedInputState", 0, 0, "Get weighted input signal", "p f(d input)", PROCEDURE(p_getw), },
     308        { "getInputSum", 0, 0, "Get signal sum", "p f(d input)", PROCEDURE(p_getsum), },
     309        { "getWeightedInputSum", 0, 0, "Get weighted signal sum", "p f(d input)", PROCEDURE(p_getwsum), "Uses any number of inputs starting with the specified input. getWeightedInputSum(0)=weightedInputSum" },
     310        { "getInputCount", 0, PARAM_READONLY, "Get input count", "d", GETONLY(count), },
     311        { "inputSum", 0, PARAM_READONLY, "Full signal sum", "f", GETONLY(sum), },
     312        { "weightedInputSum", 0, PARAM_READONLY, "Full weighted signal sum", "f", GETONLY(wsum), },
     313        { "getInputChannelCount", 0, 0, "Get channel count for input", "p d(d input)", PROCEDURE(p_getchancount), },
     314        { "getInputStateChannel", 0, 0, "Get input signal from channel", "p f(d input,d channel)", PROCEDURE(p_getchan), },
     315        { "getWeightedInputStateChannel", 0, 0, "Get weighted input signal from channel", "p f(d input,d channel)", PROCEDURE(p_getwchan), },
     316        { "state", 0, 0, "Neuron state (channel 0)", "f", GETSET(state), "When read, returns the current neuron state.\nWhen written, sets the 'internal' neuron state that will become current in the next step.\nTypically you should use this field, and not currState." },
     317        { "channelCount", 0, 0, "Number of output channels", "d", GETSET(channels), },
     318        { "getStateChannel", 0, 0, "Get state for channel", "p f(d channel)", PROCEDURE(p_getstate), },
     319        { "setStateChannel", 0, 0, "Set state for channel", "p(d channel,f value)", PROCEDURE(p_setstate), },
     320        { "hold", 0, 0, "Hold state", "d 0 1", GETSET(hold), "\"Holding\" means keeping the neuron state as is, blocking the regular neuron operation. This is useful when your script needs to inject some control signals into the NN. Without \"holding\", live neurons would be constantly overwriting your changes, and the rest of the NN could see inconsistent states, depending on the connections. Setting hold=1 ensures the neuron state will be only set by you, and not by the neuron. The enforced signal value can be set using Neuro.currState before or after setting hold=1. Set hold=0 to resume normal operation.", },
     321        { "currState", 0, 0, "Current neuron state (channel 0)", "f", GETSET(cstate), "When read, it behaves just like the 'state' field.\nWhen written, changes the current neuron state immediately, which disturbs the regular synchronous NN operation.\nThis feature should only be used while controlling the neuron 'from outside' (like a neuro probe) and not in the neuron definition. See also: Neuro.hold", },
     322        { "setCurrStateChannel", 0, 0, "Set current neuron state for channel", "p(d channel,f value)", PROCEDURE(p_setcstate), "Analogous to \"currState\"." },
     323        { "position_x", 0, PARAM_READONLY, "Position x", "f", GETONLY(position_x), },
     324        { "position_y", 0, PARAM_READONLY, "Position y", "f", GETONLY(position_y), },
     325        { "position_z", 0, PARAM_READONLY, "Position z", "f", GETONLY(position_z), },
     326        { "creature", 0, PARAM_READONLY, "Gets owner creature", "o Creature", GETONLY(creature), },
     327        { "part", 0, PARAM_READONLY, "The Part object where this neuron is located", "o MechPart", GETONLY(part), },
     328        { "joint", 0, PARAM_READONLY, "The Joint object where this neuron is located", "o MechJoint", GETONLY(joint), },
     329        { "neuroproperties", 0, PARAM_READONLY, "Custom neuron fields", "o NeuroProperties", GETONLY(fields),
     330        "Neurons can have different fields depending on their class. Script neurons have their fields defined using the \"property:\" syntax. If you develop a custom neuron script you should use the NeuroProperties object for accessing your own neuron fields. The Neuro.neuroproperties property is meant for accessing the neuron fields from the outside script.\n"
     331        "Examples:\n"
     332        "var c=Populations.createFromString(\"X[N]\");\n"
     333        "Simulator.print(\"standard neuron inertia=\"+c.getNeuro(0).neuroproperties.in);\n"
     334        "c=Populations.createFromString(\"X[Nn,e:0.1]\");\n"
     335        "Simulator.print(\"noisy neuron error rate=\"+c.getNeuro(0).neuroproperties.e);\n"
     336        "\n"
     337        "The Interface object can be used to discover which fields are available for a certain neuron object:\n"
     338        "c=Populations.createFromString(\"X[N]\");\n"
     339        "var iobj=Interface.makeFrom(c.getNeuro(0).neuroproperties);\n"
     340        "var i;\n"
     341        "for(i=0;i<iobj.size;i++)\n"
     342        " Simulator.print(iobj.getId(i)+\" (\"+iobj.getName(i)+\")\");", },
     343        { "def", 0, PARAM_READONLY, "Neuron definition from which this live neuron was built", "o NeuroDef", GETONLY(neurodef), },
     344        { "classObject", 0, PARAM_READONLY, "Neuron class for this neuron", "o NeuroClass", GETONLY(classObject), },
    337345#ifdef NEURO_SIGNALS
    338 {"signals",0,PARAM_READONLY,"Signals","o NeuroSignals",FIELD(sigs_obj),},
    339 #endif
    340 
    341 {0,0,0,},
     346        { "signals", 0, PARAM_READONLY, "Signals", "o NeuroSignals", FIELD(sigs_obj), },
     347#endif
     348
     349        { 0, 0, 0, },
    342350};
    343351#undef FIELDSTRUCT
    344352
    345353#ifdef NEURO_SIGNALS
    346 ParamEntry neurosignals_paramtab[]=
    347  {
    348 {"NeuroSignals",1,8,"NeuroSignals","Signals attached to a neuron.\nSee also: Signal, WorldSignals, CreatureSignals.\nscripts/light.neuro and scripts/seelight.neuro are simple custom neuron examples demonstrating how to send/receive signals between creatures.",},
     354ParamEntry neurosignals_paramtab[] =
     355{
     356        { "NeuroSignals", 1, 8, "NeuroSignals", "Signals attached to a neuron.\nSee also: Signal, WorldSignals, CreatureSignals.\nscripts/light.neuro and scripts/seelight.neuro are simple custom neuron examples demonstrating how to send/receive signals between creatures.", },
    349357
    350358#define FIELDSTRUCT NeuroSignals
    351 SIGNPAR_ADD(""),
    352 SIGNPAR_RECEIVE(""),
    353 SIGNPAR_RECEIVESET(""),
    354 SIGNPAR_RECEIVEFILTER(""),
    355 SIGNPAR_RECEIVESINGLE(""),
     359        SIGNPAR_ADD(""),
     360        SIGNPAR_RECEIVE(""),
     361        SIGNPAR_RECEIVESET(""),
     362        SIGNPAR_RECEIVEFILTER(""),
     363        SIGNPAR_RECEIVESINGLE(""),
    356364#undef FIELDSTRUCT
    357365
    358366#define FIELDSTRUCT SignalSet
    359 SIGNSETPAR_GET,
    360 SIGNSETPAR_SIZE,
    361 SIGNSETPAR_CLEAR,
     367        SIGNSETPAR_GET,
     368        SIGNSETPAR_SIZE,
     369        SIGNSETPAR_CLEAR,
    362370#undef FIELDSTRUCT
    363 {0,0,0,},
    364  };
     371        { 0, 0, 0, },
     372};
    365373
    366374Param& NeuroSignals::getStaticParam()
    367375{
    368 static Param p(neurosignals_paramtab,0);
    369 return p;
     376        static Param p(neurosignals_paramtab, 0);
     377        return p;
    370378}
    371379#endif
    372380
    373381#ifdef NEURO_SIGNALS
    374 class NeuroSigSource: public SigSource
    375 {
    376   protected:
    377 NeuroImpl* owner;
    378   public:
    379 NeuroSigSource(NeuroImpl *n,Creature *c):SigSource(0,c),owner(n) {}
    380 bool update();
     382class NeuroSigSource : public SigSource
     383{
     384protected:
     385        NeuroImpl* owner;
     386public:
     387        NeuroSigSource(NeuroImpl *n, Creature *c) :SigSource(0, c), owner(n) {}
     388        bool update();
    381389};
    382390
    383391bool NeuroSigSource::update()
    384392{
    385 Pt3D p;
    386 if (owner->getPosition(p))
    387         {
    388         setLocation(p);
    389         return true;
    390         }
    391 return false;
     393        Pt3D p;
     394        if (owner->getPosition(p))
     395        {
     396                setLocation(p);
     397                return true;
     398        }
     399        return false;
    392400}
    393401
    394402Creature *NeuroSignals::getCreature()
    395403{
    396 if (!cr)
    397         {
    398         cr=owner->getCreature();
    399         }
    400 return cr;
     404        if (!cr)
     405        {
     406                cr = owner->getCreature();
     407        }
     408        return cr;
    401409}
    402410
    403411void NeuroSignals::p_add(PARAMPROCARGS)
    404412{
    405 SigSource *s=new NeuroSigSource(owner,getCreature());
    406 if (owner->owner->channels)
    407         {
    408         SigChannel *ch=owner->owner->channels->getChannel(args->getString(),true);
    409         ch->addSource(s);
    410         }
    411 else
    412         SigChannel::dummy_channel.addSource(s);
    413 sigs+=s;
    414 s->setupObject(ret);
     413        SigSource *s = new NeuroSigSource(owner, getCreature());
     414        if (owner->owner->channels)
     415        {
     416                SigChannel *ch = owner->owner->channels->getChannel(args->getString(), true);
     417                ch->addSource(s);
     418        }
     419        else
     420                SigChannel::dummy_channel.addSource(s);
     421        sigs += s;
     422        s->setupObject(ret);
    415423}
    416424
    417425void NeuroSignals::p_receive(PARAMPROCARGS)
    418426{
    419 SigChannel *ch; Pt3D p;
    420 if (owner->owner->channels && (ch=owner->owner->channels->getChannel(args->getString(),false)) && owner->getPosition(p))
    421         ret->setDouble(ch->receive(&p,getCreature()));
    422 else
    423         ret->setDouble(0);
     427        SigChannel *ch; Pt3D p;
     428        if (owner->owner->channels && (ch = owner->owner->channels->getChannel(args->getString(), false)) && owner->getPosition(p))
     429                ret->setDouble(ch->receive(&p, getCreature()));
     430        else
     431                ret->setDouble(0);
    424432}
    425433
    426434void NeuroSignals::p_receiveFilter(PARAMPROCARGS)
    427435{
    428 SigChannel *ch; Pt3D p;
    429 if (owner->owner->channels && (ch=owner->owner->channels->getChannel(args[3].getString(),false)) && owner->getPosition(p))
    430         ret->setDouble(ch->receive(&p,getCreature(),args[2].getDouble(),args[1].getDouble(),args[0].getDouble()));
    431 else
    432         ret->setDouble(0);
     436        SigChannel *ch; Pt3D p;
     437        if (owner->owner->channels && (ch = owner->owner->channels->getChannel(args[3].getString(), false)) && owner->getPosition(p))
     438                ret->setDouble(ch->receive(&p, getCreature(), args[2].getDouble(), args[1].getDouble(), args[0].getDouble()));
     439        else
     440                ret->setDouble(0);
    433441}
    434442
    435443void NeuroSignals::p_receiveSet(PARAMPROCARGS)
    436444{
    437 SigChannel *ch; Pt3D p;
    438 SigVector *vec=new SigVector();
    439 if (owner->owner->channels && (ch=owner->owner->channels->getChannel(args[1].getString(),false)) && owner->getPosition(p))
    440         ch->receiveSet(vec,&p,getCreature(),args[0].getDouble());
    441 ret->setObject(vec->makeObject());
     445        SigChannel *ch; Pt3D p;
     446        SigVector *vec = new SigVector();
     447        if (owner->owner->channels && (ch = owner->owner->channels->getChannel(args[1].getString(), false)) && owner->getPosition(p))
     448                ch->receiveSet(vec, &p, getCreature(), args[0].getDouble());
     449        ret->setObject(vec->makeObject());
    442450}
    443451
    444452void NeuroSignals::p_receiveSingle(PARAMPROCARGS)
    445453{
    446 SigChannel *ch; Pt3D p;
    447 if (owner->owner->channels && (ch=owner->owner->channels->getChannel(args[1].getString(),false)) && owner->getPosition(p))
    448         {
    449         SigSource *src=ch->receiveSingle(&p,getCreature(),args[0].getDouble(),0,1e99);
    450         if (src)
     454        SigChannel *ch; Pt3D p;
     455        if (owner->owner->channels && (ch = owner->owner->channels->getChannel(args[1].getString(), false)) && owner->getPosition(p))
     456        {
     457                SigSource *src = ch->receiveSingle(&p, getCreature(), args[0].getDouble(), 0, 1e99);
     458                if (src)
    451459                {
    452                 src->setupObject(ret);
    453                 return;
     460                        src->setupObject(ret);
     461                        return;
    454462                }
    455463        }
    456 ret->setEmpty();
     464        ret->setEmpty();
    457465}
    458466#endif
     
    460468#ifndef SDK_WITHOUT_FRAMS
    461469extern ParamEntry creature_paramtab[];
    462 static Param creature_param(creature_paramtab,0);
     470static Param creature_param(creature_paramtab, 0);
    463471#endif
    464472
     
    466474{
    467475#ifndef SDK_WITHOUT_FRAMS
    468 CreatMechObject *cmo=(CreatMechObject *)neuro->owner->userdata[CreatMechObject::modeltags_id];
    469 return cmo->creature;
     476        CreatMechObject *cmo = (CreatMechObject *)neuro->owner->userdata[CreatMechObject::modeltags_id];
     477        return cmo->creature;
    470478#else
    471 return 0;
     479        return 0;
    472480#endif
    473481}
     
    476484{
    477485#ifndef SDK_WITHOUT_FRAMS
    478 ret->setObject(ExtObject(&creature_param,getCreature()));
     486        ret->setObject(ExtObject(&creature_param, getCreature()));
    479487#endif
    480488}
     
    483491{
    484492#ifndef SDK_WITHOUT_FRAMS
    485 Part *pa;
    486 if (pa=neuro->getPart())
    487         ret->setObject(ExtObject(&MechPart::getStaticParam(),((MechPart *)pa->userdata[CreatMechObject::modeltags_id])));
    488 else
    489         ret->setEmpty();
     493        Part *pa;
     494        if (pa = neuro->getPart())
     495                ret->setObject(ExtObject(&MechPart::getStaticParam(), ((MechPart *)pa->userdata[CreatMechObject::modeltags_id])));
     496        else
     497                ret->setEmpty();
    490498#endif
    491499}
     
    494502{
    495503#ifndef SDK_WITHOUT_FRAMS
    496 Joint *jo;
    497 if (jo=neuro->getJoint())
    498         ret->setObject(ExtObject(&MechJoint::getStaticParam(),((MechJoint*)jo->userdata[CreatMechObject::modeltags_id])));
    499 else
    500         ret->setEmpty();
     504        Joint *jo;
     505        if (jo = neuro->getJoint())
     506                ret->setObject(ExtObject(&MechJoint::getStaticParam(), ((MechJoint*)jo->userdata[CreatMechObject::modeltags_id])));
     507        else
     508                ret->setEmpty();
    501509#endif
    502510}
     
    505513{
    506514#ifndef SDK_WITHOUT_FRAMS
    507 Part *pa; Joint *jo;
    508 if (pa=neuro->getPart())
    509         {pos=((MechPart *)pa->userdata[CreatMechObject::modeltags_id])->p; return true;}
    510 if (jo=neuro->getJoint())
    511         {
    512         if (neuro->getClass()->getVisualHints() & NeuroClass::AtFirstPart)
    513                 pos=((MechPart*)jo->part1->userdata[CreatMechObject::modeltags_id])->p;
    514         else if (neuro->getClass()->getVisualHints() & NeuroClass::AtSecondPart)
    515                 pos=((MechPart*)jo->part2->userdata[CreatMechObject::modeltags_id])->p;
    516         else pos=(((MechPart*)jo->part1->userdata[CreatMechObject::modeltags_id])->p
    517                    +((MechPart*)jo->part2->userdata[CreatMechObject::modeltags_id])->p)/2;
    518         return true;
    519         }
    520 #endif
    521 return false;
     515        Part *pa; Joint *jo;
     516        if (pa = neuro->getPart())
     517        {
     518                pos = ((MechPart *)pa->userdata[CreatMechObject::modeltags_id])->p;
     519                return true;
     520        }
     521        if (jo = neuro->getJoint())
     522        {
     523                if (neuro->getClass()->getVisualHints() & NeuroClass::AtFirstPart)
     524                        pos = ((MechPart*)jo->part1->userdata[CreatMechObject::modeltags_id])->p;
     525                else if (neuro->getClass()->getVisualHints() & NeuroClass::AtSecondPart)
     526                        pos = ((MechPart*)jo->part2->userdata[CreatMechObject::modeltags_id])->p;
     527                else pos = (((MechPart*)jo->part1->userdata[CreatMechObject::modeltags_id])->p
     528                        + ((MechPart*)jo->part2->userdata[CreatMechObject::modeltags_id])->p) / 2;
     529                return true;
     530        }
     531#endif
     532        return false;
    522533}
    523534
    524535void NeuroImpl::get_position_x(ExtValue *ret)
    525 {Pt3D pos; if (getPosition(pos)) ret->setDouble(pos.x); else ret->setEmpty();}
     536{
     537        Pt3D pos;
     538        if (getPosition(pos)) ret->setDouble(pos.x); else ret->setEmpty();
     539}
    526540void NeuroImpl::get_position_y(ExtValue *ret)
    527 {Pt3D pos; if (getPosition(pos)) ret->setDouble(pos.y); else ret->setEmpty();}
     541{
     542        Pt3D pos;
     543        if (getPosition(pos)) ret->setDouble(pos.y); else ret->setEmpty();
     544}
    528545void NeuroImpl::get_position_z(ExtValue *ret)
    529 {Pt3D pos; if (getPosition(pos)) ret->setDouble(pos.z); else ret->setEmpty();}
     546{
     547        Pt3D pos;
     548        if (getPosition(pos)) ret->setDouble(pos.z); else ret->setEmpty();
     549}
    530550
    531551
    532552void NeuroImpl::createFieldsObject()
    533553{
    534 fields_param=new Param(paramentries?paramentries:(ParamEntry*)&empty_paramtab,this,"NeuroProperties");
    535 fields_object=new ExtObject(fields_param);
     554        fields_param = new Param(paramentries ? paramentries : (ParamEntry*)&empty_paramtab, this, "NeuroProperties");
     555        fields_object = new ExtObject(fields_param);
    536556}
    537557
    538558void NeuroImpl::get_fields(ExtValue *ret)
    539559{
    540 if (!fields_object)
    541         createFieldsObject();
    542 ret->setObject(*fields_object);
     560        if (!fields_object)
     561                createFieldsObject();
     562        ret->setObject(*fields_object);
    543563}
    544564
    545565void NeuroImpl::get_neurodef(ExtValue *ret)
    546566{
    547 ret->setObject(ExtObject(&Neuro::getStaticParam(),neuro));
     567        ret->setObject(ExtObject(&Neuro::getStaticParam(), neuro));
    548568}
    549569
     
    551571{
    552572#ifndef SDK_WITHOUT_FRAMS
    553 NeuroClassExt::makeStaticObject(ret,neuroclass);
     573        NeuroClassExt::makeStaticObject(ret, neuroclass);
    554574#endif
    555575}
     
    557577NeuroImpl::~NeuroImpl()
    558578{
    559 if (fields_param)
    560         {
    561         delete fields_param;
    562         delete fields_object;
    563         }
    564 }
     579        if (fields_param)
     580        {
     581                delete fields_param;
     582                delete fields_object;
     583        }
     584}
Note: See TracChangeset for help on using the changeset viewer.