Changeset 720 for cpp/frams/neuro
- Timestamp:
- 01/14/18 11:24:22 (7 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
cpp/frams/neuro/neuroimpl.cpp
r492 r720 1 1 // This file is a part of Framsticks SDK. http://www.framsticks.com/ 2 // Copyright (C) 1999-201 5Maciej Komosinski and Szymon Ulatowski.2 // Copyright (C) 1999-2018 Maciej Komosinski and Szymon Ulatowski. 3 3 // See LICENSE.txt for details. 4 4 … … 14 14 #endif 15 15 16 const int NeuroImpl::ENDDRAWING =-9999;17 const int NeuroImpl::MAXDRAWINGXY =0xffff;18 19 int NeuroNetImpl::mytags_id =0;16 const int NeuroImpl::ENDDRAWING = -9999; 17 const int NeuroImpl::MAXDRAWINGXY = 0xffff; 18 19 int NeuroNetImpl::mytags_id = 0; 20 20 21 21 ///////////////////////////////////////////////////////// 22 22 23 23 #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 }; 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 }; 32 32 #undef FIELDSTRUCT 33 33 34 34 NeuroNetConfig::NeuroNetConfig(NeuroFactory *fac) 35 :par(nncfg_paramtab, this),36 37 38 39 35 :par(nncfg_paramtab, this), 36 randominit(0.01), 37 nnoise(0), 38 touchrange(1), 39 factory(fac) 40 40 {} 41 41 … … 44 44 NeuroNetImpl::NeuroNetImpl(Model& model, NeuroNetConfig& conf 45 45 #ifdef NEURO_SIGNALS 46 , ChannelSpace *ch47 #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) 51 51 #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)); 102 108 } 103 109 104 110 void NeuroNetImpl::destroyNN(CALLBACKARGS) 105 111 { 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; 119 125 } 120 126 121 127 NeuroNetImpl::~NeuroNetImpl() 122 128 { 123 destroyNN(0,0);129 destroyNN(0, 0); 124 130 } 125 131 126 132 void NeuroNetImpl::simulateNeuroNet() 127 133 { 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 146 void NeuroNetImpl::simulateNeuroPhysics() 147 { 148 NeuroImpl *ni; 131 149 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(); 147 153 } 148 154 … … 151 157 void NeuroImpl::setChannelCount(int c) 152 158 { 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 173 void 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 181 void 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; 178 187 } 179 188 180 189 double NeuroImpl::getNewState(int channel) 181 190 { 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); 186 195 } 187 196 188 197 double NeuroImpl::getState(int channel) 189 198 { 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); 193 202 } 194 203 195 204 void NeuroImpl::commit() 196 205 { 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) 203 212 { 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; 208 217 } 209 218 } … … 212 221 int NeuroImpl::getInputChannelCount(int i) 213 222 { 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 230 double 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); 231 240 } 232 241 233 242 double NeuroImpl::getWeightedInputState(int i, int channel) 234 243 { 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); 244 253 } 245 254 246 255 double NeuroImpl::getInputSum(int startwith) 247 256 { 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; 254 263 } 255 264 256 265 double NeuroImpl::getWeightedInputSum(int startwith) 257 266 { 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; 265 274 } 266 275 267 276 void NeuroImpl::readParam() 268 277 { 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()); 276 284 } 277 285 278 286 Param& NeuroImpl::getStaticParam() 279 287 { 280 static Param p(neuroimpl_tab,0,"Neuro");281 return p;288 static Param p(neuroimpl_tab, 0, "Neuro"); 289 return p; 282 290 } 283 291 … … 291 299 292 300 #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),},301 ParamEntry 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), }, 337 345 #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, }, 342 350 }; 343 351 #undef FIELDSTRUCT 344 352 345 353 #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.",},354 ParamEntry 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.", }, 349 357 350 358 #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(""), 356 364 #undef FIELDSTRUCT 357 365 358 366 #define FIELDSTRUCT SignalSet 359 SIGNSETPAR_GET,360 SIGNSETPAR_SIZE,361 SIGNSETPAR_CLEAR,367 SIGNSETPAR_GET, 368 SIGNSETPAR_SIZE, 369 SIGNSETPAR_CLEAR, 362 370 #undef FIELDSTRUCT 363 {0,0,0,},364 }; 371 { 0, 0, 0, }, 372 }; 365 373 366 374 Param& NeuroSignals::getStaticParam() 367 375 { 368 static Param p(neurosignals_paramtab,0);369 return p;376 static Param p(neurosignals_paramtab, 0); 377 return p; 370 378 } 371 379 #endif 372 380 373 381 #ifdef NEURO_SIGNALS 374 class NeuroSigSource : public SigSource375 { 376 377 NeuroImpl* owner;378 379 NeuroSigSource(NeuroImpl *n,Creature *c):SigSource(0,c),owner(n) {}380 bool update();382 class NeuroSigSource : public SigSource 383 { 384 protected: 385 NeuroImpl* owner; 386 public: 387 NeuroSigSource(NeuroImpl *n, Creature *c) :SigSource(0, c), owner(n) {} 388 bool update(); 381 389 }; 382 390 383 391 bool NeuroSigSource::update() 384 392 { 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; 392 400 } 393 401 394 402 Creature *NeuroSignals::getCreature() 395 403 { 396 if (!cr)397 { 398 cr=owner->getCreature();399 } 400 return cr;404 if (!cr) 405 { 406 cr = owner->getCreature(); 407 } 408 return cr; 401 409 } 402 410 403 411 void NeuroSignals::p_add(PARAMPROCARGS) 404 412 { 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 else412 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); 415 423 } 416 424 417 425 void NeuroSignals::p_receive(PARAMPROCARGS) 418 426 { 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 else423 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); 424 432 } 425 433 426 434 void NeuroSignals::p_receiveFilter(PARAMPROCARGS) 427 435 { 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 else432 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); 433 441 } 434 442 435 443 void NeuroSignals::p_receiveSet(PARAMPROCARGS) 436 444 { 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()); 442 450 } 443 451 444 452 void NeuroSignals::p_receiveSingle(PARAMPROCARGS) 445 453 { 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) 451 459 { 452 src->setupObject(ret);453 return;460 src->setupObject(ret); 461 return; 454 462 } 455 463 } 456 ret->setEmpty();464 ret->setEmpty(); 457 465 } 458 466 #endif … … 460 468 #ifndef SDK_WITHOUT_FRAMS 461 469 extern ParamEntry creature_paramtab[]; 462 static Param creature_param(creature_paramtab, 0);470 static Param creature_param(creature_paramtab, 0); 463 471 #endif 464 472 … … 466 474 { 467 475 #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; 470 478 #else 471 return 0;479 return 0; 472 480 #endif 473 481 } … … 476 484 { 477 485 #ifndef SDK_WITHOUT_FRAMS 478 ret->setObject(ExtObject(&creature_param,getCreature()));486 ret->setObject(ExtObject(&creature_param, getCreature())); 479 487 #endif 480 488 } … … 483 491 { 484 492 #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 else489 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(); 490 498 #endif 491 499 } … … 494 502 { 495 503 #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 else500 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(); 501 509 #endif 502 510 } … … 505 513 { 506 514 #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; 522 533 } 523 534 524 535 void 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 } 526 540 void 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 } 528 545 void 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 } 530 550 531 551 532 552 void NeuroImpl::createFieldsObject() 533 553 { 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); 536 556 } 537 557 538 558 void NeuroImpl::get_fields(ExtValue *ret) 539 559 { 540 if (!fields_object)541 createFieldsObject();542 ret->setObject(*fields_object);560 if (!fields_object) 561 createFieldsObject(); 562 ret->setObject(*fields_object); 543 563 } 544 564 545 565 void NeuroImpl::get_neurodef(ExtValue *ret) 546 566 { 547 ret->setObject(ExtObject(&Neuro::getStaticParam(),neuro));567 ret->setObject(ExtObject(&Neuro::getStaticParam(), neuro)); 548 568 } 549 569 … … 551 571 { 552 572 #ifndef SDK_WITHOUT_FRAMS 553 NeuroClassExt::makeStaticObject(ret,neuroclass);573 NeuroClassExt::makeStaticObject(ret, neuroclass); 554 574 #endif 555 575 } … … 557 577 NeuroImpl::~NeuroImpl() 558 578 { 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.