X-Git-Url: https://oss.titaniummirror.com/gitweb/?a=blobdiff_plain;f=tos%2Flib%2Ftossim%2FCpmModelC.nc;h=f28895efb64df5e406e8aabaef6d9fb3eea03aaf;hb=b33b490271a59663a9363e47ef64f3ba0d39390f;hp=bfa4f60f9ba9098503e80d46167f0f071057420d;hpb=618c63a3bd6752cdd94d8511ffecaac79499283a;p=tinyos-2.x.git diff --git a/tos/lib/tossim/CpmModelC.nc b/tos/lib/tossim/CpmModelC.nc index bfa4f60f..f28895ef 100644 --- a/tos/lib/tossim/CpmModelC.nc +++ b/tos/lib/tossim/CpmModelC.nc @@ -24,11 +24,10 @@ /** * * CPM (closest-pattern matching) is a wireless noise simulation model - * based on statistical extraction from empirical noise data. - * This model provides far more precise - * software simulation environment by exploiting time-correlated noise - * characteristic and shadowing effect as well as path-loss model. For - * details, please refer to the paper + * based on statistical extraction from empirical noise data. This + * model provides far more precise software simulation environment by + * exploiting time-correlated noise characteristics. For details, + * please refer to the paper * * "Improving Wireless Simulation through Noise Modeling." HyungJune * Lee and Philip Levis, IPSN 2007. You can find a copy at @@ -59,6 +58,8 @@ implementation { sim_time_t start; sim_time_t end; double power; + double reversePower; + int8_t strength; bool lost; bool ack; message_t* msg; @@ -68,8 +69,14 @@ implementation { receive_message_t* outstandingReceptionHead = NULL; receive_message_t* allocate_receive_message(); + void free_receive_message(receive_message_t* msg); sim_event_t* allocate_receive_event(sim_time_t t, receive_message_t* m); + bool shouldReceive(double SNR); + bool checkReceive(receive_message_t* msg); + double packetNoise(receive_message_t* msg); + double checkPrr(receive_message_t* msg); + double timeInMs() { sim_time_t ftime = sim_time(); int hours, minutes, seconds; @@ -120,7 +127,7 @@ implementation { else { noise_val = (double)sim_noise_generate(node_id, quotient); } - dbg("CpmModelC", "OUT: noise_hash_generation()\n"); + dbg("CpmModelC,Tal", "%s: OUT: noise_hash_generation(): %lf\n", sim_time_string(), noise_val); return noise_val; } @@ -131,10 +138,52 @@ implementation { return (signalStr - noise); } + double arr_estimate_from_snr(double SNR) { + double beta1 = 1.3687; + double beta2 = 0.9187; + double SNR_lin = pow(10.0, SNR/10.0); + double X = fabs(SNR_lin-beta2); + double PSE = 0.5*erfc(beta1*sqrt(X/2)); + double prr_hat = pow(1-PSE, 23*2); + dbg("CpmModelC,SNRLoss", "SNR is %lf, ARR is %lf\n", SNR, prr_hat); + if (prr_hat > 1) + prr_hat = 1; + else if (prr_hat < 0) + prr_hat = 0; + + return prr_hat; + } + + int shouldAckReceive(double snr) { + double prr = arr_estimate_from_snr(snr); + double coin = RandomUniform(); + if ( (prr != 0) && (prr != 1) ) { + if (coin < prr) + prr = 1.0; + else + prr = 0.0; + } + return (int)prr; + } + void sim_gain_ack_handle(sim_event_t* evt) { - if (outgoing != NULL && requestAck && sim_mote_is_on(sim_node())) { - signal Model.acked(outgoing); + // Four conditions must hold for an ack to be issued: + // 1) Transmitter is still sending a packet (i.e., not cancelled) + // 2) The packet requested an acknowledgment + // 3) The transmitter is on + // 4) The packet passes the SNR/ARR curve + if (requestAck && // This + outgoing != NULL && + sim_mote_is_on(sim_node())) { + receive_message_t* rcv = (receive_message_t*)evt->data; + double power = rcv->reversePower; + double noise = packetNoise(rcv); + double snr = power - noise; + if (shouldAckReceive(snr)) { + signal Model.acked(outgoing); + } } + free_receive_message((receive_message_t*)evt->data); } sim_event_t receiveEvent; @@ -151,18 +200,21 @@ implementation { } command bool Model.clearChannel() { - dbg("CpmModelC", "Checking clear channel @ %s: %f <= %f \n", sim_time_string(), (double)noise_hash_generation(), clearThreshold); - return noise_hash_generation() < clearThreshold; + dbg("CpmModelC", "Checking clear channel @ %s: %f <= %f \n", sim_time_string(), (double)packetNoise(NULL), clearThreshold); + return packetNoise(NULL) < clearThreshold; } - void sim_gain_schedule_ack(int source, sim_time_t t) { + void sim_gain_schedule_ack(int source, sim_time_t t, receive_message_t* r) { sim_event_t* ackEvent = (sim_event_t*)malloc(sizeof(sim_event_t)); + ackEvent->mote = source; ackEvent->force = 1; ackEvent->cancelled = 0; ackEvent->time = t; ackEvent->handle = sim_gain_ack_handle; ackEvent->cleanup = sim_queue_cleanup_event; + ackEvent->data = r; + sim_queue_insert(ackEvent); } @@ -173,7 +225,7 @@ implementation { double X = fabs(SNR_lin-beta2); double PSE = 0.5*erfc(beta1*sqrt(X/2)); double prr_hat = pow(1-PSE, 23*2); - dbg("CpmModelC", "SNR is %lf, PRR is %lf\n", SNR, prr_hat); + dbg("CpmModelC,SNR", "SNR is %lf, PRR is %lf\n", SNR, prr_hat); if (prr_hat > 1) prr_hat = 1; else if (prr_hat < 0) @@ -227,6 +279,9 @@ implementation { } + /* Handle a packet reception. If the packet is being acked, + pass the corresponding receive_message_t* to the ack handler, + otherwise free it. */ void sim_gain_receive_handle(sim_event_t* evt) { receive_message_t* mine = (receive_message_t*)evt->data; receive_message_t* predecessor = NULL; @@ -248,14 +303,19 @@ implementation { else { dbgerror("CpmModelC", "Incoming packet list structure is corrupted: entry is not the head and no entry points to it.\n"); } - + dbg("CpmModelC,SNRLoss", "Packet from %i to %i\n", (int)mine->source, (int)sim_node()); if (!checkReceive(mine)) { - dbg("CpmModelC", "Lost packet as SNR was too low.\n"); + dbg("CpmModelC,SNRLoss", " - lost packet from %i as SNR was too low.\n", (int)mine->source); mine->lost = 1; } - if (!mine->lost) { - dbg_clear("CpmModelC", " -signaling reception, "); + // Copy this receiver's packet signal strength to the metadata region + // of the packet. Note that this packet is actually shared across all + // receivers: a higher layer performs the copy. + tossim_metadata_t* meta = (tossim_metadata_t*)(&mine->msg->metadata); + meta->strength = mine->strength; + + dbg_clear("CpmModelC,SNRLoss", " -signaling reception\n"); signal Model.receive(mine->msg); if (mine->ack) { dbg_clear("CpmModelC", " acknowledgment requested, "); @@ -266,32 +326,53 @@ implementation { // If we scheduled an ack, receiving = 0 when it completes if (mine->ack && signal Model.shouldAck(mine->msg)) { dbg_clear("CpmModelC", " scheduling ack.\n"); - sim_gain_schedule_ack(mine->source, sim_time() + 1); + sim_gain_schedule_ack(mine->source, sim_time() + 1, mine); + } + else { // Otherwise free the receive_message_t* + free_receive_message(mine); } // We're searching for new packets again receiving = 0; } // If the packet was lost, then we're searching for new packets again else { + if (RandomUniform() < 0.001) { + dbg("CpmModelC,SNRLoss", "Packet was technically lost, but TOSSIM introduces an ack false positive rate.\n"); + if (mine->ack && signal Model.shouldAck(mine->msg)) { + dbg_clear("CpmModelC", " scheduling ack.\n"); + sim_gain_schedule_ack(mine->source, sim_time() + 1, mine); + } + else { // Otherwise free the receive_message_t* + free_receive_message(mine); + } + } + else { + free_receive_message(mine); + } receiving = 0; - dbg_clear("CpmModelC", " -packet was lost.\n"); + dbg_clear("CpmModelC,SNRLoss", " -packet was lost.\n"); } - free(mine); } // Create a record that a node is receiving a packet, // enqueue a receive event to figure out what happens. - void enqueue_receive_event(int source, sim_time_t endTime, message_t* msg, bool receive, double power) { + void enqueue_receive_event(int source, sim_time_t endTime, message_t* msg, bool receive, double power, double reversePower) { sim_event_t* evt; + receive_message_t* list; receive_message_t* rcv = allocate_receive_message(); double noiseStr = packetNoise(rcv); rcv->source = source; rcv->start = sim_time(); rcv->end = endTime; rcv->power = power; + rcv->reversePower = reversePower; + // The strength of a packet is the sum of the signal and noise. In most cases, this means + // the signal. By sampling this here, it assumes that the packet RSSI is sampled at + // the beginning of the packet. This is true for the CC2420, but is not true for all + // radios. But generalizing seems like complexity for minimal gain at this point. + rcv->strength = (int8_t)(floor(10.0 * log(pow(10.0, power/10.0) + pow(10.0, noiseStr/10.0)) / log(10.0))); rcv->msg = msg; rcv->lost = 0; rcv->ack = receive; - // If I'm off, I never receive the packet, but I need to keep track of // it in case I turn on and someone else starts sending me a weaker // packet. So I don't set receiving to 1, but I keep track of @@ -302,29 +383,42 @@ implementation { rcv->lost = 1; } else if (!shouldReceive(power - noiseStr)) { + dbg("CpmModelC,SNRLoss", "Lost packet from %i to %i due to SNR being too low (%i)\n", source, sim_node(), (int)(power - noiseStr)); rcv->lost = 1; } else if (receiving) { + dbg("CpmModelC,SNRLoss", "Lost packet from %i due to %i being mid-reception\n", source, sim_node()); rcv->lost = 1; } else { receiving = 1; - rcv->next = outstandingReceptionHead; - outstandingReceptionHead = rcv; - evt = allocate_receive_event(endTime, rcv); - sim_queue_insert(evt); } + + list = outstandingReceptionHead; + while (list != NULL) { + if (!shouldReceive(list->power - rcv->power)) { + dbg("Gain,SNRLoss", "Going to lose packet from %i with signal %lf as am receiving a packet from %i with signal %lf\n", list->source, list->power, source, rcv->power); + list->lost = 1; + } + list = list->next; + } + + rcv->next = outstandingReceptionHead; + outstandingReceptionHead = rcv; + evt = allocate_receive_event(endTime, rcv); + sim_queue_insert(evt); + } - void sim_gain_put(int dest, message_t* msg, sim_time_t endTime, bool receive, double power) { + void sim_gain_put(int dest, message_t* msg, sim_time_t endTime, bool receive, double power, double reversePower) { int prevNode = sim_node(); dbg("CpmModelC", "Enqueing reception event for %i at %llu with power %lf.\n", dest, endTime, power); sim_set_node(dest); - enqueue_receive_event(prevNode, endTime, msg, receive, power); + enqueue_receive_event(prevNode, endTime, msg, receive, power, reversePower); sim_set_node(prevNode); } - command void Model.putOnAirTo(int dest, message_t* msg, bool ack, sim_time_t endTime, double power) { + command void Model.putOnAirTo(int dest, message_t* msg, bool ack, sim_time_t endTime, double power, double reversePower) { gain_entry_t* neighborEntry = sim_gain_first(sim_node()); requestAck = ack; outgoing = msg; @@ -332,7 +426,7 @@ implementation { while (neighborEntry != NULL) { int other = neighborEntry->mote; - sim_gain_put(other, msg, endTime, ack && (other == dest), power + sim_gain_value(sim_node(), other)); + sim_gain_put(other, msg, endTime, ack, power + sim_gain_value(sim_node(), other), reversePower + sim_gain_value(other, sim_node())); neighborEntry = sim_gain_next(neighborEntry); } } @@ -357,5 +451,8 @@ implementation { receive_message_t* allocate_receive_message() { return (receive_message_t*)malloc(sizeof(receive_message_t)); } - + + void free_receive_message(receive_message_t* msg) { + free(msg); + } }