gpt4 book ai didi

c++ - 结构被库函数覆盖

转载 作者:行者123 更新时间:2023-11-30 02:21:24 25 4
gpt4 key购买 nike

我对一个 bug 感到困惑,在这个 bug 中,结构的成员有时会被调用一个库函数覆盖,而这个库函数本不应该与它有任何关系。

在看似随机调用 Navagator::update() 之后,行 GPS.parse(GPS.lastNMEA()) 将覆盖导航器对象的路点变量指向的内容。

这个错误很奇怪,我有没有可能把指针放错地方了?

// TransAt.ino
// ---------------------
#include "motors.h"
#include "navagator.h"

Navagator* nav;
Waypoint w = { 43.36, -75.1 };

uint32_t timer = millis();

void setup()
{
Serial.begin(115200);
Serial.println("MIT TransAt Vehicle Debugging");

nav = &Navagator(&w, 1);

Serial.print("\Setup 1 Loc: "); Serial.print(nav->waypoints->lat);
Serial.print(", "); Serial.println(nav->waypoints->lon);

Serial.print("\nSetup 2 Loc: "); Serial.print(nav->waypoints->lat);
Serial.print(", "); Serial.println(nav->waypoints->lon);

}

void loop()
{
Serial.print("\nOuter Loop 1 Loc: "); Serial.print(nav->waypoints->lat);
Serial.print(", "); Serial.println(nav->waypoints->lon);

nav->update();

Serial.print("\nOuter Loop 2 Loc: "); Serial.print(nav->waypoints->lat);
Serial.print(", "); Serial.println(nav->waypoints->lon);

//delay(100000);

if (timer > millis()) timer = millis();

if (millis() - timer > 2000) {
Serial.print("\nLoop 2 Loc: "); Serial.print(nav->waypoints->lat);
Serial.print(", "); Serial.println(nav->waypoints->lon);

timer = millis(); // reset the timer
nav->diagnostic();

Serial.print("\nLoop 3 Loc: "); Serial.print(nav->waypoints->lat);
Serial.print(", "); Serial.println(nav->waypoints->lon);

int course = nav->getCourse();
Serial.println("\nCourse: "); Serial.println(course);

Serial.print("\nLoop 4 Loc: "); Serial.print(nav->waypoints->lat);
Serial.print(", "); Serial.println(nav->waypoints->lon);
}

Serial.print("\nLoop 5 Loc: "); Serial.print(nav->waypoints->lat);
Serial.print(", "); Serial.println(nav->waypoints->lon);

}

-

// navagator.h
// ---------------------
#ifndef _NAVAGATOR_h
#define _NAVAGATOR_h

#if defined(ARDUINO) && ARDUINO >= 100
#include "Arduino.h"
#else
#include "WProgram.h"
#endif

#include <Adafruit_GPS.h>


struct Waypoint {
double lat, lon;
};

class Navagator {
public:
Navagator(Waypoint* w, int);
int getCourse(); // Returns course to next waypoint (compass bearings 0-360 with 0 true North)
void update(); // Updates navagator (Call this frequently in the main loop)
void diagnostic();
Waypoint* waypoints; // Array of waypoints to pass through


private:
int pointCount, next; // Number of waypoints, index of next waypoint
int course; // Last calculated course to waypoint

bool checkWaypoint();
void updateWaypoints();
void startGPS();
void updateGPS();
};


double degreesToRadians(double);
double radiansToDegrees(double);
int calculateCourse(double lat1, double lon1, double lat2, double lon2);
double calculateCoordinateDistance(double, double, double, double);
double getLatitude();
double getLongitude();

#endif

-

// 
// Library for navigator guiding the TransAt vehicle
//
// Note: The navigator uses 0-360 compass bearings with 0 equivalent to true North and assumes 1 degree of precision
// All distances are measured in km
// The course is the ideal angle between the vehicle and a waypoint
// navagator.cpp
// -------------------

#include "navagator.h"
#include <math.h>

#define EARTH_RADIUS 6371 // in km
#define WAYPOINT_RADIUS 5 // in km

#include <Adafruit_GPS.h>
#define GPSSerial Serial3
Adafruit_GPS GPS(&GPSSerial);

Navagator::Navagator(Waypoint* w, int count) {
waypoints = w;
pointCount = count;
next = 0; // start with first waypoint
course = 90; // Notice that initial course is due East
startGPS();
}

// Returns course between 0-360 degrees, where 0 is true North
int Navagator::getCourse() {
if (!GPS.fix) // Without a fix, continue along last course.
return course;

// Get coordinates (In decimal degrees)
double waypointLon = waypoints->lon;
double waypointLat = waypoints->lat;
double currentLon = getLongitude();
double currentLat = getLatitude();

Serial.print("Waypoint Loc: "); Serial.print(waypoints->lat);
Serial.print(", "); Serial.println(waypoints->lon);

// Update course
course = calculateCourse(currentLat, currentLon, waypointLat, waypointLon);
return course;
}

// Passed coordinates in decimal degrees
// Returns course in integer compass bearings
int calculateCourse(double lat1, double lon1, double lat2, double lon2) {
// From https://www.movable-type.co.uk/scripts/latlong.html

// Convert to radians
lat1 = degreesToRadians(lat1);
lon1 = degreesToRadians(lon1);
lat2 = degreesToRadians(lat2);
lon2 = degreesToRadians(lon2);

double y = sin(lon2 - lon1) * cos(lat2);
double x = cos(lat1) * sin(lat2) - sin(lat1) * cos(lat2) * cos(lon2 - lon1);
int course = ((int)radiansToDegrees(atan2(y, x)) + 360) % 360; // We convert the -pi to pi result of atan2 to 360 degree compass bearings

return course;
}

// Call this from the main loop to keep navigation up to date
void Navagator::update() {

Serial.print("Update 1 Loc: "); Serial.print(waypoints->lat);
Serial.print(", "); Serial.println(waypoints->lon);

updateGPS();

Serial.print("Update 2 Loc: "); Serial.print(waypoints->lat);
Serial.print(", "); Serial.println(waypoints->lon);

updateWaypoints();

Serial.print("Update 3 Loc: "); Serial.print(waypoints->lat);
Serial.print(", "); Serial.println(waypoints->lon);
}

void Navagator::updateWaypoints() {
if (checkWaypoint()) { // If we've reached a waypoint

if (next + 1 < pointCount) // If there are more waypoints,
next++; // Move to the next waypoint (Else, keep seeking the last waypoint)
}
}

// Returns true if we've reached the next waypoint, else false
bool Navagator::checkWaypoint() {
if (!GPS.fix) // Without a fix, assume we haven't reached a waypoint
return false;

// Get coordinates
double waypointLon = (waypoints + next)->lon;
double waypointLat = (waypoints + next)->lat;
double currentLon = getLongitude();
double currentLat = getLatitude();

// Return if distance between them is less than the waypoint
return calculateCoordinateDistance(currentLat, currentLon, waypointLat, waypointLon) < WAYPOINT_RADIUS;
}

// Takes coordinates in decimal degrees
// Returns distance between in km
double calculateCoordinateDistance(double lat1, double lon1, double lat2, double lon2) {
// Halversine Formula https://www.movable-type.co.uk/scripts/latlong.html

// Convert to radians
lat1 = degreesToRadians(lat1);
lon1 = degreesToRadians(lon1);
lat2 = degreesToRadians(lat2);
lon2 = degreesToRadians(lon2);

// Find distance on unit sphere
double a = pow(sin((lat2 - lat1) / 2), 2) + cos(lat1) * cos(lat2) * pow(sin((lon2 - lon1) / 2), 2); // For right triangle with sides a, b, and c
double c = 2 * atan2(sqrt(a), sqrt(1 - a));

return EARTH_RADIUS * c;
}

double degreesToRadians(double degrees) {
return degrees * M_PI / 180;
}

double radiansToDegrees(double radians) {
return radians * 180 / M_PI;
}

// Provides decimal degree latitude with ~1km of precision
double getLatitude() {
double lat = GPS.latitude_fixed;

if (GPS.lat == 'S') { // Note we're doing a character comparision here so the == is appropriate
lat = -lat; // Southern latitudes are negative
}

return lat / 10000000.0;
}

// Provides decimal degree latitude with ~1km of precision
double getLongitude() {
double lon = GPS.longitude_fixed;

if (GPS.lon == 'W') { // Note we're doing a character comparision here so the == is appropriate
lon = -lon; // Western lattitudes are negative
}

return lon / 10000000.0;
}

// Configures and begins reading GPS
void Navagator::startGPS() {
GPS.begin(9600);

GPS.sendCommand(PMTK_SET_NMEA_OUTPUT_RMCGGA); // Turn on RMC (recommended minimum) and GGA (fix data) including altitude
GPS.sendCommand(PMTK_SET_NMEA_UPDATE_1HZ); // 1 Hz update rate (In final version, these rates should be lowered and the interupt used less frequently to conserve clock cycles)
delay(1000);

// Create interrupt
OCR0A = 0xAF; // We'll use comparison register A (OCR0A) for the ATMega's ~1Hz Timer0 (When Timer0 == OCR0A == 0xAF, the interupt will fire)
TIMSK0 |= _BV(OCIE0A); // enable compare A interrupts
// Note: TIMSK0 is a macro for the 'Timer Interrupt Mask Register' and OCIE0A is the bit mask specifing 'Timer/Counter Output Compare Match A Interrupt'

// Wait for GPS to get fix
// Actually we can't do that
// Trying to loop here produces weird behavior where nothing is printed to Serial or we never get any data from the gps
// Possibly try to figure out what is going on later?
}

// Interrupt is called once a millisecond, looks for any new GPS data, and stores it
SIGNAL(TIMER0_COMPA_vect) {
GPS.read(); // read any new GPS data (We still have to parse completed sentences in the main loop)
}

// Parses new NMEA sentences
void Navagator::updateGPS() {
Serial.print("UpdateGPS 1 Loc: "); Serial.print(waypoints->lat);
Serial.print(", "); Serial.println(waypoints->lon);
if (GPS.newNMEAreceived())
Serial.print("**UpdateGPS 2 Loc: "); Serial.print(waypoints->lat);
Serial.print(", "); Serial.println(waypoints->lon);
Serial.println(GPS.parse(GPS.lastNMEA()));

Serial.print("UpdateGPS 3 Loc: "); Serial.print(waypoints->lat);
Serial.print(", "); Serial.println(waypoints->lon);
}

void Navagator::diagnostic() {

Serial.print("\nNav 1 Loc: "); Serial.print(waypoints->lat);
Serial.print(", "); Serial.println(waypoints->lon);

Serial.println("\n\nNavagation Diagnostic");
Serial.print("Time: ");
Serial.print(GPS.hour, DEC); Serial.print(':');
Serial.print(GPS.minute, DEC); Serial.print(':');
Serial.print(GPS.seconds, DEC); Serial.print('.');
Serial.println(GPS.milliseconds);
Serial.print("Date: ");
Serial.print(GPS.day, DEC); Serial.print('/');
Serial.print(GPS.month, DEC); Serial.print("/20");
Serial.println(GPS.year, DEC);
Serial.print("Fix: "); Serial.print((int)GPS.fix);
Serial.print(" quality: "); Serial.println((int)GPS.fixquality);
if (GPS.fix) {
Serial.print("Location: ");
Serial.print(getLatitude()); Serial.print(GPS.lat); // Decimal Degrees (1/10,000,000 of a degree)
Serial.print(", ");
Serial.print(getLongitude()); Serial.println(GPS.lon); // Decimal Degrees (1/10,000,000 of a degree)
Serial.print("Speed (knots): "); Serial.println(GPS.speed);
Serial.print("Angle: "); Serial.println(GPS.angle);
Serial.print("Altitude: "); Serial.println(GPS.altitude);
Serial.print("Satellites: "); Serial.println((int)GPS.satellites);
}
Serial.print("Waypoint: "); Serial.println(next);

Serial.print("\nNav 2 Loc: "); Serial.print(waypoints->lat);
Serial.print(", "); Serial.println(waypoints->lon);
}

-

输出

...

0
UpdateGPS 3 Loc: 43.36, -75.10
Update 2 Loc: 43.36, -75.10
Update 3 Loc: 43.36, -75.10

Outer Loop 2 Loc: 43.36, -75.10

Loop 5 Loc: 43.36, -75.10

Outer Loop 1 Loc: 43.36, -75.10
Update 1 Loc: 43.36, -75.10
UpdateGPS 1 Loc: 43.36, -75.10
**UpdateGPS 2 Loc: 43.36, -75.10
1
UpdateGPS 3 Loc: 0.00, 0.00
Update 2 Loc: 0.00, 0.00
Update 3 Loc: 0.00, 0.00

Outer Loop 2 Loc: 0.00, 0.00

Loop 5 Loc: 0.00, 0.00

Outer Loop 1 Loc: 0.00, 0.00
Update 1 Loc: 0.00, 0.00
UpdateGPS 1 Loc: 0.00, 0.00
0.00, 0.00
1
UpdateGPS 3 Loc: 0.00, 0.00
Update 2 Loc: 0.00, 0.00
Update 3 Loc: 0.00, 0.00

Outer Loop 2 Loc: 0.00, 0.00

Loop 5 Loc: 0.00, 0.00

Outer Loop 1 Loc: 0.00, 0.00
Update 1 Loc: 0.00, 0.00
UpdateGPS 1 Loc: 0.00, 0.00
0.00, 0.00
1

...

最佳答案

一个问题是这一行:

nav = &Navagator(&w, 1);

那个Navigator对象被创建,然后立即销毁。它的生命周期就是那个声明,所以你正在获取一些不会存在的地址。因此,如果您使用 nav,该程序将表现出未定义的行为。 ,假设它仍然指向某个有效的地方。

nav是指向 Navigator 的指针,并且您当前的程序将其声明为全局变量(有问题,但这是另一回事),所有这些的更好方法是使用 std::unique_ptr<Navigator> .这将允许创建一个 Navigator动态,并会在 std::unique_ptr 时自动删除自身超出范围(当您的程序终止时)。

例如:

#include <memory>
//...
std::unique_ptr<Navigator> nav;

然后在你的setup()功能:

nav = std::make_unique<Navigator>(&w, 1);

然后如果你想得到底层nav指针,使用 get() std::unique_ptr 提供的功能:

Navigator* ptr = nav.get();

关于c++ - 结构被库函数覆盖,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48352957/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com