Ejemplo n.º 1
0
    def __set_parameters(self, force, **kwargs):
        """Sends Sonar head command to set sonar properties.

        Only the parameters specified will be modified.

        If initialized, arguments are compared to current properties in order
        to see if sending the command is necessary.

        Args:
            force: Whether to force set parameters.
            See set().
        """
        rospy.logwarn("Setting parameters...")

        # Set and compare sonar properties.
        necessary = not self.has_cfg or self.no_params or force
        only_reverse = not necessary
        for key, value in kwargs.iteritems():
            if value is not None:
                if hasattr(self, key) and self.__getattribute__(key) != value:
                    self.__setattr__(key, value)
                    necessary = True
                    if key != "scanright":
                        only_reverse = False

        # Return if unnecessary.
        if not necessary:
            rospy.logwarn("Parameters are already set")
            return

        # Return if only switching the motor's direction is necessary.
        if only_reverse:
            rospy.logwarn("Only reversing direction")
            self.scanright = not self.scanright
            return self.reverse()

        # Log properties.
        rospy.loginfo("CONTINUOUS:  %s", self.continuous)
        rospy.loginfo("LEFT LIMIT:  %s rad", self.left_limit)
        rospy.loginfo("RIGHT LIMIT: %s rad", self.right_limit)
        rospy.loginfo("STEP SIZE:   %s rad", self.step)
        rospy.loginfo("N BINS:      %s", self.nbins)
        rospy.loginfo("RANGE:       %s m", self.range)
        rospy.loginfo("INVERTED:    %s", self.inverted)
        rospy.loginfo("AD HIGH:     %s dB", self.ad_high)
        rospy.loginfo("AD LOW:      %s dB", self.ad_low)
        rospy.loginfo("ADC 8 ON:    %s", self.adc8on)
        rospy.loginfo("GAIN:        %s%%", self.gain * 100)
        rospy.loginfo("MOTOR TIME:  %s us", self.mo_time)
        rospy.loginfo("CLOCKWISE:   %s", self.scanright)
        rospy.loginfo("SPEED:       %s m/s", self.speed)

        # This device is not Dual Channel so skip the “V3B” Gain Parameter
        # block: 0x01 for normal, 0x1D for extended V3B Gain Parameters.
        v3b = bitstring.pack("0x01")

        # Construct the HdCtrl bytes to control operation:
        #   Bit 0:  adc8on          0: 4-bit        1: 8-bit
        #   Bit 1:  cont            0: sector-scan  1: continuous
        #   Bit 2:  scanright       0: left         1: right
        #   Bit 3:  invert          0: upright      1: inverted
        #   Bit 4:  motoff          0: on           1: off
        #   Bit 5:  txoff           0: on           1: off (for testing)
        #   Bit 6:  spare           0: default      1: N/A
        #   Bit 7:  chan2           0: default      1: N/A
        #   Bit 8:  raw             0: N/A          1: default
        #   Bit 9:  hasmot          0: lol          1: has a motor (always)
        #   Bit 10: applyoffset     0: default      1: heading offset
        #   Bit 11: pingpong        0: default      1: side-scanning sonar
        #   Bit 12: stareLLim       0: default      1: N/A
        #   Bit 13: ReplyASL        0: N/A          1: default
        #   Bit 14: ReplyThr        0: default      1: N/A
        #   Bit 15: IgnoreSensor    0: default      1: emergencies
        hd_ctrl = bitstring.pack("0b001000110000, bool, bool, bool, bool",
                                 self.inverted, self.scanright,
                                 self.continuous, self.adc8on)
        hd_ctrl.byteswap()  # Little endian please.

        # Set the sonar type: 0x11 for DST.
        hd_type = bitstring.pack("0x11")

        # TX/RX transmitter constants: N/A to DST so fill with 15 zero bytes.
        # TX pulse length: N/A to DST so fill with 2 zero bytes.
        tx_rx = bitstring.BitStream(144)

        # Range scale does not control the sonar, only provides a way to note
        # the current settings in a human readable format.
        # The lower 14 bits are the range scale * 10 units and the higher 2
        # bits are coded units:
        #   0: meters
        #   1: feet
        #   2: fathoms
        #   3: yards
        # Only the metric system is implemented for now, because it is better.
        range_scale = bitstring.pack("uintle:16", int(self.range * 10))

        # Left/right angles limits are in 1/16th of a gradian.
        _left_angle = to_sonar_angles(self.left_limit)
        _right_angle = to_sonar_angles(self.right_limit)
        left_limit = bitstring.pack("uintle:16", _left_angle)
        right_limit = bitstring.pack("uintle:16", _right_angle)

        # Set the mapping of the received sonar echo amplitudes.
        # If the ADC is set to 8-bit, MAX = 255 else MAX = 15.
        # ADLow = MAX * low / 80 where low is the desired minimum amplitude.
        # ADSpan = MAX * range / 80 where range is the desired amplitude range.
        # The full range is between ADLow and ADLow + ADSpan.
        MAX_SIZE = 255 if self.adc8on else 15
        ad_low = bitstring.pack("uint:8", int(MAX_SIZE * self.ad_low / 80))
        _ad_diff = self.ad_high - self.ad_low
        ad_span = bitstring.pack("uint:8", int(MAX_SIZE * _ad_diff / 80))

        # Set the initial gain of each channel of the sonar receiver.
        # The gain ranges from 0 to 210.
        _mapped_gain = int(self.gain * 210)
        gain = bitstring.pack("uint:8, uint:8", _mapped_gain, _mapped_gain)

        # Slope setting is N/A to DST: fill 4 bytes with zeroes.
        slope = bitstring.BitStream(32)

        # Set the high speed limit of the motor in units of 10 microseconds.
        mo_time = bitstring.pack("uint:8", int(self.mo_time / 10))

        # Set the step angle size in 1/16th of a gradian.
        #   32: low resolution
        #   16: medium resolution
        #   8:  high resolution
        #   4:  ultimate resolution
        _step_size = to_sonar_angles(self.step)
        step = bitstring.pack("uint:8", _step_size)

        # ADInterval defines the sampling interval of each bin and is in units
        # of 640 nanoseconds.
        nbins = bitstring.pack("uintle:16", self.nbins)
        _interval = 2 * self.range / self.speed / self.nbins / 640e-9
        _interval = _interval + 1 if _interval % 2 else _interval
        ad_interval = bitstring.pack("uintle:16", int(_interval))

        # Factory defaults. Don't ask.
        max_ad_buf = bitstring.pack("uintle:16", 500)
        lockout = bitstring.pack("uintle:16", 100)
        minor_axis = bitstring.pack("uintle:16", 1600)
        major_axis = bitstring.pack("uint:8", 1)

        # Ctl2 is for testing.
        ctl2 = bitstring.pack("uint:8", 0)

        # Special devices setting. Should be left blank.
        scanz = bitstring.pack("uint:8, uint:8", 0, 0)

        # Order and construct bitstream.
        bitstream = (v3b, hd_ctrl, hd_type, tx_rx, range_scale, left_limit,
                     right_limit, ad_span, ad_low, gain, slope, mo_time, step,
                     ad_interval, nbins, max_ad_buf, lockout, minor_axis,
                     major_axis, ctl2, scanz)
        payload = bitstring.BitStream()
        for chunk in bitstream:
            payload.append(chunk)

        self.send(Message.HEAD_COMMAND, payload)
        rospy.logwarn("Parameters are sent")
Ejemplo n.º 2
0
    def __set_parameters(self, force, **kwargs):
        """Sends Sonar head command to set sonar properties.

        Only the parameters specified will be modified.

        If initialized, arguments are compared to current properties in order
        to see if sending the command is necessary.

        Args:
            force: Whether to force set parameters.
            See set().
        """
        rospy.logwarn("Setting parameters...")

        # Set and compare sonar properties.
        necessary = not self.has_cfg or self.no_params or force
        only_reverse = not necessary
        for key, value in kwargs.iteritems():
            if value is not None:
                if hasattr(self, key) and self.__getattribute__(key) != value:
                    self.__setattr__(key, value)
                    necessary = True
                    if key != "scanright":
                        only_reverse = False

        # Return if unnecessary.
        if not necessary:
            rospy.logwarn("Parameters are already set")
            return

        # Return if only switching the motor's direction is necessary.
        if only_reverse:
            rospy.logwarn("Only reversing direction")
            self.scanright = not self.scanright
            return self.reverse()

        # Log properties.
        rospy.loginfo("CONTINUOUS:  %s", self.continuous)
        rospy.loginfo("LEFT LIMIT:  %s rad", self.left_limit)
        rospy.loginfo("RIGHT LIMIT: %s rad", self.right_limit)
        rospy.loginfo("STEP SIZE:   %s rad", self.step)
        rospy.loginfo("N BINS:      %s", self.nbins)
        rospy.loginfo("RANGE:       %s m", self.range)
        rospy.loginfo("INVERTED:    %s", self.inverted)
        rospy.loginfo("AD HIGH:     %s dB", self.ad_high)
        rospy.loginfo("AD LOW:      %s dB", self.ad_low)
        rospy.loginfo("ADC 8 ON:    %s", self.adc8on)
        rospy.loginfo("GAIN:        %s%%", self.gain * 100)
        rospy.loginfo("MOTOR TIME:  %s us", self.mo_time)
        rospy.loginfo("CLOCKWISE:   %s", self.scanright)
        rospy.loginfo("SPEED:       %s m/s", self.speed)

        # This device is not Dual Channel so skip the “V3B” Gain Parameter
        # block: 0x01 for normal, 0x1D for extended V3B Gain Parameters.
        v3b = bitstring.pack("0x01")

        # Construct the HdCtrl bytes to control operation:
        #   Bit 0:  adc8on          0: 4-bit        1: 8-bit
        #   Bit 1:  cont            0: sector-scan  1: continuous
        #   Bit 2:  scanright       0: left         1: right
        #   Bit 3:  invert          0: upright      1: inverted
        #   Bit 4:  motoff          0: on           1: off
        #   Bit 5:  txoff           0: on           1: off (for testing)
        #   Bit 6:  spare           0: default      1: N/A
        #   Bit 7:  chan2           0: default      1: N/A
        #   Bit 8:  raw             0: N/A          1: default
        #   Bit 9:  hasmot          0: lol          1: has a motor (always)
        #   Bit 10: applyoffset     0: default      1: heading offset
        #   Bit 11: pingpong        0: default      1: side-scanning sonar
        #   Bit 12: stareLLim       0: default      1: N/A
        #   Bit 13: ReplyASL        0: N/A          1: default
        #   Bit 14: ReplyThr        0: default      1: N/A
        #   Bit 15: IgnoreSensor    0: default      1: emergencies
        hd_ctrl = bitstring.pack(
            "0b001000110000, bool, bool, bool, bool",
            self.inverted, self.scanright, self.continuous, self.adc8on
        )
        hd_ctrl.byteswap()  # Little endian please.

        # Set the sonar type: 0x11 for DST.
        hd_type = bitstring.pack("0x11")

        # TX/RX transmitter constants: N/A to DST so fill with 15 zero bytes.
        # TX pulse length: N/A to DST so fill with 2 zero bytes.
        tx_rx = bitstring.BitStream(144)

        # Range scale does not control the sonar, only provides a way to note
        # the current settings in a human readable format.
        # The lower 14 bits are the range scale * 10 units and the higher 2
        # bits are coded units:
        #   0: meters
        #   1: feet
        #   2: fathoms
        #   3: yards
        # Only the metric system is implemented for now, because it is better.
        range_scale = bitstring.pack("uintle:16", int(self.range * 10))

        # Left/right angles limits are in 1/16th of a gradian.
        _left_angle = to_sonar_angles(self.left_limit)
        _right_angle = to_sonar_angles(self.right_limit)
        left_limit = bitstring.pack("uintle:16", _left_angle)
        right_limit = bitstring.pack("uintle:16", _right_angle)

        # Set the mapping of the received sonar echo amplitudes.
        # If the ADC is set to 8-bit, MAX = 255 else MAX = 15.
        # ADLow = MAX * low / 80 where low is the desired minimum amplitude.
        # ADSpan = MAX * range / 80 where range is the desired amplitude range.
        # The full range is between ADLow and ADLow + ADSpan.
        MAX_SIZE = 255 if self.adc8on else 15
        ad_low = bitstring.pack("uint:8", int(MAX_SIZE * self.ad_low / 80))
        _ad_diff = self.ad_high - self.ad_low
        ad_span = bitstring.pack("uint:8", int(MAX_SIZE * _ad_diff / 80))

        # Set the initial gain of each channel of the sonar receiver.
        # The gain ranges from 0 to 210.
        _mapped_gain = int(self.gain * 210)
        gain = bitstring.pack("uint:8, uint:8", _mapped_gain, _mapped_gain)

        # Slope setting is N/A to DST: fill 4 bytes with zeroes.
        slope = bitstring.BitStream(32)

        # Set the high speed limit of the motor in units of 10 microseconds.
        mo_time = bitstring.pack("uint:8", int(self.mo_time / 10))

        # Set the step angle size in 1/16th of a gradian.
        #   32: low resolution
        #   16: medium resolution
        #   8:  high resolution
        #   4:  ultimate resolution
        _step_size = to_sonar_angles(self.step)
        step = bitstring.pack("uint:8", _step_size)

        # ADInterval defines the sampling interval of each bin and is in units
        # of 640 nanoseconds.
        nbins = bitstring.pack("uintle:16", self.nbins)
        _interval = 2 * self.range / self.speed / self.nbins / 640e-9
        _interval = _interval + 1 if _interval % 2 else _interval
        ad_interval = bitstring.pack("uintle:16", int(_interval))

        # Factory defaults. Don't ask.
        max_ad_buf = bitstring.pack("uintle:16", 500)
        lockout = bitstring.pack("uintle:16", 100)
        minor_axis = bitstring.pack("uintle:16", 1600)
        major_axis = bitstring.pack("uint:8", 1)

        # Ctl2 is for testing.
        ctl2 = bitstring.pack("uint:8", 0)

        # Special devices setting. Should be left blank.
        scanz = bitstring.pack("uint:8, uint:8", 0, 0)

        # Order and construct bitstream.
        bitstream = (
            v3b, hd_ctrl, hd_type, tx_rx, range_scale, left_limit, right_limit,
            ad_span, ad_low, gain, slope, mo_time, step, ad_interval, nbins,
            max_ad_buf, lockout, minor_axis, major_axis, ctl2, scanz
        )
        payload = bitstring.BitStream()
        for chunk in bitstream:
            payload.append(chunk)

        self.send(Message.HEAD_COMMAND, payload)
        rospy.logwarn("Parameters are sent")
Ejemplo n.º 3
0
    def __set_parameters(self, force, **kwargs):
        """
        Sends Sonar head command to set sonar properties. This function is called
        by ``set()`` method. See ``set()`` method for more information

        Only the parameters specified will be modified.

        If initialized, arguments are compared to current properties in order
        to see if sending the command is necessary.

        :param force: Whether to force set parameters.
        """
        rospy.logwarn("Setting parameters...")

        # Set and compare sonar properties.
        necessary = not self.has_cfg or self.no_params or force
        only_reverse = not necessary
        for key, value in kwargs.iteritems():
            if value is not None:
                if hasattr(self, key) and self.__getattribute__(key) != value:
                    self.__setattr__(key, value)
                    necessary = True
                    if key != "scanright":
                        only_reverse = False


        # Return if unnecessary.
        if not necessary:
            rospy.logwarn("Parameters are already set")
            return

        port_enabled = kwargs.get('port_enabled')
        self.port_enabled = port_enabled
        self.conn.port_enabled = port_enabled
        print ('cambiando port enabled', port_enabled, self.port_enabled)


        # if port_enabled:
        #     self.port_enabled = True
        #
        # else:
        #     self.port_enabled = False

        #self.port_enabled = True


        self.port = kwargs.get('profiler_port')
        self.baudrate = kwargs.get('profiler_port_baudrate')

        # Return if only switching the motor's direction is necessary.
        if only_reverse:
            rospy.logwarn("Only reversing direction")
            self.scanright = not self.scanright
            return self.reverse()

        # self.left_limit = to_radians(16)
        #
        # self.range = 1.00
        # self.right_limit = to_radians(16)
        # self.scanright = True
        # self.step = Resolution.ULTIMATE

        # Log properties.
        rospy.loginfo("PRF Alternate scan:   %s", self.prf_alt)
        rospy.loginfo("LEFT LIMIT:           %s rad", self.left_limit)
        rospy.loginfo("RIGHT LIMIT:          %s rad", self.right_limit)
        rospy.loginfo("STEP SIZE:            %s rad", self.step)
        rospy.loginfo("RANGE:                %s m", self.range)
        rospy.loginfo("INVERTED:             %s", self.inverted)
        rospy.loginfo("ADC THRESHOLD:        %s ", self.adc_threshold)
        rospy.loginfo("LOCKOUT:              %s%%", self.lockout)
        rospy.loginfo("ADAPTIVE GAIN CONTROL %s", self.agc)
        rospy.loginfo("GAIN:                 %s%%", self.gain * 100)
        rospy.loginfo("MOTOR TIME:           %s us", self.mo_time)
        rospy.loginfo("CLOCKWISE:            %s", self.scanright)
        rospy.loginfo("SPEED:                %s m/s", self.speed)
        rospy.loginfo("PORT ENABLED:         %s", self.port_enabled)
        rospy.loginfo("PORT:                 %s", self.port)
        rospy.loginfo("BAUDRATE:             %s bauds", self.baudrate)

        # This device is not Dual Channel so skip the “V3B” Gain Parameter
        # block: 0x01 for normal, 0x1D for extended V3B Gain Parameters.
        v3b = bitstring.pack("0x1D")

        # Construct the HdCtrl bytes to control operation:
        #   Bit 0:  prf_AGC         0: AGC off(def) 1: AGC On
        #   Bit 1:  prf_alt         0: continuous   1: alternating scan
        #   Bit 2:  scanright       0: left         1: right
        #   Bit 3:  invert          0: upright      1: inverted
        #   Bit 4:  motoff          0: on           1: off
        #   Bit 5:  txoff           0: on           1: off (for testing)
        #   Bit 6:  prf_t10         0: default      1: N/A
        #   Bit 7:  chan2           0: default      1: N/A
        #   Bit 8:  prf_first       0: N/A          1: default
        #   Bit 9:  hasmot          0: lol          1: has a motor (always)
        #   Bit 10: prf_PingSync    0: no sync      1: Ping Sync control on, default
        #   Bit 11: prf_ScanSync    0: default      1: use when dual head profiler
        #   Bit 12: stareLLim       0: default      1: N/A
        #   Bit 13: prf_Master      0: N/A          1: default for single profiler
        #   Bit 14: prf_Mirror      0: default      1: N/A
        #   Bit 15: IgnoreSensor    0: default      1: emergencies
        # hd_ctrl = bitstring.pack(
        #     "0b001000110000, bool, bool, bool, bool",
        #     self.inverted, self.scanright, self.prf_alt, self.agc
        # )
        # hd_ctrl = bitstring.pack(
        #     "0b 0010 1111 0000, bool, bool, bool, bool",
        #     self.inverted, self.scanright, self.prf_alt, self.agc
        # )
        hd_ctrl = bitstring.pack(
            "0b 011000111000, bool, bool, bool, bool",
            self.inverted, self.scanright, self.prf_alt, self.agc
        )

        hd_ctrl.byteswap()  # Little endian please.

        # Set the sonar type: 0x05 for Profiler.
        # Profiler allows also Imaging functionality (0x02)
        hd_type = bitstring.pack("0x05")

        # TX/RX transmitter constants:
        # f = transmitter frequency in Hertz

        f_txrx_ch1 = 600000 # in Hz
        f_txrx_ch2 = 1100000 # in Hz

        TxN_ch1 = int(f_txrx_ch1*pow(2,32)/(32*pow(10,6))) # = 147639500

        TxN_ch2 = int(f_txrx_ch2 * pow(2, 32) / (32 * pow(10, 6))) #= 147639500

        RxN_ch1 = int((f_txrx_ch1 + 455000)*pow(2,32)/(32 * pow(10,6)))
        RxN_ch2 = int((f_txrx_ch2 + 455000)*pow(2,32)/(32 * pow(10,6)))


        # TX pulse length: length of sonar pulse in microseconds. Variable with rangescale
        # use default ofs and mul
        Ofs = 10
        Mul = 25
        TxPulseLen = (self.range + Ofs)*Mul/10

        # Packing Tx/Rx constants and  TX pulse length
        tx_rx = bitstring.pack('uintle:32,uintle:32,uintle:32,uintle:32,uintle:16',
                                TxN_ch1, TxN_ch2, RxN_ch1, RxN_ch2, TxPulseLen)


        # Range scale does not control the sonar, only provides a way to note
        # the current settings in a human readable format.
        # The lower 14 bits are the range scale * 10 units and the higher 2
        # bits are coded units:
        #   0: meters
        #   1: feet
        #   2: fathoms
        #   3: yards
        # Only the metric system is implemented for now, because it is better.
        range_scale = bitstring.pack("uintle:16", int(self.range * 10))

        # Left/right angles limits are in 1/16th of a gradian.
        _left_angle = to_sonar_angles(self.left_limit)
        _right_angle = to_sonar_angles(self.right_limit)
        left_limit = bitstring.pack("uintle:16", _left_angle)
        right_limit = bitstring.pack("uintle:16", _right_angle)

        # The ADC Threshold sets the analogue threshold level on the receiver and controls
        # the sensitive of the profiler. Higher threshold makes the device less sensitive
        # Default value for Seaking Profiler is 50
        adc_threshold = bitstring.pack("uint:8", int(50))

        # This is the level of Adaptive Gain Control (%) that is applied to the receiver.
        # For SeaKing Profilers use default of 20
        filt_gain = bitstring.pack("uint:8", int(20))


        # Set the initial gain of each channel of the sonar receiver.
        # The gain ranges from 0 to 210.
        AGC_Max = int(self.gain * 210)
        AGC_SetPoint = 189 # default value = 90, but Seanet sends this value...
        AGC_args = bitstring.pack("uint:8, uint:8",AGC_Max, AGC_SetPoint)
        #

        # Slope setting is according to the sonar frequency
        # The equation is slope = (f*7/1000+11560)/142
        _slope_ch1 = (f_txrx_ch1*7/1000+11560)/142
        _slope_ch2 = (f_txrx_ch2*7/1000+11560)/142
        slope = bitstring.pack('uintle:16, uintle:16', _slope_ch1,_slope_ch2)

        # Set the high speed limit of the motor in units of 10 microseconds.
        mo_time = bitstring.pack("uint:8", int(self.mo_time / 10))

        # Set the step angle size in 1/16th of a gradian.
        #   32: low resolution
        #   24: medium resolution
        #   16:  high resolution
        #   8:  ultimate resolution
        _step_size = to_sonar_angles(self.step)
        step = bitstring.pack("uint:8", _step_size)

        # ScanTime in 10 ms units.
        nbins = bitstring.pack("uintle:16", self.nbins)
        #_interval = 2 * self.range * self.nbins/ self.speed / 10e-3
        #_interval = _interval + 1 if _interval % 2 else _interval
        _interval = 30 # Seanet as well
        ScanTime = bitstring.pack("uintle:16", int(_interval))

        # Spare bytes, fill with zero
        PrfSp1 = bitstring.pack('uintle:16', 0)

        # Controls for special operation. Normally set to zero
        PrfCtl2 = bitstring.pack('uintle:16', 0)

        # Factory defaults. Don't ask.

        lockout = bitstring.pack("uintle:16", self.lockout)
        minor_axis = bitstring.pack("uintle:16", 1600)
        major_axis = bitstring.pack("uint:8", 1)

        # Ctl2 is for testing.
        ctl2 = bitstring.pack("uint:8", 0)

        # Special devices setting. Should be left blank.
        scanz = bitstring.pack("uint:8, uint:8", 0, 0)

        v3b_adth1     = bitstring.pack('uintle:8',self.adc_threshold)
        v3b_adth2     = bitstring.pack('uintle:8',self.adc_threshold)
        v3b_filtgain1 = bitstring.pack('0x01')
        v3b_filtgain2 = bitstring.pack('0x14')
        v3b_agcmax1   = bitstring.pack('uintle:8', AGC_Max)
        v3b_agcmax2   = bitstring.pack('uintle:8', AGC_Max)
        v3b_setpoint1 = bitstring.pack('uintle:8', AGC_SetPoint)
        v3b_setpoint2 = bitstring.pack('uintle:8', AGC_SetPoint)
        v3b_slope1    = bitstring.pack('uintle:16', _slope_ch1)
        v3b_slope2    = bitstring.pack('uintle:16', _slope_ch2)
        v3b_sloped1   = bitstring.pack('uintle:16', 0)
        v3b_sloped2   = bitstring.pack('uintle:16', 0)

        # Order and construct bitstream.
        bitstream = (
            v3b, hd_ctrl, hd_type, tx_rx, range_scale, left_limit, right_limit,
            adc_threshold, filt_gain, AGC_args, slope, mo_time, step, ScanTime, PrfSp1,
            PrfCtl2, lockout, minor_axis, major_axis, ctl2, scanz, v3b_adth1,
            v3b_adth2, v3b_filtgain1, v3b_filtgain2, v3b_agcmax1, v3b_agcmax2,
            v3b_setpoint1, v3b_setpoint2, v3b_slope1, v3b_slope2, v3b_sloped1,
            v3b_sloped2
        )

        payload = bitstring.BitStream()
        for chunk in bitstream:
            payload.append(chunk)

        if port_enabled :
            self.conn.conn.port = self.port
            self.conn.conn.baudrate = self.baudrate
            self.conn.open()
            self.send(Message.HEAD_COMMAND, payload)
            rospy.logwarn("Parameters are sent")
        elif not port_enabled and self.initialized:
            self.conn.close()

        # while not self.port_enabled:
        #     pass
        return hd_ctrl,hd_type,TxN_ch1,TxN_ch2,RxN_ch1,RxN_ch2,TxPulseLen,tx_rx,
        range_scale, left_limit,right_limit,adc_threshold,filt_gain,
        AGC_args,slope,mo_time,step,ScanTime,lockout,minor_axis,
        major_axis,payload