How to set copters Attitude via DroneKit -- SET_ATTITUDE_TARGET not working - dronekit-python

I have Dronekit working properly with SITL sim, however for my project I want to be able to command the attitude of the copter. Obviously I can do this via RC over ride in ALT_HOLD mode, however I don't like that approach.
I have been trying to use the Mavlink message SET_ATTITUDE_TARGET (#82), however when I send the messages to the sim, nothing happens. I have been able to set the velocity and the position, and those work fine.
Here is my function:
def att_msg_mode():
print "=========== Building Message"
veh1.mode = VehicleMode("ALT_HOLD")
msg = veh1.message_factory.set_attitude_target_encode(
0,
0, #target system
0, #target component
0b11100010, #type mask
[.9438,0,0,.17364], #q
0, #body roll rate
0, #body pitch rate
0, #body yaw rate
0) #thrust
time.sleep(1)
veh1.send_mavlink(msg)
veh1.flush()
print "=========== Message Sent"
Can someone help me out?

SET_ATTITUDE_TARGET is now available to be used in guided_mode.
You can even test it using mavproxy attitude command.

SET_ATTITUDE_TARGET is now implemented, and will be released with ArduCopter 3.4

It is not possible to set the attitude directly because the command is not supported by Copter in either guided mode or AUTO mode/missions). The list of supported commands in guided mode is here and AUTO commands here.
What you can do is set the yaw. Another (hacky) approach that may work is setting the ROI as this will point the camera (and often the whole vehicle) at a target.
This sounds like a reasonable requirement - perhaps create a request with explanation of why this is useful for you?

Related

BlueNRG Bluetooth: read central device name

I'm using the STM BlueNRG-MS chip on my peripheral device and after connection I'd like to read the name of the connected central device (android phone).
I thought I can do this directly in my user_notify routine which is registered as hci callback
/* Initialize the Host-Controller Interface */
hci_init(user_notify, NULL);
So on the EVT_LE_CONN_COMPLETE event, I take the provided handle for the central device and I use aci_gatt_read_using_charac_uuid() to read what I thought is the characteristic with the device name (uuid 0x2a00).
case EVT_LE_META_EVENT:
{
evt_le_meta_event *evt = (void *)event_pckt->data;
switch(evt->subevent){
case EVT_LE_CONN_COMPLETE:
{
evt_le_connection_complete *cc = (void *)evt->data;
GAP_ConnectionComplete_CB(cc->peer_bdaddr, cc->handle);
uint16_t uuid = 0x2a00;
resp = aci_gatt_read_using_charac_uuid(cc->handle, 0, 1, UUID_TYPE_16, (uint8_t*)&uuid);
LOG("GATT read status: %d", resp);
enqueEvent(EVENT_BLE_CONNECTED);
}
break;
}
}
Long story short, it doesn't work. First thing I'm not sure about is, what is the start_handle and end_handle parameter of aci_gatt_read_using_charac_uuid(), it returns ERR_INVALID_HCI_CMD_PARAMS.
Can someone shed some light here?
update
What also puzzles me is that the function aci_gatt_read_using_charac_uuid() is nowehere referenced in the BlueNRG-MS Programming Guidelines.
update2
I changed the function call to aci_gatt_read_using_charac_uuid(cc->handle, 0x0001, 0xffff, UUID_TYPE_16, (uint8_t*)&uuid); but I still get the ERR_INVALID_HCI_CMD_PARAMS. What which paramter could even be invalid? The uuid exists, I can read the device name if I use the BlueNRG GUI with a bluetooth dongle.
update3
Has anyone ever used this function or somehow managed to read a characteristic from a central device? I'd highly appreciate any help or hint.
Here you go, The BlueNRG-MS Bluetooth® LE stack application command interface (ACI) - User manual
page 75 - 4.6.25 Aci_Gatt_Read_Charac_Using_UUID()
and make sure you have called Aci_Gatt_Init()
The user manual is last revised July 2019, the document you link to is from 2018, don't know if this is why ?
The start_handle and end_handle is the range of handles in your service as pictured here -
Here is a discussion to the closest thing I could find to match your question.
As it turned out there are two bugs in the BlueNRG API.
In bluenrg_aci_const.h file the OCF code OCF_GATT_READ_USING_CHARAC_UUID shall be 0x119 instead of 0x109.
And in the implementation of the aci_gatt_read_using_charac_uuid() function, there is a missing setting on event:
rq.event = EVT_CMD_STATUS;
Patching them fixed the issue.

CANOPEN SYNC timeout after enable Operation

I am a newbie in CANOPEN. I wrote a program that read actual position via PDO1 (default is statusword + actual position).
void canopen_init() {
// code1 setup PDO mapping
nmtPreOperation();
disablePDO(PDO_TX1_CONFIG_COMM);
setTransmissionTypePDO(PDO_TX1_CONFIG_COMM, 1);
setInhibitTimePDO(PDO_TX1_CONFIG_COMM, 0);
setEventTimePDO(PDO_TX1_CONFIG_COMM, 0);
enablePDO(PDO_TX1_CONFIG_COMM);
setCyclePeriod(1000);
setSyncWindow(100);
//code 2: enable OPeration
readyToSwitchOn();
switchOn();
enableOperation();
motionStart();
// code 3
nmtActiveNode();
}
int main (void) {
canopen_init();
while {
delay_ms(1);
send_sync();
}
}
If I remove "code 2" (the servo is in Switch_on_disable status), i can read position each time sync send. But if i use "code 2", the driver has error "sync frame timeout". I dont know driver has problem or my code has problem. Does my code has problem? thank you!
I don't know what protocol stack this is or how it works, but these:
setCyclePeriod(1000);
setSyncWindow(100);
likely correspond to these OD entries :
Object 1006h: Communication cycle period (CiA 301 7.5.2.6)
Object 1007h: Synchronous window length (CiA 301 7.5.2.7)
They set the SYNC interval and time window for synchronous PDOs respectively. The latter is described by the standard as:
If the synchronous window length expires all synchronous TPDOs may be discarded and an EMCY message may be transmitted; all synchronous RPDOs may be discarded until the next SYNC message is received. Synchronous RPDO processing is resumed with the next SYNC message.
Now if you set this sync time window to 100us but have a sloppy busy-wait delay delay_ms(1), then that doesn't add up. If you write zero to Object 1007h, you disable the sync window feature. I suppose setSyncWindow(0); might do that. You can try to do that to see if that's the issue. If so, you have to drop your busy-wait in favour for proper hardware timers, one for the SYNC period and one for PDO timeout (if you must use that feature).
Problem fixed. Due to much EMI from servo, that make my controller didn't work properly. After isolating, it worked very well :)!

get_multiple_points volttron RPC call

Any chance I could get a tip for proper way to build an agent that could do read multiple points from multiple devices on a BACnet system? I am viewing the actuator agent code trying learn how to make the proper rpc call.
So going through the agent development procedure with the agent creation wizard.
In the init I have this just hard coded at the moment:
def __init__(self, **kwargs):
super(Setteroccvav, self).__init__(**kwargs)
_log.debug("vip_identity: " + self.core.identity)
self.default_config = {}
self.agent_id = "dr_event_setpoint_adj_agent"
self.topic = "slipstream_internal/slipstream_hq/"
self.jci_zonetemp_string = "/ZN-T"
So the BACnet system in the building has JCI VAV boxes all with the same zone temperature sensor point self.jci_zonetemp_string and self.topic is how I pulled them into volttron/config store through BACnet discovery processes.
In my actuate point function (copied from CSV driver example) am I at all close for how to make the rpc call named reads using the get_multiple_points? Hoping to scrape the zone temperature sensor readings on BACnet device ID's 6,7,8,9,10 which are all the same VAV box controller with the same points/BAS program running.
def actuate_point(self):
"""
Request that the Actuator set a point on the CSV device
"""
# Create a start and end timestep to serve as the times we reserve to communicate with the CSV Device
_now = get_aware_utc_now()
str_now = format_timestamp(_now)
_end = _now + td(seconds=10)
str_end = format_timestamp(_end)
# Wrap the timestamps and device topic (used by the Actuator to identify the device) into an actuator request
schedule_request = [[self.ahu_topic, str_now, str_end]]
# Use a remote procedure call to ask the actuator to schedule us some time on the device
result = self.vip.rpc.call(
'platform.actuator', 'request_new_schedule', self.agent_id, 'my_test', 'HIGH', schedule_request).get(
timeout=4)
_log.info(f'*** [INFO] *** - SCHEDULED TIME ON ACTUATOR From "actuate_point" method sucess')
reads = publish_agent.vip.rpc.call(
'platform.actuator',
'get_multiple_points',
self.agent_id,
[(('self.topic'+'6', self.jci_zonetemp_string)),
(('self.topic'+'7', self.jci_zonetemp_string)),
(('self.topic'+'8', self.jci_zonetemp_string)),
(('self.topic'+'9', self.jci_zonetemp_string)),
(('self.topic'+'10', self.jci_zonetemp_string))]).get(timeout=10)
Any tips before I break something on the live system greatly appreciated :)
The basic form of an RPC call to the actuator is as follows:
# use the agent's VIP connection to make an RPC call to the actuator agent
result = self.vip.rpc.call('platform.actuator', <RPC exported function>, <args>).get(timeout=<seconds>)
Because we're working with devices, we need to know which devices we're interested in, and what their topics are. We also need to know which points on the devices that we're interested in.
device_map = {
'device1': '201201',
'device2': '201202',
'device3': '201203',
'device4': '201204',
}
building_topic = 'campus/building'
all_device_points = ['point1', 'point2', 'point3']
Getting points with the actuator requires a list of point topics, or device/point topic pairs.
# we only need one of the following:
point topics = []
for device in device_map.values():
for point in all_device_points:
point_topics.append('/'.join([building_topic, device, point]))
device_point_pairs = []
for device in device_map.values():
for point in all_device_points:
device_point_pairs.append(('/'.join([building_topic, device]),point,))
Now we send our RPC request to the actuator:
# can use instead device_point_pairs
point_results = self.vip.rpc.call('platform.actuator', 'get_multiple_points', point_topics).get(timeout=3)
maybe it's just my interpretation of your question, but it seems a little open-ended - so I shall respond in a similar vein - general (& I'll try to keep it short).
First, you need the list of info for targeting each device in-turn; i.e. it might consist of just a IP(v4) address (for the physical device) & the (logical) device's BOIN (BACnet Object Instance Number) - or if the request is been routed/forwarded on by/via a BACnet router/BACnet gateway then maybe also the DNET # & the DADR too.
Then you probably want - for each device/one at a time, to retrieve the first/0-element value of the device's Object-List property - in order to get the number of objects it contains, to allow you to know how many objects are available (including the logical device/device-type object) - that you need to retrieve from it/iterate over; NOTE: in the real world, as much as it's common for the device-type object to be the first one in the list, there's no guarantee it will always be the case.
As much as the BACnet standard started allowing for the retrieval of the Property-List (property) from each & every object, most equipment don't as-yet support it, so you might need your own idea of what properties (/at least the ones of interest to you) that each different object-type supports; probably at the very-very least know which ones/object-types support the Present-Value property & which ones don't.
One ideal would be to have the following mocked facets - as fakes for testing purposes instead of testing against a live/important device (- or at least consider testing against a noddy BACnet enabled Raspberry PI or the harware-based like):
a mock for your BACnet service
a mock for the BACnet communication stack
a mock for your device as a whole (- if you can't write your own one, then maybe even start with the YABE 'Room Control Simulator' as a starting point)
Hope this helps (in some way).

Dronekit Example Follow Me Python Script not working

I try to run an example script from dronekit. the code is looks like this :
import gps
import socket
import time
from droneapi.lib import VehicleMode, Location
def followme():
"""
followme - A DroneAPI example
This is a somewhat more 'meaty' example on how to use the DroneAPI. It uses the
python gps package to read positions from the GPS attached to your laptop an
every two seconds it sends a new goto command to the vehicle.
To use this example:
* Run mavproxy.py with the correct options to connect to your vehicle
* module load api
* api start <path-to-follow_me.py>
When you want to stop follow-me, either change vehicle modes from your RC
transmitter or type "api stop".
"""
try:
# First get an instance of the API endpoint (the connect via web case will be similar)
api = local_connect()
# Now get our vehicle (we assume the user is trying to control the first vehicle attached to the GCS)
v = api.get_vehicles()[0]
# Don't let the user try to fly while the board is still booting
if v.mode.name == "INITIALISING":
print "Vehicle still booting, try again later"
return
cmds = v.commands
is_guided = False # Have we sent at least one destination point?
# Use the python gps package to access the laptop GPS
gpsd = gps.gps(mode=gps.WATCH_ENABLE)
while not api.exit:
# This is necessary to read the GPS state from the laptop
gpsd.next()
if is_guided and v.mode.name != "GUIDED":
print "User has changed flight modes - aborting follow-me"
break
# Once we have a valid location (see gpsd documentation) we can start moving our vehicle around
if (gpsd.valid & gps.LATLON_SET) != 0:
altitude = 30 # in meters
dest = Location(gpsd.fix.latitude, gpsd.fix.longitude, altitude, is_relative=True)
print "Going to: %s" % dest
# A better implementation would only send new waypoints if the position had changed significantly
cmds.goto(dest)
is_guided = True
v.flush()
# Send a new target every two seconds
# For a complete implementation of follow me you'd want adjust this delay
time.sleep(2)
except socket.error:
print "Error: gpsd service does not seem to be running, plug in USB GPS or run run-fake-gps.sh"
followme()
I try to run it in my Raspberry with Raspbian OS, but i got an error message like this :
Error : gpsd service does not seem to be running, plug in USB GPS or run run-fake-gps.sh
I get a feeling that my raspberry is needed a gps kind of device to be attached before i can run this script, but i dont really know.
Please kindly tell me whats wrong with it..
the full path of instruction i got from here :
http://python.dronekit.io/1.5.0/examples/follow_me.html
As the example says:
[This example] will use a USB GPS attached to your laptop to have the vehicle follow you as you walk around a field.
Without a GPS device, the code doesn't know where you are so it would not be possible to implement any sort of "following" behavior. Before running the example, you would need to:
Acquire some sort of GPS device (I use one of these, but there are lots of alternatives).
Configure gpsd on your laptop to interface with the GPS device.

Move graph trained the GPU to be tested on the CPU

So I have this CNN which I train on the GPU. During the training, I regularly save checkpoint.
Later on, I want to have a small script that reads .meta file and the checkpoint and do some tests on a CPU. I use the following the code:
sess = tf.Session(config=tf.ConfigProto(log_device_placement=True))
with sess.as_default():
with tf.device('/cpu:0'):
saver = tf.train.import_meta_graph('{}.meta'.format(model))
saver.restore(sess,model)
I keep getting this error which tell me that the saver is trying to put the operation on the GPU.
How can i change that?
Move all the ops to CPU using _set_device API. https://github.com/tensorflow/tensorflow/blob/r1.14/tensorflow/python/framework/ops.py#L2255
with tf.Session() as sess:
g = tf.get_default_graph()
ops = g.get_operations()
for op in ops:
op._set_device('/device:CPU:*')
Hacky work-around, open your graph definition file (ending with .pbtxt), and remove all lines starting with device:
For programmatic approach you can see how TensorFlow exporter does this with clear_devices although that uses regular Saver, not meta graph exporter

Resources