Class: Crubyflie::Log

Inherits:
Object
  • Object
show all
Includes:
CRTPConstants, Logging
Defined in:
lib/crubyflie/crazyflie/log.rb

Overview

The logging facility class

This class is used to read packages received in the Logging port. It maintains a list of log blocks, which are conveniently added, or removed and for which logging is started or stopped. When a packet with new information for log block comes in, the block in question unpacks the data and triggers a callback.

In Crubyflie, the Log class includes all the functionality which is to be found in the Python library LogEntry class (start logging, add block etc) and the Crazyflie class (callbacks for intialization), so interfacing with Log should be done through this class primarily.

Unlike the original Pyhton library, there are no callbacks registered somewhere else or anything and functions being called from them. In turn, the Crazyflie class will queue all the logging requests in the @in_queue while a thread in the Logging class takes care of processing them and doing the appropiate. This saves us from registering callbacks in other places and from selecting which data we are to use here.

Constant Summary

Constants included from CRTPConstants

CRTPConstants::CMD_APPEND_BLOCK, CRTPConstants::CMD_CREATE_BLOCK, CRTPConstants::CMD_DELETE_BLOCK, CRTPConstants::CMD_RESET_LOGGING, CRTPConstants::CMD_START_LOGGING, CRTPConstants::CMD_STOP_LOGGING, CRTPConstants::CMD_TOC_ELEMENT, CRTPConstants::CMD_TOC_INFO, CRTPConstants::CRTP_PORTS, CRTPConstants::LOG_DATA_CHANNEL, CRTPConstants::LOG_SETTINGS_CHANNEL, CRTPConstants::PARAM_READ_CHANNEL, CRTPConstants::PARAM_WRITE_CHANNEL, CRTPConstants::TOC_CHANNEL, CRTPConstants::WAIT_PACKET_TIMEOUT

Instance Attribute Summary collapse

Instance Method Summary collapse

Methods included from Logging

logger, #logger, #logger=

Constructor Details

#initialize(crazyflie) ⇒ Log

Store the crazyflie, find the incoming packet queue for this facility and initialize a new TOC

Parameters:


176
177
178
179
180
181
182
# File 'lib/crubyflie/crazyflie/log.rb', line 176

def initialize(crazyflie)
    @log_blocks = {}
    @crazyflie = crazyflie
    @in_queue = crazyflie.crtp_queues[:logging]
    @toc = TOC.new(@crazyflie.cache_folder, LogTOCElement)
    @packet_reader_thread = nil
end

Instance Attribute Details

#log_blocksObject (readonly)

Returns the value of attribute log_blocks


172
173
174
# File 'lib/crubyflie/crazyflie/log.rb', line 172

def log_blocks
  @log_blocks
end

#tocObject (readonly)

Returns the value of attribute toc


172
173
174
# File 'lib/crubyflie/crazyflie/log.rb', line 172

def toc
  @toc
end

Instance Method Details

#[](block_id) ⇒ Object

Finds a log block by id

Parameters:

  • block_id (Integer)

    the block ID

Returns:

  • p


303
304
305
# File 'lib/crubyflie/crazyflie/log.rb', line 303

def [](block_id)
    @log_blocks[block_id]
end

#create_log_block(log_conf) ⇒ Integer

Creates a log block with the information from a configuration object.

Parameters:

  • log_conf (LogConf)

    Configuration for this block

Returns:

  • (Integer)

    block ID if things went well,


199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
# File 'lib/crubyflie/crazyflie/log.rb', line 199

def create_log_block(log_conf)
    start_packet_reader_thread() if !@packet_reader_thread
    block = LogBlock.new(log_conf.variables,
                         {:period => log_conf.period})
    block_id = block.ident
    @log_blocks[block_id] = block
    packet = packet_factory()
    packet.data = [CMD_CREATE_BLOCK, block_id]
    log_conf.variables.each do |var|
        if var.is_toc_variable?
            packet.data << var.stored_fetch_as
            packet.data << @toc[var.name].ident
        else
            bin_stored_fetch_as = [var.stored_fetch_as].pack('C')
            bin_address = [var.address].pack('L<')
            packet.data += bin_stored_fetch_as.unpack('C*')
            packet.data += bin_address.unpack('C*')
        end
    end
    logger.debug "Adding block #{block_id}"
    @crazyflie.send_packet(packet)
    return block_id
end

#delete_block(block_id) ⇒ Object

Sends the DELETE_BLOCK command to the Crazyflie for a given block. It fails silently if the block does not exist. To be called after #stop_logging.


260
261
262
263
264
265
266
# File 'lib/crubyflie/crazyflie/log.rb', line 260

def delete_block(block_id)
    block = @log_blocks.delete(block_id)
    return if !block
    packet = packet_factory()
    packet.data = [CMD_DELETE_BLOCK, block_id]
    @crazyflie.send_packet(packet)
end

#refresh_tocObject

Refreshes the TOC. TOC class implement this step synchronously so there is no need to provide callbacks or anything


186
187
188
189
190
191
192
193
# File 'lib/crubyflie/crazyflie/log.rb', line 186

def refresh_toc
    reset_packet = packet_factory()
    reset_packet.data = [CMD_RESET_LOGGING]
    port = Crazyflie::CRTP_PORTS[:logging]
    channel = TOC_CHANNEL
    @crazyflie.send_packet(reset_packet)
    @toc.fetch_from_crazyflie(@crazyflie, port, @in_queue)
end

#start_logging(block_id, &data_callback) ⇒ Object

Sends the START_LOGGING command for a given block. It should be called after #create_toc_log_block. This call will return immediately, but the provided block will be called regularly as logging data is received, until #stop_logging is issued for the same log Crazyflie. It fails silently if the block does not exist.

Parameters:

  • block_id (Integer)
  • data_callback (Proc)

    a block to be called everytime the log data is received.


233
234
235
236
237
238
239
240
241
242
243
# File 'lib/crubyflie/crazyflie/log.rb', line 233

def start_logging(block_id, &data_callback)
    block = @log_blocks[block_id]
    block.data_callback = data_callback
    return if !block
    start_packet_reader_thread() if !@packet_reader_thread
    packet = packet_factory()
    period = block.period
    packet.data = [CMD_START_LOGGING, block_id, period]
    logger.debug("Start logging on #{block_id} every #{period*10} ms")
    @crazyflie.send_packet(packet)
end

#start_packet_reader_threadObject

A thread that processes the queue of packets intended for this facility. Recommended to start it after TOC has been refreshed.


270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
# File 'lib/crubyflie/crazyflie/log.rb', line 270

def start_packet_reader_thread
    stop_packet_reader_thread()
    @packet_reader_thread = Thread.new do
        Thread.current.priority = -4
        loop do
            packet = @in_queue.pop() # block here if nothing is up
            # @todo align these two
            case packet.channel()
            when LOG_SETTINGS_CHANNEL
                handle_settings_packet(packet)
            when LOG_DATA_CHANNEL
                handle_logdata_packet(packet)
            when TOC_CHANNEL
                # We are refreshing TOC probably
                @in_queue << packet
                sleep 0.2
            else
                logger.debug("Log on #{packet.channel}. Cannot handle")
                ## in_queue << packet
            end
        end
    end
end

#stop_logging(block_id) ⇒ Object

Sends the STOP_LOGGING command to the crazyflie for a given block. It fails silently if the block does not exist.

Parameters:

  • block_id (Integer)

248
249
250
251
252
253
254
255
# File 'lib/crubyflie/crazyflie/log.rb', line 248

def stop_logging(block_id)
    block = @log_blocks[block_id]
    return if !block
    packet = packet_factory()
    packet.data = [CMD_STOP_LOGGING, block_id]
    logger.debug("Stop logging on #{block_id}")
    @crazyflie.send_packet(packet)
end

#stop_packet_reader_threadObject

Stop the facility's packet processing


295
296
297
298
# File 'lib/crubyflie/crazyflie/log.rb', line 295

def stop_packet_reader_thread
    @packet_reader_thread.kill() if @packet_reader_thread
    @packet_reader_thread = nil
end